/**************************************************************************** *** 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; }
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; }