/* * This readdir function which call a special version of it that allows * browsing if browsable_dirs=yes was set on the map. */ int amfs_generic_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count) { int browsable, full; /* check if map is browsable */ browsable = 0; if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { mntent_t mnt; mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; if (amu_hasmntopt(&mnt, "fullybrowsable")) browsable = 2; else if (amu_hasmntopt(&mnt, "browsable")) browsable = 1; } full = (browsable == 2); if (nfs_dispatcher == nfs_program_2) { if (browsable) return amfs_readdir_browsable(mp, cookie, dp, ep, count, full); else return amfs_readdir(mp, cookie, dp, ep, count); } else { if (browsable) return amfs_readdir3_browsable(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count, full); else return amfs_readdir3(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count); } }
/* * start with an empty string. for each opts1 option that is not * in opts2, add it to the string (make sure the reverse of it * isn't in either). finally add opts2. return new string. * Both opts1 and opts2 must not be null! * Caller must eventually free the string being returned. */ static char * merge_opts(const char *opts1, const char *opts2) { mntent_t mnt2; /* place holder for opts2 */ char *newstr; /* new string to return (malloc'ed) */ char *tmpstr; /* temp */ char *eq; /* pointer to whatever follows '=' within temp */ char oneopt[80]; /* one option w/o value if any */ char *revoneopt; /* reverse of oneopt */ size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */ char *s1 = strdup(opts1); /* copy of opts1 to munge */ /* initialization */ mnt2.mnt_opts = (char *) opts2; newstr = xmalloc(len); newstr[0] = '\0'; for (tmpstr = strtok(s1, ","); tmpstr; tmpstr = strtok(NULL, ",")) { /* copy option to temp buffer */ xstrlcpy(oneopt, tmpstr, sizeof(oneopt)); /* if option has a value such as rsize=1024, chop the value part */ if ((eq = haseq(oneopt))) *eq = '\0'; /* find reverse option of oneopt */ revoneopt = reverse_option(oneopt); /* if option orits reverse exist in opts2, ignore it */ if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt)) continue; /* add option to returned string */ if (newstr[0]) { xstrlcat(newstr, ",", len); xstrlcat(newstr, tmpstr, len); } else { xstrlcpy(newstr, tmpstr, len); } } /* finally, append opts2 itself */ if (newstr[0]) { xstrlcat(newstr, ",", len); xstrlcat(newstr, opts2, len); } else { xstrlcpy(newstr, opts2, len); } XFREE(s1); return newstr; }
/* * Utility routine which returns the string value of * an option in the mount options (such as proto=udp). * Returns NULL if the option is not specified. * Returns malloc'ed string (caller must free!) */ char * hasmntstr(mntent_t *mnt, char *opt) { char *str = amu_hasmntopt(mnt, opt); if (str) { /* The option was there */ char *eq = hasmnteq(mnt, opt); if (eq) { /* and had an = after it */ char *endptr = strchr(eq, ','); /* if saw no comma, return strdup'd string */ if (!endptr) return strdup(eq); else { /* else we need to copy only the chars needed */ int len = endptr - eq; char *buf = xmalloc(len + 1); strncpy(buf, eq, len); buf[len] = '\0'; return buf; } } } return NULL; }
nfsstatfsres * nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) { static nfsstatfsres res; am_node *mp; int retry; mntent_t mnt; if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "statfs:"); mp = fh_to_mp3(argp, &retry, VLOOK_CREATE); if (mp == NULL) { if (retry < 0) { amd_stats.d_drops++; return 0; } res.sfr_status = nfs_error(retry); } else { nfsstatfsokres *fp; if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path); /* * just return faked up file system information */ fp = &res.sfr_u.sfr_reply_u; fp->sfrok_tsize = 1024; fp->sfrok_bsize = 1024; /* check if map is browsable and show_statfs_entries=yes */ if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) && mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; if (amu_hasmntopt(&mnt, "browsable")) { count_map_entries(mp, &fp->sfrok_blocks, &fp->sfrok_bfree, &fp->sfrok_bavail); } } else { fp->sfrok_blocks = 0; /* set to 1 if you don't want empty automounts */ fp->sfrok_bfree = 0; fp->sfrok_bavail = 0; } res.sfr_status = NFS_OK; mp->am_stats.s_statfs++; } return &res; }
/* * Utility routine which returns a pointer to whatever * follows an = in a mount option. Returns null if option * doesn't exist or doesn't have an '='. Won't fail for opt,foo=. */ char * hasmnteq(mntent_t *mnt, char *opt) { if (mnt && opt) { /* disallow null input pointers */ if ( *opt ) { /* disallow the null string as an opt */ char *str = amu_hasmntopt(mnt, opt); if ( str ) { /* option was there */ char *eq = str + strlen(opt); /* Look at char just after option */ if (*eq == '=') /* Is it '=' ? */ return ++eq; /* If so, return pointer to remaining str */ } } } return NULL; }
/* * Utility routine which determines the value of a numeric option in the * mount options (such as port=%d), and fills in the value in the argument * valp (argument won't be touched if no value is set, for example due to an * error). * * Returns non-zero (1) on error; returns 0 on success. * * XXX: eventually, all use of hasmntval() should be replaced with * hasmntvalerr(). */ unsigned int hasmntvalerr(mntent_t *mnt, char *opt, int *valp) { char *str = amu_hasmntopt(mnt, opt); int err = 1; /* 1 means no good value was set (an error) */ char *eq, *endptr; long int i; /* exit if no option specificed */ if (!str) { goto out; } eq = hasmnteq(mnt, opt); if (!eq) { /* no argument to option ('=' sign was missing) */ plog(XLOG_MAP, "numeric option to \"%s\" missing", opt); goto out; } /* if got here, then we had an '=' after option name */ endptr = NULL; i = strtol(eq, &endptr, 0); /* hex and octal allowed ;-) */ if (!endptr || (endptr != eq && (*endptr == ',' || *endptr == '\0'))) { /* * endptr set means strtol saw a non-digit. If the non-digit is a * comma, it's probably the start of the next option. If the comma is * the first char though, complain about it (foo=,bar is made * noticeable by this). * * Similar reasoning for '\0' instead of comma, it's the end of the * string. */ *valp = (int) i; /* set good value */ err = 0; /* no error */ } else { /* whatever was after the '=' sign wasn't a number */ plog(XLOG_MAP, "invalid numeric option in \"%s\": \"%s\"", opt, str); /* fall through to error/exit processing */ } out: return err; }
/* compute generic mount flags */ int compute_mount_flags(mntent_t *mntp) { struct opt_tab *opt; int flags = 0; #ifdef MNT2_GEN_OPT_NEWTYPE flags |= MNT2_GEN_OPT_NEWTYPE; #endif /* MNT2_GEN_OPT_NEWTYPE */ #ifdef MNT2_GEN_OPT_AUTOMOUNTED flags |= MNT2_GEN_OPT_AUTOMOUNTED; #endif /* not MNT2_GEN_OPT_AUTOMOUNTED */ /* * Crack basic mount options */ for (opt = mnt_flags; opt->opt; opt++) { flags |= amu_hasmntopt(mntp, opt->opt) ? opt->flag : 0; } return flags; }
static int mount_udf(char *mntdir, char *fs_name, char *opts, int on_autofs) { udf_args_t udf_args; mntent_t mnt; int flags; char *str; #if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) uid_t uid_nobody; gid_t gid_nobody; #endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */ /* * Figure out the name of the file system type. */ MTYPE_TYPE type = MOUNT_TYPE_UDF; #if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) uid_nobody = a_uid("nobody", "user"); if (uid_nobody == 0) { plog(XLOG_ERROR, "mount_udf: invalid uid for nobody"); return EPERM; } #endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */ #if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID) gid_nobody = a_gid("nobody", "group"); if (gid_nobody == 0) { plog(XLOG_ERROR, "mount_udf: invalid gid for nobody"); return EPERM; } #endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID) */ str = NULL; memset((voidp) &udf_args, 0, sizeof(udf_args)); /* Paranoid */ /* * Fill in the mount structure */ memset((voidp)&mnt, 0, sizeof(mnt)); mnt.mnt_dir = mntdir; mnt.mnt_fsname = fs_name; mnt.mnt_type = MNTTAB_TYPE_UDF; mnt.mnt_opts = opts; flags = compute_mount_flags(&mnt); #ifdef HAVE_UDF_ARGS_T_UDFMFLAGS # if defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION) if (amu_hasmntopt(&mnt, MNTTAB_OPT_CLOSESESSION)) udf_args.udfmflags |= MNT2_UDF_OPT_CLOSESESSION; # endif /* defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION) */ #endif /* HAVE_UDF_ARGS_T_UDFMFLAGS */ #ifdef HAVE_UDF_ARGS_T_NOBODY_UID udf_args.nobody_uid = uid_nobody; #endif /* HAVE_UDF_ARGS_T_NOBODY_UID */ #ifdef HAVE_UDF_ARGS_T_NOBODY_GID udf_args.nobody_gid = gid_nobody; #endif /* HAVE_UDF_ARGS_T_NOBODY_GID */ #ifdef HAVE_UDF_ARGS_T_ANON_UID udf_args.anon_uid = uid_nobody; /* default to nobody */ if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) { udf_args.anon_uid = a_uid(str, MNTTAB_OPT_USER); XFREE(str); } #endif /* HAVE_UDF_ARGS_T_ANON_UID */ #ifdef HAVE_UDF_ARGS_T_ANON_GID udf_args.anon_gid = gid_nobody; /* default to nobody */ if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) { udf_args.anon_gid = a_gid(str, MNTTAB_OPT_GROUP); XFREE(str); } #endif /* HAVE_UDF_ARGS_T_ANON_GID */ #ifdef HAVE_UDF_ARGS_T_GMTOFF udf_args.gmtoff = 0; if ((str = hasmntstr(&mnt, MNTTAB_OPT_GMTOFF)) != NULL) { udf_args.gmtoff = a_num(str, MNTTAB_OPT_GMTOFF); XFREE(str); } #endif /* HAVE_UDF_ARGS_T_GMTOFF */ #ifdef HAVE_UDF_ARGS_T_SESSIONNR udf_args.sessionnr = 0; if ((str = hasmntstr(&mnt, MNTTAB_OPT_SESSIONNR)) != NULL) { udf_args.sessionnr = a_num(str, MNTTAB_OPT_SESSIONNR); XFREE(str); } #endif /* HAVE_UDF_ARGS_T_SESSIONNR */ #ifdef HAVE_UDF_ARGS_T_VERSION # ifdef UDFMNT_VERSION udf_args.version = UDFMNT_VERSION; # endif /* UDFMNT_VERSION */ #endif /* HAVE_UDF_ARGS_T_VERSION */ #ifdef HAVE_UFS_ARGS_T_FSPEC udf_args.fspec = fs_name; #endif /* HAVE_UFS_ARGS_T_FSPEC */ /* * Call generic mount routine */ return mount_fs(&mnt, flags, (caddr_t)&udf_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); }
/* * This readdir function which call a special version of it that allows * browsing if browsable_dirs=yes was set on the map. */ int amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) { u_int gen = *(u_int *) cookie; am_node *xp; mntent_t mnt; dp->dl_eof = FALSE; /* assume readdir not done */ /* check if map is browsable */ if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; if (amu_hasmntopt(&mnt, "fullybrowsable")) return amfs_readdir_browsable(mp, cookie, dp, ep, count, TRUE); if (amu_hasmntopt(&mnt, "browsable")) return amfs_readdir_browsable(mp, cookie, dp, ep, count, FALSE); } /* when gen is 0, we start reading from the beginning of the directory */ if (gen == 0) { /* * In the default instance (which is used to start a search) we return * "." and "..". * * This assumes that the count is big enough to allow both "." and ".." * to be returned in a single packet. If it isn't (which would be * fairly unbelievable) then tough. */ dlog("amfs_generic_readdir: default search"); /* * Check for enough room. This is extremely approximate but is more * than enough space. Really need 2 times: * 4byte fileid * 4byte cookie * 4byte name length * 4byte name * plus the dirlist structure */ if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))) return EINVAL; xp = next_nonerror_node(mp->am_child); dp->dl_entries = ep; /* construct "." */ ep[0].ne_fileid = mp->am_gen; ep[0].ne_name = "."; ep[0].ne_nextentry = &ep[1]; (void)memset(ep[0].ne_cookie, 0, sizeof(u_int)); /* construct ".." */ if (mp->am_parent) ep[1].ne_fileid = mp->am_parent->am_gen; else ep[1].ne_fileid = mp->am_gen; ep[1].ne_name = ".."; ep[1].ne_nextentry = NULL; (void)memcpy(ep[1].ne_cookie, (xp ? &xp->am_gen : &dotdotcookie), sizeof(dotdotcookie)); if (!xp) dp->dl_eof = TRUE; /* by default assume readdir done */ if (amuDebug(D_READDIR)) { nfsentry *ne; int j; for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) { u_int cookie; (void)memcpy(&cookie, ne->ne_cookie, sizeof(cookie)); plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%d ck=%d", j++, ne->ne_name, ne->ne_fileid, cookie); } } return 0; } dlog("amfs_generic_readdir: real child"); if (gen == DOT_DOT_COOKIE) { dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path); dp->dl_eof = TRUE; dp->dl_entries = NULL; if (amuDebug(D_READDIR)) plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n"); return 0; } /* non-browsable directories code */ xp = mp->am_child; while (xp && xp->am_gen != gen) xp = xp->am_osib; if (xp) { int nbytes = count / 2; /* conservative */ int todo = MAX_READDIR_ENTRIES; dp->dl_entries = ep; do { am_node *xp_next = next_nonerror_node(xp->am_osib); if (xp_next) { (void)memcpy(ep->ne_cookie, &xp_next->am_gen, sizeof(xp_next->am_gen)); } else { (void)memcpy(ep->ne_cookie, &dotdotcookie, sizeof(dotdotcookie)); dp->dl_eof = TRUE; } ep->ne_fileid = xp->am_gen; ep->ne_name = xp->am_name; nbytes -= sizeof(*ep) + 1; if (xp->am_name) nbytes -= strlen(xp->am_name); xp = xp_next; if (nbytes > 0 && !dp->dl_eof && todo > 1) { ep->ne_nextentry = ep + 1; ep++; --todo; } else { todo = 0; } } while (todo > 0); ep->ne_nextentry = NULL; if (amuDebug(D_READDIR)) { nfsentry *ne; int j; for (j=0,ne=ep; ne; ne=ne->ne_nextentry) { u_int cookie; (void)memcpy(&cookie, ne->ne_cookie, sizeof(cookie)); plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%d ck=%d", j++, ne->ne_name, ne->ne_fileid, cookie); } } return 0; } return ESTALE; }
static int mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs) { cdfs_args_t cdfs_args; mntent_t mnt; int genflags, cdfs_flags, retval; /* * Figure out the name of the file system type. */ MTYPE_TYPE type = MOUNT_TYPE_CDFS; memset((voidp) &cdfs_args, 0, sizeof(cdfs_args)); /* Paranoid */ cdfs_flags = 0; /* * Fill in the mount structure */ memset((voidp) &mnt, 0, sizeof(mnt)); mnt.mnt_dir = mntdir; mnt.mnt_fsname = fs_name; mnt.mnt_type = MNTTAB_TYPE_CDFS; mnt.mnt_opts = opts; #if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) if (amu_hasmntopt(&mnt, MNTTAB_OPT_DEFPERM)) # ifdef MNT2_CDFS_OPT_DEFPERM cdfs_flags |= MNT2_CDFS_OPT_DEFPERM; # else /* not MNT2_CDFS_OPT_DEFPERM */ cdfs_flags &= ~MNT2_CDFS_OPT_NODEFPERM; # endif /* not MNT2_CDFS_OPT_DEFPERM */ #endif /* defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) */ #if defined(MNT2_CDFS_OPT_NODEFPERM) && defined(MNTTAB_OPT_NODEFPERM) if (amu_hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM)) cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM; #endif /* MNTTAB_OPT_NODEFPERM */ #if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION)) cdfs_flags |= MNT2_CDFS_OPT_NOVERSION; #endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */ #if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP)) cdfs_flags |= MNT2_CDFS_OPT_RRIP; #endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */ #if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP)) cdfs_flags |= MNT2_CDFS_OPT_NORRIP; #endif /* defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) */ #if defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS)) cdfs_flags |= MNT2_CDFS_OPT_GENS; #endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */ #if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT)) cdfs_flags |= MNT2_CDFS_OPT_EXTATT; #endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */ genflags = compute_mount_flags(&mnt); #ifdef HAVE_FS_AUTOFS if (on_autofs) genflags |= autofs_compute_mount_flags(&mnt); #endif /* HAVE_FS_AUTOFS */ #ifdef HAVE_CDFS_ARGS_T_FLAGS cdfs_args.flags = cdfs_flags; #endif /* HAVE_CDFS_ARGS_T_FLAGS */ #ifdef HAVE_CDFS_ARGS_T_ISO_FLAGS cdfs_args.iso_flags = genflags | cdfs_flags; #endif /* HAVE_CDFS_ARGS_T_ISO_FLAGS */ #ifdef HAVE_CDFS_ARGS_T_ISO_PGTHRESH cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH); #endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */ #ifdef HAVE_CDFS_ARGS_T_NORRIP /* XXX: need to provide norrip mount opt */ cdfs_args.norrip = 0; /* use Rock-Ridge Protocol extensions */ #endif /* HAVE_CDFS_ARGS_T_NORRIP */ #ifdef HAVE_CDFS_ARGS_T_SSECTOR /* XXX: need to provide ssector mount option */ cdfs_args.ssector = 0; /* use 1st session on disk */ #endif /* HAVE_CDFS_ARGS_T_SSECTOR */ #ifdef HAVE_CDFS_ARGS_T_FSPEC cdfs_args.fspec = fs_name; #endif /* HAVE_CDFS_ARGS_T_FSPEC */ /* * Call generic mount routine */ retval = mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); return retval; }
/* * Fill in the many possible fields and flags of struct nfs_args. * * nap: pre-allocated structure to fill in. * mntp: mount entry structure (includes options) * genflags: generic mount flags already determined * nfsncp: (TLI only) netconfig entry for this NFS mount * ip_addr: IP address of file server * nfs_version: 2, 3, (4 in the future), or 0 if unknown * nfs_proto: "udp", "tcp", or NULL. * fhp: file handle structure pointer * host_name: name of remote NFS host * fs_name: remote file system name to mount */ void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name) { /* initialize just in case */ memset((voidp) nap, 0, sizeof(nfs_args_t)); /* compute all of the NFS attribute-cache flags */ compute_nfs_attrcache_flags(nap, mntp); /************************************************************************/ /*** FILEHANDLE DATA AND LENGTH ***/ /************************************************************************/ #ifdef HAVE_FS_NFS3 if (nfs_version == NFS_VERSION3) { # if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) /* * Some systems (Irix/bsdi3) have a separate field in nfs_args for * the length of the file handle for NFS V3. They insist that * the file handle set in nfs_args be plain bytes, and not * include the length field. */ NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data); # else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */ NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3); # endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */ # ifdef MNT2_NFS_OPT_NFSV3 nap->flags |= MNT2_NFS_OPT_NFSV3; # endif /* MNT2_NFS_OPT_NFSV3 */ # ifdef MNT2_NFS_OPT_VER3 nap->flags |= MNT2_NFS_OPT_VER3; # endif /* MNT2_NFS_OPT_VER3 */ } else #endif /* HAVE_FS_NFS3 */ NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2); #ifdef HAVE_NFS_ARGS_T_FHSIZE # ifdef HAVE_FS_NFS3 if (nfs_version == NFS_VERSION3) nap->fhsize = fhp->v3.am_fh3_length; else # endif /* HAVE_FS_NFS3 */ nap->fhsize = FHSIZE; #endif /* HAVE_NFS_ARGS_T_FHSIZE */ /* this is the version of the nfs_args structure, not of NFS! */ #ifdef HAVE_NFS_ARGS_T_FH_LEN # ifdef HAVE_FS_NFS3 if (nfs_version == NFS_VERSION3) nap->fh_len = fhp->v3.am_fh3_length; else # endif /* HAVE_FS_NFS3 */ nap->fh_len = FHSIZE; #endif /* HAVE_NFS_ARGS_T_FH_LEN */ /************************************************************************/ /*** HOST NAME ***/ /************************************************************************/ /* * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a * struct nfs_args, or truncate our concocted "hostname:/path" * string prematurely. */ NFS_HN_DREF(nap->hostname, host_name); #ifdef MNT2_NFS_OPT_HOSTNAME nap->flags |= MNT2_NFS_OPT_HOSTNAME; #endif /* MNT2_NFS_OPT_HOSTNAME */ /************************************************************************/ /*** IP ADDRESS OF REMOTE HOST ***/ /************************************************************************/ if (ip_addr) { #ifdef HAVE_TRANSPORT_TYPE_TLI nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */ #endif /* HAVE_TRANSPORT_TYPE_TLI */ NFS_SA_DREF(nap, ip_addr); } /************************************************************************/ /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/ /************************************************************************/ #ifdef MNT2_NFS_OPT_TCP if (nfs_proto && STREQ(nfs_proto, "tcp")) nap->flags |= MNT2_NFS_OPT_TCP; #endif /* MNT2_NFS_OPT_TCP */ #ifdef HAVE_NFS_ARGS_T_SOTYPE /* bsdi3 uses this */ if (nfs_proto) { if (STREQ(nfs_proto, "tcp")) nap->sotype = SOCK_STREAM; else if (STREQ(nfs_proto, "udp")) nap->sotype = SOCK_DGRAM; } #endif /* HAVE_NFS_ARGS_T_SOTYPE */ #ifdef HAVE_NFS_ARGS_T_PROTO nap->proto = 0; /* bsdi3 sets this field to zero */ # ifdef IPPROTO_TCP if (nfs_proto) { if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */ nap->proto = IPPROTO_TCP; else if (STREQ(nfs_proto, "udp")) nap->proto = IPPROTO_UDP; } # endif /* IPPROTO_TCP */ #endif /* HAVE_NFS_ARGS_T_SOTYPE */ #ifdef HAVE_NFS_ARGS_T_VERSION # ifdef NFS_ARGSVERSION nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */ # endif /* NFS_ARGSVERSION */ # ifdef DG_MOUNT_NFS_VERSION nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */ # endif /* DG_MOUNT_NFS_VERSION */ #endif /* HAVE_NFS_ARGS_VERSION */ /************************************************************************/ /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/ /************************************************************************/ #ifdef MNT2_NFS_OPT_NOCONN /* check if user specified to use unconnected or connected sockets */ if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL) nap->flags |= MNT2_NFS_OPT_NOCONN; else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL) nap->flags &= ~MNT2_NFS_OPT_NOCONN; else { /* * Some OSs want you to set noconn always. Some want you to always turn * it off. Others want you to turn it on/off only if NFS V.3 is used. * And all of that changes from revision to another. This is * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than * attempt to auto-detect this, I'm forced to "fix" it in the individual * conf/nfs_prot/nfs_prot_*.h files. */ # ifdef USE_UNCONNECTED_NFS_SOCKETS if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) { nap->flags |= MNT2_NFS_OPT_NOCONN; plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)"); } # endif /* USE_UNCONNECTED_NFS_SOCKETS */ # ifdef USE_CONNECTED_NFS_SOCKETS if (nap->flags & MNT2_NFS_OPT_NOCONN) { nap->flags &= ~MNT2_NFS_OPT_NOCONN; plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)"); } # endif /* USE_CONNECTED_NFS_SOCKETS */ } #endif /* MNT2_NFS_OPT_NOCONN */ #ifdef MNT2_NFS_OPT_RESVPORT # ifdef MNTTAB_OPT_RESVPORT if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL) nap->flags |= MNT2_NFS_OPT_RESVPORT; # else /* not MNTTAB_OPT_RESVPORT */ nap->flags |= MNT2_NFS_OPT_RESVPORT; # endif /* not MNTTAB_OPT_RESVPORT */ #endif /* MNT2_NFS_OPT_RESVPORT */ /************************************************************************/ /*** OTHER FLAGS AND OPTIONS ***/ /************************************************************************/ #ifdef HAVE_TRANSPORT_TYPE_TLI /* set up syncaddr field */ nap->syncaddr = (struct netbuf *) NULL; /* set up knconf field */ if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) { plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args"); going_down(1); } /* update the flags field for knconf */ nap->flags |= MNT2_NFS_OPT_KNCONF; #endif /* HAVE_TRANSPORT_TYPE_TLI */ #ifdef MNT2_NFS_OPT_FSNAME nap->fsname = fs_name; nap->flags |= MNT2_NFS_OPT_FSNAME; #endif /* MNT2_NFS_OPT_FSNAME */ nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE); #ifdef MNT2_NFS_OPT_RSIZE if (nap->rsize) nap->flags |= MNT2_NFS_OPT_RSIZE; #endif /* MNT2_NFS_OPT_RSIZE */ if (nfs_version == NFS_VERSION && nap->rsize > 8192) nap->rsize = 8192; nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE); #ifdef MNT2_NFS_OPT_WSIZE if (nap->wsize) nap->flags |= MNT2_NFS_OPT_WSIZE; #endif /* MNT2_NFS_OPT_WSIZE */ if (nfs_version == NFS_VERSION && nap->wsize > 8192) nap->wsize = 8192; nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO); #ifdef MNT2_NFS_OPT_TIMEO if (nap->timeo) nap->flags |= MNT2_NFS_OPT_TIMEO; #endif /* MNT2_NFS_OPT_TIMEO */ nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS); #ifdef MNT2_NFS_OPT_RETRANS if (nap->retrans) nap->flags |= MNT2_NFS_OPT_RETRANS; #endif /* MNT2_NFS_OPT_RETRANS */ #ifdef MNT2_NFS_OPT_BIODS if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS))) nap->flags |= MNT2_NFS_OPT_BIODS; #endif /* MNT2_NFS_OPT_BIODS */ #ifdef MNT2_NFS_OPT_SOFT if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL) nap->flags |= MNT2_NFS_OPT_SOFT; #endif /* MNT2_NFS_OPT_SOFT */ #ifdef MNT2_NFS_OPT_SPONGY if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) { nap->flags |= MNT2_NFS_OPT_SPONGY; if (nap->flags & MNT2_NFS_OPT_SOFT) { plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored"); nap->flags &= ~MNT2_NFS_OPT_SOFT; } } #endif /* MNT2_NFS_OPT_SPONGY */ #if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) /* Ultrix has separate generic and NFS ro flags */ if (genflags & MNT2_GEN_OPT_RONLY) nap->flags |= MNT2_NFS_OPT_RONLY; #endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */ #ifdef MNTTAB_OPT_INTR if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL) /* * Either turn on the "allow interrupts" option, or * turn off the "disallow interrupts" option" */ # ifdef MNT2_NFS_OPT_INTR nap->flags |= MNT2_NFS_OPT_INTR; # endif /* MNT2_NFS_OPT_INTR */ # ifdef MNT2_NFS_OPT_NOINTR nap->flags &= ~MNT2_NFS_OPT_NOINTR; # endif /* MNT2_NFS_OPT_NOINTR */ # ifdef MNT2_NFS_OPT_INT nap->flags |= MNT2_NFS_OPT_INT; # endif /* MNT2_NFS_OPT_INT */ # ifdef MNT2_NFS_OPT_NOINT nap->flags &= ~MNT2_NFS_OPT_NOINT; # endif /* MNT2_NFS_OPT_NOINT */ #endif /* MNTTAB_OPT_INTR */ #ifdef MNTTAB_OPT_NODEVS if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL) nap->flags |= MNT2_NFS_OPT_NODEVS; #endif /* MNTTAB_OPT_NODEVS */ #ifdef MNTTAB_OPT_COMPRESS if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL) nap->flags |= MNT2_NFS_OPT_COMPRESS; #endif /* MNTTAB_OPT_COMPRESS */ #ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */ if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL) nap->flags |= MNT2_NFS_OPT_PRIVATE; #endif /* MNTTAB_OPT_PRIVATE */ #ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */ if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL))) nap->flags |= MNT2_NFS_OPT_SYMTTL; #endif /* MNTTAB_OPT_SYMTTL */ #ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */ if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH))) nap->flags |= MNT2_NFS_OPT_PGTHRESH; #endif /* MNT2_NFS_OPT_PGTHRESH */ #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL) nap->flags |= MNT2_NFS_OPT_NOCTO; #endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */ #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX) if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) { nap->flags |= MNT2_NFS_OPT_POSIX; # ifdef HAVE_NFS_ARGS_T_PATHCONF nap->pathconf = NULL; # endif /* HAVE_NFS_ARGS_T_PATHCONF */ } #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */ #if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL) nap->flags |= MNT2_NFS_OPT_PROPLIST; #endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */ #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS); if (nap->maxgrouplist != 0) nap->flags |= MNT2_NFS_OPT_MAXGRPS; #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */ #if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL) nap->flags |= MNT2_NFS_OPT_NONLM; #endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */ #if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL) nap->flags |= MNT2_NFS_OPT_XLATECOOKIE; #endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */ #ifdef HAVE_NFS_ARGS_T_OPTSTR nap->optstr = mntp->mnt_opts; #endif /* HAVE_NFS_ARGS_T_OPTSTR */ /************************************************************************/ /*** FINAL ACTIONS ***/ /************************************************************************/ #ifdef HAVE_NFS_ARGS_T_GFS_FLAGS /* Ultrix stores generic flags in nfs_args.gfs_flags. */ nap->gfs_flags = genflags; #endif /* HAVE_NFS_ARGS_T_FLAGS */ return; /* end of compute_nfs_args() function */ }
/* * Compute all NFS attribute cache related flags separately. Note that this * function now computes attribute-cache flags for both Amd's automount * points (NFS) as well as any normal NFS mount that Amd performs. Edit * with caution. */ static void compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) { int acval = 0; int err_acval = 1; /* 1 means we found no 'actimeo' value */ #if defined(HAVE_NFS_ARGS_T_ACREGMIN) || defined(HAVE_NFS_ARGS_T_ACREGMAX) || defined(HAVE_NFS_ARGS_T_ACDIRMIN) || defined(HAVE_NFS_ARGS_T_ACDIRMAX) int err_acrdmm; /* for ac{reg,dir}{min,max} */ #endif /* HAVE_NFS_ARGS_T_AC{REG,DIR}{MIN,MAX} */ /************************************************************************/ /*** ATTRIBUTE CACHES ***/ /************************************************************************/ /* * acval is set to 0 at the top of the function. If actimeo mount option * exists and defined in mntopts, then its acval is set to it. * If the value is non-zero, then we set all attribute cache fields to it. * If acval is zero, it means it was never defined in mntopts or the * actimeo mount option does not exist, in which case we check for * individual mount options per attribute cache. * Regardless of the value of acval, mount flags are set based directly * on the values of the attribute caches. */ #ifdef MNTTAB_OPT_ACTIMEO err_acval = hasmntvalerr(mntp, MNTTAB_OPT_ACTIMEO, &acval); /* attr cache timeout (sec) */ #endif /* MNTTAB_OPT_ACTIMEO */ /*** acregmin ***/ #ifdef HAVE_NFS_ARGS_T_ACREGMIN err_acrdmm = 1; /* 1 means we found no acregmin value */ if (!err_acval) { nap->acregmin = acval; /* min ac timeout for reg files (sec) */ } else { # ifdef MNTTAB_OPT_ACREGMIN err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, (int *) &nap->acregmin); # else /* not MNTTAB_OPT_ACREGMIN */ nap->acregmin = 0; # endif /* not MNTTAB_OPT_ACREGMIN */ } /* set this flag iff we changed acregmin (possibly to zero) */ # ifdef MNT2_NFS_OPT_ACREGMIN if (!err_acval || !err_acrdmm) nap->flags |= MNT2_NFS_OPT_ACREGMIN; # endif /* MNT2_NFS_OPT_ACREGMIN */ #endif /* HAVE_NFS_ARGS_T_ACREGMIN */ /*** acregmax ***/ #ifdef HAVE_NFS_ARGS_T_ACREGMAX err_acrdmm = 1; /* 1 means we found no acregmax value */ if (!err_acval) { nap->acregmax = acval; /* max ac timeout for reg files (sec) */ } else { # ifdef MNTTAB_OPT_ACREGMAX err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, (int *) &nap->acregmax); # else /* not MNTTAB_OPT_ACREGMAX */ nap->acregmax = 0; # endif /* not MNTTAB_OPT_ACREGMAX */ } /* set this flag iff we changed acregmax (possibly to zero) */ # ifdef MNT2_NFS_OPT_ACREGMAX if (!err_acval || !err_acrdmm) nap->flags |= MNT2_NFS_OPT_ACREGMAX; # endif /* MNT2_NFS_OPT_ACREGMAX */ #endif /* HAVE_NFS_ARGS_T_ACREGMAX */ /*** acdirmin ***/ #ifdef HAVE_NFS_ARGS_T_ACDIRMIN err_acrdmm = 1; /* 1 means we found no acdirmin value */ if (!err_acval) { nap->acdirmin = acval; /* min ac timeout for dirs (sec) */ } else { # ifdef MNTTAB_OPT_ACDIRMIN err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, (int *) &nap->acdirmin); # else /* not MNTTAB_OPT_ACDIRMIN */ nap->acdirmin = 0; # endif /* not MNTTAB_OPT_ACDIRMIN */ } /* set this flag iff we changed acdirmin (possibly to zero) */ # ifdef MNT2_NFS_OPT_ACDIRMIN if (!err_acval || !err_acrdmm) nap->flags |= MNT2_NFS_OPT_ACDIRMIN; # endif /* MNT2_NFS_OPT_ACDIRMIN */ #endif /* HAVE_NFS_ARGS_T_ACDIRMIN */ /*** acdirmax ***/ #ifdef HAVE_NFS_ARGS_T_ACDIRMAX err_acrdmm = 1; /* 1 means we found no acdirmax value */ if (!err_acval) { nap->acdirmax = acval; /* max ac timeout for dirs (sec) */ } else { # ifdef MNTTAB_OPT_ACDIRMAX err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, (int *) &nap->acdirmax); # else /* not MNTTAB_OPT_ACDIRMAX */ nap->acdirmax = 0; # endif /* not MNTTAB_OPT_ACDIRMAX */ } /* set this flag iff we changed acdirmax (possibly to zero) */ # ifdef MNT2_NFS_OPT_ACDIRMAX if (!err_acval || !err_acrdmm) nap->flags |= MNT2_NFS_OPT_ACDIRMAX; # endif /* MNT2_NFS_OPT_ACDIRMAX */ #endif /* HAVE_NFS_ARGS_T_ACDIRMAX */ /* don't cache attributes */ #if defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC) if (amu_hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL) nap->flags |= MNT2_NFS_OPT_NOAC; #endif /* defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC) */ (void)err_acval; }
int mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname, int on_autofs) { int error = 0; #ifdef MOUNT_TABLE_ON_FILE char *zopts = NULL, *xopts = NULL; size_t l; #endif /* MOUNT_TABLE_ON_FILE */ char *mnt_dir = NULL; #ifdef NEED_AUTOFS_SPACE_HACK char *old_mnt_dir = NULL; /* perform space hack */ if (on_autofs) { old_mnt_dir = mnt->mnt_dir; mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir); } else #endif /* NEED_AUTOFS_SPACE_HACK */ mnt_dir = strdup(mnt->mnt_dir); dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)", mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts); again: error = MOUNT_TRAP(type, mnt, flags, mnt_data); if (error < 0) { plog(XLOG_ERROR, "'%s': mount: %m", mnt_dir); /* * The following code handles conditions which shouldn't * occur. They are possible either because amd screws up * in preparing for the mount, or because some human * messed with the mount point. Both have been known to * happen. -- stolcke 2/22/95 */ if (errno == EBUSY) { /* * Also, sometimes unmount isn't called, e.g., because * our mountlist is garbled. This leaves old mount * points around which need to be removed before we * can mount something new in their place. */ errno = umount_fs(mnt_dir, mnttabname, on_autofs); if (errno != 0) plog(XLOG_ERROR, "'%s': umount: %m", mnt_dir); else { plog(XLOG_WARNING, "extra umount required for '%s'", mnt_dir); error = MOUNT_TRAP(type, mnt, flags, mnt_data); } } } if (error < 0 && --retry > 0) { sleep(1); goto again; } #ifdef NEED_AUTOFS_SPACE_HACK /* Undo space hack */ if (on_autofs) mnt->mnt_dir = old_mnt_dir; #endif /* NEED_AUTOFS_SPACE_HACK */ if (error < 0) { error = errno; goto out; } #ifdef MOUNT_TABLE_ON_FILE /* * Allocate memory for options: * dev=..., vers={2,3}, proto={tcp,udp} */ l = strlen(mnt->mnt_opts) + 48; zopts = (char *) xmalloc(l); /* copy standard options */ xopts = mnt->mnt_opts; xstrlcpy(zopts, xopts, l); # ifdef MNTTAB_OPT_DEV { /* add the extra dev= field to the mount table */ struct stat stb; if (lstat(mnt_dir, &stb) == 0) { char optsbuf[48]; if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */ xsnprintf(optsbuf, sizeof(optsbuf), "%s=%04lx", MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff); else /* e.g. System Vr4 */ xsnprintf(optsbuf, sizeof(optsbuf), "%s=%08lx", MNTTAB_OPT_DEV, (u_long) stb.st_dev); append_opts(zopts, l, optsbuf); } } # endif /* MNTTAB_OPT_DEV */ # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) /* * add the extra vers={2,3} field to the mount table, * unless already specified by user */ if (nfs_version == NFS_VERSION3 && hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) { char optsbuf[48]; xsnprintf(optsbuf, sizeof(optsbuf), "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3); append_opts(zopts, l, optsbuf); } # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */ # ifdef MNTTAB_OPT_PROTO /* * add the extra proto={tcp,udp} field to the mount table, * unless already specified by user. */ if (nfs_proto && !amu_hasmntopt(mnt, MNTTAB_OPT_PROTO)) { char optsbuf[48]; xsnprintf(optsbuf, sizeof(optsbuf), "%s=%s", MNTTAB_OPT_PROTO, nfs_proto); append_opts(zopts, l, optsbuf); } # endif /* MNTTAB_OPT_PROTO */ /* finally, store the options into the mount table structure */ mnt->mnt_opts = zopts; /* * Additional fields in mntent_t * are fixed up here */ # ifdef HAVE_MNTENT_T_MNT_CNODE mnt->mnt_cnode = 0; # endif /* HAVE_MNTENT_T_MNT_CNODE */ # ifdef HAVE_MNTENT_T_MNT_RO mnt->mnt_ro = (amu_hasmntopt(mnt, MNTTAB_OPT_RO) != NULL); # endif /* HAVE_MNTENT_T_MNT_RO */ # ifdef HAVE_MNTENT_T_MNT_TIME # ifdef HAVE_MNTENT_T_MNT_TIME_STRING { /* allocate enough space for a long */ size_t l = 13 * sizeof(char); char *str = (char *) xmalloc(l); xsnprintf(str, l, "%ld", time((time_t *) NULL)); mnt->mnt_time = str; } # else /* not HAVE_MNTENT_T_MNT_TIME_STRING */ mnt->mnt_time = time((time_t *) NULL); # endif /* not HAVE_MNTENT_T_MNT_TIME_STRING */ # endif /* HAVE_MNTENT_T_MNT_TIME */ write_mntent(mnt, mnttabname); # ifdef MNTTAB_OPT_DEV if (xopts) { XFREE(mnt->mnt_opts); mnt->mnt_opts = xopts; } # endif /* MNTTAB_OPT_DEV */ #endif /* MOUNT_TABLE_ON_FILE */ out: XFREE(mnt_dir); return error; }
static int mount_tmpfs(char *mntdir, char *fs_name, char *opts, int on_autofs) { tmpfs_args_t tmpfs_args; mntent_t mnt; int flags; const char *p; /* * Figure out the name of the file system type. */ MTYPE_TYPE type = MOUNT_TYPE_TMPFS; p = NULL; memset((voidp) &tmpfs_args, 0, sizeof(tmpfs_args)); /* Paranoid */ /* * Fill in the mount structure */ memset((voidp) &mnt, 0, sizeof(mnt)); mnt.mnt_dir = mntdir; mnt.mnt_fsname = fs_name; mnt.mnt_type = MNTTAB_TYPE_TMPFS; mnt.mnt_opts = opts; flags = compute_mount_flags(&mnt); #ifdef HAVE_FS_AUTOFS if (on_autofs) flags |= autofs_compute_mount_flags(&mnt); #endif /* HAVE_FS_AUTOFS */ #if defined(HAVE_TMPFS_ARGS_T_TA_VERSION) && defined(TMPFS_ARGS_VERSION) tmpfs_args.ta_version = TMPFS_ARGS_VERSION; #endif /* HAVE_TMPFS_ARGS_T_TA_VERSION && TMPFS_ARGS_VERSION */ #ifdef HAVE_TMPFS_ARGS_T_TA_NODES_MAX if ((p = amu_hasmntopt(&mnt, "nodes")) == NULL) p = "1000000"; tmpfs_args.ta_nodes_max = atoi(p); #endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */ #ifdef HAVE_TMPFS_ARGS_T_TA_SIZE_MAX if ((p = amu_hasmntopt(&mnt, "size")) == NULL) p = "10000000"; tmpfs_args.ta_size_max = atoi(p); #endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */ #ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_UID if ((p = amu_hasmntopt(&mnt, "uid")) == NULL) p = "0"; tmpfs_args.ta_root_uid = atoi(p); #endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_UID */ #ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_GID if ((p = amu_hasmntopt(&mnt, "gid")) == NULL) p = "0"; tmpfs_args.ta_root_gid = atoi(p); #endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_GID */ #ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_MODE if ((p = amu_hasmntopt(&mnt, "mode")) == NULL) p = "01777"; tmpfs_args.ta_root_mode = strtol(p, NULL, 8); #endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_MODE */ /* * Call generic mount routine */ return mount_fs(&mnt, flags, (caddr_t) &tmpfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); }
void am_mounted(am_node *mp) { int notimeout = 0; /* assume normal timeouts initially */ mntfs *mf = mp->am_al->al_mnt; /* * This is the parent mntfs which does the mf->mf_fo (am_opts type), and * we're passing TRUE here to tell mf_mounted to actually free the * am_opts. See a related comment in mf_mounted(). */ mf_mounted(mf, TRUE); #ifdef HAVE_FS_AUTOFS if (mf->mf_flags & MFF_IS_AUTOFS) autofs_mounted(mp); #endif /* HAVE_FS_AUTOFS */ /* * Patch up path for direct mounts */ if (mp->am_parent && mp->am_parent->am_al->al_mnt->mf_fsflags & FS_DIRECT) mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", "."); /* * Check whether this mount should be cached permanently or not, * and handle user-requested timeouts. */ /* first check if file system was set to never timeout */ if (mf->mf_fsflags & FS_NOTIMEOUT) notimeout = 1; /* next, alter that decision by map flags */ if (mf->mf_mopts) { mntent_t mnt; mnt.mnt_opts = mf->mf_mopts; /* umount option: user wants to unmount this entry */ if (amu_hasmntopt(&mnt, "unmount") || amu_hasmntopt(&mnt, "umount")) notimeout = 0; /* noumount option: user does NOT want to unmount this entry */ if (amu_hasmntopt(&mnt, "nounmount") || amu_hasmntopt(&mnt, "noumount")) notimeout = 1; /* utimeout=N option: user wants to unmount this option AND set timeout */ if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0) mp->am_timeo = gopt.am_timeo; /* otherwise use default timeout */ else notimeout = 0; /* special case: don't try to unmount "/" (it can never succeed) */ if (mf->mf_mount[0] == '/' && mf->mf_mount[1] == '\0') notimeout = 1; } /* finally set actual flags */ if (notimeout) { mp->am_flags |= AMF_NOTIMEOUT; plog(XLOG_INFO, "%s set to never timeout", mp->am_path); } else { mp->am_flags &= ~AMF_NOTIMEOUT; plog(XLOG_INFO, "%s set to timeout in %d seconds", mp->am_path, mp->am_timeo); } /* * If this node is a symlink then * compute the length of the returned string. */ if (mp->am_fattr.na_type == NFLNK) mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mf->mf_mount); /* * Record mount time, and update am_stats at the same time. */ mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime); new_ttl(mp); /* * Update mtime of parent node (copying "struct nfstime" in '=' below) */ if (mp->am_parent && mp->am_parent->am_al->al_mnt) mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime; /* * This is ugly, but essentially unavoidable * Sublinks must be treated separately as type==link * when the base type is different. */ if (mp->am_link && mf->mf_ops != &amfs_link_ops) amfs_link_ops.mount_fs(mp, mf); /* * Now, if we can, do a reply to our client here * to speed things up. */ #ifdef HAVE_FS_AUTOFS if (mp->am_flags & AMF_AUTOFS) autofs_mount_succeeded(mp); else #endif /* HAVE_FS_AUTOFS */ nfs_quick_reply(mp, 0); /* * Update stats */ amd_stats.d_mok++; }