88
99#include <wordexp.h>
1010#include <getopt.h>
11+ #include <regex.h>
12+ #include <errno.h>
13+ #include <string.h>
1114
1215#include <daos_errno.h>
1316
@@ -22,55 +25,123 @@ safe_strcat(char *dst, const char *src, size_t dst_size)
2225 strncat (dst , src , remaining_space );
2326}
2427
28+ static void
29+ print_regx_error (int rc , regex_t * preg , const char * regex_buf )
30+ {
31+ char * buf ;
32+ size_t buf_size ;
33+
34+ buf_size = regerror (rc , preg , NULL , 0 );
35+ D_ALLOC_ARRAY (buf , buf_size );
36+ D_ASSERT (buf != NULL );
37+ regerror (rc , preg , buf , buf_size );
38+ D_CRIT ("Invalid regex '%s': %s" , regex_buf , buf );
39+ D_FREE (buf );
40+ }
41+
2542int
2643vos_path_parse (const char * path , struct vos_file_parts * vos_file_parts )
2744{
28- uint32_t path_len = strlen (path ) + 1 ;
29- char * path_copy ;
30- char * tok ;
31- int rc = - DER_INVAL ;
45+ enum {
46+ DB_PATH_IDX = 1 ,
47+ POOL_UUID_IDX = 3 ,
48+ VOS_FILE_NAME_IDX = 5 ,
49+ TARGET_IDX_IDX = 6 ,
50+ MATCH_SIZE = 7 ,
51+ POOL_UUID_LEN = 36
52+ };
53+ const char * regex_buf =
54+ "^(/?([^/]+/)*)([0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})/"
55+ "(vos-([0-9]|([1-9][0-9]+)))$" ;
56+ char * endptr ;
57+ uint64_t target_idx ;
58+ regex_t preg ;
59+ char pool_uuid [POOL_UUID_LEN + 1 ];
60+ regmatch_t match [MATCH_SIZE + 1 ];
61+ size_t vos_file_name_len ;
62+ int rc ;
3263
3364 D_ASSERT (path != NULL && vos_file_parts != NULL );
3465
35- D_ALLOC (path_copy , path_len );
36- if (path_copy == NULL )
37- return - DER_NOMEM ;
38- strcpy (path_copy , path );
39-
40- tok = strtok (path_copy , "/" );
41- while (tok != NULL && rc != 0 ) {
42- rc = uuid_parse (tok , vos_file_parts -> vf_pool_uuid );
43- if (!SUCCESS (rc )) {
44- safe_strcat (vos_file_parts -> vf_db_path , "/" , DB_PATH_LEN );
45- safe_strcat (vos_file_parts -> vf_db_path , tok , DB_PATH_LEN );
66+ rc = regcomp (& preg , regex_buf , REG_EXTENDED );
67+ if (rc != 0 ) {
68+ print_regx_error (rc , & preg , regex_buf );
69+ rc = - DER_INVAL ;
70+ goto out ;
71+ }
72+
73+ rc = regexec (& preg , path , MATCH_SIZE , match , 0 );
74+ if (rc == REG_NOMATCH ) {
75+ D_ERROR ("Innvalid VOS path: '%s'\n" , path );
76+ rc = - DER_INVAL ;
77+ goto out_preg ;
78+ }
79+ D_ASSERT (SUCCESS (rc ));
80+
81+ vos_file_parts -> vf_db_path [0 ] = '\0' ;
82+ if ((match [DB_PATH_IDX ].rm_eo - match [DB_PATH_IDX ].rm_so ) != 0 ) {
83+ D_ASSERT (match [DB_PATH_IDX ].rm_so == 0 );
84+ if (match [DB_PATH_IDX ].rm_eo > DB_PATH_SIZE ) {
85+ D_ERROR ("DB path '%.*s' too long in VOS path '%s': get=%i, max=%i\n" ,
86+ match [DB_PATH_IDX ].rm_eo - 1 , & path [match [DB_PATH_IDX ].rm_so ], path ,
87+ match [DB_PATH_IDX ].rm_eo - 1 , DB_PATH_SIZE - 1 );
88+ rc = - DER_INVAL ;
89+ goto out_preg ;
4690 }
47- tok = strtok (NULL , "/" );
91+ memcpy (vos_file_parts -> vf_db_path , path , match [DB_PATH_IDX ].rm_eo - 1 );
92+ vos_file_parts -> vf_db_path [match [DB_PATH_IDX ].rm_eo - 1 ] = '\0' ;
4893 }
4994
50- if (rc != 0 || tok == NULL ) {
51- D_ERROR ("Incomplete path: %s\n" , path );
52- D_GOTO (done , rc = - DER_INVAL );
95+ D_ASSERT (match [POOL_UUID_IDX ].rm_so != (regoff_t )- 1 );
96+ D_ASSERT (match [POOL_UUID_IDX ].rm_eo - match [POOL_UUID_IDX ].rm_so == POOL_UUID_LEN );
97+ memcpy (pool_uuid , & path [match [POOL_UUID_IDX ].rm_so ], POOL_UUID_LEN );
98+ pool_uuid [POOL_UUID_LEN ] = '\0' ;
99+ rc = uuid_parse (pool_uuid , vos_file_parts -> vf_pool_uuid );
100+ if (!SUCCESS (rc )) {
101+ D_CRIT ("Invalid Pool UUID '%s' in VOS path '%s'\n" , pool_uuid , path );
102+ rc = - DER_INVAL ;
103+ goto out_preg ;
53104 }
54105
55- strncpy (vos_file_parts -> vf_vos_file , tok , ARRAY_SIZE (vos_file_parts -> vf_vos_file ) - 1 );
56-
57- /*
58- * file name should be vos-N ... split on "-"
59- * If not, might be test, just assume target of 0
60- */
61- strtok (tok , "-" );
62- tok = strtok (NULL , "-" );
63- if (tok != NULL ) {
64- D_WARN ("vos file name not in correct format: %s\n" , vos_file_parts -> vf_vos_file );
65- vos_file_parts -> vf_target_idx = atoi (tok );
106+ D_ASSERT (match [VOS_FILE_NAME_IDX ].rm_so != (regoff_t )- 1 );
107+ vos_file_name_len = match [VOS_FILE_NAME_IDX ].rm_eo - match [VOS_FILE_NAME_IDX ].rm_so ;
108+ if (vos_file_name_len + 1 > VOS_FILE_NAME_SIZE ) {
109+ D_ERROR ("VOS file name '%.*s' too long in VOS path '%s': get=%zu, max=%i\n" ,
110+ (int )vos_file_name_len , & path [match [VOS_FILE_NAME_IDX ].rm_so ], path ,
111+ vos_file_name_len , VOS_FILE_NAME_SIZE - 1 );
112+ rc = - DER_INVAL ;
113+ goto out_preg ;
114+ }
115+ memcpy (vos_file_parts -> vf_vos_file_name , & path [match [VOS_FILE_NAME_IDX ].rm_so ],
116+ vos_file_name_len );
117+ vos_file_parts -> vf_vos_file_name [vos_file_name_len ] = '\0' ;
118+
119+ D_ASSERT (match [TARGET_IDX_IDX ].rm_so != (regoff_t )- 1 );
120+ errno = 0 ;
121+ target_idx = strtoull (& path [match [TARGET_IDX_IDX ].rm_so ], & endptr , 10 );
122+ if (errno != 0 || endptr == & path [match [TARGET_IDX_IDX ].rm_so ] || * endptr != '\0' ) {
123+ D_CRIT ("Invalid target index '%s' in VOS path '%s': %s\n" ,
124+ & path [match [TARGET_IDX_IDX ].rm_so ], path , strerror (errno ));
125+ rc = - DER_INVAL ;
126+ goto out_preg ;
66127 }
128+ if (target_idx > UINT32_MAX ) {
129+ D_ERROR ("Target index " DF_U64
130+ "' out of range in VOS path '%s': min=0 , max=%" PRIu32 "\n" ,
131+ target_idx , path , UINT32_MAX );
132+ rc = - DER_INVAL ;
133+ goto out_preg ;
134+ }
135+ vos_file_parts -> vf_target_idx = target_idx ;
67136
68- done :
69- if (!SUCCESS (rc )) {
70- /* Reset to if not valid */
137+ rc = - DER_SUCCESS ;
138+
139+ out_preg :
140+ regfree (& preg );
141+ out :
142+ /* Reset to zero if not valid */
143+ if (!SUCCESS (rc ))
71144 memset (vos_file_parts , 0 , sizeof (* vos_file_parts ));
72- }
73- D_FREE (path_copy );
74145 return rc ;
75146}
76147
0 commit comments