/* * return string option which is the reverse of opt. * nosuid -> suid * quota -> noquota * ro -> rw * etc. * may return pointer to static buffer or subpointer within opt. */ static char * reverse_option(const char *opt) { static char buf[80]; /* sanity check */ if (!opt) return NULL; /* check special cases */ /* XXX: if this gets too long, rewrite the code more flexibly */ if (STREQ(opt, "ro")) return "rw"; if (STREQ(opt, "rw")) return "ro"; if (STREQ(opt, "bg")) return "fg"; if (STREQ(opt, "fg")) return "bg"; if (STREQ(opt, "soft")) return "hard"; if (STREQ(opt, "hard")) return "soft"; /* check if string starts with 'no' and chop it */ if (NSTREQ(opt, "no", 2)) { xstrlcpy(buf, &opt[2], sizeof(buf)); } else { /* finally return a string prepended with 'no' */ xstrlcpy(buf, "no", sizeof(buf)); xstrlcat(buf, opt, sizeof(buf)); } return buf; }
/* convert from ix386 mnttab to amd mntent */ static mntent_t * mnt_dup(mntent_t *mp) { /* note: may not be null terminated */ mntent_t *new_mp = ALLOC(mntent_t); char nullcpy[128]; xstrlcpy(nullcpy, mp->mt_dev, 32); new_mp->mnt_fsname = strdup(nullcpy); xstrlcpy(nullcpy, mp->mt_filsys, 32); new_mp->mnt_dir = strdup(nullcpy); xstrlcpy(nullcpy, mp->mt_fstyp, 16); new_mp->mnt_type = strdup(nullcpy); xstrlcpy(nullcpy, mp->mt_mntopts, 64); new_mp->mnt_opts = strdup(nullcpy); new_mp->mnt_freq = 0; new_mp->mnt_passno = 0; new_mp->mnt_time = mp->mt_time; new_mp->mnt_ro = mp->mt_ro_flg; return new_mp; }
/* * Take a little-endian domain name and * transform into a big-endian Un*x pathname. * For example: kiska.doc.ic -> ic/doc/kiska */ static char * compute_hostpath(char *hn) { char *p = xmalloc(MAXPATHLEN); char *d; char path[MAXPATHLEN]; xstrlcpy(p, hn, MAXPATHLEN); domain_strip(p, hostname); path[0] = '\0'; do { d = strrchr(p, '.'); if (d) { *d = 0; xstrlcat(path, d + 1, sizeof(path)); xstrlcat(path, "/", sizeof(path)); } else { xstrlcat(path, p, sizeof(path)); } } while (d); fsi_log("hostpath of '%s' is '%s'", hn, path); xstrlcpy(p, path, MAXPATHLEN); return p; }
/// Gets the hostname of the current machine. /// /// @param hostname Buffer to store the hostname. /// @param size Size of `hostname`. void os_get_hostname(char *hostname, size_t size) { #ifdef HAVE_SYS_UTSNAME_H struct utsname vutsname; if (uname(&vutsname) < 0) { *hostname = '\0'; } else { xstrlcpy(hostname, vutsname.nodename, size); } #elif defined(WIN32) wchar_t host_utf16[MAX_COMPUTERNAME_LENGTH + 1]; DWORD host_wsize = sizeof(host_utf16) / sizeof(host_utf16[0]); if (GetComputerNameW(host_utf16, &host_wsize) == 0) { *hostname = '\0'; DWORD err = GetLastError(); EMSG2("GetComputerNameW failed: %d", err); return; } host_utf16[host_wsize] = '\0'; char *host_utf8; int conversion_result = utf16_to_utf8(host_utf16, &host_utf8); if (conversion_result != 0) { EMSG2("utf16_to_utf8 failed: %d", conversion_result); return; } xstrlcpy(hostname, host_utf8, size); xfree(host_utf8); #else EMSG("os_get_hostname failed: missing uname()"); *hostname = '\0'; #endif }
int main(int argc, char *argv[]) { int ch; char *aux, *base, *conf_file; struct manpaths dirs; char buf[MAXPATHLEN]; extern char *optarg; extern int optind; progname = strrchr(argv[0], '/'); if (progname == NULL) progname = argv[0]; else ++progname; aux = base = conf_file = NULL; xstrlcpy(buf, "/var/www/cache/man.cgi", MAXPATHLEN); while (-1 != (ch = getopt(argc, argv, "C:fm:M:o:v"))) switch (ch) { case ('C'): conf_file = optarg; break; case ('f'): force = 1; break; case ('m'): aux = optarg; break; case ('M'): base = optarg; break; case ('o'): xstrlcpy(buf, optarg, MAXPATHLEN); break; case ('v'): verbose++; break; default: usage(); return(EXIT_FAILURE); } argc -= optind; argv += optind; if (argc > 0) { usage(); return(EXIT_FAILURE); } memset(&dirs, 0, sizeof(struct manpaths)); manpath_parse(&dirs, conf_file, base, aux); ch = manup(&dirs, buf); manpath_free(&dirs); return(ch ? EXIT_SUCCESS : EXIT_FAILURE); }
/* * Update the destination's file-tree with respect to changes in the * source manpath components. * "Change" is defined by an updated index or btree database. * Returns 1 on success, 0 on failure. */ static int manup(const struct manpaths *dirs, char *base) { char dst[MAXPATHLEN], src[MAXPATHLEN]; const char *path; int i, c; size_t sz; FILE *f; /* Create the path and file for the catman.conf file. */ sz = strlen(base); xstrlcpy(dst, base, MAXPATHLEN); xstrlcat(dst, "/etc", MAXPATHLEN); if (-1 == mkpath(dst, 0755, 0755)) { perror(dst); return(0); } xstrlcat(dst, "/catman.conf", MAXPATHLEN); if (NULL == (f = fopen(dst, "w"))) { perror(dst); return(0); } else if (verbose) printf("%s\n", dst); for (i = 0; i < dirs->sz; i++) { path = dirs->paths[i]; dst[(int)sz] = '\0'; xstrlcat(dst, path, MAXPATHLEN); if (-1 == mkpath(dst, 0755, 0755)) { perror(dst); break; } xstrlcpy(src, path, MAXPATHLEN); if (-1 == (c = treecpy(dst, src))) break; else if (0 == c) continue; /* * We want to use a relative path here because manpath.h * will realpath() when invoked with man.cgi, and we'll * make sure to chdir() into the cache directory before. * * This allows the cache directory to be in an arbitrary * place, working in both chroot() and non-chroot() * "safe" modes. */ assert('/' == path[0]); fprintf(f, "_whatdb %s/whatis.db\n", path + 1); } fclose(f); return(i == dirs->sz); }
/* * 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; }
/* * The routine transform_dir(path) transforms pathnames of directories * mounted with the amd automounter to produce a more "natural" version. * The automount table is obtained from the local amd via the rpc interface * and reverse lookups are repeatedly performed on the directory name * substituting the name of the automount link for the value of the link * whenever it occurs as a prefix of the directory name. */ static char * transform_dir(char *dir) { #ifdef DISK_HOME_HACK char *ch; #endif /* DISK_HOME_HACK */ char *server; struct sockaddr_in server_addr; int s = RPC_ANYSOCK; CLIENT *clnt; struct hostent *hp; struct timeval tmo = {10, 0}; char *dummystr; amq_string *spp; #ifdef DISK_HOME_HACK if (ch = hack_name(dir)) return ch; #endif /* DISK_HOME_HACK */ #ifdef HAVE_CNODEID server = cluster_server(); #else /* not HAVE_CNODEID */ server = localhost; #endif /* not HAVE_CNODEID */ if ((hp = gethostbyname(server)) == NULL) return dir; memset(&server_addr, 0, sizeof(server_addr)); /* as per POSIX, sin_len need not be set (used internally by kernel) */ server_addr.sin_family = AF_INET; server_addr.sin_addr = *(struct in_addr *) hp->h_addr; clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s); if (clnt == NULL) clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0); if (clnt == NULL) return dir; xstrlcpy(transform, dir, sizeof(transform)); dummystr = transform; spp = amqproc_pawd_1((amq_string *) &dummystr, clnt); if (spp && *spp && **spp) { xstrlcpy(transform, *spp, sizeof(transform)); XFREE(*spp); } clnt_destroy(clnt); return transform; }
int ndbm_init(mnt_map *m, char *map, time_t *tp) { DBM *db; db = dbm_open(map, O_RDONLY, 0); if (db) { struct stat stb; int error; #ifdef DBM_SUFFIX char dbfilename[256]; xstrlcpy(dbfilename, map, sizeof(dbfilename)); xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename)); error = stat(dbfilename, &stb); #else /* not DBM_SUFFIX */ error = fstat(dbm_pagfno(db), &stb); #endif /* not DBM_SUFFIX */ if (error < 0) *tp = clocktime(NULL); else *tp = stb.st_mtime; dbm_close(db); return 0; } return errno; }
int ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) { DBM *db; db = dbm_open(map, O_RDONLY, 0); if (db) { struct stat stb; int error; #ifdef DBM_SUFFIX char dbfilename[256]; xstrlcpy(dbfilename, map, sizeof(dbfilename)); xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename)); error = stat(dbfilename, &stb); #else /* not DBM_SUFFIX */ error = fstat(dbm_pagfno(db), &stb); #endif /* not DBM_SUFFIX */ if (!error && *tp < stb.st_mtime) { *tp = stb.st_mtime; error = -1; } else { error = search_ndbm(m, db, key, pval); } (void) dbm_close(db); return error; } return errno; }
static mntent_t * mnt_dup(struct statfs *mp) { mntent_t *new_mp = ALLOC(mntent_t); char *ty; char *at; char mntfrombuf[MNAMELEN]; char *mntfromptr; /* * Under DEC OSF/1 T1.2-2 the f_mntfromname fields of * the statfs structure can be in the format <fs>@<host> * instead of <host>:<fs>. Here we check for this and * reformat it if necessary. */ mntfromptr = mp->f_mntfromname; switch (mp->f_type) { case MOUNT_TYPE_NFS: #ifdef HAVE_FS_NFS3 case MOUNT_TYPE_NFS3: #endif /* HAVE_FS_NFS3 */ at = strchr(mp->f_mntfromname, '@'); if (at != '\0') { xstrlcpy(mntfrombuf, (at + 1), sizeof(mntfrombuf)); xstrlcat(mntfrombuf, ":", sizeof(mntfrombuf)); strncat(mntfrombuf, mp->f_mntfromname, (at - mp->f_mntfromname)); mntfromptr = mntfrombuf; } } new_mp->mnt_fsname = strdup(mntfromptr); new_mp->mnt_dir = strdup(mp->f_mntonname); switch (mp->f_type) { case MOUNT_TYPE_UFS: ty = MNTTAB_TYPE_UFS; break; #ifdef HAVE_FS_NFS3 case MOUNT_TYPE_NFS3: ty = MNTTAB_TYPE_NFS3; break; #endif /* HAVE_FS_NFS3 */ case MOUNT_TYPE_NFS: ty = MNTTAB_TYPE_NFS; break; case MOUNT_TYPE_MFS: ty = MNTTAB_TYPE_MFS; break; default: ty = "unknown"; break; } new_mp->mnt_type = strdup(ty); new_mp->mnt_opts = strdup("unset"); new_mp->mnt_freq = 0; new_mp->mnt_passno = 0; return new_mp; }
/* convert back (static alloc) */ static mntent_t * mtab_of(mntent_t *mnt) { static mntent_t mt; xstrlcpy(mt.mt_dev, mnt->mnt_fsname, 32); xstrlcpy(mt.mt_filsys, mnt->mnt_dir, 32); mt.mt_ro_flg = mnt->mnt_ro; mt.mt_time = mnt->mnt_time; xstrlcpy(mt.mt_fstyp, mnt->mnt_type, 16); xstrlcpy(mt.mt_mntopts, mnt->mnt_opts, 64); return &mt; }
/* * Take a log format string and expand occurrences of %m * with the current error code taken from errno. Make sure * 'e' never gets longer than maxlen characters. */ static const char * expand_error(const char *f, char *e, size_t maxlen) { const char *p; char *q; int error = errno; size_t len = 0, l; *e = '\0'; for (p = f, q = e; len < maxlen && (*q = *p); len++, q++, p++) { if (p[0] == '%' && p[1] == 'm') { if (len >= maxlen) break; xstrlcpy(q, strerror(error), maxlen - len); l = strlen(q); if (l != 0) l--; len += l; q += l; p++; } } e[maxlen - 1] = '\0'; /* null terminate, to be sure */ return e; }
/* * Process PAWD string of remote pawd tool. * * We repeat the resolution of the string until the resolved string resolves * to itself. This ensures that we follow path resolutions through all * possible Amd mount points until we reach some sort of convergence. To * prevent possible infinite loops, we break out of this loop if the strings * do not converge after MAX_PAWD_TRIES times. */ amq_string * amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp) { static amq_string res; #define MAX_PAWD_TRIES 10 int index, len, maxagain = MAX_PAWD_TRIES; am_node *mp; char *mountpoint; char *dir = *(char **) argp; static char tmp_buf[MAXPATHLEN]; char prev_buf[MAXPATHLEN]; tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */ do { for (mp = get_first_exported_ap(&index); mp; mp = get_next_exported_ap(&index)) { if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "toplvl")) continue; if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "auto")) continue; mountpoint = (mp->am_link ? mp->am_link : mp->am_al->al_mnt->mf_mount); len = strlen(mountpoint); if (len == 0) continue; if (!NSTREQ(mountpoint, dir, len)) continue; if (dir[len] != '\0' && dir[len] != '/') continue; xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf)); xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf)); break; } /* end of "for" loop */ /* once tmp_buf and prev_buf are equal, break out of "do" loop */ if (STREQ(tmp_buf, prev_buf)) break; else xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf)); } while (--maxagain); /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */ if (maxagain <= 0) plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries", tmp_buf, MAX_PAWD_TRIES); res = tmp_buf; return &res; }
/* * Display a pwd data */ static void show_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag) { int len; while (mt) { len = strlen(mt->mt_mountpoint); if (NSTREQ(path, mt->mt_mountpoint, len) && !STREQ(mt->mt_directory, mt->mt_mountpoint)) { char buf[MAXPATHLEN+1]; /* must be same size as 'path' */ xstrlcpy(buf, mt->mt_directory, sizeof(buf)); xstrlcat(buf, &path[len], sizeof(buf)); xstrlcpy(path, buf, l); *flag = 1; } show_pwd(mt->mt_next, path, l, flag); mt = mt->mt_child; } }
/* getawd() is a substitute for getwd() which transforms the path */ static char * getawd(char *path, size_t l) { #ifdef HAVE_GETCWD char *wd = getcwd(path, MAXPATHLEN); #else /* not HAVE_GETCWD */ char *wd = getwd(path); #endif /* not HAVE_GETCWD */ if (wd == NULL) { return NULL; } xstrlcpy(path, transform_dir(wd), l); return path; }
int autofs_get_fh(am_node *mp) { autofs_fh_t *fh; char buf[MAXHOSTNAMELEN]; mntfs *mf = mp->am_al->al_mnt; struct utsname utsname; plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path); fh = ALLOC(autofs_fh_t); memset((voidp) fh, 0, sizeof(autofs_fh_t)); /* Paranoid */ /* * SET MOUNT ARGS */ if (uname(&utsname) < 0) { xstrlcpy(buf, "localhost.autofs", sizeof(buf)); } else { xstrlcpy(buf, utsname.nodename, sizeof(buf)); xstrlcat(buf, ".autofs", sizeof(buf)); } #ifdef HAVE_AUTOFS_ARGS_T_ADDR fh->addr.buf = xstrdup(buf); fh->addr.len = fh->addr.maxlen = strlen(buf); #endif /* HAVE_AUTOFS_ARGS_T_ADDR */ fh->direct = (mf->mf_fsflags & FS_DIRECT) ? 1 : 0; fh->rpc_to = 1; /* XXX: arbitrary */ fh->mount_to = mp->am_timeo; fh->path = mp->am_path; fh->opts = ""; /* XXX: arbitrary */ fh->map = mp->am_path; /* this is what we get back in readdir */ mp->am_autofs_fh = fh; return 0; }
/* * Copy s into p, reallocating p if necessary */ char * strealloc(char *p, char *s) { size_t len = strlen(s) + 1; p = (char *) xrealloc((voidp) p, len); xstrlcpy(p, s, len); #ifdef DEBUG_MEM # if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) malloc_verify(); # endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */ #endif /* DEBUG_MEM */ return p; }
/* * replacement for hasmntopt if the system does not have it. */ char * amu_hasmntopt(mntent_t *mnt, char *opt) { char t[MNTMAXSTR]; char *f; char *o = t; size_t l = strlen(opt); xstrlcpy(t, mnt->mnt_opts, sizeof(t)); while (*(f = nextmntopt(&o))) if (NSTREQ(opt, f, l)) return f - t + mnt->mnt_opts; return 0; }
/* * Determine the mount point: * * The next change we put in to better handle PCs. This is a bit * disgusting, so you'd better sit down. We change the make_mntpt function * to look for exported file systems without a leading '/'. If they don't * have a leading '/', we add one. If the export is 'a:' through 'z:' * (without a leading slash), we change it to 'a%' (or b% or z%). This * allows the entire PC disk to be mounted. */ static void make_mntpt(char *mntpt, size_t l, const exports ex, const char *mf_mount) { if (ex->ex_dir[0] == '/') { if (ex->ex_dir[1] == 0) xstrlcpy(mntpt, mf_mount, l); else xsnprintf(mntpt, l, "%s%s", mf_mount, ex->ex_dir); } else if (ex->ex_dir[0] >= 'a' && ex->ex_dir[0] <= 'z' && ex->ex_dir[1] == ':' && ex->ex_dir[2] == '/' && ex->ex_dir[3] == 0) xsnprintf(mntpt, l, "%s/%c%%", mf_mount, ex->ex_dir[0]); else xsnprintf(mntpt, l, "%s/%s", mf_mount, ex->ex_dir); }
/* return malloc'ed buffer. caller must free it */ char * print_wires(void) { addrlist *al; char s[256]; int i; char *buf; int bufcount = 0; int buf_size = 1024; buf = SALLOC(buf_size); /* initial allocation (may grow!) */ if (!buf) return NULL; if (!localnets) { xstrlcpy(buf, "No networks\n", buf_size); return buf; } /* check if there's more than one network */ if (!localnets->ip_next) { /* use buf_size for sizeof(buf) because of the realloc() below */ xsnprintf(buf, buf_size, "Network: wire=\"%s\" (netnumber=%s).\n", localnets->ip_net_name, localnets->ip_net_num); return buf; } buf[0] = '\0'; /* null out buffer before appending */ for (i = 1, al = localnets; al; al = al->ip_next, i++) { xsnprintf(s, sizeof(s), "Network %d: wire=\"%s\" (netnumber=%s).\n", i, al->ip_net_name, al->ip_net_num); bufcount += strlen(s); if (bufcount > buf_size) { buf_size *= 2; buf = xrealloc(buf, buf_size); } xstrlcat(buf, s, buf_size); } return buf; }
void fatal(char *mess) { if (logfile && !STREQ(logfile, "stderr")) { char lessmess[128]; int messlen; messlen = strlen(mess); if (!STREQ(&mess[messlen + 1 - sizeof(ERRM)], ERRM)) fprintf(stderr, "%s: %s\n", am_get_progname(), mess); else { xstrlcpy(lessmess, mess, sizeof(lessmess)); lessmess[messlen - 4] = '\0'; fprintf(stderr, "%s: %s: %s\n", am_get_progname(), lessmess, strerror(errno)); } } plog(XLOG_FATAL, "%s", mess); hlfsd_going_down(1); }
/// End try block, set the error message if any and return true if an error /// occurred. /// /// @param err Pointer to the stack-allocated error object /// @return true if an error occurred bool try_end(Error *err) { --trylevel; // Without this it stops processing all subsequent VimL commands and // generates strange error messages if I e.g. try calling Test() in a // cycle did_emsg = false; if (got_int) { if (did_throw) { // If we got an interrupt, discard the current exception discard_current_exception(); } api_set_error(err, Exception, _("Keyboard interrupt")); got_int = false; } else if (msg_list != NULL && *msg_list != NULL) { int should_free; char *msg = (char *)get_exception_string(*msg_list, ET_ERROR, NULL, &should_free); xstrlcpy(err->msg, msg, sizeof(err->msg)); err->set = true; free_global_msglist(); if (should_free) { xfree(msg); } } else if (did_throw) { api_set_error(err, Exception, "%s", current_exception->value); discard_current_exception(); } return err->set; }
static int amfs_host_mount(am_node *am, mntfs *mf) { struct timeval tv2; CLIENT *client; enum clnt_stat clnt_stat; int n_export; int j, k; exports exlist = 0, ex; exports *ep = NULL; am_nfs_handle_t *fp = NULL; char *host; int error = 0; struct sockaddr_in sin; int sock = RPC_ANYSOCK; int ok = FALSE; mntlist *mlist; char fs_name[MAXPATHLEN], *rfs_dir; char mntpt[MAXPATHLEN]; struct timeval tv; u_long mnt_version; /* * WebNFS servers don't necessarily run mountd. */ if (mf->mf_flags & MFF_WEBNFS) { plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS"); return EIO; } /* * Read the mount list */ mlist = read_mtab(mf->mf_mount, mnttab_file_name); #ifdef MOUNT_TABLE_ON_FILE /* * Unlock the mount list */ unlock_mntlist(); #endif /* MOUNT_TABLE_ON_FILE */ /* * Take a copy of the server hostname, address, and nfs version * to mount version conversion. */ host = mf->mf_server->fs_host; sin = *mf->mf_server->fs_ip; plog(XLOG_INFO, "amfs_host_mount: NFS version %d", (int) mf->mf_server->fs_version); #ifdef HAVE_FS_NFS3 if (mf->mf_server->fs_version == NFS_VERSION3) mnt_version = AM_MOUNTVERS3; else #endif /* HAVE_FS_NFS3 */ mnt_version = MOUNTVERS; /* * The original 10 second per try timeout is WAY too large, especially * if we're only waiting 10 or 20 seconds max for the response. * That would mean we'd try only once in 10 seconds, and we could * lose the transmit or receive packet, and never try again. * A 2-second per try timeout here is much more reasonable. * 09/28/92 Mike Mitchell, [email protected] */ tv.tv_sec = 2; tv.tv_usec = 0; /* * Create a client attached to mountd */ client = get_mount_client(host, &sin, &tv, &sock, mnt_version); if (client == NULL) { #ifdef HAVE_CLNT_SPCREATEERROR plog(XLOG_ERROR, "get_mount_client failed for %s: %s", host, clnt_spcreateerror("")); #else /* not HAVE_CLNT_SPCREATEERROR */ plog(XLOG_ERROR, "get_mount_client failed for %s", host); #endif /* not HAVE_CLNT_SPCREATEERROR */ error = EIO; goto out; } if (!nfs_auth) { error = make_nfs_auth(); if (error) goto out; } client->cl_auth = nfs_auth; dlog("Fetching export list from %s", host); /* * Fetch the export list */ tv2.tv_sec = 10; tv2.tv_usec = 0; clnt_stat = clnt_call(client, MOUNTPROC_EXPORT, (XDRPROC_T_TYPE) xdr_void, 0, (XDRPROC_T_TYPE) xdr_exports, (SVC_IN_ARG_TYPE) & exlist, tv2); if (clnt_stat != RPC_SUCCESS) { const char *msg = clnt_sperrno(clnt_stat); plog(XLOG_ERROR, "host_mount rpc failed: %s", msg); /* clnt_perror(client, "rpc"); */ error = EIO; goto out; } /* * Figure out how many exports were returned */ for (n_export = 0, ex = exlist; ex; ex = ex->ex_next) { n_export++; } /* * Allocate an array of pointers into the list * so that they can be sorted. If the filesystem * is already mounted then ignore it. */ ep = (exports *) xmalloc(n_export * sizeof(exports)); for (j = 0, ex = exlist; ex; ex = ex->ex_next) { make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount); if (already_mounted(mlist, mntpt)) /* we have at least one mounted f/s, so don't fail the mount */ ok = TRUE; else ep[j++] = ex; } n_export = j; /* * Sort into order. * This way the mounts are done in order down the tree, * instead of any random order returned by the mount * daemon (the protocol doesn't specify...). */ qsort(ep, n_export, sizeof(exports), sortfun); /* * Allocate an array of filehandles */ fp = (am_nfs_handle_t *) xmalloc(n_export * sizeof(am_nfs_handle_t)); /* * Try to obtain filehandles for each directory. * If a fetch fails then just zero out the array * reference but discard the error. */ for (j = k = 0; j < n_export; j++) { /* Check and avoid a duplicated export entry */ if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) { dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir); ep[j] = NULL; } else { k = j; error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j], mf->mf_server->fs_version); if (error) ep[j] = NULL; } } /* * Mount each filesystem for which we have a filehandle. * If any of the mounts succeed then mark "ok" and return * error code 0 at the end. If they all fail then return * the last error code. */ xstrlcpy(fs_name, mf->mf_info, sizeof(fs_name)); if ((rfs_dir = strchr(fs_name, ':')) == (char *) NULL) { plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon"); error = EINVAL; goto out; } ++rfs_dir; for (j = 0; j < n_export; j++) { ex = ep[j]; if (ex) { /* * Note: the sizeof space left in rfs_dir is what's left in fs_name * after strchr() above returned a pointer _inside_ fs_name. The * calculation below also takes into account that rfs_dir was * incremented by the ++ above. */ xstrlcpy(rfs_dir, ex->ex_dir, sizeof(fs_name) - (rfs_dir - fs_name)); make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount); if (do_mount(&fp[j], mntpt, fs_name, mf) == 0) ok = TRUE; } } /* * Clean up and exit */ out: discard_mntlist(mlist); XFREE(ep); XFREE(fp); if (sock != RPC_ANYSOCK) (void) amu_close(sock); if (client) clnt_destroy(client); if (exlist) xdr_pri_free((XDRPROC_T_TYPE) xdr_exports, (caddr_t) &exlist); if (ok) return 0; return error; }
int main(int argc, char *argv[]) { char *domdot, *verstr, *vertmp; int ppid = 0; int error; char *progname = NULL; /* "amd" */ char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */ /* * Make sure some built-in assumptions are true before we start */ assert(sizeof(nfscookie) >= sizeof(u_int)); assert(sizeof(int) >= 4); /* * Set processing status. */ amd_state = Start; /* * Determine program name */ if (argv[0]) { progname = strrchr(argv[0], '/'); if (progname && progname[1]) progname++; else progname = argv[0]; } if (!progname) progname = "amd"; am_set_progname(progname); /* * Initialize process id. This is kept * cached since it is used for generating * and using file handles. */ am_set_mypid(); /* * Get local machine name */ if (gethostname(hostname, sizeof(hostname)) < 0) { plog(XLOG_FATAL, "gethostname: %m"); going_down(1); } hostname[sizeof(hostname) - 1] = '\0'; /* * Check it makes sense */ if (!*hostname) { plog(XLOG_FATAL, "host name is not set"); going_down(1); } /* * Initialize global options structure. */ init_global_options(); /* * Partially initialize hostd[]. This * is completed in get_args(). */ if ((domdot = strchr(hostname, '.'))) { /* * Hostname already contains domainname. * Split out hostname and domainname * components */ *domdot++ = '\0'; hostdomain = domdot; } xstrlcpy(hostd, hostname, sizeof(hostd)); am_set_hostname(hostname); /* * Setup signal handlers */ /* SIGINT: trap interrupts for shutdowns */ setup_sighandler(SIGINT, sigterm); /* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */ setup_sighandler(SIGTERM, sigterm); /* SIGHUP: hangups tell us to reload the cache */ setup_sighandler(SIGHUP, sighup); /* * SIGCHLD: trap Death-of-a-child. These allow us to pick up the exit * status of backgrounded mounts. See "sched.c". */ setup_sighandler(SIGCHLD, sigchld); #ifdef HAVE_SIGACTION /* construct global "masked_sigs" used in nfs_start.c */ sigemptyset(&masked_sigs); sigaddset(&masked_sigs, SIGINT); sigaddset(&masked_sigs, SIGTERM); sigaddset(&masked_sigs, SIGHUP); sigaddset(&masked_sigs, SIGCHLD); #endif /* HAVE_SIGACTION */ /* * Fix-up any umask problems. Most systems default * to 002 which is not too convenient for our purposes */ orig_umask = umask(0); /* * Figure out primary network name */ getwire(&PrimNetName, &PrimNetNum); /* * Determine command-line arguments */ get_args(argc, argv); /* * Log version information. */ vertmp = get_version_string(); verstr = strtok(vertmp, "\n"); plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:"); while (verstr) { plog(XLOG_INFO, "%s", verstr); verstr = strtok(NULL, "\n"); } XFREE(vertmp); /* * Get our own IP address so that we can mount the automounter. We pass * localhost_address which could be used as the default localhost * name/address in amu_get_myaddress(). */ amu_get_myaddress(&myipaddr, gopt.localhost_address); plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr)); /* avoid hanging on other NFS servers if started elsewhere */ if (chdir("/") < 0) plog(XLOG_INFO, "cannot chdir to /: %m"); /* * Now check we are root. */ if (geteuid() != 0) { plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid()); going_down(1); } #ifdef HAVE_MAP_NIS /* * If the domain was specified then bind it here * to circumvent any default bindings that may * be done in the C library. */ if (gopt.nis_domain && yp_bind(gopt.nis_domain)) { plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain); going_down(1); } #endif /* HAVE_MAP_NIS */ if (!amuDebug(D_DAEMON)) ppid = daemon_mode(); /* * Lock process text and data segment in memory. */ if (gopt.flags & CFM_PROCESS_LOCK) { do_memory_locking(); } do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval; /* * Register automounter with system. */ error = mount_automounter(ppid); if (error && ppid) kill(ppid, SIGALRM); #ifdef HAVE_FS_AUTOFS /* * XXX this should be part of going_down(), but I can't move it there * because it would be calling non-library code from the library... ugh */ if (amd_use_autofs) destroy_autofs_service(); #endif /* HAVE_FS_AUTOFS */ going_down(error); abort(); return 1; /* should never get here */ }
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; }
void am_set_hostname(char *hn) { xstrlcpy(am_hostname, hn, sizeof(am_hostname)); }
/* * Write out a mount list */ void rewrite_mtab(mntlist *mp, const char *mnttabname) { FILE *mfp; int error = 0; char tmpname[64]; int retries; int tmpfd; char *cp; char mcp[128]; if (!mtab_is_writable()) { return; } /* * Concoct a temporary name in the same directory as the target mount * table so that rename() will work. */ xstrlcpy(mcp, mnttabname, sizeof(mcp)); cp = strrchr(mcp, '/'); if (cp) { memmove(tmpname, mcp, cp - mcp); tmpname[cp - mcp] = '\0'; } else { plog(XLOG_WARNING, "No '/' in mtab (%s), using \".\" as tmp directory", mnttabname); tmpname[0] = '.'; tmpname[1] = '\0'; } xstrlcat(tmpname, "/mtabXXXXXX", sizeof(tmpname)); retries = 0; enfile1: #ifdef HAVE_MKSTEMP tmpfd = mkstemp(tmpname); fchmod(tmpfd, 0644); #else /* not HAVE_MKSTEMP */ mktemp(tmpname); tmpfd = open(tmpname, O_RDWR | O_CREAT | O_TRUNC, 0644); #endif /* not HAVE_MKSTEMP */ if (tmpfd < 0) { if (errno == ENFILE && retries++ < NFILE_RETRIES) { sleep(1); goto enfile1; } plog(XLOG_ERROR, "%s: open: %m", tmpname); return; } if (close(tmpfd) < 0) plog(XLOG_ERROR, "Couldn't close tmp file descriptor: %m"); retries = 0; enfile2: mfp = setmntent(tmpname, "w"); if (!mfp) { if (errno == ENFILE && retries++ < NFILE_RETRIES) { sleep(1); goto enfile2; } plog(XLOG_ERROR, "setmntent(\"%s\", \"w\"): %m", tmpname); error = 1; goto out; } while (mp) { if (mp->mnt) { if (addmntent(mfp, mp->mnt)) { plog(XLOG_ERROR, "Can't write entry to %s", tmpname); error = 1; goto out; } } mp = mp->mnext; } /* * SunOS 4.1 manuals say that the return code from entmntent() * is always 1 and to treat as a void. That means we need to * call fflush() to make sure the new mtab file got written. */ if (fflush(mfp)) { plog(XLOG_ERROR, "flush new mtab file: %m"); error = 1; goto out; } (void) endmntent(mfp); /* * Rename temporary mtab to real mtab */ if (rename(tmpname, mnttabname) < 0) { plog(XLOG_ERROR, "rename %s to %s: %m", tmpname, mnttabname); error = 1; goto out; } out: if (error) (void) unlink(tmpname); }
nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) { static nfsdiropres res; int idx; uid_t uid = (uid_t) INVALIDID; gid_t gid = (gid_t) INVALIDID; if (!started) { started++; rootfattr.na_ctime = startup; rootfattr.na_mtime = startup; slinkfattr.na_ctime = startup; slinkfattr.na_mtime = startup; un_fattr.na_ctime = startup; un_fattr.na_mtime = startup; } if (eq_fh(&argp->da_fhandle, &slink)) { res.dr_status = NFSERR_NOTDIR; return &res; } if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) { res.dr_status = NFSERR_NOENT; return &res; } if (eq_fh(&argp->da_fhandle, &root)) { if (argp->da_name[0] == '.' && (argp->da_name[1] == '\0' || (argp->da_name[1] == '.' && argp->da_name[2] == '\0'))) { #if 0 /* * XXX: increment mtime of parent directory, causes NFS clients to * invalidate their cache for that directory. * Some NFS clients may need this code. */ if (uid != rootfattr.na_uid) { clocktime(&rootfattr.na_mtime); rootfattr.na_uid = uid; } #endif /* 0 */ res.dr_u.dr_drok_u.drok_fhandle = root; res.dr_u.dr_drok_u.drok_attributes = rootfattr; res.dr_status = NFS_OK; return &res; } if (STREQ(argp->da_name, slinkname)) { #ifndef MNT2_NFS_OPT_SYMTTL /* * This code is needed to defeat Solaris 2.4's (and newer) symlink * values cache. It forces the last-modified time of the symlink to be * current. It is not needed if the O/S has an nfs flag to turn off the * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez. * * Additionally, Linux currently ignores the nt_useconds field, * so we must update the nt_seconds field every time. */ if (uid != slinkfattr.na_uid) { clocktime(&slinkfattr.na_mtime); slinkfattr.na_uid = uid; } #endif /* not MNT2_NFS_OPT_SYMTTL */ res.dr_u.dr_drok_u.drok_fhandle = slink; res.dr_u.dr_drok_u.drok_attributes = slinkfattr; res.dr_status = NFS_OK; return &res; } if (gid != hlfs_gid) { res.dr_status = NFSERR_NOENT; return &res; } /* if gets here, gid == hlfs_gid */ if ((idx = untab_index(argp->da_name)) < 0) { res.dr_status = NFSERR_NOENT; return &res; } else { /* entry found and gid is permitted */ u_int xuid; un_fattr.na_fileid = untab[idx].uid; res.dr_u.dr_drok_u.drok_attributes = un_fattr; memset(&un_fhandle, 0, sizeof(am_nfs_fh)); xuid = (u_int) untab[idx].uid; memcpy(un_fhandle.fh_data, &xuid, sizeof(xuid)); xstrlcpy((char *) &un_fhandle.fh_data[sizeof(xuid)], untab[idx].username, sizeof(am_nfs_fh) - sizeof(xuid)); res.dr_u.dr_drok_u.drok_fhandle = un_fhandle; res.dr_status = NFS_OK; dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s", (long) uid, (long) gid, untab[idx].username); return &res; } } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */ res.dr_status = NFSERR_STALE; return &res; }
/* * Map from conventional mount arguments * to Solaris 2.x (SunOS 5.x) style arguments. */ int mount_svr4(char *fsname, char *dir, int flags, MTYPE_TYPE type, caddr_t data, const char *optstr) { #if defined(MNT2_GEN_OPT_OPTIONSTR) && defined(MAX_MNTOPT_STR) char mountopts[MAX_MNTOPT_STR]; /* * Save a copy of the mount options. The kernel will overwrite them with * those it recognizes. */ xstrlcpy(mountopts, optstr, MAX_MNTOPT_STR); #endif /* defined(MNT2_GEN_OPT_OPTIONSTR) && defined(MAX_MNTOPT_STR) */ #if defined(MOUNT_TYPE_NFS3) && defined(MNTTAB_TYPE_NFS3) if (STREQ(type, MOUNT_TYPE_NFS3)) { return sys_mount(fsname, dir, (MNT2_GEN_OPT_DATA | flags), type, (char *) data, sizeof(nfs_args_t)); } #endif /* defined(MOUNT_TYPE_NFS3) && defined(MNTTAB_TYPE_NFS3) */ #if defined(MOUNT_TYPE_NFS) && defined(MNTTAB_TYPE_NFS) if (STREQ(type, MOUNT_TYPE_NFS)) { return sys_mount(fsname, dir, (MNT2_GEN_OPT_DATA | flags), type, (char *) data, sizeof(nfs_args_t)); } #endif /* defined(MOUNT_TYPE_NFS) && defined(MNTTAB_TYPE_NFS) */ #if defined(MOUNT_TYPE_AUTOFS) && defined(MNTTAB_TYPE_AUTOFS) if (STREQ(type, MOUNT_TYPE_AUTOFS)) { return sys_mount(fsname, dir, (MNT2_GEN_OPT_DATA | flags), type, (char *) data, sizeof(autofs_args_t)); } #endif /* defined(MOUNT_TYPE_AUTOFS) && defined(MNTTAB_TYPE_AUTOFS) */ #if defined(MOUNT_TYPE_UFS) && defined(MNTTAB_TYPE_UFS) if (STREQ(type, MOUNT_TYPE_UFS)) return sys_mount(fsname, dir, (MNT2_GEN_OPT_DATA | flags), type, (char *) data, sizeof(ufs_args_t)); #endif /* defined(MOUNT_TYPE_UFS) && defined(MNTTAB_TYPE_UFS) */ #if defined(MOUNT_TYPE_PCFS) && defined(MNTTAB_TYPE_PCFS) if (STREQ(type, MOUNT_TYPE_PCFS)) return sys_mount(fsname, dir, (MNT2_GEN_OPT_DATA | flags), type, (char *) data, sizeof(pcfs_args_t)); #endif /* defined(MOUNT_TYPE_PCFS) && defined(MNTTAB_TYPE_PCFS) */ #if defined(MOUNT_TYPE_CDFS) && defined(MNTTAB_TYPE_CDFS) /* * HSFS on Solaris allows for 3 HSFSMNT_* flags to be passed * as arguments to the mount(). These flags are bit fields in an * integer, and that integer is passed as the "data" of this system * call. The flags are described in <sys/fs/hsfs_rrip.h>. However, * Solaris does not have an interface to these. It does not define * a structure hsfs_args or anything that one can figure out what * arguments to pass to mount(2) for this type of filesystem. * Therefore, until Sun does, no arguments are passed to this mount * below. * -Erez Zadok <*****@*****.**>. */ if (STREQ(type, MOUNT_TYPE_CDFS)) return sys_mount(fsname, dir, (MNT2_GEN_OPT_FSS | flags), type, (char *) NULL, 0); #endif /* defined(MOUNT_TYPE_CDFS) && defined(MNTTAB_TYPE_CDFS) */ #if defined(MOUNT_TYPE_LOFS) && defined(MNTTAB_TYPE_LOFS) if (STREQ(type, MOUNT_TYPE_LOFS)) return sys_mount(fsname, dir, (MNT2_GEN_OPT_FSS | flags), type, (char *) NULL, 0); #endif /* defined(MOUNT_TYPE_LOFS) && defined(MNTTAB_TYPE_LOFS) */ #ifdef HAVE_FS_CACHEFS # if defined(MOUNT_TYPE_CACHEFS) && defined(MNTTAB_TYPE_CACHEFS) if (STREQ(type, MOUNT_TYPE_CACHEFS)) return sys_mount(fsname, dir, (MNT2_GEN_OPT_DATA | flags), type, (char *) data, sizeof(cachefs_args_t)); # endif /* defined(MOUNT_TYPE_CACHEFS) && defined(MNTTAB_TYPE_CACHEFS) */ #endif /*HAVE_FS_CACHEFS */ #ifdef HAVE_FS_AUTOFS # if defined(MOUNT_TYPE_AUTOFS) && defined(MNTTAB_TYPE_AUTOFS) if (STREQ(type, MOUNT_TYPE_AUTOFS)) return sys_mount(fsname, dir, (MNT2_GEN_OPT_DATA | flags), type, (char *) data, sizeof(autofs_args_t)); # endif /* defined(MOUNT_TYPE_AUTOFS) && defined(MNTTAB_TYPE_AUTOFS) */ #endif /* HAVE_FS_AUTOFS */ return EINVAL; }