Exemplo n.º 1
0
/*
 * Macro-expand an option.  Note that this does not
 * handle recursive expansions.  They will go badly wrong.
 * If sel is true then old expand selectors, otherwise
 * don't expand selectors.
 */
static char *
expand_op(char *opt, int sel_p)
{
  static const char expand_error[] = "No space to expand \"%s\"";
  char expbuf[MAXPATHLEN + 1];
  char nbuf[NLEN + 1];
  char *ep = expbuf;
  char *cp = opt;
  char *dp;
  struct opt *op;
  char *cp_orig = opt;

  while ((dp = strchr(cp, '$'))) {
    char ch;
    /*
     * First copy up to the $
     */
    {
      int len = dp - cp;

      if (BUFSPACE(ep, len)) {
	strncpy(ep, cp, len);
	ep += len;
      } else {
	plog(XLOG_ERROR, expand_error, opt);
	goto out;
      }
    }

    cp = dp + 1;
    ch = *cp++;
    if (ch == '$') {
      if (BUFSPACE(ep, 1)) {
	*ep++ = '$';
      } else {
	plog(XLOG_ERROR, expand_error, opt);
	goto out;
      }
    } else if (ch == '{') {
      /* Expansion... */
      enum {
	E_All, E_Dir, E_File, E_Domain, E_Host
      } todo;
      /*
       * Find closing brace
       */
      char *br_p = strchr(cp, '}');
      int len;

      /*
       * Check we found it
       */
      if (!br_p) {
	/*
	 * Just give up
	 */
	plog(XLOG_USER, "No closing '}' in \"%s\"", opt);
	goto out;
      }
      len = br_p - cp;

      /*
       * Figure out which part of the variable to grab.
       */
      if (*cp == '/') {
	/*
	 * Just take the last component
	 */
	todo = E_File;
	cp++;
	--len;
      } else if (br_p[-1] == '/') {
	/*
	 * Take all but the last component
	 */
	todo = E_Dir;
	--len;
      } else if (*cp == '.') {
	/*
	 * Take domain name
	 */
	todo = E_Domain;
	cp++;
	--len;
      } else if (br_p[-1] == '.') {
	/*
	 * Take host name
	 */
	todo = E_Host;
	--len;
      } else {
	/*
	 * Take the whole lot
	 */
	todo = E_All;
      }

      /*
       * Truncate if too long.  Since it won't
       * match anyway it doesn't matter that
       * it has been cut short.
       */
      if (len > NLEN)
	len = NLEN;

      /*
       * Put the string into another buffer so
       * we can do comparisons.
       */
      strncpy(nbuf, cp, len);
      nbuf[len] = '\0';

      /*
       * Advance cp
       */
      cp = br_p + 1;

      /*
       * Search the option array
       */
      for (op = opt_fields; op->name; op++) {
	/*
	 * Check for match
	 */
	if (len == op->nlen && STREQ(op->name, nbuf)) {
	  char xbuf[NLEN + 3];
	  char *val;
	  /*
	   * Found expansion.  Copy
	   * the correct value field.
	   */
	  if (!(!op->sel_p == !sel_p)) {
	    /*
	     * Copy the string across unexpanded
	     */
	    sprintf(xbuf, "${%s%s%s}",
		    todo == E_File ? "/" :
		    todo == E_Domain ? "." : "",
		    nbuf,
		    todo == E_Dir ? "/" :
		    todo == E_Host ? "." : "");
	    val = xbuf;
	    /*
	     * Make sure expansion doesn't
	     * munge the value!
	     */
	    todo = E_All;
	  } else if (op->sel_p) {
	    val = *op->sel_p;
	  } else {
	    val = *op->optp;
	  }

	  if (val) {
	    /*
	     * Do expansion:
	     * ${/var} means take just the last part
	     * ${var/} means take all but the last part
	     * ${.var} means take all but first part
	     * ${var.} means take just the first part
	     * ${var} means take the whole lot
	     */
	    int vlen = strlen(val);
	    char *vptr = val;
	    switch (todo) {
	    case E_Dir:
	      vptr = strrchr(val, '/');
	      if (vptr)
		vlen = vptr - val;
	      vptr = val;
	      break;
	    case E_File:
	      vptr = strrchr(val, '/');
	      if (vptr) {
		vptr++;
		vlen = strlen(vptr);
	      } else
		vptr = val;
	      break;
	    case E_Domain:
	      vptr = strchr(val, '.');
	      if (vptr) {
		vptr++;
		vlen = strlen(vptr);
	      } else {
		vptr = "";
		vlen = 0;
	      }
	      break;
	    case E_Host:
	      vptr = strchr(val, '.');
	      if (vptr)
		vlen = vptr - val;
	      vptr = val;
	      break;
	    case E_All:
	      break;
	    }

	    if (BUFSPACE(ep, vlen)) {
	      strcpy(ep, vptr);
	      ep += vlen;
	    } else {
	      plog(XLOG_ERROR, expand_error, opt);
	      goto out;
	    }
	  }
	  /*
	   * Done with this variable
	   */
	  break;
	}
      }

      /*
       * Check that the search was successful
       */
      if (!op->name) {
	/*
	 * If it wasn't then scan the
	 * environment for that name
	 * and use any value found
	 */
	char *env = getenv(nbuf);

	if (env) {
	  int vlen = strlen(env);

	  if (BUFSPACE(ep, vlen)) {
	    strcpy(ep, env);
	    ep += vlen;
	  } else {
	    plog(XLOG_ERROR, expand_error, opt);
	    goto out;
	  }
	  amuDebug(D_STR)
	    plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env);
	} else {
	  plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf);
	}
      }
    } else {
      /*
       * Error, error
       */
      plog(XLOG_USER, "Unknown $ sequence in \"%s\"", opt);
    }
  }

