@@ -148,16 +148,52 @@ show_pool_stats(spa_t *spa)
148148 nvlist_free (config );
149149}
150150
151+ /* *k_out must be freed by the caller */
152+ static int
153+ set_global_var_parse_kv (const char * arg , char * * k_out , u_longlong_t * v_out )
154+ {
155+ int err ;
156+ VERIFY (arg );
157+ char * d = strdup (arg );
158+
159+ char * save = NULL ;
160+ char * k = strtok_r (d , "=" , & save );
161+ char * v_str = strtok_r (NULL , "=" , & save );
162+ char * follow = strtok_r (NULL , "=" , & save );
163+ if (k == NULL || v_str == NULL || follow != NULL ) {
164+ err = EINVAL ;
165+ goto err_free ;
166+ }
167+
168+ u_longlong_t val = strtoull (v_str , NULL , 0 );
169+ if (val > UINT32_MAX ) {
170+ fprintf (stderr , "Value for global variable '%s' must "
171+ "be a 32-bit unsigned integer, got '%s'\n" , k , v_str );
172+ err = EOVERFLOW ;
173+ goto err_free ;
174+ }
175+
176+ * k_out = k ;
177+ * v_out = val ;
178+ return (0 );
179+
180+ err_free :
181+ free (k );
182+
183+ return (err );
184+ }
185+
151186/*
152187 * Sets given global variable in libzpool to given unsigned 32-bit value.
153188 * arg: "<variable>=<value>"
154189 */
155190int
156- set_global_var (char * arg )
191+ set_global_var (char const * arg )
157192{
158193 void * zpoolhdl ;
159- char * varname = arg , * varval ;
194+ char * varname ;
160195 u_longlong_t val ;
196+ int ret ;
161197
162198#ifndef _ZFS_LITTLE_ENDIAN
163199 /*
@@ -167,19 +203,12 @@ set_global_var(char *arg)
167203 */
168204 fprintf (stderr , "Setting global variables is only supported on "
169205 "little-endian systems\n" );
170- return (ENOTSUP );
206+ ret = ENOTSUP ;
207+ goto out_ret ;
171208#endif
172- if (arg != NULL && (varval = strchr (arg , '=' )) != NULL ) {
173- * varval = '\0' ;
174- varval ++ ;
175- val = strtoull (varval , NULL , 0 );
176- if (val > UINT32_MAX ) {
177- fprintf (stderr , "Value for global variable '%s' must "
178- "be a 32-bit unsigned integer\n" , varname );
179- return (EOVERFLOW );
180- }
181- } else {
182- return (EINVAL );
209+
210+ if ((ret = set_global_var_parse_kv (arg , & varname , & val )) != 0 ) {
211+ goto out_ret ;
183212 }
184213
185214 zpoolhdl = dlopen ("libzpool.so" , RTLD_LAZY );
@@ -189,18 +218,25 @@ set_global_var(char *arg)
189218 if (var == NULL ) {
190219 fprintf (stderr , "Global variable '%s' does not exist "
191220 "in libzpool.so\n" , varname );
192- return (EINVAL );
221+ ret = EINVAL ;
222+ goto out_dlclose ;
193223 }
194224 * var = (uint32_t )val ;
195225
196- dlclose (zpoolhdl );
197226 } else {
198227 fprintf (stderr , "Failed to open libzpool.so to set global "
199228 "variable\n" );
200- return (EIO );
229+ ret = EIO ;
230+ goto out_dlclose ;
201231 }
202232
203- return (0 );
233+ ret = 0 ;
234+
235+ out_dlclose :
236+ dlclose (zpoolhdl );
237+ free (varname );
238+ out_ret :
239+ return (ret );
204240}
205241
206242static nvlist_t *
0 commit comments