/* * Mount an automounter directory. * The automounter is connected into the system * as a user-level NFS server. mount_amfs_toplvl constructs * the necessary NFS parameters to be given to the * kernel so that it will talk back to us. * * NOTE: automounter mounts in themselves are using NFS Version 2. */ static int mount_amfs_toplvl(char *dir, char *opts) { char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1]; int retry, error, genflags; mntent_t mnt; nfs_args_t nfs_args; am_nfs_fh *fhp; am_nfs_handle_t anh; MTYPE_TYPE type = MOUNT_TYPE_NFS; #ifndef HAVE_TRANSPORT_TYPE_TLI u_short port; struct sockaddr_in sin; #endif /* not HAVE_TRANSPORT_TYPE_TLI */ memset((voidp) &mnt, 0, sizeof(mnt)); mnt.mnt_dir = dir; mnt.mnt_fsname = pid_fsname; mnt.mnt_opts = opts; /* * Make sure that amd's top-level NFS mounts are hidden by default * from df. * If they don't appear to support the either the "ignore" mnttab * option entry, or the "auto" one, set the mount type to "nfs". */ mnt.mnt_type = HIDE_MOUNT_TYPE; retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); if (retry <= 0) retry = 2; /* XXX */ /* * SET MOUNT ARGS */ /* * get fhandle of remote path for automount point */ fhp = root_fh(dir); if (!fhp) { plog(XLOG_FATAL, "Can't find root file handle for %s", dir); return EINVAL; } #ifndef HAVE_TRANSPORT_TYPE_TLI /* * Create sockaddr to point to the local machine. 127.0.0.1 * is not used since that will not work in HP-UX clusters and * this is no more expensive. */ memset((voidp) &sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = myipaddr; port = hasmntval(&mnt, MNTTAB_OPT_PORT); if (port) { sin.sin_port = htons(port); } else { plog(XLOG_ERROR, "no port number specified for %s", dir); return EINVAL; } #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* * Make a ``hostname'' string for the kernel */ sprintf(fs_hostname, "pid%ld@%s:%s", (long) (foreground ? am_mypid : getppid()), am_get_hostname(), dir); /* * Most kernels have a name length restriction (64 bytes)... */ if (strlen(fs_hostname) >= MAXHOSTNAMELEN) strcpy(fs_hostname + MAXHOSTNAMELEN - 3, ".."); #ifdef HOSTNAMESZ /* * ... and some of these restrictions are 32 bytes (HOSTNAMESZ) * If you need to get the definition for HOSTNAMESZ found, you may * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file. */ if (strlen(fs_hostname) >= HOSTNAMESZ) strcpy(fs_hostname + HOSTNAMESZ - 3, ".."); #endif /* HOSTNAMESZ */ /* * Finally we can compute the mount genflags set above, * and add any automounter specific flags. */ genflags = compute_mount_flags(&mnt); genflags |= compute_automounter_mount_flags(&mnt); /* setup the many fields and flags within nfs_args */ memmove(&anh.v2.fhs_fh, fhp, sizeof(*fhp)); #ifdef HAVE_TRANSPORT_TYPE_TLI compute_nfs_args(&nfs_args, &mnt, genflags, nfsncp, NULL, /* remote host IP addr is set below */ NFS_VERSION, /* version 2 */ "udp", &anh, fs_hostname, pid_fsname); /* * IMPORTANT: set the correct IP address AFTERWARDS. It cannot * be done using the normal mechanism of compute_nfs_args(), because * that one will allocate a new address and use NFS_SA_DREF() to copy * parts to it, while assuming that the ip_addr passed is always * a "struct sockaddr_in". That assumption is incorrect on TLI systems, * because they define a special macro HOST_SELF which is DIFFERENT * than localhost (127.0.0.1)! */ nfs_args.addr = &nfsxprt->xp_ltaddr; #else /* not HAVE_TRANSPORT_TYPE_TLI */ compute_nfs_args(&nfs_args, &mnt, genflags, &sin, NFS_VERSION, /* version 2 */ "udp", &anh, fs_hostname, pid_fsname); #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /************************************************************************* * NOTE: while compute_nfs_args() works ok for regular NFS mounts * * the toplvl one is not, and so some options must be corrected by hand * * more carefully, *after* compute_nfs_args() runs. * *************************************************************************/ compute_automounter_nfs_args(&nfs_args, &mnt); /* This is it! Here we try to mount amd on its mount points */ #ifdef DEBUG amuDebug(D_TRACE) { print_nfs_args(&nfs_args, 0); plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags); } #endif /* DEBUG */ error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name); #ifdef HAVE_TRANSPORT_TYPE_TLI free_knetconfig(nfs_args.knconf); /* * local automounter mounts do not allocate a special address, so * no need to XFREE(nfs_args.addr) under TLI. */ #endif /* HAVE_TRANSPORT_TYPE_TLI */ return error; }
int main(int argc, char *argv[]) { char *dot; char *mntopts = (char *) NULL; char hostpid_fs[MAXHOSTNAMELEN + 1 + 16]; /* room for ":(pid###)" */ char progpid_fs[PROGNAMESZ + 1 + 11]; /* room for ":pid" */ char preopts[128]; char *progname; int forcecache = 0; int forcefast = 0; int genflags = 0; int opt, ret; int opterrs = 0; int retry; int soNFS; /* NFS socket */ int s = -99; mntent_t mnt; nfs_args_t nfs_args; am_nfs_handle_t anh; struct dirent *direntry; struct group *grp; struct stat stmodes; DIR *mountdir; MTYPE_TYPE type = MOUNT_TYPE_NFS; #ifdef HAVE_SIGACTION struct sigaction sa; #endif /* not HAVE_SIGACTION */ #ifndef HAVE_TRANSPORT_TYPE_TLI struct sockaddr_in localsocket; #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* get program name and truncate so we don't overflow progpid_fs */ if ((progname = strrchr(argv[0], '/')) != NULL) progname++; else progname = argv[0]; if ((int) strlen(progname) > PROGNAMESZ) /* truncate to reasonable size */ progname[PROGNAMESZ] = '\0'; am_set_progname(progname); while ((opt = getopt(argc, argv, "a:c:CD:fg:hi:l:no:pP:x:v")) != -1) switch (opt) { case 'a': if (!optarg || optarg[0] != '/') { printf("%s: invalid directory for -a: %s\n", am_get_progname(), optarg); exit(3); } alt_spooldir = optarg; break; case 'c': if (!atoi(optarg)) { printf("%s: invalid interval for -c: %s\n", am_get_progname(), optarg); exit(3); } cache_interval = atoi(optarg); break; case 'C': forcecache++; break; case 'f': forcefast++; break; case 'g': hlfs_group = optarg; break; case 'i': if (!atoi(optarg)) { printf("%s: invalid interval for -i: %s\n", am_get_progname(), optarg); exit(3); } reloadinterval.it_interval.tv_sec = atoi(optarg); reloadinterval.it_value.tv_sec = atoi(optarg); break; case 'l': logfile = optarg; break; case 'n': noverify++; break; case 'o': mntopts = optarg; break; case 'p': printpid++; break; case 'P': passwdfile = optarg; break; case 'v': fprintf(stderr, "%s\n", HLFSD_VERSION); exit(0); case 'x': opterrs += switch_option(optarg); break; case 'D': #ifdef DEBUG opterrs += debug_option(optarg); #else /* not DEBUG */ fprintf(stderr, "%s: not compiled with DEBUG -- sorry.\n", am_get_progname()); #endif /* not DEBUG */ break; case 'h': case '?': opterrs++; } /* set some default debugging options */ if (xlog_level_init == ~0) switch_option(""); /* need my pid before any dlog/plog */ am_set_mypid(); #ifdef DEBUG switch_option("debug"); #endif /* DEBUG */ /* * Terminate if did not ask to forcecache (-C) and hlfsd would not be able * to set the minimum cache intervals. */ #if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN) if (!forcecache) { fprintf(stderr, "%s: will not be able to turn off attribute caches.\n", am_get_progname()); exit(1); } #endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN) */ switch (argc - optind) { case 2: home_subdir = argv[optind + 1]; case 1: dir_name = argv[optind]; case 0: break; default: opterrs++; } if (opterrs) usage(); /* ensure that only root can run hlfsd */ if (geteuid()) { fprintf(stderr, "hlfsd can only be run as root\n"); exit(1); } setbuf(stdout, (char *) NULL); umask(0); /* find gid for hlfs_group */ if ((grp = getgrnam(hlfs_group)) == (struct group *) NULL) { fprintf(stderr, "%s: cannot get gid for group \"%s\".\n", am_get_progname(), hlfs_group); } else { hlfs_gid = grp->gr_gid; } /* get hostname for logging and open log before we reset umask */ gethostname(hostname, sizeof(hostname)); hostname[sizeof(hostname) - 1] = '\0'; if ((dot = strchr(hostname, '.')) != NULL) *dot = '\0'; orig_umask = umask(0); if (logfile) switch_to_logfile(logfile, orig_umask); #if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) if (debug_flags & D_MTAB) dlog("-D mtab option ignored"); #endif /* defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) */ /* avoid hanging on other NFS servers if started elsewhere */ if (chdir("/") < 0) fatal("cannot chdir to /: %m"); if (geteuid() != 0) fatal("must be root to mount filesystems"); /* * dir_name must match "^(/.*)/([^/]+)$", and is split at last '/' with * slinkname = `basename $dir_name` - requires dir_name be writable */ if (dir_name[0] != '/' || ((slinkname = strrchr(dir_name, '/')), *slinkname++ = '\0', (dir_name[0] == '\0' || slinkname[0] == '\0'))) { if (slinkname) *--slinkname = '/'; printf("%s: invalid mount directory/link %s\n", am_get_progname(), dir_name); exit(3); } clock_valid = 0; /* invalidate logging clock */ if (!forcefast) { /* make sure mount point exists and is at least mode 555 */ if (stat(dir_name, &stmodes) < 0) if (errno != ENOENT || mkdirs(dir_name, 0555) < 0 || stat(dir_name, &stmodes) < 0) fatalerror(dir_name); if ((stmodes.st_mode & 0555) != 0555) { fprintf(stderr, "%s: directory %s not read/executable\n", am_get_progname(), dir_name); plog(XLOG_WARNING, "directory %s not read/executable", dir_name); } /* warn if extraneous stuff will be hidden by mount */ if ((mountdir = opendir(dir_name)) == NULL) fatalerror(dir_name); while ((direntry = readdir(mountdir)) != NULL) { if (!NSTREQ(".", direntry->d_name, NAMLEN(direntry)) && !NSTREQ("..", direntry->d_name, NAMLEN(direntry)) && !NSTREQ(slinkname, direntry->d_name, NAMLEN(direntry))) break; } if (direntry != NULL) { fprintf(stderr, "%s: %s/%s will be hidden by mount\n", am_get_progname(), dir_name, direntry->d_name); plog(XLOG_WARNING, "%s/%s will be hidden by mount\n", dir_name, direntry->d_name); } closedir(mountdir); /* make sure alternate spool dir exists */ if ((errno = mkdirs(alt_spooldir, OPEN_SPOOLMODE))) { fprintf(stderr, "%s: cannot create alternate dir ", am_get_progname()); perror(alt_spooldir); plog(XLOG_ERROR, "cannot create alternate dir %s: %m", alt_spooldir); } chmod(alt_spooldir, OPEN_SPOOLMODE); /* create failsafe link to alternate spool directory */ slinkname[-1] = '/'; /* unsplit dir_name to include link */ if (lstat(dir_name, &stmodes) == 0 && (stmodes.st_mode & S_IFMT) != S_IFLNK) { fprintf(stderr, "%s: failsafe %s not a symlink\n", am_get_progname(), dir_name); plog(XLOG_WARNING, "failsafe %s not a symlink\n", dir_name); } else { unlink(dir_name); if (symlink(alt_spooldir, dir_name) < 0) { fprintf(stderr, "%s: cannot create failsafe symlink %s -> ", am_get_progname(), dir_name); perror(alt_spooldir); plog(XLOG_WARNING, "cannot create failsafe symlink %s -> %s: %m", dir_name, alt_spooldir); } } slinkname[-1] = '\0'; /* resplit dir_name */ } /* end of "if (!forcefast) {" */ /* * Register hlfsd as an nfs service with the portmapper. */ #ifdef HAVE_TRANSPORT_TYPE_TLI ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); #else /* not HAVE_TRANSPORT_TYPE_TLI */ ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); #endif /* not HAVE_TRANSPORT_TYPE_TLI */ if (ret != 0) fatal("cannot create NFS service"); #ifdef HAVE_SIGACTION sa.sa_handler = proceed; sa.sa_flags = 0; sigemptyset(&(sa.sa_mask)); sigaddset(&(sa.sa_mask), SIGUSR2); sigaction(SIGUSR2, &sa, NULL); #else /* not HAVE_SIGACTION */ signal(SIGUSR2, proceed); #endif /* not HAVE_SIGACTION */ plog(XLOG_INFO, "Initializing hlfsd..."); hlfsd_init(); /* start up child (forking) to run svc_run */ #ifdef HAVE_SIGACTION sa.sa_handler = reaper; sa.sa_flags = 0; sigemptyset(&(sa.sa_mask)); sigaddset(&(sa.sa_mask), SIGCHLD); sigaction(SIGCHLD, &sa, NULL); #else /* not HAVE_SIGACTION */ signal(SIGCHLD, reaper); #endif /* not HAVE_SIGACTION */ #ifdef DEBUG /* * In the parent, if -D nodaemon (or -D daemon) , we don't need to * set this signal handler. */ amuDebug(D_DAEMON) { #endif /* DEBUG */ /* XXX: port to use pure svr4 signals */ s = -99; while (stoplight != SIGUSR2) { plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight); s = sigpause(0); /* wait for child to set up */ sleep(1); } #ifdef DEBUG } #endif /* DEBUG */ /* * setup options to mount table (/etc/{mtab,mnttab}) entry */ sprintf(hostpid_fs, "%s:(pid%d)", hostname, masterpid); memset((char *) &mnt, 0, sizeof(mnt)); mnt.mnt_dir = dir_name; /* i.e., "/mail" */ mnt.mnt_fsname = hostpid_fs; if (mntopts) { mnt.mnt_opts = mntopts; } else { strcpy(preopts, default_mntopts); /* * Turn off all kinds of attribute and symlink caches as * much as possible. Also make sure that mount does not * show up to df. */ #ifdef MNTTAB_OPT_INTR strcat(preopts, ","); strcat(preopts, MNTTAB_OPT_INTR); #endif /* MNTTAB_OPT_INTR */ #ifdef MNTTAB_OPT_IGNORE strcat(preopts, ","); strcat(preopts, MNTTAB_OPT_IGNORE); #endif /* MNTTAB_OPT_IGNORE */ #ifdef MNT2_GEN_OPT_CACHE strcat(preopts, ",nocache"); #endif /* MNT2_GEN_OPT_CACHE */ #ifdef MNT2_NFS_OPT_SYMTTL strcat(preopts, ",symttl=0"); #endif /* MNT2_NFS_OPT_SYMTTL */ mnt.mnt_opts = preopts; } /* * Make sure that amd's top-level NFS mounts are hidden by default * from df. * If they don't appear to support the either the "ignore" mnttab * option entry, or the "auto" one, set the mount type to "nfs". */ #ifdef HIDE_MOUNT_TYPE mnt.mnt_type = HIDE_MOUNT_TYPE; #else /* not HIDE_MOUNT_TYPE */ mnt.mnt_type = "nfs"; #endif /* not HIDE_MOUNT_TYPE */ /* some systems don't have a mount type, but a mount flag */ #ifndef HAVE_TRANSPORT_TYPE_TLI amu_get_myaddress(&localsocket.sin_addr); localsocket.sin_family = AF_INET; localsocket.sin_port = htons(nfsxprt->xp_port); #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* * Update hostname field. * Make some name prog:pid (i.e., hlfsd:174) for hostname */ sprintf(progpid_fs, "%s:%d", am_get_progname(), masterpid); /* Most kernels have a name length restriction. */ if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN) strcpy(progpid_fs + MAXHOSTNAMELEN - 3, ".."); genflags = compute_mount_flags(&mnt); retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); if (retry <= 0) retry = 1; /* XXX */ memmove(&anh.v2.fhs_fh, root_fhp, sizeof(*root_fhp)); #ifdef HAVE_TRANSPORT_TYPE_TLI compute_nfs_args(&nfs_args, &mnt, genflags, nfsncp, NULL, /* remote host IP addr is set below */ NFS_VERSION, /* version 2 */ "udp", /* XXX: shouldn't this be "udp"? */ &anh, progpid_fs, /* host name for kernel */ hostpid_fs); /* filesystem name for kernel */ /* * IMPORTANT: set the correct IP address AFTERWARDS. It cannot * be done using the normal mechanism of compute_nfs_args(), because * that one will allocate a new address and use NFS_SA_DREF() to copy * parts to it, while assuming that the ip_addr passed is always * a "struct sockaddr_in". That assumption is incorrect on TLI systems, * because they define a special macro HOST_SELF which is DIFFERENT * than localhost (127.0.0.1)! */ nfs_args.addr = &nfsxprt->xp_ltaddr; #else /* not HAVE_TRANSPORT_TYPE_TLI */ compute_nfs_args(&nfs_args, &mnt, genflags, NULL, &localsocket, NFS_VERSION, /* version 2 */ "udp", /* XXX: shouldn't this be "udp"? */ &anh, progpid_fs, /* host name for kernel */ hostpid_fs); /* filesystem name for kernel */ #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /************************************************************************* * NOTE: while compute_nfs_args() works ok for regular NFS mounts * * the toplvl one is not, and so some options must be corrected by hand * * more carefully, *after* compute_nfs_args() runs. * *************************************************************************/ compute_automounter_nfs_args(&nfs_args, &mnt); clock_valid = 0; /* invalidate logging clock */ /* * The following code could be cleverly ifdef-ed, but I duplicated the * mount_fs call three times for simplicity and readability. */ #ifdef DEBUG /* * For some reason, this mount may have to be done in the background, if I am * using -D nodebug. I suspect that the actual act of mounting requires * calling to hlfsd itself to invoke one or more of its nfs calls, to stat * /mail. That means that even if you say -D nodaemon, at least the mount * of hlfsd itself on top of /mail will be done in the background. * The other alternative I have is to run svc_run, but set a special * signal handler to perform the mount in N seconds via some alarm. * -Erez Zadok. */ amuDebug(D_DAEMON) { /* asked for -D daemon */ plog(XLOG_INFO, "parent NFS mounting hlfsd service points"); if (mount_fs2(&mnt, dir_name, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0) fatal("nfsmount: %m"); } else { /* asked for -D nodaemon */ if (fork() == 0) { /* child runs mount */
/* * Mount an automounter directory. * The automounter is connected into the system * as a user-level NFS server. amfs_mount constructs * the necessary NFS parameters to be given to the * kernel so that it will talk back to us. * * NOTE: automounter mounts in themselves are using NFS Version 2 (UDP). * * NEW: on certain systems, mounting can be done using the * kernel-level automount (autofs) support. In that case, * we don't need NFS at all here. */ int amfs_mount(am_node *mp, mntfs *mf, char *opts) { char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1]; int retry, error = 0, genflags; int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; char *dir = mf->mf_mount; mntent_t mnt; MTYPE_TYPE type; int forced_unmount = 0; /* are we using forced unmounts? */ u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher); memset(&mnt, 0, sizeof(mnt)); mnt.mnt_dir = dir; mnt.mnt_fsname = pid_fsname; mnt.mnt_opts = opts; #ifdef HAVE_FS_AUTOFS if (mf->mf_flags & MFF_IS_AUTOFS) { type = MOUNT_TYPE_AUTOFS; /* * Make sure that amd's top-level autofs mounts are hidden by default * from df. * XXX: It works ok on Linux, might not work on other systems. */ mnt.mnt_type = "autofs"; } else #endif /* HAVE_FS_AUTOFS */ { type = MOUNT_TYPE_NFS; /* * Make sure that amd's top-level NFS mounts are hidden by default * from df. * If they don't appear to support the either the "ignore" mnttab * option entry, or the "auto" one, set the mount type to "nfs". */ mnt.mnt_type = HIDE_MOUNT_TYPE; } retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); if (retry <= 0) retry = 2; /* XXX: default to 2 retries */ /* * SET MOUNT ARGS */ /* * Make a ``hostname'' string for the kernel */ xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s", get_server_pid(), am_get_hostname(), dir); /* * Most kernels have a name length restriction (64 bytes)... */ if (strlen(fs_hostname) >= MAXHOSTNAMELEN) xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..", sizeof(fs_hostname) - MAXHOSTNAMELEN + 3); #ifdef HOSTNAMESZ /* * ... and some of these restrictions are 32 bytes (HOSTNAMESZ) * If you need to get the definition for HOSTNAMESZ found, you may * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file. */ if (strlen(fs_hostname) >= HOSTNAMESZ) xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..", sizeof(fs_hostname) - HOSTNAMESZ + 3); #endif /* HOSTNAMESZ */ /* * Finally we can compute the mount genflags set above, * and add any automounter specific flags. */ genflags = compute_mount_flags(&mnt); #ifdef HAVE_FS_AUTOFS if (on_autofs) genflags |= autofs_compute_mount_flags(&mnt); #endif /* HAVE_FS_AUTOFS */ genflags |= compute_automounter_mount_flags(&mnt); again: if (!(mf->mf_flags & MFF_IS_AUTOFS)) { nfs_args_t nfs_args; am_nfs_handle_t *fhp, anh; #ifndef HAVE_TRANSPORT_TYPE_TLI u_short port; struct sockaddr_in sin; #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* * get fhandle of remote path for automount point */ fhp = get_root_nfs_fh(dir, &anh); if (!fhp) { plog(XLOG_FATAL, "Can't find root file handle for %s", dir); return EINVAL; } #ifndef HAVE_TRANSPORT_TYPE_TLI /* * Create sockaddr to point to the local machine. */ memset(&sin, 0, sizeof(sin)); /* as per POSIX, sin_len need not be set (used internally by kernel) */ sin.sin_family = AF_INET; sin.sin_addr = myipaddr; port = hasmntval(&mnt, MNTTAB_OPT_PORT); if (port) { sin.sin_port = htons(port); } else { plog(XLOG_ERROR, "no port number specified for %s", dir); return EINVAL; } #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* setup the many fields and flags within nfs_args */ #ifdef HAVE_TRANSPORT_TYPE_TLI compute_nfs_args(&nfs_args, &mnt, genflags, nfsncp, NULL, /* remote host IP addr is set below */ nfs_version, "udp", fhp, fs_hostname, pid_fsname); /* * IMPORTANT: set the correct IP address AFTERWARDS. It cannot * be done using the normal mechanism of compute_nfs_args(), because * that one will allocate a new address and use NFS_SA_DREF() to copy * parts to it, while assuming that the ip_addr passed is always * a "struct sockaddr_in". That assumption is incorrect on TLI systems, * because they define a special macro HOST_SELF which is DIFFERENT * than localhost (127.0.0.1)! */ nfs_args.addr = &nfsxprt->xp_ltaddr; #else /* not HAVE_TRANSPORT_TYPE_TLI */ compute_nfs_args(&nfs_args, &mnt, genflags, NULL, &sin, nfs_version, "udp", fhp, fs_hostname, pid_fsname); #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /************************************************************************* * NOTE: while compute_nfs_args() works ok for regular NFS mounts * * the toplvl one is not quite regular, and so some options must be * * corrected by hand more carefully, *after* compute_nfs_args() runs. * *************************************************************************/ compute_automounter_nfs_args(&nfs_args, &mnt); if (amuDebug(D_TRACE)) { print_nfs_args(&nfs_args, 0); plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags); } /* This is it! Here we try to mount amd on its mount points */ error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name, on_autofs); #ifdef HAVE_TRANSPORT_TYPE_TLI free_knetconfig(nfs_args.knconf); /* * local automounter mounts do not allocate a special address, so * no need to XFREE(nfs_args.addr) under TLI. */ #endif /* HAVE_TRANSPORT_TYPE_TLI */ #ifdef HAVE_FS_AUTOFS } else { /* This is it! Here we try to mount amd on its mount points */ error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh, retry, type, 0, NULL, mnttab_file_name, on_autofs); #endif /* HAVE_FS_AUTOFS */ } if (error == 0 || forced_unmount) return error; /* * If user wants forced/lazy unmount semantics, then try it iff the * current mount failed with EIO or ESTALE. */ if (gopt.flags & CFM_FORCED_UNMOUNTS) { switch (errno) { case ESTALE: case EIO: forced_unmount = errno; plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path); if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name, AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) { plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path); errno = forced_unmount; } else goto again; default: break; } } return error; }