10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51914Scasper * Common Development and Distribution License (the "License"). 61914Scasper * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 220Sstevel@tonic-gate /* All Rights Reserved */ 230Sstevel@tonic-gate 240Sstevel@tonic-gate 250Sstevel@tonic-gate /* 266007Sthurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 270Sstevel@tonic-gate * Use is subject to license terms. 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <stdio.h> 311914Scasper #include <stdio_ext.h> 320Sstevel@tonic-gate #include <limits.h> 330Sstevel@tonic-gate #include <fcntl.h> 340Sstevel@tonic-gate #include <unistd.h> 350Sstevel@tonic-gate #include <stdlib.h> 360Sstevel@tonic-gate #include <string.h> 370Sstevel@tonic-gate #include <stdarg.h> 380Sstevel@tonic-gate #include <sys/types.h> 390Sstevel@tonic-gate #include <sys/stat.h> 400Sstevel@tonic-gate #include <sys/statvfs.h> 410Sstevel@tonic-gate #include <errno.h> 420Sstevel@tonic-gate #include <sys/mnttab.h> 430Sstevel@tonic-gate #include <sys/mntent.h> 440Sstevel@tonic-gate #include <sys/mount.h> 450Sstevel@tonic-gate #include <sys/vfstab.h> 460Sstevel@tonic-gate #include <sys/param.h> 470Sstevel@tonic-gate #include <sys/wait.h> 480Sstevel@tonic-gate #include <sys/signal.h> 490Sstevel@tonic-gate #include <sys/resource.h> 500Sstevel@tonic-gate #include <stropts.h> 510Sstevel@tonic-gate #include <sys/conf.h> 520Sstevel@tonic-gate #include <locale.h> 530Sstevel@tonic-gate #include "fslib.h" 540Sstevel@tonic-gate 550Sstevel@tonic-gate #define VFS_PATH "/usr/lib/fs" 560Sstevel@tonic-gate #define ALT_PATH "/etc/fs" 570Sstevel@tonic-gate #define REMOTE "/etc/dfs/fstypes" 580Sstevel@tonic-gate 590Sstevel@tonic-gate #define ARGV_MAX 16 600Sstevel@tonic-gate #define TIME_MAX 50 610Sstevel@tonic-gate #define FSTYPE_MAX 8 620Sstevel@tonic-gate #define REMOTE_MAX 64 630Sstevel@tonic-gate 640Sstevel@tonic-gate #define OLD 0 650Sstevel@tonic-gate #define NEW 1 660Sstevel@tonic-gate 670Sstevel@tonic-gate #define READONLY 0 680Sstevel@tonic-gate #define READWRITE 1 690Sstevel@tonic-gate #define SUID 2 700Sstevel@tonic-gate #define NOSUID 3 710Sstevel@tonic-gate #define SETUID 4 720Sstevel@tonic-gate #define NOSETUID 5 730Sstevel@tonic-gate #define DEVICES 6 740Sstevel@tonic-gate #define NODEVICES 7 750Sstevel@tonic-gate 760Sstevel@tonic-gate #define FORMAT "%a %b %e %H:%M:%S %Y\n" /* date time format */ 770Sstevel@tonic-gate /* a - abbreviated weekday name */ 780Sstevel@tonic-gate /* b - abbreviated month name */ 790Sstevel@tonic-gate /* e - day of month */ 800Sstevel@tonic-gate /* H - hour */ 810Sstevel@tonic-gate /* M - minute */ 820Sstevel@tonic-gate /* S - second */ 830Sstevel@tonic-gate /* Y - Year */ 840Sstevel@tonic-gate /* n - newline */ 850Sstevel@tonic-gate 86*8155STim.Haley@Sun.COM /* 87*8155STim.Haley@Sun.COM * The fs-local method understands this exit code to mean that one or 88*8155STim.Haley@Sun.COM * more failures occurred and that all the failures were of attempted 89*8155STim.Haley@Sun.COM * lofs mounts. 90*8155STim.Haley@Sun.COM */ 91*8155STim.Haley@Sun.COM #define ALL_LOFS_FAILURES 111 92*8155STim.Haley@Sun.COM 930Sstevel@tonic-gate extern int optind; 940Sstevel@tonic-gate extern char *optarg; 950Sstevel@tonic-gate 960Sstevel@tonic-gate extern void usage(void); 970Sstevel@tonic-gate extern char *flags(char *, int); 980Sstevel@tonic-gate extern char *remote(char *, FILE *); 990Sstevel@tonic-gate extern char *default_fstype(char *); 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate char *myopts[] = { 1020Sstevel@tonic-gate MNTOPT_RO, 1030Sstevel@tonic-gate MNTOPT_RW, 1040Sstevel@tonic-gate MNTOPT_SUID, 1050Sstevel@tonic-gate MNTOPT_NOSUID, 1060Sstevel@tonic-gate MNTOPT_SETUID, 1070Sstevel@tonic-gate MNTOPT_NOSETUID, 1080Sstevel@tonic-gate MNTOPT_DEVICES, 1090Sstevel@tonic-gate MNTOPT_NODEVICES, 1100Sstevel@tonic-gate NULL 1110Sstevel@tonic-gate }; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate static char *myname; /* point to argv[0] */ 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* 1160Sstevel@tonic-gate * Set the limit to double the number of characters a user should be allowed to 1170Sstevel@tonic-gate * type in one line. 1180Sstevel@tonic-gate * This should cover the different shells, which don't use POSIX_MAX_INPUT, 1190Sstevel@tonic-gate * and should cover the case where a long option string can be in 1200Sstevel@tonic-gate * the /etc/vfstab file. 1210Sstevel@tonic-gate */ 1220Sstevel@tonic-gate char mntflags[(_POSIX_MAX_INPUT+1) * 2]; 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate char realdir[MAXPATHLEN]; /* buffer for realpath() calls */ 1250Sstevel@tonic-gate char *vfstab = VFSTAB; 1260Sstevel@tonic-gate char *mnttab = MNTTAB; 1270Sstevel@tonic-gate char *specific_opts; /* holds specific mount options */ 1280Sstevel@tonic-gate char *generic_opts; /* holds generic mount options */ 1290Sstevel@tonic-gate int maxrun; 1300Sstevel@tonic-gate int nrun; 131*8155STim.Haley@Sun.COM int failcnt; /* total count of failures */ 1320Sstevel@tonic-gate int lofscnt; /* presence of lofs prohibits parallel */ 1330Sstevel@tonic-gate /* mounting */ 134*8155STim.Haley@Sun.COM int lofsfail; /* count of failures of lofs mounts */ 1350Sstevel@tonic-gate int exitcode; 1360Sstevel@tonic-gate int aflg, cflg, fflg, Fflg, gflg, oflg, pflg, rflg, vflg, Vflg, mflg, Oflg, 1370Sstevel@tonic-gate dashflg, questflg, dflg, qflg; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate /* 1400Sstevel@tonic-gate * Currently, mounting cachefs instances simultaneously uncovers various 1410Sstevel@tonic-gate * problems. For the short term, we serialize cachefs activity while we fix 1420Sstevel@tonic-gate * these cachefs bugs. 1430Sstevel@tonic-gate */ 1440Sstevel@tonic-gate #define CACHEFS_BUG 1450Sstevel@tonic-gate #ifdef CACHEFS_BUG 1460Sstevel@tonic-gate int cachefs_running; /* parallel cachefs not supported yet */ 1470Sstevel@tonic-gate #endif 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * Each vfsent_t describes a vfstab entry. It is used to manage and cleanup 1510Sstevel@tonic-gate * each child that performs the particular mount for the entry. 1520Sstevel@tonic-gate */ 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate typedef struct vfsent { 1550Sstevel@tonic-gate struct vfstab v; /* the vfstab entry */ 1560Sstevel@tonic-gate char *rpath; /* resolved pathname so far */ 1570Sstevel@tonic-gate int mlevel; /* how deep is this mount point */ 1580Sstevel@tonic-gate int order; /* vfstab serial order of this vfs */ 1590Sstevel@tonic-gate int flag; 1600Sstevel@tonic-gate pid_t pid; /* the pid of this mount process */ 1610Sstevel@tonic-gate int exitcode; /* process's exitcode */ 1620Sstevel@tonic-gate #define RDPIPE 0 1630Sstevel@tonic-gate #define WRPIPE 1 1640Sstevel@tonic-gate int sopipe[2]; /* pipe attached to child's stdout */ 1650Sstevel@tonic-gate int sepipe[2]; /* pipe attached to child's stderr */ 1660Sstevel@tonic-gate struct vfsent *next; /* used when in linked list */ 1670Sstevel@tonic-gate } vfsent_t; 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate #define VRPFAILED 0x01 /* most recent realpath failed on */ 1700Sstevel@tonic-gate /* this mount point */ 1710Sstevel@tonic-gate #define VNOTMOUNTED 0x02 /* mount point could not be mounted */ 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate vfsent_t *vfsll, *vfslltail; /* head and tail of the global */ 1740Sstevel@tonic-gate /* linked list of vfstab entries */ 1750Sstevel@tonic-gate vfsent_t **vfsarray; /* global array of vfsent_t's */ 1760Sstevel@tonic-gate int vfsarraysize; /* length of the list */ 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate /* 1790Sstevel@tonic-gate * This structure is used to build a linked list of 1800Sstevel@tonic-gate * mnttab structures from /etc/mnttab. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate typedef struct mountent { 1830Sstevel@tonic-gate struct extmnttab *ment; 1840Sstevel@tonic-gate int flag; 1850Sstevel@tonic-gate struct mountent *next; 1860Sstevel@tonic-gate } mountent_t; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate #define MSORTED 0x1 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate static vfsent_t **make_vfsarray(char **, int); 1910Sstevel@tonic-gate static vfsent_t *new_vfsent(struct vfstab *, int); 1920Sstevel@tonic-gate static vfsent_t *getvfsall(char *, int); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate static void doexec(char *, char **); 1950Sstevel@tonic-gate static void nomem(); 1960Sstevel@tonic-gate static void cleanup(int); 1970Sstevel@tonic-gate static char *setrpath(vfsent_t *); 1980Sstevel@tonic-gate static int dowait(); 1990Sstevel@tonic-gate static int setup_iopipe(vfsent_t *); 2000Sstevel@tonic-gate static void setup_output(vfsent_t *); 2010Sstevel@tonic-gate static void doio(vfsent_t *); 2020Sstevel@tonic-gate static void do_mounts(); 2030Sstevel@tonic-gate static int parmount(char **, int, char *); 2040Sstevel@tonic-gate static int mlevelcmp(const void *, const void *); 2050Sstevel@tonic-gate static int mordercmp(const void *, const void *); 2060Sstevel@tonic-gate static int check_fields(char *, char *); 2070Sstevel@tonic-gate static int cleanupkid(pid_t, int); 2080Sstevel@tonic-gate static void print_mnttab(int, int); 2090Sstevel@tonic-gate static void vfserror(int, char *); 2100Sstevel@tonic-gate static void mnterror(int); 2110Sstevel@tonic-gate static int ignore(char *); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate /* 2140Sstevel@tonic-gate * This is /usr/sbin/mount: the generic command that in turn 2150Sstevel@tonic-gate * execs the appropriate /usr/lib/fs/{fstype}/mount. 2160Sstevel@tonic-gate * The -F flag and argument are NOT passed. 2170Sstevel@tonic-gate * If the usr file system is not mounted a duplicate copy 2180Sstevel@tonic-gate * can be found in /sbin and this version execs the 2190Sstevel@tonic-gate * appropriate /etc/fs/{fstype}/mount 2200Sstevel@tonic-gate * 2210Sstevel@tonic-gate * If the -F fstype, special or directory are missing, 2220Sstevel@tonic-gate * /etc/vfstab is searched to fill in the missing arguments. 2230Sstevel@tonic-gate * 2240Sstevel@tonic-gate * -V will print the built command on the stdout. 2250Sstevel@tonic-gate * It isn't passed either. 2260Sstevel@tonic-gate */ 227821Sdh145677 int 228821Sdh145677 main(int argc, char *argv[]) 2290Sstevel@tonic-gate { 2306007Sthurlow char *special, /* argument of special/resource */ 2316007Sthurlow *mountp, /* argument of mount directory */ 2326007Sthurlow *fstype, /* wherein the fstype name is filled */ 2336007Sthurlow *newargv[ARGV_MAX], /* arg list for specific command */ 2346007Sthurlow *farg = NULL, *Farg = NULL; 2350Sstevel@tonic-gate int ii, ret, cc, fscnt; 2360Sstevel@tonic-gate struct stat64 stbuf; 2370Sstevel@tonic-gate struct vfstab vget, vref; 2380Sstevel@tonic-gate mode_t mode; 2390Sstevel@tonic-gate FILE *fd; 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 2440Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 2450Sstevel@tonic-gate #endif 2460Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate myname = strrchr(argv[0], '/'); 2490Sstevel@tonic-gate if (myname) 2500Sstevel@tonic-gate myname++; 2510Sstevel@tonic-gate else 2520Sstevel@tonic-gate myname = argv[0]; 2530Sstevel@tonic-gate if (myname == 0) myname = "path unknown"; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* Process the args. */ 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate while ((cc = getopt(argc, argv, "?acd:f:F:gmno:pqrvVO")) != -1) 2580Sstevel@tonic-gate switch (cc) { 2590Sstevel@tonic-gate case 'a': 2600Sstevel@tonic-gate aflg++; 2610Sstevel@tonic-gate break; 2620Sstevel@tonic-gate case 'c': 2630Sstevel@tonic-gate cflg++; 2640Sstevel@tonic-gate break; 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate #ifdef DEBUG 2670Sstevel@tonic-gate case 'd': 2680Sstevel@tonic-gate dflg = atoi(optarg); 2690Sstevel@tonic-gate break; 2700Sstevel@tonic-gate #endif 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate case 'f': 2730Sstevel@tonic-gate fflg++; 2740Sstevel@tonic-gate farg = optarg; 2750Sstevel@tonic-gate break; 2760Sstevel@tonic-gate case 'F': 2770Sstevel@tonic-gate Fflg++; 2780Sstevel@tonic-gate Farg = optarg; 2790Sstevel@tonic-gate break; 2800Sstevel@tonic-gate case 'g': 2810Sstevel@tonic-gate gflg++; 2820Sstevel@tonic-gate break; 2830Sstevel@tonic-gate case 'm': 2840Sstevel@tonic-gate mflg++; 2850Sstevel@tonic-gate break; /* do not update /etc/mnttab */ 2860Sstevel@tonic-gate case 'o': 2870Sstevel@tonic-gate oflg++; 2880Sstevel@tonic-gate if ((specific_opts = strdup(optarg)) == NULL) 2890Sstevel@tonic-gate nomem(); 2900Sstevel@tonic-gate break; /* fstype dependent options */ 2910Sstevel@tonic-gate case 'O': 2920Sstevel@tonic-gate Oflg++; 2930Sstevel@tonic-gate break; 2940Sstevel@tonic-gate case 'p': 2950Sstevel@tonic-gate pflg++; 2960Sstevel@tonic-gate break; 2970Sstevel@tonic-gate case 'q': 2980Sstevel@tonic-gate qflg++; 2990Sstevel@tonic-gate break; 3000Sstevel@tonic-gate case 'r': 3010Sstevel@tonic-gate rflg++; 3020Sstevel@tonic-gate generic_opts = "ro"; 3030Sstevel@tonic-gate break; 3040Sstevel@tonic-gate case 'v': 3050Sstevel@tonic-gate vflg++; 3060Sstevel@tonic-gate break; 3070Sstevel@tonic-gate case 'V': 3080Sstevel@tonic-gate Vflg++; 3090Sstevel@tonic-gate break; 3100Sstevel@tonic-gate case '?': 3110Sstevel@tonic-gate questflg++; 3120Sstevel@tonic-gate break; 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate /* copy '--' to specific */ 3160Sstevel@tonic-gate if (strcmp(argv[optind-1], "--") == 0) 3170Sstevel@tonic-gate dashflg++; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* option checking */ 3200Sstevel@tonic-gate /* more than two args not allowed if !aflg */ 3210Sstevel@tonic-gate if (!aflg && (argc - optind > 2)) 3220Sstevel@tonic-gate usage(); 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate /* pv mututally exclusive */ 3250Sstevel@tonic-gate if (pflg + vflg + aflg > 1) { 3260Sstevel@tonic-gate fprintf(stderr, gettext 3276007Sthurlow ("%s: -a, -p, and -v are mutually exclusive\n"), 3286007Sthurlow myname); 3290Sstevel@tonic-gate usage(); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate /* 3330Sstevel@tonic-gate * Can't have overlaying mounts on the same mount point during 3340Sstevel@tonic-gate * a parallel mount. 3350Sstevel@tonic-gate */ 3360Sstevel@tonic-gate if (aflg && Oflg) { 3370Sstevel@tonic-gate fprintf(stderr, gettext 3386007Sthurlow ("%s: -a and -O are mutually exclusive\n"), myname); 3390Sstevel@tonic-gate usage(); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate /* dfF mutually exclusive */ 3430Sstevel@tonic-gate if (fflg + Fflg > 1) { 3440Sstevel@tonic-gate fprintf(stderr, gettext 3456007Sthurlow ("%s: More than one FSType specified\n"), myname); 3460Sstevel@tonic-gate usage(); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate /* no arguments, only allow p,v,V or [F]? */ 3500Sstevel@tonic-gate if (!aflg && optind == argc) { 3510Sstevel@tonic-gate if (cflg || fflg || mflg || oflg || rflg || qflg) 3520Sstevel@tonic-gate usage(); 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate if (Fflg && !questflg) 3550Sstevel@tonic-gate usage(); 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate if (questflg) { 3580Sstevel@tonic-gate if (Fflg) { 3590Sstevel@tonic-gate newargv[2] = "-?"; 3600Sstevel@tonic-gate newargv[3] = NULL; 3610Sstevel@tonic-gate doexec(Farg, newargv); 3620Sstevel@tonic-gate } 3630Sstevel@tonic-gate usage(); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate if (questflg) 3680Sstevel@tonic-gate usage(); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate /* one or two args, allow any but p,v */ 3710Sstevel@tonic-gate if (optind != argc && (pflg || vflg)) { 3720Sstevel@tonic-gate fprintf(stderr, 3730Sstevel@tonic-gate gettext("%s: Cannot use -p and -v with arguments\n"), myname); 3740Sstevel@tonic-gate usage(); 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate /* if only reporting mnttab, generic prints mnttab and exits */ 3790Sstevel@tonic-gate if (!aflg && optind == argc) { 3800Sstevel@tonic-gate if (Vflg) { 3810Sstevel@tonic-gate printf("%s", myname); 3820Sstevel@tonic-gate if (pflg) 3830Sstevel@tonic-gate printf(" -p"); 3840Sstevel@tonic-gate if (vflg) 3850Sstevel@tonic-gate printf(" -v"); 3860Sstevel@tonic-gate printf("\n"); 3870Sstevel@tonic-gate exit(0); 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate print_mnttab(vflg, pflg); 3910Sstevel@tonic-gate exit(0); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate /* 3950Sstevel@tonic-gate * Get filesystem type here. If "-F FStype" is specified, use 3960Sstevel@tonic-gate * that fs type. Otherwise, determine the fs type from /etc/vfstab 3970Sstevel@tonic-gate * if the entry exists. Otherwise, determine the local or remote 3980Sstevel@tonic-gate * fs type from /etc/default/df or /etc/dfs/fstypes respectively. 3990Sstevel@tonic-gate */ 4000Sstevel@tonic-gate if (fflg) { 4010Sstevel@tonic-gate if ((strcmp(farg, "S51K") != 0) && 4020Sstevel@tonic-gate (strcmp(farg, "S52K") != 0)) { 4030Sstevel@tonic-gate fstype = farg; 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate else 4060Sstevel@tonic-gate fstype = "ufs"; 4070Sstevel@tonic-gate } else /* if (Fflg) */ 4080Sstevel@tonic-gate fstype = Farg; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate fscnt = argc - optind; 4110Sstevel@tonic-gate if (aflg && (fscnt != 1)) 4120Sstevel@tonic-gate exit(parmount(argv + optind, fscnt, fstype)); 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate /* 4150Sstevel@tonic-gate * Then don't bother with the parallel over head. Everything 4160Sstevel@tonic-gate * from this point is simple/normal single execution. 4170Sstevel@tonic-gate */ 4180Sstevel@tonic-gate aflg = 0; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate /* get special and/or mount-point from arg(s) */ 4210Sstevel@tonic-gate if (fscnt == 2) 4220Sstevel@tonic-gate special = argv[optind++]; 4230Sstevel@tonic-gate else 4240Sstevel@tonic-gate special = NULL; 4250Sstevel@tonic-gate if (optind < argc) 4260Sstevel@tonic-gate mountp = argv[optind++]; 4270Sstevel@tonic-gate else 4280Sstevel@tonic-gate mountp = NULL; 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate /* lookup only if we need to */ 4310Sstevel@tonic-gate if (fstype == NULL || specific_opts == NULL || special == NULL || 4320Sstevel@tonic-gate mountp == NULL) { 4330Sstevel@tonic-gate if ((fd = fopen(vfstab, "r")) == NULL) { 4340Sstevel@tonic-gate if (fstype == NULL || special == NULL || 4356007Sthurlow mountp == NULL) { 4360Sstevel@tonic-gate fprintf(stderr, gettext( 4376007Sthurlow "%s: Cannot open %s\n"), 4386007Sthurlow myname, vfstab); 4390Sstevel@tonic-gate exit(1); 4400Sstevel@tonic-gate } else { 4410Sstevel@tonic-gate /* 4420Sstevel@tonic-gate * No vfstab, but we know what we want 4430Sstevel@tonic-gate * to mount. 4440Sstevel@tonic-gate */ 4450Sstevel@tonic-gate goto out; 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate vfsnull(&vref); 4490Sstevel@tonic-gate vref.vfs_special = special; 4500Sstevel@tonic-gate vref.vfs_mountp = mountp; 4510Sstevel@tonic-gate vref.vfs_fstype = fstype; 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /* get a vfstab entry matching mountp or special */ 4540Sstevel@tonic-gate while ((ret = getvfsany(fd, &vget, &vref)) > 0) 4550Sstevel@tonic-gate vfserror(ret, vget.vfs_special); 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate /* if no entry and there was only one argument */ 4580Sstevel@tonic-gate /* then the argument could be the special */ 4590Sstevel@tonic-gate /* and not mount point as we thought earlier */ 4600Sstevel@tonic-gate if (ret == -1 && special == NULL) { 4610Sstevel@tonic-gate rewind(fd); 4620Sstevel@tonic-gate special = vref.vfs_special = mountp; 4630Sstevel@tonic-gate mountp = vref.vfs_mountp = NULL; 4640Sstevel@tonic-gate /* skip erroneous lines; they were reported above */ 4656007Sthurlow while ((ret = getvfsany(fd, &vget, &vref)) > 0) 4666007Sthurlow ; 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate fclose(fd); 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate if (ret == 0) { 4720Sstevel@tonic-gate if (fstype == NULL) 4730Sstevel@tonic-gate fstype = vget.vfs_fstype; 4740Sstevel@tonic-gate if (special == NULL) 4750Sstevel@tonic-gate special = vget.vfs_special; 4760Sstevel@tonic-gate if (mountp == NULL) 4770Sstevel@tonic-gate mountp = vget.vfs_mountp; 4780Sstevel@tonic-gate if (oflg == 0 && vget.vfs_mntopts) { 4790Sstevel@tonic-gate oflg++; 4800Sstevel@tonic-gate specific_opts = vget.vfs_mntopts; 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate } else if (special == NULL) { 4830Sstevel@tonic-gate if (stat64(mountp, &stbuf) == -1) { 4840Sstevel@tonic-gate fprintf(stderr, gettext("%s: cannot stat %s\n"), 4856007Sthurlow myname, mountp); 4860Sstevel@tonic-gate exit(2); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate if (((mode = (stbuf.st_mode & S_IFMT)) == S_IFBLK) || 4896007Sthurlow (mode == S_IFCHR)) { 4900Sstevel@tonic-gate fprintf(stderr, 4910Sstevel@tonic-gate gettext("%s: mount point cannot be determined\n"), 4926007Sthurlow myname); 4930Sstevel@tonic-gate exit(1); 4940Sstevel@tonic-gate } else 4950Sstevel@tonic-gate { 4960Sstevel@tonic-gate fprintf(stderr, 4970Sstevel@tonic-gate gettext("%s: special cannot be determined\n"), 4986007Sthurlow myname); 4990Sstevel@tonic-gate exit(1); 5000Sstevel@tonic-gate } 5010Sstevel@tonic-gate } else if (fstype == NULL) 5020Sstevel@tonic-gate fstype = default_fstype(special); 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate out: 5060Sstevel@tonic-gate if (check_fields(fstype, mountp)) 5070Sstevel@tonic-gate exit(1); 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate if (realpath(mountp, realdir) == NULL) { 5100Sstevel@tonic-gate (void) fprintf(stderr, "mount: "); 5110Sstevel@tonic-gate perror(mountp); 5120Sstevel@tonic-gate exit(1); 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate if ((mountp = strdup(realdir)) == NULL) 5160Sstevel@tonic-gate nomem(); 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate /* create the new arg list, and end the list with a null pointer */ 5190Sstevel@tonic-gate ii = 2; 5200Sstevel@tonic-gate if (cflg) 5210Sstevel@tonic-gate newargv[ii++] = "-c"; 5220Sstevel@tonic-gate if (gflg) 5230Sstevel@tonic-gate newargv[ii++] = "-g"; 5240Sstevel@tonic-gate if (mflg) 5250Sstevel@tonic-gate newargv[ii++] = "-m"; 5260Sstevel@tonic-gate /* 5270Sstevel@tonic-gate * The q option needs to go before the -o option as some 5280Sstevel@tonic-gate * filesystems complain during first pass option parsing. 5290Sstevel@tonic-gate */ 5300Sstevel@tonic-gate if (qflg) 5310Sstevel@tonic-gate newargv[ii++] = "-q"; 5320Sstevel@tonic-gate if (oflg) { 5330Sstevel@tonic-gate newargv[ii++] = "-o"; 5340Sstevel@tonic-gate newargv[ii++] = specific_opts; 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate if (Oflg) 5370Sstevel@tonic-gate newargv[ii++] = "-O"; 5380Sstevel@tonic-gate if (rflg) 5390Sstevel@tonic-gate newargv[ii++] = "-r"; 5400Sstevel@tonic-gate if (dashflg) 5410Sstevel@tonic-gate newargv[ii++] = "--"; 5420Sstevel@tonic-gate newargv[ii++] = special; 5430Sstevel@tonic-gate newargv[ii++] = mountp; 5440Sstevel@tonic-gate newargv[ii] = NULL; 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate doexec(fstype, newargv); 547821Sdh145677 return (0); 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate void 551821Sdh145677 usage(void) 5520Sstevel@tonic-gate { 5530Sstevel@tonic-gate fprintf(stderr, gettext("Usage:\n%s [-v | -p]\n"), myname); 5540Sstevel@tonic-gate fprintf(stderr, gettext( 5556007Sthurlow "%s [-F FSType] [-V] [current_options] [-o specific_options]"), 5566007Sthurlow myname); 5570Sstevel@tonic-gate fprintf(stderr, gettext("\n\t{special | mount_point}\n")); 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate fprintf(stderr, gettext( 5606007Sthurlow "%s [-F FSType] [-V] [current_options] [-o specific_options]"), 5616007Sthurlow myname); 5620Sstevel@tonic-gate fprintf(stderr, gettext("\n\tspecial mount_point\n")); 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate fprintf(stderr, gettext( 5650Sstevel@tonic-gate "%s -a [-F FSType ] [-V] [current_options] [-o specific_options]\n"), 5666007Sthurlow myname); 5670Sstevel@tonic-gate fprintf(stderr, gettext("\t[mount_point ...]\n")); 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate exit(1); 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate /* 5730Sstevel@tonic-gate * Get rid of "dev=[hex string]" clause, if any. It's not legal 5740Sstevel@tonic-gate * when printing in vfstab format. 5750Sstevel@tonic-gate */ 5760Sstevel@tonic-gate void 5770Sstevel@tonic-gate elide_dev(char *mntopts) 5780Sstevel@tonic-gate { 5790Sstevel@tonic-gate char *dev, *other; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate if (mntopts != NULL) { 5820Sstevel@tonic-gate dev = strstr(mntopts, "dev="); 5830Sstevel@tonic-gate if (dev != NULL) { 5840Sstevel@tonic-gate other = strpbrk(dev, ","); 5850Sstevel@tonic-gate if (other == NULL) { 5860Sstevel@tonic-gate /* last option */ 5870Sstevel@tonic-gate if (dev != mntopts) { 5880Sstevel@tonic-gate *--dev = '\0'; 5890Sstevel@tonic-gate } else { 5900Sstevel@tonic-gate *dev = '\0'; 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate } else { 5930Sstevel@tonic-gate /* first or intermediate option */ 5940Sstevel@tonic-gate memmove(dev, other+1, strlen(other+1)+1); 5950Sstevel@tonic-gate } 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate void 601821Sdh145677 print_mnttab(int vflg, int pflg) 6020Sstevel@tonic-gate { 6030Sstevel@tonic-gate FILE *fd; 6040Sstevel@tonic-gate FILE *rfp; /* this will be NULL if fopen fails */ 6050Sstevel@tonic-gate int ret; 6060Sstevel@tonic-gate char time_buf[TIME_MAX]; /* array to hold date and time */ 6070Sstevel@tonic-gate struct extmnttab mget; 6080Sstevel@tonic-gate time_t ltime; 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate if ((fd = fopen(mnttab, "r")) == NULL) { 6110Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot open mnttab\n"), myname); 6120Sstevel@tonic-gate exit(1); 6130Sstevel@tonic-gate } 6140Sstevel@tonic-gate rfp = fopen(REMOTE, "r"); 6150Sstevel@tonic-gate while ((ret = getextmntent(fd, &mget, sizeof (struct extmnttab))) 6166007Sthurlow == 0) { 6170Sstevel@tonic-gate if (ignore(mget.mnt_mntopts)) 6180Sstevel@tonic-gate continue; 6190Sstevel@tonic-gate if (mget.mnt_special && mget.mnt_mountp && 6200Sstevel@tonic-gate mget.mnt_fstype && mget.mnt_time) { 6210Sstevel@tonic-gate ltime = atol(mget.mnt_time); 6220Sstevel@tonic-gate cftime(time_buf, FORMAT, <ime); 6230Sstevel@tonic-gate if (pflg) { 6240Sstevel@tonic-gate elide_dev(mget.mnt_mntopts); 6250Sstevel@tonic-gate printf("%s - %s %s - no %s\n", 6266007Sthurlow mget.mnt_special, 6276007Sthurlow mget.mnt_mountp, 6286007Sthurlow mget.mnt_fstype, 6296007Sthurlow mget.mnt_mntopts != NULL ? 6306007Sthurlow mget.mnt_mntopts : "-"); 6310Sstevel@tonic-gate } else if (vflg) { 6320Sstevel@tonic-gate printf("%s on %s type %s %s%s on %s", 6336007Sthurlow mget.mnt_special, 6346007Sthurlow mget.mnt_mountp, 6356007Sthurlow mget.mnt_fstype, 6366007Sthurlow remote(mget.mnt_fstype, rfp), 6376007Sthurlow flags(mget.mnt_mntopts, NEW), 6386007Sthurlow time_buf); 6390Sstevel@tonic-gate } else 6400Sstevel@tonic-gate printf("%s on %s %s%s on %s", 6416007Sthurlow mget.mnt_mountp, 6426007Sthurlow mget.mnt_special, 6436007Sthurlow remote(mget.mnt_fstype, rfp), 6446007Sthurlow flags(mget.mnt_mntopts, OLD), 6456007Sthurlow time_buf); 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate if (ret > 0) 6490Sstevel@tonic-gate mnterror(ret); 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate char * 653821Sdh145677 flags(char *mntopts, int flag) 6540Sstevel@tonic-gate { 6550Sstevel@tonic-gate char opts[sizeof (mntflags)]; 6560Sstevel@tonic-gate char *value; 6570Sstevel@tonic-gate int rdwr = 1; 6580Sstevel@tonic-gate int suid = 1; 6590Sstevel@tonic-gate int devices = 1; 6600Sstevel@tonic-gate int setuid = 1; 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate if (mntopts == NULL || *mntopts == '\0') 6630Sstevel@tonic-gate return ("read/write/setuid/devices"); 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate strcpy(opts, ""); 6660Sstevel@tonic-gate while (*mntopts != '\0') { 6670Sstevel@tonic-gate switch (getsubopt(&mntopts, myopts, &value)) { 6680Sstevel@tonic-gate case READONLY: 6690Sstevel@tonic-gate rdwr = 0; 6700Sstevel@tonic-gate break; 6710Sstevel@tonic-gate case READWRITE: 6720Sstevel@tonic-gate rdwr = 1; 6730Sstevel@tonic-gate break; 6740Sstevel@tonic-gate case SUID: 6750Sstevel@tonic-gate suid = 1; 6760Sstevel@tonic-gate break; 6770Sstevel@tonic-gate case NOSUID: 6780Sstevel@tonic-gate suid = 0; 6790Sstevel@tonic-gate break; 6800Sstevel@tonic-gate case SETUID: 6810Sstevel@tonic-gate setuid = 1; 6820Sstevel@tonic-gate break; 6830Sstevel@tonic-gate case NOSETUID: 6840Sstevel@tonic-gate setuid = 0; 6850Sstevel@tonic-gate break; 6860Sstevel@tonic-gate case DEVICES: 6870Sstevel@tonic-gate devices = 1; 6880Sstevel@tonic-gate break; 6890Sstevel@tonic-gate case NODEVICES: 6900Sstevel@tonic-gate devices = 0; 6910Sstevel@tonic-gate break; 6920Sstevel@tonic-gate default: 6930Sstevel@tonic-gate /* cat '/' separator to mntflags */ 6940Sstevel@tonic-gate if (*opts != '\0' && value != NULL) 6950Sstevel@tonic-gate strcat(opts, "/"); 6960Sstevel@tonic-gate strcat(opts, value); 6970Sstevel@tonic-gate break; 6980Sstevel@tonic-gate } 6990Sstevel@tonic-gate } 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate strcpy(mntflags, ""); 7020Sstevel@tonic-gate if (rdwr) 7030Sstevel@tonic-gate strcat(mntflags, "read/write"); 7040Sstevel@tonic-gate else if (flag == OLD) 7050Sstevel@tonic-gate strcat(mntflags, "read only"); 7060Sstevel@tonic-gate else 7070Sstevel@tonic-gate strcat(mntflags, "read-only"); 7080Sstevel@tonic-gate if (suid) { 7090Sstevel@tonic-gate if (setuid) 7100Sstevel@tonic-gate strcat(mntflags, "/setuid"); 7110Sstevel@tonic-gate else 7120Sstevel@tonic-gate strcat(mntflags, "/nosetuid"); 7130Sstevel@tonic-gate if (devices) 7140Sstevel@tonic-gate strcat(mntflags, "/devices"); 7150Sstevel@tonic-gate else 7160Sstevel@tonic-gate strcat(mntflags, "/nodevices"); 7170Sstevel@tonic-gate } else { 7180Sstevel@tonic-gate strcat(mntflags, "/nosetuid/nodevices"); 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate if (*opts != '\0') { 7210Sstevel@tonic-gate strcat(mntflags, "/"); 7220Sstevel@tonic-gate strcat(mntflags, opts); 7230Sstevel@tonic-gate } 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate /* 7260Sstevel@tonic-gate * The assumed assertion 7270Sstevel@tonic-gate * assert (strlen(mntflags) < sizeof mntflags); 7280Sstevel@tonic-gate * is valid at this point in the code. Note that a call to "assert" 7290Sstevel@tonic-gate * is not appropriate in production code since it halts the program. 7300Sstevel@tonic-gate */ 7310Sstevel@tonic-gate return (mntflags); 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate char * 735821Sdh145677 remote(char *fstype, FILE *rfp) 7360Sstevel@tonic-gate { 7370Sstevel@tonic-gate char buf[BUFSIZ]; 7380Sstevel@tonic-gate char *fs; 7390Sstevel@tonic-gate extern char *strtok(); 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate if (rfp == NULL || fstype == NULL || 7426007Sthurlow strlen(fstype) > (size_t)FSTYPE_MAX) 7430Sstevel@tonic-gate return (""); /* not a remote */ 7440Sstevel@tonic-gate rewind(rfp); 7450Sstevel@tonic-gate while (fgets(buf, sizeof (buf), rfp) != NULL) { 7460Sstevel@tonic-gate fs = strtok(buf, " \t\n"); 7470Sstevel@tonic-gate if (strcmp(fstype, fs) == 0) 7480Sstevel@tonic-gate return ("remote/"); /* is a remote fs */ 7490Sstevel@tonic-gate } 7500Sstevel@tonic-gate return (""); /* not a remote */ 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate void 7550Sstevel@tonic-gate vfserror(int flag, char *special) 7560Sstevel@tonic-gate { 7570Sstevel@tonic-gate if (special == NULL) 7580Sstevel@tonic-gate special = "<null>"; 7590Sstevel@tonic-gate switch (flag) { 7600Sstevel@tonic-gate case VFS_TOOLONG: 7610Sstevel@tonic-gate fprintf(stderr, 7620Sstevel@tonic-gate gettext("%s: Warning: Line in vfstab for \"%s\" exceeds %d characters\n"), 7636007Sthurlow myname, special, VFS_LINE_MAX-1); 7640Sstevel@tonic-gate break; 7650Sstevel@tonic-gate case VFS_TOOFEW: 7660Sstevel@tonic-gate fprintf(stderr, 7670Sstevel@tonic-gate gettext("%s: Warning: Line for \"%s\" in vfstab has too few entries\n"), 7686007Sthurlow myname, special); 7690Sstevel@tonic-gate break; 7700Sstevel@tonic-gate case VFS_TOOMANY: 7710Sstevel@tonic-gate fprintf(stderr, 7720Sstevel@tonic-gate gettext("%s: Warning: Line for \"%s\" in vfstab has too many entries\n"), 7736007Sthurlow myname, special); 7740Sstevel@tonic-gate break; 7750Sstevel@tonic-gate default: 7760Sstevel@tonic-gate fprintf(stderr, gettext( 7776007Sthurlow "%s: Warning: Error in line for \"%s\" in vfstab\n"), 7786007Sthurlow myname, special); 7790Sstevel@tonic-gate } 7800Sstevel@tonic-gate } 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate void 783821Sdh145677 mnterror(int flag) 7840Sstevel@tonic-gate { 7850Sstevel@tonic-gate switch (flag) { 7860Sstevel@tonic-gate case MNT_TOOLONG: 7870Sstevel@tonic-gate fprintf(stderr, 7886007Sthurlow gettext("%s: Line in mnttab exceeds %d characters\n"), 7896007Sthurlow myname, MNT_LINE_MAX-2); 7900Sstevel@tonic-gate break; 7910Sstevel@tonic-gate case MNT_TOOFEW: 7920Sstevel@tonic-gate fprintf(stderr, 7936007Sthurlow gettext("%s: Line in mnttab has too few entries\n"), 7946007Sthurlow myname); 7950Sstevel@tonic-gate break; 7960Sstevel@tonic-gate case MNT_TOOMANY: 7970Sstevel@tonic-gate fprintf(stderr, 7986007Sthurlow gettext("%s: Line in mnttab has too many entries\n"), 7996007Sthurlow myname); 8000Sstevel@tonic-gate break; 8010Sstevel@tonic-gate } 8020Sstevel@tonic-gate exit(1); 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate void 806821Sdh145677 doexec(char *fstype, char *newargv[]) 8070Sstevel@tonic-gate { 8080Sstevel@tonic-gate char full_path[PATH_MAX]; 8090Sstevel@tonic-gate char alter_path[PATH_MAX]; 8100Sstevel@tonic-gate char *vfs_path = VFS_PATH; 8110Sstevel@tonic-gate char *alt_path = ALT_PATH; 8120Sstevel@tonic-gate int i; 8136007Sthurlow int smbfs; 8146007Sthurlow 8156007Sthurlow /* 8166007Sthurlow * Special case smbfs file system. 8176007Sthurlow * Execute command in profile if possible. 8186007Sthurlow */ 8196007Sthurlow smbfs = strcmp(fstype, "smbfs") == 0; 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* build the full pathname of the fstype dependent command. */ 8220Sstevel@tonic-gate sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname); 8230Sstevel@tonic-gate sprintf(alter_path, "%s/%s/%s", alt_path, fstype, myname); 8240Sstevel@tonic-gate newargv[1] = myname; 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate if (Vflg) { 8270Sstevel@tonic-gate printf("%s -F %s", newargv[1], fstype); 8280Sstevel@tonic-gate for (i = 2; newargv[i]; i++) 8290Sstevel@tonic-gate printf(" %s", newargv[i]); 8300Sstevel@tonic-gate printf("\n"); 8310Sstevel@tonic-gate fflush(stdout); 8320Sstevel@tonic-gate exit(0); 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate /* 8360Sstevel@tonic-gate * Try to exec the fstype dependent portion of the mount. 8370Sstevel@tonic-gate * See if the directory is there before trying to exec dependent 8380Sstevel@tonic-gate * portion. This is only useful for eliminating the 8390Sstevel@tonic-gate * '..mount: not found' message when '/usr' is mounted 8400Sstevel@tonic-gate */ 8410Sstevel@tonic-gate if (access(full_path, 0) == 0) { 8426007Sthurlow if (smbfs) { 8436007Sthurlow /* 8446007Sthurlow * Run mount_smbfs(1m) with pfexec so that we can 8456007Sthurlow * add sys_mount privilege, (via exec_attr, etc.) 8466007Sthurlow * allowing normal users to mount on any directory 8476007Sthurlow * they own. 8486007Sthurlow */ 8496007Sthurlow newargv[0] = "pfexec"; 8506007Sthurlow newargv[1] = full_path; 8516007Sthurlow execv("/usr/bin/pfexec", &newargv[0]); 8526007Sthurlow newargv[1] = myname; 8536007Sthurlow } 8540Sstevel@tonic-gate execv(full_path, &newargv[1]); 8550Sstevel@tonic-gate if (errno == EACCES) { 8560Sstevel@tonic-gate fprintf(stderr, 8570Sstevel@tonic-gate gettext("%s: Cannot execute %s - permission denied\n"), 8586007Sthurlow myname, full_path); 8590Sstevel@tonic-gate } 8600Sstevel@tonic-gate if (errno == ENOEXEC) { 8610Sstevel@tonic-gate newargv[0] = "sh"; 8620Sstevel@tonic-gate newargv[1] = full_path; 8630Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 8640Sstevel@tonic-gate } 8650Sstevel@tonic-gate } 8666007Sthurlow if (smbfs) { 8676007Sthurlow newargv[0] = "pfexec"; 8686007Sthurlow newargv[1] = alter_path; 8696007Sthurlow execv("/usr/bin/pfexec", &newargv[0]); 8706007Sthurlow newargv[1] = myname; 8716007Sthurlow } 8720Sstevel@tonic-gate execv(alter_path, &newargv[1]); 8730Sstevel@tonic-gate if (errno == EACCES) { 8740Sstevel@tonic-gate fprintf(stderr, gettext( 8756007Sthurlow "%s: Cannot execute %s - permission denied\n"), 8766007Sthurlow myname, alter_path); 8770Sstevel@tonic-gate exit(1); 8780Sstevel@tonic-gate } 8790Sstevel@tonic-gate if (errno == ENOEXEC) { 8800Sstevel@tonic-gate newargv[0] = "sh"; 8810Sstevel@tonic-gate newargv[1] = alter_path; 8820Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 8830Sstevel@tonic-gate } 8840Sstevel@tonic-gate fprintf(stderr, 8856007Sthurlow gettext("%s: Operation not applicable to FSType %s\n"), 8866007Sthurlow myname, fstype); 8870Sstevel@tonic-gate exit(1); 8880Sstevel@tonic-gate } 8890Sstevel@tonic-gate 8900Sstevel@tonic-gate char *mntopts[] = { MNTOPT_IGNORE, NULL }; 8910Sstevel@tonic-gate #define IGNORE 0 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate /* 8940Sstevel@tonic-gate * Return 1 if "ignore" appears in the options string 8950Sstevel@tonic-gate */ 8960Sstevel@tonic-gate int 897821Sdh145677 ignore(char *opts) 8980Sstevel@tonic-gate { 8990Sstevel@tonic-gate char *value; 9000Sstevel@tonic-gate char *saveptr, *my_opts; 9010Sstevel@tonic-gate int rval = 0; 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate if (opts == NULL || *opts == NULL) 9040Sstevel@tonic-gate return (0); 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate /* 9070Sstevel@tonic-gate * we make a copy of the option string to pass to getsubopt(), 9080Sstevel@tonic-gate * because getsubopt() modifies the string. We also save 9090Sstevel@tonic-gate * the original pointer returned by strdup, because getsubopt 9100Sstevel@tonic-gate * changes the pointer passed into it. If strdup fails (unlikely), 9110Sstevel@tonic-gate * we act as if the "ignore" option isn't set rather than fail. 9120Sstevel@tonic-gate */ 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate if ((saveptr = my_opts = strdup(opts)) == NULL) 9150Sstevel@tonic-gate nomem(); 9160Sstevel@tonic-gate 9170Sstevel@tonic-gate while (*my_opts != '\0') { 9180Sstevel@tonic-gate if (getsubopt(&my_opts, mntopts, &value) == IGNORE) 9190Sstevel@tonic-gate rval = 1; 9200Sstevel@tonic-gate } 9210Sstevel@tonic-gate 9220Sstevel@tonic-gate free(saveptr); 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate return (rval); 9250Sstevel@tonic-gate } 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate /* 9280Sstevel@tonic-gate * Perform the parallel version of mount. If count == 0, mount all 9290Sstevel@tonic-gate * vfstab filesystems with the automnt field == "yes". Use fstype if 9300Sstevel@tonic-gate * supplied. If mntlist supplied, then attempt to only mount those. 9310Sstevel@tonic-gate */ 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate int 9340Sstevel@tonic-gate parmount(char **mntlist, int count, char *fstype) 9350Sstevel@tonic-gate { 9360Sstevel@tonic-gate int maxfd = OPEN_MAX; 9370Sstevel@tonic-gate struct rlimit rl; 9380Sstevel@tonic-gate vfsent_t **vl, *vp; 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate /* 9410Sstevel@tonic-gate * Process scaling. After running a series 9420Sstevel@tonic-gate * of tests based on the number of simultaneous processes and 9430Sstevel@tonic-gate * processors available, optimum performance was achieved near or 9440Sstevel@tonic-gate * at (PROCN * 2). 9450Sstevel@tonic-gate */ 9460Sstevel@tonic-gate if ((maxrun = sysconf(_SC_NPROCESSORS_ONLN)) == -1) 9470Sstevel@tonic-gate maxrun = 4; 9480Sstevel@tonic-gate else 9490Sstevel@tonic-gate maxrun = maxrun * 2 + 1; 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 9520Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max; 9530Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rl) == 0) 9540Sstevel@tonic-gate maxfd = (int)rl.rlim_cur; 9550Sstevel@tonic-gate } 9561914Scasper (void) enable_extended_FILE_stdio(-1, -1); 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate /* 9590Sstevel@tonic-gate * The parent needs to maintain 3 of its own fd's, plus 2 for 9600Sstevel@tonic-gate * each child (the stdout and stderr pipes). 9610Sstevel@tonic-gate */ 9620Sstevel@tonic-gate maxfd = (maxfd / 2) - 6; /* 6 takes care of temporary */ 9630Sstevel@tonic-gate /* periods of open fds */ 9640Sstevel@tonic-gate if (maxfd < maxrun) 9650Sstevel@tonic-gate maxrun = maxfd; 9660Sstevel@tonic-gate if (maxrun < 4) 9670Sstevel@tonic-gate maxrun = 4; /* sanity check */ 9680Sstevel@tonic-gate 9690Sstevel@tonic-gate if (count == 0) 9700Sstevel@tonic-gate mntlist = NULL; /* used as a flag later */ 9710Sstevel@tonic-gate else 9720Sstevel@tonic-gate fstype = NULL; /* mount points supplied: */ 9730Sstevel@tonic-gate /* ignore fstype */ 9740Sstevel@tonic-gate /* 9750Sstevel@tonic-gate * Read the whole vfstab into a linked list for quick processing. 9760Sstevel@tonic-gate * On average, this is the most efficient way to collect and 9770Sstevel@tonic-gate * manipulate the vfstab data. 9780Sstevel@tonic-gate */ 9790Sstevel@tonic-gate vfsll = getvfsall(fstype, mntlist == NULL); 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate /* 9820Sstevel@tonic-gate * Make an array out of the vfs linked list for sorting purposes. 9830Sstevel@tonic-gate */ 9840Sstevel@tonic-gate if (vfsll == NULL || 9850Sstevel@tonic-gate (vfsarray = make_vfsarray(mntlist, count)) == NULL) { 9860Sstevel@tonic-gate if (mntlist == NULL) /* not an error - just none found */ 9870Sstevel@tonic-gate return (0); 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate fprintf(stderr, gettext("%s: No valid entries found in %s\n"), 9906007Sthurlow myname, vfstab); 9910Sstevel@tonic-gate return (1); 9920Sstevel@tonic-gate } 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate /* 9950Sstevel@tonic-gate * Sort the entries based on their resolved path names 9960Sstevel@tonic-gate * 9970Sstevel@tonic-gate * If an lofs is encountered, then the original order of the vfstab 9980Sstevel@tonic-gate * file needs to be maintained until we are done mounting lofs's. 9990Sstevel@tonic-gate */ 10000Sstevel@tonic-gate if (!lofscnt) 10010Sstevel@tonic-gate qsort((void *)vfsarray, vfsarraysize, sizeof (vfsent_t *), 10026007Sthurlow mlevelcmp); 10030Sstevel@tonic-gate 10040Sstevel@tonic-gate /* 10050Sstevel@tonic-gate * Shrink the vfsll linked list down to the new list. This will 10060Sstevel@tonic-gate * speed up the pid search in cleanupkid() later. 10070Sstevel@tonic-gate */ 10080Sstevel@tonic-gate vfsll = vfsarray[0]; 10090Sstevel@tonic-gate for (vl = vfsarray; vp = *vl; ) 10100Sstevel@tonic-gate vp->next = *++vl; 10110Sstevel@tonic-gate 10120Sstevel@tonic-gate /* 10130Sstevel@tonic-gate * Try to handle interrupts in a reasonable way. 10140Sstevel@tonic-gate */ 10150Sstevel@tonic-gate sigset(SIGHUP, cleanup); 10160Sstevel@tonic-gate sigset(SIGQUIT, cleanup); 10170Sstevel@tonic-gate sigset(SIGINT, cleanup); 10180Sstevel@tonic-gate 10190Sstevel@tonic-gate do_mounts(); /* do the mounts */ 1020*8155STim.Haley@Sun.COM 1021*8155STim.Haley@Sun.COM if (failcnt > 0 && failcnt == lofsfail) 1022*8155STim.Haley@Sun.COM return (ALL_LOFS_FAILURES); 1023*8155STim.Haley@Sun.COM 10240Sstevel@tonic-gate return (exitcode); 10250Sstevel@tonic-gate } 10260Sstevel@tonic-gate 10270Sstevel@tonic-gate /* 10280Sstevel@tonic-gate * Read all vstab (fp) entries into memory if fstype == NULL. 10290Sstevel@tonic-gate * If fstype is specified, than read all those that match it. 10300Sstevel@tonic-gate * 10310Sstevel@tonic-gate * Returns a linked list. 10320Sstevel@tonic-gate */ 10330Sstevel@tonic-gate vfsent_t * 10340Sstevel@tonic-gate getvfsall(char *fstype, int takeall) 10350Sstevel@tonic-gate { 10360Sstevel@tonic-gate vfsent_t *vhead, *vtail; 10370Sstevel@tonic-gate struct vfstab vget; 10380Sstevel@tonic-gate FILE *fp; 10390Sstevel@tonic-gate int cnt = 0, ret; 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate if ((fp = fopen(vfstab, "r")) == NULL) { 10420Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot open %s\n"), 10436007Sthurlow myname, vfstab); 10440Sstevel@tonic-gate exit(1); 10450Sstevel@tonic-gate } 10460Sstevel@tonic-gate 10470Sstevel@tonic-gate vhead = vtail = NULL; 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate while ((ret = getvfsent(fp, &vget)) != -1) { 10500Sstevel@tonic-gate vfsent_t *vp; 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate if (ret > 0) { 10530Sstevel@tonic-gate vfserror(ret, vget.vfs_mountp); 10540Sstevel@tonic-gate continue; 10550Sstevel@tonic-gate } 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate /* 10580Sstevel@tonic-gate * If mount points were not specified, then we ignore 10590Sstevel@tonic-gate * entries that aren't marked "yes". 10600Sstevel@tonic-gate */ 10610Sstevel@tonic-gate if (takeall && 10620Sstevel@tonic-gate (vget.vfs_automnt == NULL || 10630Sstevel@tonic-gate strcmp(vget.vfs_automnt, "yes"))) 10640Sstevel@tonic-gate continue; 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate if (fstype && vget.vfs_fstype && 10670Sstevel@tonic-gate strcmp(fstype, vget.vfs_fstype)) 10680Sstevel@tonic-gate continue; 10690Sstevel@tonic-gate 10700Sstevel@tonic-gate if (vget.vfs_mountp == NULL || 10710Sstevel@tonic-gate (vget.vfs_fstype && (strcmp(vget.vfs_fstype, "swap") == 0))) 10720Sstevel@tonic-gate continue; 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate if (check_fields(vget.vfs_fstype, vget.vfs_mountp)) { 10750Sstevel@tonic-gate exitcode = 1; 10760Sstevel@tonic-gate continue; 10770Sstevel@tonic-gate } 10780Sstevel@tonic-gate 10790Sstevel@tonic-gate vp = new_vfsent(&vget, cnt); /* create new vfs entry */ 10800Sstevel@tonic-gate if (vhead == NULL) 10810Sstevel@tonic-gate vhead = vp; 10820Sstevel@tonic-gate else 10830Sstevel@tonic-gate vtail->next = vp; 10840Sstevel@tonic-gate vtail = vp; 10850Sstevel@tonic-gate cnt++; 10860Sstevel@tonic-gate } 10870Sstevel@tonic-gate fclose(fp); 10880Sstevel@tonic-gate if (vtail == NULL) { 10890Sstevel@tonic-gate vfsarraysize = 0; 10900Sstevel@tonic-gate vfslltail = NULL; 10910Sstevel@tonic-gate return (NULL); 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate vtail->next = NULL; 10940Sstevel@tonic-gate vfslltail = vtail; /* save it in the global variable */ 10950Sstevel@tonic-gate vfsarraysize = cnt; 10960Sstevel@tonic-gate return (vhead); 10970Sstevel@tonic-gate } 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate /* 11010Sstevel@tonic-gate * Returns an array of vfsent_t's based on vfsll & mntlist. 11020Sstevel@tonic-gate */ 11030Sstevel@tonic-gate vfsent_t ** 11040Sstevel@tonic-gate make_vfsarray(char **mntlist, int count) 11050Sstevel@tonic-gate { 11060Sstevel@tonic-gate vfsent_t *vp, *vmark, *vpprev, **vpp; 11070Sstevel@tonic-gate int ndx, found; 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate if (vfsll == NULL) 11100Sstevel@tonic-gate return (NULL); 11110Sstevel@tonic-gate 11120Sstevel@tonic-gate if (count > 0) 11130Sstevel@tonic-gate vfsarraysize = count; 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate vpp = (vfsent_t **)malloc(sizeof (*vpp) * (vfsarraysize + 1)); 11160Sstevel@tonic-gate if (vpp == NULL) 11170Sstevel@tonic-gate nomem(); 11180Sstevel@tonic-gate 11190Sstevel@tonic-gate if (mntlist == NULL) { 11200Sstevel@tonic-gate /* 11210Sstevel@tonic-gate * No mount list specified: take all vfstab mount points. 11220Sstevel@tonic-gate */ 11230Sstevel@tonic-gate for (ndx = 0, vp = vfsll; vp; vp = vp->next) { 11240Sstevel@tonic-gate (void) setrpath(vp); 11250Sstevel@tonic-gate /* 11260Sstevel@tonic-gate * Sigh. lofs entries can complicate matters so much 11270Sstevel@tonic-gate * that the best way to avoid problems is to 11280Sstevel@tonic-gate * stop parallel mounting when an lofs is 11290Sstevel@tonic-gate * encountered, so we keep a count of how many 11300Sstevel@tonic-gate * there are. 11310Sstevel@tonic-gate * Fortunately this is rare. 11320Sstevel@tonic-gate */ 11330Sstevel@tonic-gate if (vp->v.vfs_fstype && 11340Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, MNTTYPE_LOFS) == 0)) 11350Sstevel@tonic-gate lofscnt++; 11360Sstevel@tonic-gate 11370Sstevel@tonic-gate vpp[ndx++] = vp; 11380Sstevel@tonic-gate } 11390Sstevel@tonic-gate vpp[ndx] = NULL; 11400Sstevel@tonic-gate return (vpp); 11410Sstevel@tonic-gate } 11420Sstevel@tonic-gate 11430Sstevel@tonic-gate /* 11440Sstevel@tonic-gate * A list of mount points was specified on the command line 11450Sstevel@tonic-gate * and we need to search for each one. 11460Sstevel@tonic-gate */ 11470Sstevel@tonic-gate vpprev = vfslltail; 11480Sstevel@tonic-gate vpprev->next = vfsll; /* make a circle out of it */ 11490Sstevel@tonic-gate vmark = vp = vfsll; 11500Sstevel@tonic-gate /* 11510Sstevel@tonic-gate * For each specified mount point: 11520Sstevel@tonic-gate */ 11530Sstevel@tonic-gate for (ndx = 0; *mntlist; mntlist++) { 11540Sstevel@tonic-gate found = 0; 11550Sstevel@tonic-gate /* 11560Sstevel@tonic-gate * Circle our entire linked list, looking for *mntlist. 11570Sstevel@tonic-gate */ 11580Sstevel@tonic-gate while (vp) { 11590Sstevel@tonic-gate if (strcmp(*mntlist, vp->v.vfs_mountp) == 0) { 11600Sstevel@tonic-gate vpp[ndx++] = vp; /* found it. */ 11610Sstevel@tonic-gate (void) setrpath(vp); 11620Sstevel@tonic-gate if (vp->v.vfs_fstype && 11630Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, 11640Sstevel@tonic-gate MNTTYPE_LOFS) == 0)) 11650Sstevel@tonic-gate lofscnt++; 11660Sstevel@tonic-gate 11670Sstevel@tonic-gate if (vp == vpprev) { /* list exhausted */ 11680Sstevel@tonic-gate vp = NULL; 11690Sstevel@tonic-gate found++; 11700Sstevel@tonic-gate break; 11710Sstevel@tonic-gate } 11720Sstevel@tonic-gate /* 11730Sstevel@tonic-gate * Remove it from the circular list. vpprev 11740Sstevel@tonic-gate * remains unchanged. 11750Sstevel@tonic-gate */ 11760Sstevel@tonic-gate vp = vp->next; 11770Sstevel@tonic-gate vpprev->next->next = NULL; 11780Sstevel@tonic-gate vpprev->next = vp; 11790Sstevel@tonic-gate /* 11800Sstevel@tonic-gate * Set vmark to the first elem that we check 11810Sstevel@tonic-gate * each time. 11820Sstevel@tonic-gate */ 11830Sstevel@tonic-gate vmark = vp; 11840Sstevel@tonic-gate found++; 11850Sstevel@tonic-gate break; 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate vpprev = vp; 11880Sstevel@tonic-gate vp = vp->next; 11890Sstevel@tonic-gate if (vp == vmark) /* break out if we completed */ 11900Sstevel@tonic-gate /* the circle */ 11910Sstevel@tonic-gate break; 11920Sstevel@tonic-gate } 11930Sstevel@tonic-gate 11940Sstevel@tonic-gate if (!found) { 11950Sstevel@tonic-gate fprintf(stderr, gettext( 11966007Sthurlow "%s: Warning: %s not found in %s\n"), 11976007Sthurlow myname, *mntlist, vfstab); 11980Sstevel@tonic-gate exitcode = 1; 11990Sstevel@tonic-gate } 12000Sstevel@tonic-gate } 12010Sstevel@tonic-gate if (ndx == 0) 12020Sstevel@tonic-gate return (NULL); 12030Sstevel@tonic-gate 12040Sstevel@tonic-gate vpp[ndx] = NULL; /* null terminate the list */ 12050Sstevel@tonic-gate vfsarraysize = ndx; /* adjust vfsarraysize */ 12060Sstevel@tonic-gate return (vpp); 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate 12090Sstevel@tonic-gate /* 12100Sstevel@tonic-gate * Performs the exec argument processing, all of the child forking and 12110Sstevel@tonic-gate * execing, and child cleanup. 12120Sstevel@tonic-gate * Sets exitcode to non-zero if any errors occurred. 12130Sstevel@tonic-gate */ 12140Sstevel@tonic-gate void 1215821Sdh145677 do_mounts(void) 12160Sstevel@tonic-gate { 12170Sstevel@tonic-gate int i, isave, cnt; 12180Sstevel@tonic-gate vfsent_t *vp, *vpprev, **vl; 12190Sstevel@tonic-gate char *newargv[ARGV_MAX]; 12200Sstevel@tonic-gate pid_t child; 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate /* 12230Sstevel@tonic-gate * create the arg list once; the only differences among 12240Sstevel@tonic-gate * the calls are the options, special and mountp fields. 12250Sstevel@tonic-gate */ 12260Sstevel@tonic-gate i = 2; 12270Sstevel@tonic-gate if (cflg) 12280Sstevel@tonic-gate newargv[i++] = "-c"; 12290Sstevel@tonic-gate if (gflg) 12300Sstevel@tonic-gate newargv[i++] = "-g"; 12310Sstevel@tonic-gate if (mflg) 12320Sstevel@tonic-gate newargv[i++] = "-m"; 12330Sstevel@tonic-gate if (Oflg) 12340Sstevel@tonic-gate newargv[i++] = "-O"; 12350Sstevel@tonic-gate if (qflg) 12360Sstevel@tonic-gate newargv[i++] = "-q"; 12370Sstevel@tonic-gate if (rflg) 12380Sstevel@tonic-gate newargv[i++] = "-r"; 12390Sstevel@tonic-gate if (dashflg) 12400Sstevel@tonic-gate newargv[i++] = "--"; 12410Sstevel@tonic-gate if (oflg) { 12420Sstevel@tonic-gate newargv[i++] = "-o"; 12430Sstevel@tonic-gate newargv[i++] = specific_opts; 12440Sstevel@tonic-gate } 12450Sstevel@tonic-gate isave = i; 12460Sstevel@tonic-gate 12470Sstevel@tonic-gate /* 12480Sstevel@tonic-gate * Main loop for the mount processes 12490Sstevel@tonic-gate */ 12500Sstevel@tonic-gate vl = vfsarray; 12510Sstevel@tonic-gate cnt = vfsarraysize; 12520Sstevel@tonic-gate for (vpprev = *vl; vp = *vl; vpprev = vp, vl++, cnt--) { 12530Sstevel@tonic-gate /* 12540Sstevel@tonic-gate * Check to see if we cross a mount level: e.g., 12550Sstevel@tonic-gate * /a/b -> /a/b/c. If so, we need to wait for all current 12560Sstevel@tonic-gate * mounts to finish, rerun realpath on the remaining mount 12570Sstevel@tonic-gate * points, and resort the list. 12580Sstevel@tonic-gate * 12590Sstevel@tonic-gate * Also, we mount serially as long as there are lofs's 12600Sstevel@tonic-gate * to mount to avoid improper mount ordering. 12610Sstevel@tonic-gate */ 12620Sstevel@tonic-gate if (vp->mlevel > vpprev->mlevel || lofscnt > 0) { 12630Sstevel@tonic-gate vfsent_t **vlp; 12640Sstevel@tonic-gate 12650Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 12660Sstevel@tonic-gate ; 12670Sstevel@tonic-gate /* 12680Sstevel@tonic-gate * Gads! It's possible for real path mounts points to 12690Sstevel@tonic-gate * change after mounts are done at a lower mount 12700Sstevel@tonic-gate * level. 12710Sstevel@tonic-gate * Thus, we need to recalculate mount levels and 12720Sstevel@tonic-gate * resort the list from this point. 12730Sstevel@tonic-gate */ 12740Sstevel@tonic-gate for (vlp = vl; *vlp; vlp++) 12750Sstevel@tonic-gate (void) setrpath(*vlp); 12760Sstevel@tonic-gate /* 12770Sstevel@tonic-gate * Sort the remaining entries based on their newly 12780Sstevel@tonic-gate * resolved path names. 12790Sstevel@tonic-gate * Do not sort if we still have lofs's to mount. 12800Sstevel@tonic-gate */ 12810Sstevel@tonic-gate if (lofscnt == 0) { 12820Sstevel@tonic-gate qsort((void *)vl, cnt, sizeof (vfsent_t *), 12836007Sthurlow mlevelcmp); 12840Sstevel@tonic-gate vp = *vl; 12850Sstevel@tonic-gate } 12860Sstevel@tonic-gate } 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate if (vp->flag & VRPFAILED) { 12890Sstevel@tonic-gate fprintf(stderr, gettext( 12906007Sthurlow "%s: Nonexistent mount point: %s\n"), 12916007Sthurlow myname, vp->v.vfs_mountp); 12920Sstevel@tonic-gate vp->flag |= VNOTMOUNTED; 12930Sstevel@tonic-gate exitcode = 1; 12940Sstevel@tonic-gate continue; 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate /* 12980Sstevel@tonic-gate * If mount options were not specified on the command 12990Sstevel@tonic-gate * line, then use the ones found in the vfstab entry, 13000Sstevel@tonic-gate * if any. 13010Sstevel@tonic-gate */ 13020Sstevel@tonic-gate i = isave; 13030Sstevel@tonic-gate if (!oflg && vp->v.vfs_mntopts) { 13040Sstevel@tonic-gate newargv[i++] = "-o"; 13050Sstevel@tonic-gate newargv[i++] = vp->v.vfs_mntopts; 13060Sstevel@tonic-gate } 13070Sstevel@tonic-gate newargv[i++] = vp->v.vfs_special; 13080Sstevel@tonic-gate newargv[i++] = vp->rpath; 13090Sstevel@tonic-gate newargv[i] = NULL; 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate /* 13120Sstevel@tonic-gate * This should never really fail. 13130Sstevel@tonic-gate */ 13140Sstevel@tonic-gate while (setup_iopipe(vp) == -1 && (dowait() != -1)) 13150Sstevel@tonic-gate ; 13160Sstevel@tonic-gate 13170Sstevel@tonic-gate while (nrun >= maxrun && (dowait() != -1)) /* throttle */ 13180Sstevel@tonic-gate ; 13190Sstevel@tonic-gate 13200Sstevel@tonic-gate #ifdef CACHEFS_BUG 13210Sstevel@tonic-gate if (vp->v.vfs_fstype && 13220Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, "cachefs") == 0)) { 13230Sstevel@tonic-gate while (cachefs_running && (dowait() != -1)) 13240Sstevel@tonic-gate ; 13250Sstevel@tonic-gate cachefs_running = 1; 13260Sstevel@tonic-gate } 13270Sstevel@tonic-gate #endif 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate if ((child = fork()) == -1) { 13300Sstevel@tonic-gate perror("fork"); 13310Sstevel@tonic-gate cleanup(-1); 13320Sstevel@tonic-gate /* not reached */ 13330Sstevel@tonic-gate } 13340Sstevel@tonic-gate if (child == 0) { /* child */ 13350Sstevel@tonic-gate signal(SIGHUP, SIG_IGN); 13360Sstevel@tonic-gate signal(SIGQUIT, SIG_IGN); 13370Sstevel@tonic-gate signal(SIGINT, SIG_IGN); 13380Sstevel@tonic-gate setup_output(vp); 13390Sstevel@tonic-gate doexec(vp->v.vfs_fstype, newargv); 13400Sstevel@tonic-gate perror("exec"); 13410Sstevel@tonic-gate exit(1); 13420Sstevel@tonic-gate } 13430Sstevel@tonic-gate 13440Sstevel@tonic-gate /* parent */ 13450Sstevel@tonic-gate (void) close(vp->sopipe[WRPIPE]); 13460Sstevel@tonic-gate (void) close(vp->sepipe[WRPIPE]); 13470Sstevel@tonic-gate vp->pid = child; 13480Sstevel@tonic-gate nrun++; 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate /* 13510Sstevel@tonic-gate * Mostly done by now - wait and clean up the stragglers. 13520Sstevel@tonic-gate */ 13530Sstevel@tonic-gate cleanup(0); 13540Sstevel@tonic-gate } 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate 13570Sstevel@tonic-gate /* 13580Sstevel@tonic-gate * Setup stdout and stderr pipes for the children's output. 13590Sstevel@tonic-gate */ 13600Sstevel@tonic-gate int 13610Sstevel@tonic-gate setup_iopipe(vfsent_t *mp) 13620Sstevel@tonic-gate { 13630Sstevel@tonic-gate /* 13640Sstevel@tonic-gate * Make a stdout and stderr pipe. This should never fail. 13650Sstevel@tonic-gate */ 13660Sstevel@tonic-gate if (pipe(mp->sopipe) == -1) 13670Sstevel@tonic-gate return (-1); 13680Sstevel@tonic-gate if (pipe(mp->sepipe) == -1) { 13690Sstevel@tonic-gate (void) close(mp->sopipe[RDPIPE]); 13700Sstevel@tonic-gate (void) close(mp->sopipe[WRPIPE]); 13710Sstevel@tonic-gate return (-1); 13720Sstevel@tonic-gate } 13730Sstevel@tonic-gate /* 13740Sstevel@tonic-gate * Don't block on an empty pipe. 13750Sstevel@tonic-gate */ 13760Sstevel@tonic-gate (void) fcntl(mp->sopipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 13770Sstevel@tonic-gate (void) fcntl(mp->sepipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 13780Sstevel@tonic-gate /* 13790Sstevel@tonic-gate * Don't pass extra fds into children. 13800Sstevel@tonic-gate */ 13810Sstevel@tonic-gate (void) fcntl(mp->sopipe[RDPIPE], F_SETFD, FD_CLOEXEC); 13820Sstevel@tonic-gate (void) fcntl(mp->sepipe[RDPIPE], F_SETFD, FD_CLOEXEC); 13830Sstevel@tonic-gate 13840Sstevel@tonic-gate return (0); 13850Sstevel@tonic-gate } 13860Sstevel@tonic-gate 13870Sstevel@tonic-gate /* 13880Sstevel@tonic-gate * Called by a child to attach its stdout and stderr to the write side of 13890Sstevel@tonic-gate * the pipes. 13900Sstevel@tonic-gate */ 13910Sstevel@tonic-gate void 13920Sstevel@tonic-gate setup_output(vfsent_t *vp) 13930Sstevel@tonic-gate { 13940Sstevel@tonic-gate 13950Sstevel@tonic-gate (void) close(fileno(stdout)); 13960Sstevel@tonic-gate (void) dup(vp->sopipe[WRPIPE]); 13970Sstevel@tonic-gate (void) close(vp->sopipe[WRPIPE]); 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate (void) close(fileno(stderr)); 14000Sstevel@tonic-gate (void) dup(vp->sepipe[WRPIPE]); 14010Sstevel@tonic-gate (void) close(vp->sepipe[WRPIPE]); 14020Sstevel@tonic-gate } 14030Sstevel@tonic-gate 14040Sstevel@tonic-gate /* 14050Sstevel@tonic-gate * Parent uses this to print any stdout or stderr output issued by 14060Sstevel@tonic-gate * the child. 14070Sstevel@tonic-gate */ 14080Sstevel@tonic-gate static void 14090Sstevel@tonic-gate doio(vfsent_t *vp) 14100Sstevel@tonic-gate { 14110Sstevel@tonic-gate int bytes; 14120Sstevel@tonic-gate char ibuf[BUFSIZ]; 14130Sstevel@tonic-gate 14140Sstevel@tonic-gate while ((bytes = read(vp->sepipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 14150Sstevel@tonic-gate write(fileno(stderr), ibuf, bytes); 14160Sstevel@tonic-gate while ((bytes = read(vp->sopipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 14170Sstevel@tonic-gate write(fileno(stdout), ibuf, bytes); 14180Sstevel@tonic-gate 14190Sstevel@tonic-gate (void) close(vp->sopipe[RDPIPE]); 14200Sstevel@tonic-gate (void) close(vp->sepipe[RDPIPE]); 14210Sstevel@tonic-gate } 14220Sstevel@tonic-gate 14230Sstevel@tonic-gate /* 14240Sstevel@tonic-gate * Waits for 1 child to die. 14250Sstevel@tonic-gate * 14260Sstevel@tonic-gate * Returns -1 if no children are left to wait for. 14270Sstevel@tonic-gate * Returns 0 if a child died without an error. 14280Sstevel@tonic-gate * Returns 1 if a child died with an error. 14290Sstevel@tonic-gate */ 14300Sstevel@tonic-gate int 1431821Sdh145677 dowait(void) 14320Sstevel@tonic-gate { 14330Sstevel@tonic-gate int child, wstat; 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate if ((child = wait(&wstat)) == -1) 14360Sstevel@tonic-gate return (-1); 14370Sstevel@tonic-gate nrun--; 14380Sstevel@tonic-gate return (cleanupkid(child, wstat) != 0); 14390Sstevel@tonic-gate } 14400Sstevel@tonic-gate 14410Sstevel@tonic-gate /* 14420Sstevel@tonic-gate * Locates the child mount process represented by pid, outputs any io 14430Sstevel@tonic-gate * it may have, and returns its exit code. 14440Sstevel@tonic-gate * Sets the global exitcode if an error occurred. 14450Sstevel@tonic-gate */ 14460Sstevel@tonic-gate int 14470Sstevel@tonic-gate cleanupkid(pid_t pid, int wstat) 14480Sstevel@tonic-gate { 14490Sstevel@tonic-gate vfsent_t *vp, *prevp; 14500Sstevel@tonic-gate int ret; 14510Sstevel@tonic-gate 14520Sstevel@tonic-gate if (WIFEXITED(wstat)) /* this should always be true */ 14530Sstevel@tonic-gate ret = WEXITSTATUS(wstat); 14540Sstevel@tonic-gate else 14550Sstevel@tonic-gate ret = 1; /* assume some kind of error */ 1456*8155STim.Haley@Sun.COM if (ret) { 14570Sstevel@tonic-gate exitcode = 1; 1458*8155STim.Haley@Sun.COM failcnt++; 1459*8155STim.Haley@Sun.COM } 14600Sstevel@tonic-gate 14610Sstevel@tonic-gate /* 14620Sstevel@tonic-gate * Find our child. 14630Sstevel@tonic-gate * This search gets smaller and smaller as children are cleaned 14640Sstevel@tonic-gate * up. 14650Sstevel@tonic-gate */ 14660Sstevel@tonic-gate for (prevp = NULL, vp = vfsll; vp; vp = vp->next) { 14670Sstevel@tonic-gate if (vp->pid != pid) { 14680Sstevel@tonic-gate prevp = vp; 14690Sstevel@tonic-gate continue; 14700Sstevel@tonic-gate } 14710Sstevel@tonic-gate /* 14720Sstevel@tonic-gate * Found: let's remove it from this linked list. 14730Sstevel@tonic-gate */ 14740Sstevel@tonic-gate if (prevp) { 14750Sstevel@tonic-gate prevp->next = vp->next; 14760Sstevel@tonic-gate vp->next = NULL; 14770Sstevel@tonic-gate } 14780Sstevel@tonic-gate break; 14790Sstevel@tonic-gate } 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate if (vp == NULL) { 14820Sstevel@tonic-gate /* 14830Sstevel@tonic-gate * This should never happen. 14840Sstevel@tonic-gate */ 14850Sstevel@tonic-gate fprintf(stderr, gettext( 14866007Sthurlow "%s: Unknown child %d\n"), myname, pid); 14870Sstevel@tonic-gate exitcode = 1; 14880Sstevel@tonic-gate return (ret); 14890Sstevel@tonic-gate } 14900Sstevel@tonic-gate doio(vp); /* Any output? */ 14910Sstevel@tonic-gate 1492*8155STim.Haley@Sun.COM if (vp->v.vfs_fstype && 1493*8155STim.Haley@Sun.COM (strcmp(vp->v.vfs_fstype, MNTTYPE_LOFS) == 0)) { 14940Sstevel@tonic-gate lofscnt--; 1495*8155STim.Haley@Sun.COM if (ret) 1496*8155STim.Haley@Sun.COM lofsfail++; 1497*8155STim.Haley@Sun.COM } 14980Sstevel@tonic-gate 14990Sstevel@tonic-gate #ifdef CACHEFS_BUG 15000Sstevel@tonic-gate if (vp->v.vfs_fstype && (strcmp(vp->v.vfs_fstype, "cachefs") == 0)) 15010Sstevel@tonic-gate cachefs_running = 0; 15020Sstevel@tonic-gate #endif 15030Sstevel@tonic-gate 15040Sstevel@tonic-gate vp->exitcode = ret; 15050Sstevel@tonic-gate return (ret); 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate 15080Sstevel@tonic-gate 15090Sstevel@tonic-gate static vfsent_t zvmount = { 0 }; 15100Sstevel@tonic-gate 15110Sstevel@tonic-gate vfsent_t * 15120Sstevel@tonic-gate new_vfsent(struct vfstab *vin, int order) 15130Sstevel@tonic-gate { 15140Sstevel@tonic-gate vfsent_t *new; 15150Sstevel@tonic-gate 15160Sstevel@tonic-gate new = (vfsent_t *)malloc(sizeof (*new)); 15170Sstevel@tonic-gate if (new == NULL) 15180Sstevel@tonic-gate nomem(); 15190Sstevel@tonic-gate 15200Sstevel@tonic-gate *new = zvmount; 15210Sstevel@tonic-gate if (vin->vfs_special && 15220Sstevel@tonic-gate (new->v.vfs_special = strdup(vin->vfs_special)) == NULL) 15230Sstevel@tonic-gate nomem(); 15240Sstevel@tonic-gate if (vin->vfs_mountp && 15250Sstevel@tonic-gate (new->v.vfs_mountp = strdup(vin->vfs_mountp)) == NULL) 15260Sstevel@tonic-gate nomem(); 15270Sstevel@tonic-gate if (vin->vfs_fstype && 15280Sstevel@tonic-gate (new->v.vfs_fstype = strdup(vin->vfs_fstype)) == NULL) 15290Sstevel@tonic-gate nomem(); 15300Sstevel@tonic-gate /* 15310Sstevel@tonic-gate * If specific mount options were specified on the command 15320Sstevel@tonic-gate * line, then use those. Else, use the ones on the vfstab 15330Sstevel@tonic-gate * line, if any. In other words, specific options on the 15340Sstevel@tonic-gate * command line override those in /etc/vfstab. 15350Sstevel@tonic-gate */ 15360Sstevel@tonic-gate if (oflg) { 15370Sstevel@tonic-gate if ((new->v.vfs_mntopts = strdup(specific_opts)) == NULL) 15380Sstevel@tonic-gate nomem(); 15390Sstevel@tonic-gate } else if (vin->vfs_mntopts && 15406007Sthurlow (new->v.vfs_mntopts = strdup(vin->vfs_mntopts)) == NULL) 15410Sstevel@tonic-gate nomem(); 15420Sstevel@tonic-gate 15430Sstevel@tonic-gate new->order = order; 15440Sstevel@tonic-gate return (new); 15450Sstevel@tonic-gate } 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate /* 15480Sstevel@tonic-gate * Runs realpath on vp's mount point, records success or failure, 15490Sstevel@tonic-gate * resets the mount level based on the new realpath, and returns 15500Sstevel@tonic-gate * realpath()'s return value. 15510Sstevel@tonic-gate */ 15520Sstevel@tonic-gate char * 15530Sstevel@tonic-gate setrpath(vfsent_t *vp) 15540Sstevel@tonic-gate { 15550Sstevel@tonic-gate char *rp; 15560Sstevel@tonic-gate 15570Sstevel@tonic-gate if ((rp = realpath(vp->v.vfs_mountp, realdir)) == NULL) 15580Sstevel@tonic-gate vp->flag |= VRPFAILED; 15590Sstevel@tonic-gate else 15600Sstevel@tonic-gate vp->flag &= ~VRPFAILED; 15610Sstevel@tonic-gate 15620Sstevel@tonic-gate if (vp->rpath) 15630Sstevel@tonic-gate free(vp->rpath); 15640Sstevel@tonic-gate if ((vp->rpath = strdup(realdir)) == NULL) 15650Sstevel@tonic-gate nomem(); 15660Sstevel@tonic-gate vp->mlevel = fsgetmlevel(vp->rpath); 15670Sstevel@tonic-gate return (rp); 15680Sstevel@tonic-gate } 15690Sstevel@tonic-gate 15700Sstevel@tonic-gate 15710Sstevel@tonic-gate /* 15720Sstevel@tonic-gate * sort first by mlevel (1...N), then by vfstab order. 15730Sstevel@tonic-gate */ 15740Sstevel@tonic-gate int 15750Sstevel@tonic-gate mlevelcmp(const void *a, const void *b) 15760Sstevel@tonic-gate { 15770Sstevel@tonic-gate vfsent_t *a1, *b1; 15780Sstevel@tonic-gate int lcmp; 15790Sstevel@tonic-gate 15800Sstevel@tonic-gate a1 = *(vfsent_t **)a; 15810Sstevel@tonic-gate b1 = *(vfsent_t **)b; 15820Sstevel@tonic-gate 15830Sstevel@tonic-gate lcmp = a1->mlevel - b1->mlevel; 15840Sstevel@tonic-gate if (lcmp == 0) 15850Sstevel@tonic-gate lcmp = a1->order - b1->order; 15860Sstevel@tonic-gate return (lcmp); 15870Sstevel@tonic-gate } 15880Sstevel@tonic-gate 15890Sstevel@tonic-gate /* sort by vfstab order. 0..N */ 1590821Sdh145677 static int 15910Sstevel@tonic-gate mordercmp(const void *a, const void *b) 15920Sstevel@tonic-gate { 15930Sstevel@tonic-gate vfsent_t *a1, *b1; 15940Sstevel@tonic-gate 15950Sstevel@tonic-gate a1 = *(vfsent_t **)a; 15960Sstevel@tonic-gate b1 = *(vfsent_t **)b; 15970Sstevel@tonic-gate return (a1->order - b1->order); 15980Sstevel@tonic-gate } 15990Sstevel@tonic-gate 16000Sstevel@tonic-gate /* 16010Sstevel@tonic-gate * cleanup the existing children and exit with an error 16020Sstevel@tonic-gate * if asig != 0. 16030Sstevel@tonic-gate */ 16040Sstevel@tonic-gate void 16050Sstevel@tonic-gate cleanup(int asig) 16060Sstevel@tonic-gate { 16070Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 16080Sstevel@tonic-gate ; 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate if (asig != 0) 16110Sstevel@tonic-gate exit(1); 16120Sstevel@tonic-gate } 16130Sstevel@tonic-gate 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate int 16160Sstevel@tonic-gate check_fields(char *fstype, char *mountp) 16170Sstevel@tonic-gate { 16180Sstevel@tonic-gate struct stat64 stbuf; 16190Sstevel@tonic-gate 16200Sstevel@tonic-gate if (strlen(fstype) > (size_t)FSTYPE_MAX) { 16210Sstevel@tonic-gate fprintf(stderr, 16226007Sthurlow gettext("%s: FSType %s exceeds %d characters\n"), 16236007Sthurlow myname, fstype, FSTYPE_MAX); 16240Sstevel@tonic-gate return (1); 16250Sstevel@tonic-gate } 16260Sstevel@tonic-gate 16270Sstevel@tonic-gate if (mountp == NULL) { 16280Sstevel@tonic-gate fprintf(stderr, 16296007Sthurlow gettext("%s: Mount point cannot be determined\n"), 16306007Sthurlow myname); 16310Sstevel@tonic-gate return (1); 16320Sstevel@tonic-gate } 16330Sstevel@tonic-gate if (*mountp != '/') { 16340Sstevel@tonic-gate fprintf(stderr, gettext( 16356007Sthurlow "%s: Mount point %s is not an absolute pathname.\n"), 16366007Sthurlow myname, mountp); 16370Sstevel@tonic-gate return (1); 16380Sstevel@tonic-gate } 16390Sstevel@tonic-gate /* 16400Sstevel@tonic-gate * Don't do some of these checks if aflg because a mount point may 16410Sstevel@tonic-gate * not exist now, but will be mounted before we get to it. 16420Sstevel@tonic-gate * This is one of the quirks of "secondary mounting". 16430Sstevel@tonic-gate */ 16440Sstevel@tonic-gate if (!aflg && stat64(mountp, &stbuf) < 0) { 16450Sstevel@tonic-gate if (errno == ENOENT || errno == ENOTDIR) 16460Sstevel@tonic-gate fprintf(stderr, 16476007Sthurlow gettext("%s: Mount point %s does not exist.\n"), 16486007Sthurlow myname, mountp); 16490Sstevel@tonic-gate else { 16500Sstevel@tonic-gate fprintf(stderr, 16516007Sthurlow gettext("%s: Cannot stat mount point %s.\n"), 16526007Sthurlow myname, mountp); 16530Sstevel@tonic-gate perror(myname); 16540Sstevel@tonic-gate } 16550Sstevel@tonic-gate return (1); 16560Sstevel@tonic-gate } 16570Sstevel@tonic-gate return (0); 16580Sstevel@tonic-gate } 16590Sstevel@tonic-gate 16600Sstevel@tonic-gate void 1661821Sdh145677 nomem(void) 16620Sstevel@tonic-gate { 16630Sstevel@tonic-gate fprintf(stderr, gettext("%s: Out of memory\n"), myname); 16640Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 16650Sstevel@tonic-gate ; 16660Sstevel@tonic-gate exit(1); 16670Sstevel@tonic-gate } 1668