Пример #1
0
/****************************************************************************
 *** FUNCTIONS                                                             ***
 ****************************************************************************/
static am_node *
amfs_lookup_node(am_node *mp, char *fname, int *error_return)
{
  am_node *new_mp;
  int error = 0;		/* Error so far */
  int in_progress = 0;		/* # of (un)mount in progress */
  mntfs *mf;
  char *expanded_fname = NULL;

  dlog("in amfs_lookup_node");

  /*
   * If the server is shutting down
   * then don't return information
   * about the mount point.
   */
  if (amd_state == Finishing) {
    if (mp->am_al == NULL || mp->am_al->al_mnt == NULL || mp->am_al->al_mnt->mf_fsflags & FS_DIRECT) {
      dlog("%s mount ignored - going down", fname);
    } else {
      dlog("%s/%s mount ignored - going down", mp->am_path, fname);
    }
    ereturn(ENOENT);
  }

  /*
   * Handle special case of "." and ".."
   */
  if (fname[0] == '.') {
    if (fname[1] == '\0')
      return mp;		/* "." is the current node */
    if (fname[1] == '.' && fname[2] == '\0') {
      if (mp->am_parent) {
	dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);
	return mp->am_parent;	/* ".." is the parent node */
      }
      ereturn(ESTALE);
    }
  }

  /*
   * Check for valid key name.
   * If it is invalid then pretend it doesn't exist.
   */
  if (!valid_key(fname)) {
    plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname);
    ereturn(ENOENT);
  }

  /*
   * Expand key name.
   * expanded_fname is now a private copy.
   */
  expanded_fname = expand_selectors(fname);

  /*
   * Search children of this node
   */
  for (new_mp = mp->am_child; new_mp; new_mp = new_mp->am_osib) {
    if (FSTREQ(new_mp->am_name, expanded_fname)) {
      if (new_mp->am_error) {
	error = new_mp->am_error;
	continue;
      }

      /*
       * If the error code is undefined then it must be
       * in progress.
       */
      mf = new_mp->am_al->al_mnt;
      if (mf->mf_error < 0)
	goto in_progrss;

      /*
       * If there was a previous error with this node
       * then return that error code.
       */
      if (mf->mf_flags & MFF_ERROR) {
	error = mf->mf_error;
	continue;
      }
      if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) {
      in_progrss:
	/*
	 * If the fs is not mounted or it is unmounting then there
	 * is a background (un)mount in progress.  In this case
	 * we just drop the RPC request (return nil) and
	 * wait for a retry, by which time the (un)mount may
	 * have completed.
	 */
	dlog("ignoring mount of %s in %s -- %smounting in progress, flags %x",
	     expanded_fname, mf->mf_mount,
	     (mf->mf_flags & MFF_UNMOUNTING) ? "un" : "", mf->mf_flags);
	in_progress++;
	if (mf->mf_flags & MFF_UNMOUNTING) {
	  dlog("will remount later");
	  new_mp->am_flags |= AMF_REMOUNT;
	}
	continue;
      }

      /*
       * Otherwise we have a hit: return the current mount point.
       */
      dlog("matched %s in %s", expanded_fname, new_mp->am_path);
      XFREE(expanded_fname);
      return new_mp;
    }
  }

  if (in_progress) {
    dlog("Waiting while %d mount(s) in progress", in_progress);
    XFREE(expanded_fname);
    ereturn(-1);
  }

  /*
   * If an error occurred then return it.
   */
  if (error) {
    dlog("Returning error: %s", strerror(error));
    XFREE(expanded_fname);
    ereturn(error);
  }

  /*
   * If the server is going down then just return,
   * don't try to mount any more file systems
   */
  if ((int) amd_state >= (int) Finishing) {
    dlog("not found - server going down anyway");
    ereturn(ENOENT);
  }

  /*
   * Allocate a new map
   */
  new_mp = get_ap_child(mp, expanded_fname);
  XFREE(expanded_fname);
  if (new_mp == NULL)
    ereturn(ENOSPC);

  *error_return = -1;
  return new_mp;
}
Пример #2
0
int
eval_fs_opts(am_opts *fo, char *opts, char *g_opts, char *path, char *key, char *map)
{
  int ok = TRUE;

  free_opts(fo);

  /*
   * Clear out the option table
   */
  memset((voidp) &fs_static, 0, sizeof(fs_static));
  memset((voidp) vars, 0, sizeof(vars));
  memset((voidp) fo, 0, sizeof(*fo));

  /* set hostname */
  opt_host = (char *) am_get_hostname();

  /*
   * Set key, map & path before expansion
   */
  opt_key = key;
  opt_map = map;
  opt_path = path;

  opt_dkey = strchr(key, '.');
  if (!opt_dkey) {
    opt_dkey = NullStr;
    opt_keyd = key;
  } else {
    opt_keyd = strnsave(key, opt_dkey - key);
    opt_dkey++;
    if (*opt_dkey == '\0')	/* check for 'host.' */
      opt_dkey = NullStr;
  }

  /*
   * Expand global options
   */
  fs_static.fs_glob = expand_selectors(g_opts);

  /*
   * Expand local options
   */
  fs_static.fs_local = expand_selectors(opts);

  /* break global options into fs_static fields */
  if ((ok = split_opts(fs_static.fs_glob, key))) {
    dlog("global split_opts ok");
    /*
     * evaluate local selectors
     */
    if ((ok = eval_selectors(fs_static.fs_local, key))) {
      dlog("local eval_selectors ok");
      /* if the local selectors matched, then do the local overrides */
      ok = split_opts(fs_static.fs_local, key);
      if (ok)
	dlog("local split_opts ok");
    }
  }

  /*
   * Normalize remote host name.
   * 1.  Expand variables
   * 2.  Normalize relative to host tables
   * 3.  Strip local domains from the remote host
   *     name before using it in other expansions.
   *     This makes mount point names and other things
   *     much shorter, while allowing cross domain
   *     sharing of mount maps.
   */
  apply_opts(expand_opts, rhost_expansion, FALSE);
  if (ok && fs_static.opt_rhost && *fs_static.opt_rhost)
    host_normalize(&fs_static.opt_rhost);

  /*
   * Macro expand the options.
   * Do this regardless of whether we are accepting
   * this mount - otherwise nasty things happen
   * with memory allocation.
   */
  apply_opts(expand_opts, expansions, FALSE);

  /*
   * Strip trailing slashes from local pathname...
   */
  deslashify(fs_static.opt_fs);

  /*
   * ok... copy the data back out.
   */
  *fo = fs_static;

  /*
   * Clear defined options
   */
  if (opt_keyd != key && opt_keyd != nullstr)
    XFREE(opt_keyd);
  opt_keyd = nullstr;
  opt_dkey = NullStr;
  opt_key = opt_map = opt_path = nullstr;

  return ok;
}