error_t
trivfs_append_args (struct trivfs_control *trivfs_control,
		    char **argz, size_t *argz_len)
{
  struct dev *const dev = trivfs_control->hook;
  error_t err = 0;

  if (dev->rdev != (dev_t) 0)
    {
      char buf[40];
      snprintf (buf, sizeof buf, "--rdev=%d,%d",
		major (dev->rdev), minor (dev->rdev));
      err = argz_add (argz, argz_len, buf);
    }

  if (!err && dev->inhibit_cache)
    err = argz_add (argz, argz_len, "--no-cache");

  if (!err && dev->enforced)
    err = argz_add (argz, argz_len, "--enforced");

  if (!err && dev->no_fileio)
    err = argz_add (argz, argz_len, "--no-file-io");

  if (! err)
    err = argz_add (argz, argz_len,
		    dev->readonly ? "--readonly" : "--writable");

  if (! err)
    err = store_parsed_append_args (dev->store_name, argz, argz_len);

  return err;
}
Exemple #2
0
/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
   existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
   Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
   ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ.  If BEFORE is not
   in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
   ARGZ, ENOMEM is returned, else 0.  */
error_t
argz_insert (char **argz, size_t *argz_len, char *before, const char *entry)
{
  if (! before)
    return argz_add (argz, argz_len, entry);

  if (before < *argz || before >= *argz + *argz_len)
    return EINVAL;

  if (before > *argz)
    /* Make sure before is actually the beginning of an entry.  */
    while (before[-1])
      before--;

  {
    size_t after_before = *argz_len - (before - *argz);
    size_t entry_len = strlen  (entry) + 1;
    size_t new_argz_len = *argz_len + entry_len;
    char *new_argz = realloc (*argz, new_argz_len);

    if (new_argz)
      {
        before = new_argz + (before - *argz);
        memmove (before + entry_len, before, after_before);
        memmove (before, entry, entry_len);
        *argz = new_argz;
        *argz_len = new_argz_len;
        return 0;
      }
    else
      return ENOMEM;
  }
}
Exemple #3
0
error_t
argz_insert (char **argz, size_t *argz_len, char *before, const char *entry)
{
  int len = 0;

  if (before == NULL)
    argz_add(argz, argz_len, entry);

  if (before < *argz || before >= *argz + *argz_len)
    return EINVAL;

  while (before != *argz && before[-1])
    before--;

  len = strlen(entry) + 1;

  if(!(*argz = (char *)realloc(*argz, *argz_len + len)))
    return ENOMEM;
  
  memmove(before + len, before, *argz + *argz_len - before);
  memcpy(before, entry, len);

  *argz_len += len;

  return 0;
}
Exemple #4
0
int subprocess_set_command (struct subprocess *p, const char *cmd)
{
    int e;

    if (p->started) {
        errno = EINVAL;
        return (-1);
    }
    init_argz (&p->argz, &p->argz_len, NULL);

    if ((e = argz_add (&p->argz, &p->argz_len, "sh")) != 0
        || (e = argz_add (&p->argz, &p->argz_len, "-c")) != 0
        || (e = argz_add (&p->argz, &p->argz_len, cmd)) != 0) {
        errno = e;
        return (-1);
    }
    return (0);
}
Exemple #5
0
/* Return an argz string describing the current options.  Fill *ARGZ
   with a pointer to newly malloced storage holding the list and *LEN
   to the length of that storage.  */
