17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56012a713Spetede * Common Development and Distribution License (the "License").
66012a713Spetede * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate * automount.c
237c478bd9Sstevel@tonic-gate *
24*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <ctype.h>
297c478bd9Sstevel@tonic-gate #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <locale.h>
337c478bd9Sstevel@tonic-gate #include <stdarg.h>
347c478bd9Sstevel@tonic-gate #include <errno.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <dirent.h>
377c478bd9Sstevel@tonic-gate #include <signal.h>
387c478bd9Sstevel@tonic-gate #include <syslog.h>
39*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libshare.h>
40*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include <libscf.h>
417c478bd9Sstevel@tonic-gate #include <sys/param.h>
427c478bd9Sstevel@tonic-gate #include <sys/time.h>
437c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate #include <sys/stat.h>
467c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
477c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
487c478bd9Sstevel@tonic-gate #include <sys/mount.h>
497c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
507c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
517c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
527c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h>
537c478bd9Sstevel@tonic-gate #include <nsswitch.h>
547c478bd9Sstevel@tonic-gate #include <deflt.h>
557c478bd9Sstevel@tonic-gate #include <rpcsvc/daemon_utils.h>
567c478bd9Sstevel@tonic-gate #include "automount.h"
57*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States #include "smfcfg.h"
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate static int mkdir_r(char *);
607c478bd9Sstevel@tonic-gate struct autodir *dir_head;
617c478bd9Sstevel@tonic-gate struct autodir *dir_tail;
627c478bd9Sstevel@tonic-gate static struct extmnttab *find_mount();
637c478bd9Sstevel@tonic-gate int verbose = 0;
647c478bd9Sstevel@tonic-gate int trace = 0;
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate static void usage();
677c478bd9Sstevel@tonic-gate static int compare_opts(char *, char *);
687c478bd9Sstevel@tonic-gate static void do_unmounts();
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate static int mount_timeout = AUTOFS_MOUNT_TIMEOUT;
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate static char *service_list[] = { AUTOMOUNTD, NULL };
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate * XXX
767c478bd9Sstevel@tonic-gate * The following are needed because they're used in auto_subr.c and
777c478bd9Sstevel@tonic-gate * we link with it. Should avoid this.
787c478bd9Sstevel@tonic-gate */
797c478bd9Sstevel@tonic-gate mutex_t cleanup_lock;
807c478bd9Sstevel@tonic-gate cond_t cleanup_start_cv;
817c478bd9Sstevel@tonic-gate cond_t cleanup_done_cv;
827c478bd9Sstevel@tonic-gate
8311606941Sjwahlig int
main(int argc,char * argv[])8411606941Sjwahlig main(int argc, char *argv[])
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate int c;
877c478bd9Sstevel@tonic-gate struct autofs_args ai;
887c478bd9Sstevel@tonic-gate struct utsname utsname;
897c478bd9Sstevel@tonic-gate char autofs_addr[MAXADDRLEN];
907c478bd9Sstevel@tonic-gate struct autodir *dir, *d;
917c478bd9Sstevel@tonic-gate struct stat stbuf;
927c478bd9Sstevel@tonic-gate char *master_map = "auto_master";
937c478bd9Sstevel@tonic-gate int null;
947c478bd9Sstevel@tonic-gate struct extmnttab mnt, *mntp;
957c478bd9Sstevel@tonic-gate struct mnttab *omntp;
967c478bd9Sstevel@tonic-gate char mntopts[MAX_MNTOPT_STR];
977c478bd9Sstevel@tonic-gate int mntflgs;
987c478bd9Sstevel@tonic-gate int count = 0;
997c478bd9Sstevel@tonic-gate char *stack[STACKSIZ];
1007c478bd9Sstevel@tonic-gate char **stkptr;
1017c478bd9Sstevel@tonic-gate char *defval;
1027c478bd9Sstevel@tonic-gate struct sigaction sigintact;
103*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States int ret = 0, bufsz = 0;
104*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States char valbuf[6];
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate * protect this command from session termination when run in background
1087c478bd9Sstevel@tonic-gate * we test background by whether SIGINT is ignored
1097c478bd9Sstevel@tonic-gate */
1107c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, NULL, &sigintact);
1117c478bd9Sstevel@tonic-gate if (sigintact.sa_sigaction == SIG_IGN) {
1127c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN);
1137c478bd9Sstevel@tonic-gate (void) setsid();
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate /*
117*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Read in the values from SMF first before we check
118*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * commandline options so the options override the SMF values.
1197c478bd9Sstevel@tonic-gate */
120*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States bufsz = 6;
121*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = autofs_smf_get_prop("timeout", valbuf, DEFAULT_INSTANCE,
122*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SCF_TYPE_INTEGER, AUTOMOUNTD, &bufsz);
123*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK)
124*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States /*
125*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * Ignore errno. In event of failure, mount_timeout is
126*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States * already initialized to the correct value.
127*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States */
128*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States mount_timeout = strtol(valbuf, (char **)NULL, 10);
1297c478bd9Sstevel@tonic-gate
130*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States bufsz = 6;
131*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States ret = autofs_smf_get_prop("automount_verbose", valbuf, DEFAULT_INSTANCE,
132*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States SCF_TYPE_BOOLEAN, AUTOMOUNTD, &bufsz);
133*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (ret == SA_OK) {
134*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States if (strncasecmp("true", valbuf, 4) == 0)
135*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States verbose = TRUE;
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate
138*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States put_automountd_env();
139*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States
1407c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "mM:D:f:t:v?")) != EOF) {
1417c478bd9Sstevel@tonic-gate switch (c) {
1427c478bd9Sstevel@tonic-gate case 'm':
1437c478bd9Sstevel@tonic-gate pr_msg("Warning: -m option not supported");
1447c478bd9Sstevel@tonic-gate break;
1457c478bd9Sstevel@tonic-gate case 'M':
1467c478bd9Sstevel@tonic-gate pr_msg("Warning: -M option not supported");
1477c478bd9Sstevel@tonic-gate break;
1487c478bd9Sstevel@tonic-gate case 'D':
1497c478bd9Sstevel@tonic-gate pr_msg("Warning: -D option not supported");
1507c478bd9Sstevel@tonic-gate break;
1517c478bd9Sstevel@tonic-gate case 'f':
1527c478bd9Sstevel@tonic-gate pr_msg("Error: -f option no longer supported");
1537c478bd9Sstevel@tonic-gate usage();
1547c478bd9Sstevel@tonic-gate break;
1557c478bd9Sstevel@tonic-gate case 't':
1567c478bd9Sstevel@tonic-gate if (strchr(optarg, '=')) {
1577c478bd9Sstevel@tonic-gate pr_msg("Error: invalid value for -t");
1587c478bd9Sstevel@tonic-gate usage();
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate mount_timeout = atoi(optarg);
1617c478bd9Sstevel@tonic-gate break;
1627c478bd9Sstevel@tonic-gate case 'v':
1637c478bd9Sstevel@tonic-gate verbose++;
1647c478bd9Sstevel@tonic-gate break;
1657c478bd9Sstevel@tonic-gate default:
1667c478bd9Sstevel@tonic-gate usage();
1677c478bd9Sstevel@tonic-gate break;
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate if (optind < argc) {
1727c478bd9Sstevel@tonic-gate pr_msg("%s: command line mountpoints/maps "
173*dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States "no longer supported", argv[optind]);
1747c478bd9Sstevel@tonic-gate usage();
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate current_mounts = getmntlist();
1787c478bd9Sstevel@tonic-gate if (current_mounts == NULL) {
1797c478bd9Sstevel@tonic-gate pr_msg("Couldn't establish current mounts");
1807c478bd9Sstevel@tonic-gate exit(1);
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate (void) umask(0);
1847c478bd9Sstevel@tonic-gate ns_setup(stack, &stkptr);
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate openlog("automount", LOG_PID, LOG_DAEMON);
1877c478bd9Sstevel@tonic-gate (void) loadmaster_map(master_map, "", stack, &stkptr);
1887c478bd9Sstevel@tonic-gate if (dir_head != NULL) {
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate * automount maps found. enable services as needed.
1917c478bd9Sstevel@tonic-gate */
1927c478bd9Sstevel@tonic-gate _check_services(service_list);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate closelog();
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate if (uname(&utsname) < 0) {
1987c478bd9Sstevel@tonic-gate pr_msg("uname: %m");
1997c478bd9Sstevel@tonic-gate exit(1);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate (void) strcpy(autofs_addr, utsname.nodename);
2027c478bd9Sstevel@tonic-gate (void) strcat(autofs_addr, ".autofs");
2037c478bd9Sstevel@tonic-gate ai.addr.buf = autofs_addr;
2047c478bd9Sstevel@tonic-gate ai.addr.len = strlen(ai.addr.buf);
2057c478bd9Sstevel@tonic-gate ai.addr.maxlen = ai.addr.len;
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate ai.mount_to = mount_timeout;
2087c478bd9Sstevel@tonic-gate ai.rpc_to = AUTOFS_RPC_TIMEOUT;
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate /*
2117c478bd9Sstevel@tonic-gate * Mount the daemon at its mount points.
2127c478bd9Sstevel@tonic-gate */
2137c478bd9Sstevel@tonic-gate for (dir = dir_head; dir; dir = dir->dir_next) {
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate /*
2167c478bd9Sstevel@tonic-gate * Skip null entries
2177c478bd9Sstevel@tonic-gate */
2187c478bd9Sstevel@tonic-gate if (strcmp(dir->dir_map, "-null") == 0)
2197c478bd9Sstevel@tonic-gate continue;
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate /*
2227c478bd9Sstevel@tonic-gate * Skip null'ed entries
2237c478bd9Sstevel@tonic-gate */
2247c478bd9Sstevel@tonic-gate null = 0;
2257c478bd9Sstevel@tonic-gate for (d = dir->dir_prev; d; d = d->dir_prev) {
2267c478bd9Sstevel@tonic-gate if (strcmp(dir->dir_name, d->dir_name) == 0)
2277c478bd9Sstevel@tonic-gate null = 1;
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate if (null)
2307c478bd9Sstevel@tonic-gate continue;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate /*
2337c478bd9Sstevel@tonic-gate * Check whether there's already an entry
2347c478bd9Sstevel@tonic-gate * in the mnttab for this mountpoint.
2357c478bd9Sstevel@tonic-gate */
2367c478bd9Sstevel@tonic-gate if (mntp = find_mount(dir->dir_name, 1)) {
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate * If it's not an autofs mount - don't
2397c478bd9Sstevel@tonic-gate * mount over it.
2407c478bd9Sstevel@tonic-gate */
2417c478bd9Sstevel@tonic-gate if (strcmp(mntp->mnt_fstype, MNTTYPE_AUTOFS) != 0) {
2427c478bd9Sstevel@tonic-gate pr_msg("%s: already mounted",
2437c478bd9Sstevel@tonic-gate mntp->mnt_mountp);
2447c478bd9Sstevel@tonic-gate continue;
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate /*
2487c478bd9Sstevel@tonic-gate * Compare the mnttab entry with the master map
2497c478bd9Sstevel@tonic-gate * entry. If the map or mount options are
2507c478bd9Sstevel@tonic-gate * different, then update this information
2517c478bd9Sstevel@tonic-gate * with a remount.
2527c478bd9Sstevel@tonic-gate */
2537c478bd9Sstevel@tonic-gate if (strcmp(mntp->mnt_special, dir->dir_map) == 0 &&
2547c478bd9Sstevel@tonic-gate compare_opts(dir->dir_opts,
2557c478bd9Sstevel@tonic-gate mntp->mnt_mntopts) == 0) {
2567c478bd9Sstevel@tonic-gate continue; /* no change */
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate /*
2607c478bd9Sstevel@tonic-gate * Check for an overlaid direct autofs mount.
2617c478bd9Sstevel@tonic-gate * Cannot remount since it's inaccessible.
2627c478bd9Sstevel@tonic-gate */
2637c478bd9Sstevel@tonic-gate omntp = (struct mnttab *)mntp;
2647c478bd9Sstevel@tonic-gate if (hasmntopt(omntp, "direct") != NULL) {
2657c478bd9Sstevel@tonic-gate mntp = find_mount(dir->dir_name, 0);
2667c478bd9Sstevel@tonic-gate omntp = (struct mnttab *)mntp;
2677c478bd9Sstevel@tonic-gate if (hasmntopt(omntp, "direct") == NULL) {
2687c478bd9Sstevel@tonic-gate if (verbose)
2697c478bd9Sstevel@tonic-gate pr_msg("%s: cannot remount",
2707c478bd9Sstevel@tonic-gate dir->dir_name);
2717c478bd9Sstevel@tonic-gate continue;
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate dir->dir_remount = 1;
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate * Create a mount point if necessary
2807c478bd9Sstevel@tonic-gate * If the path refers to an existing symbolic
2817c478bd9Sstevel@tonic-gate * link, refuse to mount on it. This avoids
2827c478bd9Sstevel@tonic-gate * future problems.
2837c478bd9Sstevel@tonic-gate */
2847c478bd9Sstevel@tonic-gate if (lstat(dir->dir_name, &stbuf) == 0) {
2857c478bd9Sstevel@tonic-gate if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
2867c478bd9Sstevel@tonic-gate pr_msg("%s: Not a directory", dir->dir_name);
2877c478bd9Sstevel@tonic-gate continue;
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate } else {
2907c478bd9Sstevel@tonic-gate if (mkdir_r(dir->dir_name)) {
2917c478bd9Sstevel@tonic-gate pr_msg("%s: %m", dir->dir_name);
2927c478bd9Sstevel@tonic-gate continue;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate ai.path = dir->dir_name;
2977c478bd9Sstevel@tonic-gate ai.opts = dir->dir_opts;
2987c478bd9Sstevel@tonic-gate ai.map = dir->dir_map;
2997c478bd9Sstevel@tonic-gate ai.subdir = "";
3007c478bd9Sstevel@tonic-gate ai.direct = dir->dir_direct;
3017c478bd9Sstevel@tonic-gate if (dir->dir_direct)
3027c478bd9Sstevel@tonic-gate ai.key = dir->dir_name;
3037c478bd9Sstevel@tonic-gate else
3047c478bd9Sstevel@tonic-gate ai.key = "";
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate (void) sprintf(mntopts, "ignore,%s",
3077c478bd9Sstevel@tonic-gate dir->dir_direct ? "direct" : "indirect");
3087c478bd9Sstevel@tonic-gate if (dir->dir_opts && *dir->dir_opts) {
3097c478bd9Sstevel@tonic-gate (void) strcat(mntopts, ",");
3107c478bd9Sstevel@tonic-gate (void) strcat(mntopts, dir->dir_opts);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate mntflgs = MS_OPTIONSTR | (dir->dir_remount ? MS_REMOUNT : 0);
3137c478bd9Sstevel@tonic-gate if (mount(dir->dir_map, dir->dir_name, MS_DATA | mntflgs,
3147c478bd9Sstevel@tonic-gate MNTTYPE_AUTOFS, &ai, sizeof (ai), mntopts,
3157c478bd9Sstevel@tonic-gate MAX_MNTOPT_STR) < 0) {
3167c478bd9Sstevel@tonic-gate pr_msg("mount %s: %m", dir->dir_name);
3177c478bd9Sstevel@tonic-gate continue;
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate count++;
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate if (verbose) {
3237c478bd9Sstevel@tonic-gate if (dir->dir_remount)
3247c478bd9Sstevel@tonic-gate pr_msg("%s remounted", dir->dir_name);
3257c478bd9Sstevel@tonic-gate else
3267c478bd9Sstevel@tonic-gate pr_msg("%s mounted", dir->dir_name);
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate if (verbose && count == 0)
3317c478bd9Sstevel@tonic-gate pr_msg("no mounts");
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate * Now compare the /etc/mnttab with the master
3357c478bd9Sstevel@tonic-gate * map. Any autofs mounts in the /etc/mnttab
3367c478bd9Sstevel@tonic-gate * that are not in the master map must be
3377c478bd9Sstevel@tonic-gate * unmounted
3387c478bd9Sstevel@tonic-gate */
3397c478bd9Sstevel@tonic-gate do_unmounts();
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate return (0);
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /*
3457c478bd9Sstevel@tonic-gate * Find a mount entry given
3467c478bd9Sstevel@tonic-gate * the mountpoint path.
3477c478bd9Sstevel@tonic-gate * Optionally return the first
3487c478bd9Sstevel@tonic-gate * or last entry.
3497c478bd9Sstevel@tonic-gate */
3507c478bd9Sstevel@tonic-gate static struct extmnttab *
find_mount(mntpnt,first)3517c478bd9Sstevel@tonic-gate find_mount(mntpnt, first)
3527c478bd9Sstevel@tonic-gate char *mntpnt;
3537c478bd9Sstevel@tonic-gate int first;
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate struct mntlist *mntl;
3567c478bd9Sstevel@tonic-gate struct extmnttab *found = NULL;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate for (mntl = current_mounts; mntl; mntl = mntl->mntl_next) {
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate if (strcmp(mntpnt, mntl->mntl_mnt->mnt_mountp) == 0) {
3617c478bd9Sstevel@tonic-gate found = mntl->mntl_mnt;
3627c478bd9Sstevel@tonic-gate if (first)
3637c478bd9Sstevel@tonic-gate break;
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate return (found);
3687c478bd9Sstevel@tonic-gate }
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate static char *ignore_opts[] = {"ignore", "direct", "indirect", "dev", NULL};
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate * Compare mount options
3747c478bd9Sstevel@tonic-gate * ignoring "ignore", "direct", "indirect"
3757c478bd9Sstevel@tonic-gate * and "dev=".
3767c478bd9Sstevel@tonic-gate */
3777c478bd9Sstevel@tonic-gate static int
compare_opts(opts,mntopts)3787c478bd9Sstevel@tonic-gate compare_opts(opts, mntopts)
3797c478bd9Sstevel@tonic-gate char *opts, *mntopts;
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate char optbuf1[MAX_MNTOPT_STR], *s = optbuf1;
3827c478bd9Sstevel@tonic-gate char optbuf2[MAX_MNTOPT_STR];
3837c478bd9Sstevel@tonic-gate char **opttbl1, **opttbl2;
3847c478bd9Sstevel@tonic-gate int nopts1, nopts2;
3857c478bd9Sstevel@tonic-gate char *ostart, *optr, *valp;
3867c478bd9Sstevel@tonic-gate int j, i, notsame;
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate opttbl1 = opttbl2 = NULL;
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate * Parse the two option strings to split them both into
3917c478bd9Sstevel@tonic-gate * lists of individual options.
3927c478bd9Sstevel@tonic-gate */
3937c478bd9Sstevel@tonic-gate if (mntopts != NULL)
3947c478bd9Sstevel@tonic-gate (void) strcpy(s, mntopts);
3957c478bd9Sstevel@tonic-gate else
3967c478bd9Sstevel@tonic-gate *s = '\0';
3977c478bd9Sstevel@tonic-gate if (*s != '\0')
3987c478bd9Sstevel@tonic-gate nopts1 = 1;
3997c478bd9Sstevel@tonic-gate else
4007c478bd9Sstevel@tonic-gate nopts1 = 0;
4017c478bd9Sstevel@tonic-gate for (s = strchr(s, ','); s != NULL; s = strchr(s, ',')) {
4027c478bd9Sstevel@tonic-gate nopts1++;
4037c478bd9Sstevel@tonic-gate s++;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate if (nopts1)
4067c478bd9Sstevel@tonic-gate if ((opttbl1 = memalign(sizeof (char *),
4077c478bd9Sstevel@tonic-gate nopts1 * sizeof (char *))) == NULL)
4087c478bd9Sstevel@tonic-gate return (1);
4097c478bd9Sstevel@tonic-gate nopts1 = 0;
4107c478bd9Sstevel@tonic-gate s = optbuf1;
4117c478bd9Sstevel@tonic-gate for (ostart = optr = s; *optr != '\0'; ostart = optr) {
4127c478bd9Sstevel@tonic-gate if (getsubopt(&optr, ignore_opts, &valp) == -1) {
4137c478bd9Sstevel@tonic-gate opttbl1[nopts1++] = ostart;
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate s = optbuf2;
4177c478bd9Sstevel@tonic-gate if (opts != NULL)
4187c478bd9Sstevel@tonic-gate (void) strcpy(s, opts);
4197c478bd9Sstevel@tonic-gate else
4207c478bd9Sstevel@tonic-gate *s = '\0';
4217c478bd9Sstevel@tonic-gate if (*s != '\0')
4227c478bd9Sstevel@tonic-gate nopts2 = 1;
4237c478bd9Sstevel@tonic-gate else
4247c478bd9Sstevel@tonic-gate nopts2 = 0;
4257c478bd9Sstevel@tonic-gate for (s = strchr(s, ','); s != NULL; s = strchr(s, ',')) {
4267c478bd9Sstevel@tonic-gate nopts2++;
4277c478bd9Sstevel@tonic-gate s++;
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate if (nopts2)
4307c478bd9Sstevel@tonic-gate if ((opttbl2 = memalign(sizeof (char *),
4317c478bd9Sstevel@tonic-gate nopts2 * sizeof (char *))) == NULL) {
4327c478bd9Sstevel@tonic-gate notsame = 1;
4337c478bd9Sstevel@tonic-gate goto done;
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate nopts2 = 0;
4367c478bd9Sstevel@tonic-gate s = optbuf2;
4377c478bd9Sstevel@tonic-gate for (ostart = optr = s; *optr != '\0'; ostart = optr) {
4387c478bd9Sstevel@tonic-gate if (getsubopt(&optr, ignore_opts, &valp) == -1) {
4397c478bd9Sstevel@tonic-gate opttbl2[nopts2++] = ostart;
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate if (nopts2 != nopts1) {
4437c478bd9Sstevel@tonic-gate notsame = 1;
4447c478bd9Sstevel@tonic-gate goto done;
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate notsame = 0;
4477c478bd9Sstevel@tonic-gate for (i = 0; i < nopts1; i++) {
4487c478bd9Sstevel@tonic-gate notsame = 1;
4497c478bd9Sstevel@tonic-gate for (j = 0; j < nopts2; j++) {
4507c478bd9Sstevel@tonic-gate if (strcmp(opttbl1[i], opttbl2[j]) == 0) {
4517c478bd9Sstevel@tonic-gate notsame = 0;
4527c478bd9Sstevel@tonic-gate break;
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate if (notsame)
4567c478bd9Sstevel@tonic-gate break;
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate done:
4607c478bd9Sstevel@tonic-gate if (opttbl1 != NULL)
4617c478bd9Sstevel@tonic-gate free(opttbl1);
4627c478bd9Sstevel@tonic-gate if (opttbl2 != NULL)
4637c478bd9Sstevel@tonic-gate free(opttbl2);
4647c478bd9Sstevel@tonic-gate return (notsame);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate static void
usage()4687c478bd9Sstevel@tonic-gate usage()
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate pr_msg("Usage: automount [ -v ] [ -t duration ]");
4717c478bd9Sstevel@tonic-gate exit(1);
4727c478bd9Sstevel@tonic-gate /* NOTREACHED */
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate /*
4767c478bd9Sstevel@tonic-gate * Unmount any autofs mounts that
4777c478bd9Sstevel@tonic-gate * aren't in the master map
4787c478bd9Sstevel@tonic-gate */
4797c478bd9Sstevel@tonic-gate static void
do_unmounts()4807c478bd9Sstevel@tonic-gate do_unmounts()
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate struct mntlist *mntl;
4837c478bd9Sstevel@tonic-gate struct extmnttab *mnt;
4847c478bd9Sstevel@tonic-gate struct mnttab *omnt;
4857c478bd9Sstevel@tonic-gate struct autodir *dir;
4867c478bd9Sstevel@tonic-gate int current;
4877c478bd9Sstevel@tonic-gate int count = 0;
4887c478bd9Sstevel@tonic-gate struct zone_summary *zsp;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate zsp = fs_get_zone_summaries();
4917c478bd9Sstevel@tonic-gate if (zsp == NULL) {
4927c478bd9Sstevel@tonic-gate pr_msg("Couldn't establish active zones");
4937c478bd9Sstevel@tonic-gate exit(1);
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate for (mntl = current_mounts; mntl; mntl = mntl->mntl_next) {
4967c478bd9Sstevel@tonic-gate mnt = mntl->mntl_mnt;
4977c478bd9Sstevel@tonic-gate omnt = (struct mnttab *)mnt;
4987c478bd9Sstevel@tonic-gate if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS) != 0)
4997c478bd9Sstevel@tonic-gate continue;
5007c478bd9Sstevel@tonic-gate if (fs_mount_in_other_zone(zsp, mnt->mnt_mountp))
5017c478bd9Sstevel@tonic-gate continue;
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate * Don't unmount autofs mounts done
5047c478bd9Sstevel@tonic-gate * from the autofs mount command.
5057c478bd9Sstevel@tonic-gate * How do we tell them apart ?
5067c478bd9Sstevel@tonic-gate * Autofs mounts not eligible for auto-unmount
5077c478bd9Sstevel@tonic-gate * have the "nest" pseudo-option.
5087c478bd9Sstevel@tonic-gate */
5097c478bd9Sstevel@tonic-gate if (hasmntopt(omnt, "nest") != NULL)
5107c478bd9Sstevel@tonic-gate continue;
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate current = 0;
5137c478bd9Sstevel@tonic-gate for (dir = dir_head; dir; dir = dir->dir_next) {
5147c478bd9Sstevel@tonic-gate if (strcmp(dir->dir_name, mnt->mnt_mountp) == 0) {
5157c478bd9Sstevel@tonic-gate current = strcmp(dir->dir_map, "-null");
5167c478bd9Sstevel@tonic-gate break;
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate if (current)
5207c478bd9Sstevel@tonic-gate continue;
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate if (umount(mnt->mnt_mountp) == 0) {
5247c478bd9Sstevel@tonic-gate if (verbose) {
5257c478bd9Sstevel@tonic-gate pr_msg("%s unmounted",
5267c478bd9Sstevel@tonic-gate mnt->mnt_mountp);
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate count++;
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate if (verbose && count == 0)
5327c478bd9Sstevel@tonic-gate pr_msg("no unmounts");
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate static int
mkdir_r(dir)5367c478bd9Sstevel@tonic-gate mkdir_r(dir)
5377c478bd9Sstevel@tonic-gate char *dir;
5387c478bd9Sstevel@tonic-gate {
5397c478bd9Sstevel@tonic-gate int err;
5407c478bd9Sstevel@tonic-gate char *slash;
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate if (mkdir(dir, 0555) == 0 || errno == EEXIST)
5437c478bd9Sstevel@tonic-gate return (0);
5447c478bd9Sstevel@tonic-gate if (errno != ENOENT)
5457c478bd9Sstevel@tonic-gate return (-1);
5467c478bd9Sstevel@tonic-gate slash = strrchr(dir, '/');
5477c478bd9Sstevel@tonic-gate if (slash == NULL)
5487c478bd9Sstevel@tonic-gate return (-1);
5497c478bd9Sstevel@tonic-gate *slash = '\0';
5507c478bd9Sstevel@tonic-gate err = mkdir_r(dir);
5517c478bd9Sstevel@tonic-gate *slash++ = '/';
5527c478bd9Sstevel@tonic-gate if (err || !*slash)
5537c478bd9Sstevel@tonic-gate return (err);
5547c478bd9Sstevel@tonic-gate return (mkdir(dir, 0555));
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate /*
5587c478bd9Sstevel@tonic-gate * Print an error.
5597c478bd9Sstevel@tonic-gate * Works like printf (fmt string and variable args)
5607c478bd9Sstevel@tonic-gate * except that it will subsititute an error message
5617c478bd9Sstevel@tonic-gate * for a "%m" string (like syslog).
5627c478bd9Sstevel@tonic-gate */
5637c478bd9Sstevel@tonic-gate /* VARARGS1 */
5647c478bd9Sstevel@tonic-gate void
pr_msg(const char * fmt,...)5657c478bd9Sstevel@tonic-gate pr_msg(const char *fmt, ...)
5667c478bd9Sstevel@tonic-gate {
5677c478bd9Sstevel@tonic-gate va_list ap;
5687c478bd9Sstevel@tonic-gate char buf[BUFSIZ], *p2;
5697c478bd9Sstevel@tonic-gate char *p1;
5707c478bd9Sstevel@tonic-gate char *nfmt;
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate (void) strcpy(buf, "automount: ");
5737c478bd9Sstevel@tonic-gate p2 = buf + strlen(buf);
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate nfmt = gettext(fmt);
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate for (p1 = nfmt; *p1; p1++) {
5787c478bd9Sstevel@tonic-gate if (*p1 == '%' && *(p1+1) == 'm') {
579ace1a5f1Sdp (void) strcpy(p2, strerror(errno));
5807c478bd9Sstevel@tonic-gate p2 += strlen(p2);
5817c478bd9Sstevel@tonic-gate p1++;
5827c478bd9Sstevel@tonic-gate } else {
5837c478bd9Sstevel@tonic-gate *p2++ = *p1;
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate if (p2 > buf && *(p2-1) != '\n')
5877c478bd9Sstevel@tonic-gate *p2++ = '\n';
5887c478bd9Sstevel@tonic-gate *p2 = '\0';
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate va_start(ap, fmt);
5917c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, buf, ap);
5927c478bd9Sstevel@tonic-gate va_end(ap);
5937c478bd9Sstevel@tonic-gate }
594