mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 10:01:01 +03:00
libzpool: set_global_var: refactor to not modify 'arg'
Also fixes leak of the dlopen handle in the error case. Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Pavel Zakharov <pavel.zakharov@delphix.com> Signed-off-by: Christian Schwarz <me@cschwarz.com> Closes #11602
This commit is contained in:
parent
b5fffa1d29
commit
edc508ac0b
@ -652,7 +652,7 @@ extern void random_fini(void);
|
|||||||
|
|
||||||
struct spa;
|
struct spa;
|
||||||
extern void show_pool_stats(struct spa *);
|
extern void show_pool_stats(struct spa *);
|
||||||
extern int set_global_var(char *arg);
|
extern int set_global_var(char const *arg);
|
||||||
|
|
||||||
typedef struct callb_cpr {
|
typedef struct callb_cpr {
|
||||||
kmutex_t *cc_lockp;
|
kmutex_t *cc_lockp;
|
||||||
|
@ -148,16 +148,52 @@ show_pool_stats(spa_t *spa)
|
|||||||
nvlist_free(config);
|
nvlist_free(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* *k_out must be freed by the caller */
|
||||||
|
static int
|
||||||
|
set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
VERIFY(arg);
|
||||||
|
char *d = strdup(arg);
|
||||||
|
|
||||||
|
char *save = NULL;
|
||||||
|
char *k = strtok_r(d, "=", &save);
|
||||||
|
char *v_str = strtok_r(NULL, "=", &save);
|
||||||
|
char *follow = strtok_r(NULL, "=", &save);
|
||||||
|
if (k == NULL || v_str == NULL || follow != NULL) {
|
||||||
|
err = EINVAL;
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_longlong_t val = strtoull(v_str, NULL, 0);
|
||||||
|
if (val > UINT32_MAX) {
|
||||||
|
fprintf(stderr, "Value for global variable '%s' must "
|
||||||
|
"be a 32-bit unsigned integer, got '%s'\n", k, v_str);
|
||||||
|
err = EOVERFLOW;
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
*k_out = k;
|
||||||
|
*v_out = val;
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
free(k);
|
||||||
|
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets given global variable in libzpool to given unsigned 32-bit value.
|
* Sets given global variable in libzpool to given unsigned 32-bit value.
|
||||||
* arg: "<variable>=<value>"
|
* arg: "<variable>=<value>"
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
set_global_var(char *arg)
|
set_global_var(char const *arg)
|
||||||
{
|
{
|
||||||
void *zpoolhdl;
|
void *zpoolhdl;
|
||||||
char *varname = arg, *varval;
|
char *varname;
|
||||||
u_longlong_t val;
|
u_longlong_t val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
#ifndef _ZFS_LITTLE_ENDIAN
|
#ifndef _ZFS_LITTLE_ENDIAN
|
||||||
/*
|
/*
|
||||||
@ -167,19 +203,12 @@ set_global_var(char *arg)
|
|||||||
*/
|
*/
|
||||||
fprintf(stderr, "Setting global variables is only supported on "
|
fprintf(stderr, "Setting global variables is only supported on "
|
||||||
"little-endian systems\n");
|
"little-endian systems\n");
|
||||||
return (ENOTSUP);
|
ret = ENOTSUP;
|
||||||
|
goto out_ret;
|
||||||
#endif
|
#endif
|
||||||
if (arg != NULL && (varval = strchr(arg, '=')) != NULL) {
|
|
||||||
*varval = '\0';
|
if ((ret = set_global_var_parse_kv(arg, &varname, &val)) != 0) {
|
||||||
varval++;
|
goto out_ret;
|
||||||
val = strtoull(varval, NULL, 0);
|
|
||||||
if (val > UINT32_MAX) {
|
|
||||||
fprintf(stderr, "Value for global variable '%s' must "
|
|
||||||
"be a 32-bit unsigned integer\n", varname);
|
|
||||||
return (EOVERFLOW);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return (EINVAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
|
zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
|
||||||
@ -189,18 +218,25 @@ set_global_var(char *arg)
|
|||||||
if (var == NULL) {
|
if (var == NULL) {
|
||||||
fprintf(stderr, "Global variable '%s' does not exist "
|
fprintf(stderr, "Global variable '%s' does not exist "
|
||||||
"in libzpool.so\n", varname);
|
"in libzpool.so\n", varname);
|
||||||
return (EINVAL);
|
ret = EINVAL;
|
||||||
|
goto out_dlclose;
|
||||||
}
|
}
|
||||||
*var = (uint32_t)val;
|
*var = (uint32_t)val;
|
||||||
|
|
||||||
dlclose(zpoolhdl);
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Failed to open libzpool.so to set global "
|
fprintf(stderr, "Failed to open libzpool.so to set global "
|
||||||
"variable\n");
|
"variable\n");
|
||||||
return (EIO);
|
ret = EIO;
|
||||||
|
goto out_dlclose;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
ret = 0;
|
||||||
|
|
||||||
|
out_dlclose:
|
||||||
|
dlclose(zpoolhdl);
|
||||||
|
free(varname);
|
||||||
|
out_ret:
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static nvlist_t *
|
static nvlist_t *
|
||||||
|
Loading…
Reference in New Issue
Block a user