error_t
netfs_append_args (char **argz, size_t *argz_len)
{
  error_t err = 0;

  ulfs_iterate
    {
      if (! err)
	if (unionfs_flags & FLAG_UNIONFS_MODE_DEBUG)
	  err = argz_add (argz, argz_len,
			  OPT_LONG (OPT_LONG_DEBUG));
      if (! err)
	if (ulfs->flags & FLAG_ULFS_WRITABLE)
	  err = argz_add (argz, argz_len,
			  OPT_LONG (OPT_LONG_WRITABLE));
      if (! err)
	if (ulfs->priority)
	  {
	    char *buf = NULL;
	    if ((err = asprintf (&buf, "%s=%s", OPT_LONG (OPT_LONG_PRIORITY), 
		      ulfs->priority)) != -1)
	      {
		err = argz_add (argz, argz_len, buf);
		free (buf);
	      }
	  }

      if (! err)
	{
	  if (ulfs->path)
	    err = argz_add (argz, argz_len, ulfs->path);
	  else
	    err = argz_add (argz, argz_len,
			    OPT_LONG (OPT_LONG_UNDERLYING));
	}
    }

  return err;
}
Exemple #6
0
int subprocess_argv_append (struct subprocess *p, const char *s)
{
    int e;

    if (p->started) {
        errno = EINVAL;
        return (-1);
    }

    if ((e = argz_add (&p->argz, &p->argz_len, s)) != 0) {
        errno = e;
        return -1;
    }
    return (0);
}
Exemple #7
0
error_t
diskfs_append_std_options (char **argz, size_t *argz_len)
{
  error_t err;
  extern int diskfs_sync_interval;

  if (diskfs_readonly)
    err = argz_add (argz, argz_len, "--readonly");
  else
    err = argz_add (argz, argz_len, "--writable");

  if (!err && _diskfs_nosuid)
    err = argz_add (argz, argz_len, "--no-suid");
  if (!err && _diskfs_noexec)
    err = argz_add (argz, argz_len, "--no-exec");
  if (!err && _diskfs_noatime)
    err = argz_add (argz, argz_len, "--no-atime");
  if (!err && _diskfs_no_inherit_dir_group)
    err = argz_add (argz, argz_len, "--no-inherit-dir-group");

  if (! err)
    {
      if (diskfs_synchronous)
	err = argz_add (argz, argz_len, "--sync");
      else if (DEFAULT_SYNC_INTERVAL != diskfs_sync_interval)
	{
	  if (diskfs_sync_interval == 0)
	    err = argz_add (argz, argz_len, "--no-sync");
	  else
	    {
	      char buf[80];
	      sprintf (buf, "--sync=%d", diskfs_sync_interval);
	      err = argz_add (argz, argz_len, buf);
	    }
	}
    }

  return err;
}
Exemple #8
0
/* Override the standard diskfs routine so we can add our own output.  */
error_t
diskfs_append_args (char **argz, size_t *argz_len)
{
  error_t err;

  /* Get the standard things.  */
  err = diskfs_append_std_options (argz, argz_len);

#ifdef EXT2FS_DEBUG
  if (!err && ext2_debug_flag)
    err = argz_add (argz, argz_len, "--debug");
#endif
  if (! err)
    err = store_parsed_append_args (store_parsed, argz, argz_len);

  return err;
}
Exemple #9
0
/* This will be called from libtrivfs to help construct the answer
   to an fsys_get_options RPC.  */
