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