Improve CTL_BEARG_* flags support, including optional values copyout.

This commit is contained in:
mav 2014-07-05 14:32:42 +00:00
parent cd2bf77221
commit 6a3d6f3982
2 changed files with 43 additions and 25 deletions

View File

@ -2013,40 +2013,40 @@ ctl_copyin_alloc(void *user_addr, int len, char *error_str,
}
static void
ctl_free_args(int num_be_args, struct ctl_be_arg *be_args)
ctl_free_args(int num_args, struct ctl_be_arg *args)
{
int i;
if (be_args == NULL)
if (args == NULL)
return;
for (i = 0; i < num_be_args; i++) {
free(be_args[i].kname, M_CTL);
free(be_args[i].kvalue, M_CTL);
for (i = 0; i < num_args; i++) {
free(args[i].kname, M_CTL);
free(args[i].kvalue, M_CTL);
}
free(be_args, M_CTL);
free(args, M_CTL);
}
static struct ctl_be_arg *
ctl_copyin_args(int num_be_args, struct ctl_be_arg *be_args,
ctl_copyin_args(int num_args, struct ctl_be_arg *uargs,
char *error_str, size_t error_str_len)
{
struct ctl_be_arg *args;
int i;
args = ctl_copyin_alloc(be_args, num_be_args * sizeof(*be_args),
args = ctl_copyin_alloc(uargs, num_args * sizeof(*args),
error_str, error_str_len);
if (args == NULL)
goto bailout;
for (i = 0; i < num_be_args; i++) {
for (i = 0; i < num_args; i++) {
args[i].kname = NULL;
args[i].kvalue = NULL;
}
for (i = 0; i < num_be_args; i++) {
for (i = 0; i < num_args; i++) {
uint8_t *tmpptr;
args[i].kname = ctl_copyin_alloc(args[i].name,
@ -2060,31 +2060,43 @@ ctl_copyin_args(int num_be_args, struct ctl_be_arg *be_args,
goto bailout;
}
args[i].kvalue = NULL;
tmpptr = ctl_copyin_alloc(args[i].value,
args[i].vallen, error_str, error_str_len);
if (tmpptr == NULL)
goto bailout;
args[i].kvalue = tmpptr;
if ((args[i].flags & CTL_BEARG_ASCII)
&& (tmpptr[args[i].vallen - 1] != '\0')) {
snprintf(error_str, error_str_len, "Argument %d "
"value is not NUL-terminated", i);
goto bailout;
if (args[i].flags & CTL_BEARG_RD) {
tmpptr = ctl_copyin_alloc(args[i].value,
args[i].vallen, error_str, error_str_len);
if (tmpptr == NULL)
goto bailout;
if ((args[i].flags & CTL_BEARG_ASCII)
&& (tmpptr[args[i].vallen - 1] != '\0')) {
snprintf(error_str, error_str_len, "Argument "
"%d value is not NUL-terminated", i);
goto bailout;
}
args[i].kvalue = tmpptr;
} else {
args[i].kvalue = malloc(args[i].vallen,
M_CTL, M_WAITOK | M_ZERO);
}
}
return (args);
bailout:
ctl_free_args(num_be_args, args);
ctl_free_args(num_args, args);
return (NULL);
}
static void
ctl_copyout_args(int num_args, struct ctl_be_arg *args)
{
int i;
for (i = 0; i < num_args; i++) {
if (args[i].flags & CTL_BEARG_WR)
copyout(args[i].kvalue, args[i].value, args[i].vallen);
}
}
/*
* Escape characters that are illegal or not recommended in XML.
*/
@ -2945,6 +2957,8 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
retval = backend->ioctl(dev, cmd, addr, flag, td);
if (lun_req->num_be_args > 0) {
ctl_copyout_args(lun_req->num_be_args,
lun_req->kern_be_args);
ctl_free_args(lun_req->num_be_args,
lun_req->kern_be_args);
}

View File

@ -181,6 +181,10 @@ ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
STAILQ_INIT(opts);
for (i = 0; i < num_args; i++) {
if ((args[i].flags & CTL_BEARG_RD) == 0)
continue;
if ((args[i].flags & CTL_BEARG_ASCII) == 0)
continue;
opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
opt->name = malloc(strlen(args[i].kname) + 1, M_CTL, M_WAITOK);
strcpy(opt->name, args[i].kname);