out:
  /*
   * Handle common case - no expansion
   */
  if (cp == opt) {
    opt = strdup(cp);
  } else {
    /*
     * Finish off the expansion
     */
    if (BUFSPACE(ep, strlen(cp))) {
      strcpy(ep, cp);
      /* ep += strlen(ep); */
    } else {
      plog(XLOG_ERROR, expand_error, opt);
    }

    /*
     * Save the expansion
     */
    opt = strdup(expbuf);
  }

  normalize_slash(opt);

  amuDebug(D_STR) {
    plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig);
    plog(XLOG_DEBUG, "......... is \"%s\"", opt);
  }
  return opt;
}
Exemplo n.º 2
0
am_ops *
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
{
  am_ops *rop = NULL;
  char *link_dir;

  /*
   * First crack the global opts and the local opts
   */
  if (!eval_fs_opts(fo, key, g_key, path, keym, map)) {
    rop = &amfs_error_ops;
  } else if (fo->opt_type == 0) {
    plog(XLOG_USER, "No fs type specified (key = \"%s\", map = \"%s\")", keym, map);
    rop = &amfs_error_ops;
  } else {
    /*
     * Next find the correct filesystem type
     */
    rop = ops_search(fo->opt_type);
    if (!rop) {
      plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type);
      rop = &amfs_error_ops;
    }
  }

  /*
   * Make sure we have a default mount option.
   * Otherwise skip past any leading '-'.
   */
  if (fo->opt_opts == 0)
    fo->opt_opts = strdup("rw,defaults");
  else if (*fo->opt_opts == '-') {
    /*
     * We cannot simply do fo->opt_opts++ here since the opts
     * module will try to free the pointer fo->opt_opts later.
     * So just reallocate the thing -- stolcke 11/11/94
     */
    char *old = fo->opt_opts;
    fo->opt_opts = strdup(old + 1);
    XFREE(old);
  }

  /*
   * If addopts option was used, then append it to the
   * current options and remote mount options.
   */
  if (fo->opt_addopts) {
    if (STREQ(fo->opt_opts, fo->opt_remopts)) {
      /* optimize things for the common case where opts==remopts */
      char *mergedstr;
      mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
      plog(XLOG_INFO, "merge rem/opts \"%s\" add \"%s\" => \"%s\"",
	   fo->opt_opts, fo->opt_addopts, mergedstr);
      XFREE(fo->opt_opts);
      XFREE(fo->opt_remopts);
      fo->opt_opts = mergedstr;
      fo->opt_remopts = strdup(mergedstr);
    } else {
      char *mergedstr, *remmergedstr;
      mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
      plog(XLOG_INFO, "merge opts \"%s\" add \"%s\" => \"%s\"",
	   fo->opt_opts, fo->opt_addopts, mergedstr);
      XFREE(fo->opt_opts);
      fo->opt_opts = mergedstr;
      remmergedstr = merge_opts(fo->opt_remopts, fo->opt_addopts);
      plog(XLOG_INFO, "merge remopts \"%s\" add \"%s\" => \"%s\"",
	   fo->opt_remopts, fo->opt_addopts, remmergedstr);
      XFREE(fo->opt_remopts);
      fo->opt_remopts = remmergedstr;
    }
  }

  /*
   * Initialize opt_mount_type to "nfs", if it's not initialized already
   */
  if (!fo->opt_mount_type)
    fo->opt_mount_type = "nfs";

  /* Normalize the sublink and make it absolute */
  link_dir = fo->opt_sublink;
  if (link_dir && link_dir[0] && link_dir[0] != '/') {
    link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir);
    normalize_slash(link_dir);
    XFREE(fo->opt_sublink);
    fo->opt_sublink = link_dir;
  }

  /*
   * Check the filesystem is happy
   */
  if (fo->fs_mtab)
    XFREE(fo->fs_mtab);

  fo->fs_mtab = rop->fs_match(fo);
  if (fo->fs_mtab)
    return rop;

  /*
   * Return error file system
   */
  fo->fs_mtab = amfs_error_ops.fs_match(fo);
  return &amfs_error_ops;
}
Exemplo n.º 3
0
static int
amfs_nfsx_init(mntfs *mf)
{
  /*
   * mf_info has the form:
   *   host:/prefix/path,sub,sub,sub
   */
  int i;
  int glob_error;
  struct amfs_nfsx *nx;
  int asked_for_wakeup = 0;

  nx = (struct amfs_nfsx *) mf->mf_private;

  if (nx == 0) {
    char **ivec;
    char *info = 0;
    char *host;
    char *pref;
    int error = 0;

    info = strdup(mf->mf_info);
    host = strchr(info, ':');
    if (!host) {
      error = EINVAL;
      goto errexit;
    }
    pref = host + 1;
    host = info;

    /*
     * Split the prefix off from the suffices
     */
    ivec = strsplit(pref, ',', '\'');

    /*
     * Count array size
     */
    for (i = 0; ivec[i]; i++)
      /* nothing */;

    nx = ALLOC(struct amfs_nfsx);
    mf->mf_private = (opaque_t) nx;
    mf->mf_prfree = amfs_nfsx_prfree;

    nx->nx_c = i - 1;		/* i-1 because we don't want the prefix */
    nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt));
    nx->nx_mp = 0;
    {
      char *mp = 0;
      char *xinfo = 0;
      char *fs = mf->mf_fo->opt_fs;
      char *rfs = 0;
      for (i = 0; i < nx->nx_c; i++) {
	char *path = ivec[i + 1];
	rfs = str3cat(rfs, pref, "/", path);
	/*
	 * Determine the mount point.
	 * If this is the root, then don't remove
	 * the trailing slash to avoid mntfs name clashes.
	 */
	mp = str3cat(mp, fs, "/", rfs);
	normalize_slash(mp);
	deslashify(mp);
	/*
	 * Determine the mount info
	 */
	xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path);
	normalize_slash(xinfo);
	if (pref[1] != '\0')
	  deslashify(xinfo);
	dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp);
	nx->nx_v[i].n_error = -1;
	nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
	/* propagate the on_autofs flag */
	nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS;
      }
      if (rfs)
	XFREE(rfs);
      if (mp)
	XFREE(mp);
      if (xinfo)
	XFREE(xinfo);
    }

    XFREE(ivec);
  errexit:
    if (info)
      XFREE(info);
    if (error)
      return error;
  }