error_t
trivfs_append_args (struct trivfs_control *fsys,
		    char **argz, size_t *argz_len)
{
  error_t err = 0;
  char *opt;

  if (MACH_PORT_VALID (opt_device_master))
    {
      asprintf (&opt, "--device-master-port=%d", opt_device_master);

      if (opt)
	{
	  err = argz_add (argz, argz_len, opt);
	  free (opt);
	}
    }

  return err;
}
Exemple #10
0
static void insmod_request_cb (flux_t *h, flux_msg_handler_t *mh,
                               const flux_msg_t *msg, void *arg)
{
    const char *path;
    json_t *args;
    size_t index;
    json_t *value;
    char *argz = NULL;
    size_t argz_len = 0;
    module_t *m = NULL;
    error_t e;

    if (flux_request_unpack (msg, NULL, "{s:s s:o}", "path", &path,
                                                     "args", &args) < 0)
        goto error;
    if (!json_is_array (args))
        goto proto;
    json_array_foreach (args, index, value) {
        if (!json_is_string (value))
            goto proto;
        if ((e = argz_add (&argz, &argz_len, json_string_value (value)))) {
            errno = e;
            goto error;
        }
    }
    if (!(m = module_create (path, argz, argz_len)))
        goto error;
    flux_log (h, LOG_DEBUG, "insmod %s", m->name);
    if (flux_respond (h, msg, NULL) < 0)
        flux_log_error (h, "%s: flux_respond", __FUNCTION__);
    free (argz);
    return;
proto:
    errno = EPROTO;
error:
    if (flux_respond_error (h, msg, errno, NULL) < 0)
        flux_log_error (h, "%s: flux_respond_error", __FUNCTION__);
    free (argz);
}
Exemple #11
0
int main(int argc, char **argv) {
    int opt;
    struct augeas *aug;
    char *loadpath = NULL;
    size_t loadpathlen = 0;
    enum {
        VAL_NO_STDINC = CHAR_MAX + 1,
        VAL_NO_TYPECHECK = VAL_NO_STDINC + 1,
        VAL_VERSION = VAL_NO_TYPECHECK + 1
    };
    struct option options[] = {
        { "help",      0, 0, 'h' },
        { "include",   1, 0, 'I' },
        { "trace",     0, 0, 't' },
        { "nostdinc",  0, 0, VAL_NO_STDINC },
        { "notypecheck",  0, 0, VAL_NO_TYPECHECK },
        { "version",  0, 0, VAL_VERSION },
        { 0, 0, 0, 0}
    };
    int idx;
    unsigned int flags = AUG_TYPE_CHECK|AUG_NO_MODL_AUTOLOAD;
    progname = argv[0];

    setlocale(LC_ALL, "");
    while ((opt = getopt_long(argc, argv, "hI:t", options, &idx)) != -1) {
        switch(opt) {
        case 'I':
            argz_add(&loadpath, &loadpathlen, optarg);
            break;
        case 't':
            flags |= AUG_TRACE_MODULE_LOADING;
            break;
        case 'h':
            usage();
            break;
        case VAL_NO_STDINC:
            flags |= AUG_NO_STDINC;
            break;
        case VAL_NO_TYPECHECK:
            flags &= ~(AUG_TYPE_CHECK);
            break;
        case VAL_VERSION:
            print_version = true;
            break;
        default:
            usage();
            break;
        }
    }

    if (!print_version && optind >= argc) {
        fprintf(stderr, "Expected .aug file\n");
        usage();
    }

    argz_stringify(loadpath, loadpathlen, PATH_SEP_CHAR);
    aug = aug_init(NULL, loadpath, flags);
    if (aug == NULL) {
        fprintf(stderr, "Memory exhausted\n");
        return 2;
    }

    if (print_version) {
        print_version_info(aug);
        return EXIT_SUCCESS;
    }

    if (__aug_load_module_file(aug, argv[optind]) == -1) {
        fprintf(stderr, "%s\n", aug_error_message(aug));
        const char *s = aug_error_details(aug);
        if (s != NULL) {
            fprintf(stderr, "%s\n", s);
        }
        exit(EXIT_FAILURE);
    }

    aug_close(aug);
    free(loadpath);
}
Exemple #12
0
/* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
   ARGZ as necessary.  If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
   incremented by number of replacements performed.  */
error_t
argz_replace (char **argz, size_t *argz_len, const char *str, const char *with,
                unsigned *replace_count)
{
  error_t err = 0;

  if (str && *str)
    {
      char *arg = 0;
      char *src = *argz;
      size_t src_len = *argz_len;
      char *dst = 0;
      size_t dst_len = 0;
      int delayed_copy = 1;     /* True while we've avoided copying anything.  */
      size_t str_len = strlen (str), with_len = strlen (with);

      while (!err && (arg = argz_next (src, src_len, arg)))
        {
          char *match = strstr (arg, str);
          if (match)
            {
              char *from = match + str_len;
              size_t to_len = match - arg;
              char *to = strndup (arg, to_len);

              while (to && from)
                {
                  str_append (&to, &to_len, with, with_len);
                  if (to)
                    {
                      match = strstr (from, str);
                      if (match)
                        {
                          str_append (&to, &to_len, from, match - from);
                          from = match + str_len;
                        }
                      else
                        {
                          str_append (&to, &to_len, from, strlen (from));
                          from = 0;
                        }
                    }
                }

              if (to)
                {
                  if (delayed_copy)
                    /* We avoided copying SRC to DST until we found a match;
                       now that we've done so, copy everything from the start
                       of SRC.  */
                    {
                      if (arg > src)
                        err = argz_append (&dst, &dst_len, src, (arg - src));
                      delayed_copy = 0;
                    }
                  if (! err)
                    err = argz_add (&dst, &dst_len, to);
                  free (to);
                }
              else
                err = ENOMEM;

              if (replace_count)
                (*replace_count)++;
            }
          else if (! delayed_copy)
            err = argz_add (&dst, &dst_len, arg);
        }

      if (! err)
        {
          if (! delayed_copy)
            /* We never found any instances of str.  */
            {
              free (src);
              *argz = dst;
              *argz_len = dst_len;
            }
        }
      else if (dst_len > 0)
        free (dst);
    }

  return err;
}
Exemple #13
0
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
  struct fstab_argp_params *params = state->input;
  error_t err;
  switch (key)
    {
    case ARGP_KEY_INIT:
      state->child_inputs[0] = params; /* pass down to fstab_argp parser */
      break;

    case 'd':
      source_goaway = 1;
      break;

    case FAKE_KEY:
      fake = 1;
      break;

    case 'f':
      goaway_flags |= FSYS_GOAWAY_FORCE;
      break;

    case 'n':
      /* do nothing */
      break;

    case 'r':
      readonly = 1;
      break;

    case 'S':
      goaway_flags |= FSYS_GOAWAY_NOSYNC;
      break;

    case 'O':
      err = argz_create_sep (arg, ',', &test_opts, &test_opts_len);
      if (err)
	argp_failure (state, 100, ENOMEM, "%s", arg);
      break;

    case 'v':
      verbose += 1;
      break;

    case ARGP_KEY_ARG:
      err = argz_add (&targets, &targets_len, arg);
      if (err)
	argp_failure (state, 100, ENOMEM, "%s", arg);
      break;

    case ARGP_KEY_NO_ARGS:
      if (! params->do_all)
	{
	  argp_error (state,
		      "filesystem argument required if --all is not given");
	  return EINVAL;
	}
      break;

    case ARGP_KEY_END:
      if (params->do_all && targets)
	{
	  argp_error (state, "filesystem argument not allowed with --all");
	  return EINVAL;
	}
      break;

    default:
      return ARGP_ERR_UNKNOWN;
    }

  return 0;
}
Exemple #14
0
static void parse_opts(int argc, char **argv) {
    int opt;
    size_t loadpathlen = 0;
    enum {
        VAL_VERSION = CHAR_MAX + 1,
        VAL_SPAN = VAL_VERSION + 1
    };
    struct option options[] = {
        { "help",        0, 0, 'h' },
        { "typecheck",   0, 0, 'c' },
        { "backup",      0, 0, 'b' },
        { "new",         0, 0, 'n' },
        { "root",        1, 0, 'r' },
        { "include",     1, 0, 'I' },
        { "transform",   1, 0, 't' },
        { "echo",        0, 0, 'e' },
        { "file",        1, 0, 'f' },
        { "autosave",    0, 0, 's' },
        { "interactive", 0, 0, 'i' },
        { "nostdinc",    0, 0, 'S' },
        { "noload",      0, 0, 'L' },
        { "noautoload",  0, 0, 'A' },
        { "span",        0, 0, VAL_SPAN },
        { "version",     0, 0, VAL_VERSION },
        { 0, 0, 0, 0}
    };
    int idx;

    while ((opt = getopt_long(argc, argv, "hnbcr:I:t:ef:siSLA", options, &idx)) != -1) {
        switch(opt) {
        case 'c':
            flags |= AUG_TYPE_CHECK;
            break;
        case 'b':
            flags |= AUG_SAVE_BACKUP;
            break;
        case 'n':
            flags |= AUG_SAVE_NEWFILE;
            break;
        case 'h':
            usage();
            break;
        case 'r':
            root = optarg;
            break;
        case 'I':
            argz_add(&loadpath, &loadpathlen, optarg);
            break;
        case 't':
            argz_add(&transforms, &transformslen, optarg);
            break;
        case 'e':
            echo_commands = 1;
            break;
        case 'f':
            inputfile = optarg;
            break;
        case 's':
            auto_save = true;
            break;
        case 'i':
            interactive = true;
            break;
        case 'S':
            flags |= AUG_NO_STDINC;
            break;
        case 'L':
            flags |= AUG_NO_LOAD;
            break;
        case 'A':
            flags |= AUG_NO_MODL_AUTOLOAD;
            break;
        case VAL_VERSION:
            flags |= AUG_NO_MODL_AUTOLOAD;
            print_version = true;
            break;
        case VAL_SPAN:
            flags |= AUG_ENABLE_SPAN;
            break;
        default:
            usage();
            break;
        }
    }
    argz_stringify(loadpath, loadpathlen, PATH_SEP_CHAR);
}
Exemple #15
0
void module_add_arg (module_t *p, const char *arg)
{
    assert (p->magic == MODULE_MAGIC);
    if (argz_add (&p->argz, &p->argz_len, arg) < 0)
        oom ();
}
Exemple #16
0
/* Mount one filesystem.  */
static error_t
do_mount (struct fs *fs, int remount)
{
    error_t err;
    char *fsopts, *o;
    size_t fsopts_len;
    char *mntopts;
    size_t mntopts_len;
    fsys_t mounted;

    inline void explain (const char *command)
    {
        if (verbose)
        {
            const char *o;
            printf ("%s %s", command, fs->mntent.mnt_dir);
            for (o = fsopts; o; o = argz_next (fsopts, fsopts_len, o))
                printf (" %s", o);
            putchar ('\n');
        }
    }

    err = fs_fsys (fs, &mounted);
    if (err)
    {
        error (0, err, "cannot determine if %s is already mounted",
               fs->mntent.mnt_fsname);
        return err;
    }


    /* Produce an argz of translator option arguments from the
       given FS's options and the command-line options.  */

#define ARGZ(call)							      \
  err = argz_##call;							      \
  if (err)								      \
    error (3, ENOMEM, "collecting mount options");			      \

    if (fs->mntent.mnt_opts)
    {
        /* Append the fstab options to any specified on the command line.  */
        ARGZ (create_sep (fs->mntent.mnt_opts, ',', &mntopts, &mntopts_len));

        /* Remove the `noauto' and `bind' options, since they're for us not the
           filesystem.  */
        for (o = mntopts; o; o = argz_next (mntopts, mntopts_len, o))
        {
            if (strcmp (o, MNTOPT_NOAUTO) == 0)
                argz_delete (&mntopts, &mntopts_len, o);
            if (strcmp (o, "bind") == 0)
            {
                fs->mntent.mnt_type = strdup ("firmlink");
                if (!fs->mntent.mnt_type)
                    error (3, ENOMEM, "failed to allocate memory");
                argz_delete (&mntopts, &mntopts_len, o);
            }
        }

        ARGZ (append (&mntopts, &mntopts_len, options, options_len));
    }
    else
    {
        mntopts = options;
        mntopts_len = options_len;
    }

    /* Convert the list of options into a list of switch arguments.  */
    fsopts = 0;
    fsopts_len = 0;
    for (o = mntopts; o; o = argz_next (mntopts, mntopts_len, o))
        if (*o == '-')		/* Allow letter opts `-o -r,-E', BSD style.  */
        {
            ARGZ (add (&fsopts, &fsopts_len, o));
        }
        else if ((strcmp (o, "defaults") != 0) && (strlen (o) != 0))
        {
            /* Prepend `--' to the option to make a long option switch,
               e.g. `--ro' or `--rsize=1024'.  */
            char arg[2 + strlen (o) + 1];
            arg[0] = arg[1] = '-';
            memcpy (&arg[2], o, sizeof arg - 2);
            ARGZ (add (&fsopts, &fsopts_len, arg));
        }

    if (mntopts != options)
        free (mntopts);
#undef ARGZ

    if (remount)
    {
        if (mounted == MACH_PORT_NULL)
        {
            error (0, 0, "%s not already mounted", fs->mntent.mnt_fsname);
            return EBUSY;
        }

        /* Send an RPC to request the new options, including --update.  */
        explain ("fsysopts");
        err = fsys_set_options (mounted, fsopts, fsopts_len, 0);
        if (err)
            error (0, err, "cannot remount %s", fs->mntent.mnt_fsname);
        return err;
    }
    else
    {
        /* Error during file lookup; we use this to avoid duplicating error
        messages.  */
        error_t open_err = 0;
        /* The control port for any active translator we start up.  */
        fsys_t active_control;
        file_t node;		/* Port to the underlying node.  */
        struct fstype *type;

        /* The callback to start_translator opens NODE as a side effect.  */
        error_t open_node (int flags,
                           mach_port_t *underlying,
                           mach_msg_type_name_t *underlying_type,
                           task_t task, void *cookie)
        {
            node = file_name_lookup (fs->mntent.mnt_dir,
                                     flags | O_NOTRANS, 0666);
            if (node == MACH_PORT_NULL)
            {
                open_err = errno;
                return open_err;
            }

            *underlying = node;
            *underlying_type = MACH_MSG_TYPE_COPY_SEND;

            return 0;
        }

        /* Do not fail if there is an active translator if --fake is
           given. This mimics Linux mount utility more closely which
           just looks into the mtab file. */
        if (mounted != MACH_PORT_NULL && !fake)
        {
            error (0, 0, "%s already mounted", fs->mntent.mnt_fsname);
            return EBUSY;
        }

        if (strcmp (fs->mntent.mnt_type, "auto") == 0)
        {
#if HAVE_BLKID
            char *type =
                blkid_get_tag_value (NULL, "TYPE", fs->mntent.mnt_fsname);
            if (! type)
            {
                error (0, 0, "failed to detect file system type");
                return EFTYPE;
            }
            else
            {
                if (strcmp (type, "vfat") == 0)
                    fs->mntent.mnt_type = strdup ("fat");
                else
                    fs->mntent.mnt_type = strdup (type);
                if (! fs->mntent.mnt_type)
                    error (3, ENOMEM, "failed to allocate memory");
            }
#else
            fs->mntent.mnt_type = strdup ("ext2");
            if (! fs->mntent.mnt_type)
                error (3, ENOMEM, "failed to allocate memory");
#endif
        }

        err = fs_type (fs, &type);
        if (err)
        {
            error (0, err, "%s: cannot determine filesystem type",
                   fs->mntent.mnt_fsname);
            return err;
        }
        if (type->program == 0)
        {
            error (0, 0, "%s: filesystem type `%s' unknown",
                   fs->mntent.mnt_fsname, type->name);
            return EFTYPE;
        }

        /* Stick the translator program name in front of the option switches.  */
        err = argz_insert (&fsopts, &fsopts_len, fsopts, type->program);
        /* Now stick the device name on the end as the last argument.  */
        if (!err)
            err = argz_add (&fsopts, &fsopts_len, fs->mntent.mnt_fsname);
        if (err)
            error (3, ENOMEM, "collecting mount options");

        /* Now we have a translator command line argz in FSOPTS.  */

        if (fake) {
            /* Fake the translator startup. */
            mach_port_t underlying;
            mach_msg_type_name_t underlying_type;
            err = open_node (O_READ, &underlying, &underlying_type, 0, NULL);
            if (err)
                error (1, errno, "cannot mount on %s", fs->mntent.mnt_dir);

            mach_port_deallocate (mach_task_self (), underlying);

            /* See if the translator is at least executable. */
            if (access(type->program, X_OK) == -1)
                error (1, errno, "can not execute %s", type->program);

            return 0;
        }

        explain ("settrans -a");
        err = fshelp_start_translator (open_node, NULL, fsopts,
                                       fsopts, fsopts_len, timeout,
                                       &active_control);
        /* If ERR is due to a problem opening the translated node, we print
        that name, otherwise, the name of the translator.  */
        if (open_err)
            error (0, open_err, "cannot mount on %s", fs->mntent.mnt_dir);
        else if (err)
            error (0, err, "cannot start translator %s", fsopts);
        else
        {
            err = file_set_translator (node, 0, FS_TRANS_SET|FS_TRANS_EXCL, 0,
                                       0, 0,
                                       active_control, MACH_MSG_TYPE_COPY_SEND);
            if (err == EBUSY)
                error (0, 0, "%s already mounted on", fs->mntent.mnt_dir);
            else if (err)
                error (0, err, "cannot set translator on %s", fs->mntent.mnt_dir);
            if (err)
                fsys_goaway (active_control, FSYS_GOAWAY_FORCE);
            mach_port_deallocate (mach_task_self (), active_control);
        }

        return err;
    }