Exemplo n.º 4
0
static int
nfsx_init(mntfs *mf)
{
	/*
	 * mf_info has the form:
	 *   host:/prefix/path,sub,sub,sub
	 */
	int i;
	int glob_error;
	struct nfsx *nx;
	int asked_for_wakeup = 0;

	nx = (struct nfsx *) mf->mf_private;

	if (nx == 0) {
		char **ivec;
		char *info = 0;
		char *host;
		char *pref;
		int error = 0;

		info = strdup(mf->mf_info);
		host = strchr(info, ':');
		if (!host) {
			error = EINVAL;
			goto errexit;
		}

		pref = host+1;
		host = info;

		/*
		 * Split the prefix off from the suffices
		 */
		ivec = strsplit(pref, ',', '\'');

		/*
		 * Count array size
		 */
		for (i = 0; ivec[i]; i++)
			;

		nx = ALLOC(nfsx);
		mf->mf_private = nx;
		mf->mf_prfree = nfsx_prfree;

		nx->nx_c = i - 1;	/* i-1 because we don't want the prefix */
		nx->nx_v = xreallocarray(NULL, nx->nx_c, sizeof *nx->nx_v);
		{ char *mp = 0;
		  char *xinfo = 0;
		  char *fs = mf->mf_fo->opt_fs;
		  char *rfs = 0;
		  for (i = 0; i < nx->nx_c; i++) {
			char *path = ivec[i+1];
			rfs = str3cat(rfs, pref, "/", path);
			/*
			 * Determine the mount point.
			 * If this is the root, then don't remove
			 * the trailing slash to avoid mntfs name clashes.
			 */
			mp = str3cat(mp, fs, "/", rfs);
			normalize_slash(mp);
			deslashify(mp);
			/*
			 * Determine the mount info
			 */
			xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path);
			normalize_slash(xinfo);
			if (pref[1] != '\0')
				deslashify(xinfo);
#ifdef DEBUG
			dlog("nfsx: init mount for %s on %s", xinfo, mp);
#endif
			nx->nx_v[i].n_error = -1;
			nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
		  }
		  free(rfs);
		  free(mp);
		  free(xinfo);
		}

		free(ivec);
errexit:
		free(info);
		if (error)
			return error;
	}

	/*
	 * Iterate through the mntfs's and call
	 * the underlying init routine on each
	 */
	glob_error = 0;
	for (i = 0; i < nx->nx_c; i++) {
		nfsx_mnt *n = &nx->nx_v[i];
		mntfs *m = n->n_mnt;
		int error = (*m->mf_ops->fs_init)(m);
		/*
		 * If HARD_NFSX_ERRORS is defined, make any
		 * initialisation failure a hard error and
		 * fail the entire group.  Otherwise only fail
		 * if none of the group is mountable (see nfsx_fmount).
		 */
#ifdef HARD_NFSX_ERRORS
		if (error > 0)
			return error;
#else
		if (error > 0)
			n->n_error = error;
#endif
		else if (error < 0) {
			glob_error = -1;
			if (!asked_for_wakeup) {
				asked_for_wakeup = 1;
				sched_task(wakeup_task, mf, m);
			}
		}
	}

	return glob_error;
}