1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.82 */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <limits.h> 35*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 36*7c478bd9Sstevel@tonic-gate #include <unistd.h> 37*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 38*7c478bd9Sstevel@tonic-gate #include <string.h> 39*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 43*7c478bd9Sstevel@tonic-gate #include <errno.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/mount.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 52*7c478bd9Sstevel@tonic-gate #include <stropts.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 54*7c478bd9Sstevel@tonic-gate #include <locale.h> 55*7c478bd9Sstevel@tonic-gate #include "fslib.h" 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate #define VFS_PATH "/usr/lib/fs" 58*7c478bd9Sstevel@tonic-gate #define ALT_PATH "/etc/fs" 59*7c478bd9Sstevel@tonic-gate #define REMOTE "/etc/dfs/fstypes" 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #define ARGV_MAX 16 62*7c478bd9Sstevel@tonic-gate #define TIME_MAX 50 63*7c478bd9Sstevel@tonic-gate #define FSTYPE_MAX 8 64*7c478bd9Sstevel@tonic-gate #define REMOTE_MAX 64 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #define OLD 0 67*7c478bd9Sstevel@tonic-gate #define NEW 1 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #define READONLY 0 70*7c478bd9Sstevel@tonic-gate #define READWRITE 1 71*7c478bd9Sstevel@tonic-gate #define SUID 2 72*7c478bd9Sstevel@tonic-gate #define NOSUID 3 73*7c478bd9Sstevel@tonic-gate #define SETUID 4 74*7c478bd9Sstevel@tonic-gate #define NOSETUID 5 75*7c478bd9Sstevel@tonic-gate #define DEVICES 6 76*7c478bd9Sstevel@tonic-gate #define NODEVICES 7 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate #define FORMAT "%a %b %e %H:%M:%S %Y\n" /* date time format */ 79*7c478bd9Sstevel@tonic-gate /* a - abbreviated weekday name */ 80*7c478bd9Sstevel@tonic-gate /* b - abbreviated month name */ 81*7c478bd9Sstevel@tonic-gate /* e - day of month */ 82*7c478bd9Sstevel@tonic-gate /* H - hour */ 83*7c478bd9Sstevel@tonic-gate /* M - minute */ 84*7c478bd9Sstevel@tonic-gate /* S - second */ 85*7c478bd9Sstevel@tonic-gate /* Y - Year */ 86*7c478bd9Sstevel@tonic-gate /* n - newline */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate extern int optind; 89*7c478bd9Sstevel@tonic-gate extern char *optarg; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate extern void usage(void); 92*7c478bd9Sstevel@tonic-gate extern char *flags(char *, int); 93*7c478bd9Sstevel@tonic-gate extern char *remote(char *, FILE *); 94*7c478bd9Sstevel@tonic-gate extern char *default_fstype(char *); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate char *myopts[] = { 97*7c478bd9Sstevel@tonic-gate MNTOPT_RO, 98*7c478bd9Sstevel@tonic-gate MNTOPT_RW, 99*7c478bd9Sstevel@tonic-gate MNTOPT_SUID, 100*7c478bd9Sstevel@tonic-gate MNTOPT_NOSUID, 101*7c478bd9Sstevel@tonic-gate MNTOPT_SETUID, 102*7c478bd9Sstevel@tonic-gate MNTOPT_NOSETUID, 103*7c478bd9Sstevel@tonic-gate MNTOPT_DEVICES, 104*7c478bd9Sstevel@tonic-gate MNTOPT_NODEVICES, 105*7c478bd9Sstevel@tonic-gate NULL 106*7c478bd9Sstevel@tonic-gate }; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate static char *myname; /* point to argv[0] */ 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate /* 111*7c478bd9Sstevel@tonic-gate * Set the limit to double the number of characters a user should be allowed to 112*7c478bd9Sstevel@tonic-gate * type in one line. 113*7c478bd9Sstevel@tonic-gate * This should cover the different shells, which don't use POSIX_MAX_INPUT, 114*7c478bd9Sstevel@tonic-gate * and should cover the case where a long option string can be in 115*7c478bd9Sstevel@tonic-gate * the /etc/vfstab file. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate char mntflags[(_POSIX_MAX_INPUT+1) * 2]; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate char realdir[MAXPATHLEN]; /* buffer for realpath() calls */ 120*7c478bd9Sstevel@tonic-gate char *vfstab = VFSTAB; 121*7c478bd9Sstevel@tonic-gate char *mnttab = MNTTAB; 122*7c478bd9Sstevel@tonic-gate char *specific_opts; /* holds specific mount options */ 123*7c478bd9Sstevel@tonic-gate char *generic_opts; /* holds generic mount options */ 124*7c478bd9Sstevel@tonic-gate int maxrun; 125*7c478bd9Sstevel@tonic-gate int nrun; 126*7c478bd9Sstevel@tonic-gate int lofscnt; /* presence of lofs prohibits parallel */ 127*7c478bd9Sstevel@tonic-gate /* mounting */ 128*7c478bd9Sstevel@tonic-gate int exitcode; 129*7c478bd9Sstevel@tonic-gate int aflg, cflg, fflg, Fflg, gflg, oflg, pflg, rflg, vflg, Vflg, mflg, Oflg, 130*7c478bd9Sstevel@tonic-gate dashflg, questflg, dflg, qflg; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * Currently, mounting cachefs instances simultaneously uncovers various 134*7c478bd9Sstevel@tonic-gate * problems. For the short term, we serialize cachefs activity while we fix 135*7c478bd9Sstevel@tonic-gate * these cachefs bugs. 136*7c478bd9Sstevel@tonic-gate */ 137*7c478bd9Sstevel@tonic-gate #define CACHEFS_BUG 138*7c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 139*7c478bd9Sstevel@tonic-gate int cachefs_running; /* parallel cachefs not supported yet */ 140*7c478bd9Sstevel@tonic-gate #endif 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * Each vfsent_t describes a vfstab entry. It is used to manage and cleanup 144*7c478bd9Sstevel@tonic-gate * each child that performs the particular mount for the entry. 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate typedef struct vfsent { 148*7c478bd9Sstevel@tonic-gate struct vfstab v; /* the vfstab entry */ 149*7c478bd9Sstevel@tonic-gate char *rpath; /* resolved pathname so far */ 150*7c478bd9Sstevel@tonic-gate int mlevel; /* how deep is this mount point */ 151*7c478bd9Sstevel@tonic-gate int order; /* vfstab serial order of this vfs */ 152*7c478bd9Sstevel@tonic-gate int flag; 153*7c478bd9Sstevel@tonic-gate pid_t pid; /* the pid of this mount process */ 154*7c478bd9Sstevel@tonic-gate int exitcode; /* process's exitcode */ 155*7c478bd9Sstevel@tonic-gate #define RDPIPE 0 156*7c478bd9Sstevel@tonic-gate #define WRPIPE 1 157*7c478bd9Sstevel@tonic-gate int sopipe[2]; /* pipe attached to child's stdout */ 158*7c478bd9Sstevel@tonic-gate int sepipe[2]; /* pipe attached to child's stderr */ 159*7c478bd9Sstevel@tonic-gate struct vfsent *next; /* used when in linked list */ 160*7c478bd9Sstevel@tonic-gate } vfsent_t; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate #define VRPFAILED 0x01 /* most recent realpath failed on */ 163*7c478bd9Sstevel@tonic-gate /* this mount point */ 164*7c478bd9Sstevel@tonic-gate #define VNOTMOUNTED 0x02 /* mount point could not be mounted */ 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate vfsent_t *vfsll, *vfslltail; /* head and tail of the global */ 167*7c478bd9Sstevel@tonic-gate /* linked list of vfstab entries */ 168*7c478bd9Sstevel@tonic-gate vfsent_t **vfsarray; /* global array of vfsent_t's */ 169*7c478bd9Sstevel@tonic-gate int vfsarraysize; /* length of the list */ 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * This structure is used to build a linked list of 173*7c478bd9Sstevel@tonic-gate * mnttab structures from /etc/mnttab. 174*7c478bd9Sstevel@tonic-gate */ 175*7c478bd9Sstevel@tonic-gate typedef struct mountent { 176*7c478bd9Sstevel@tonic-gate struct extmnttab *ment; 177*7c478bd9Sstevel@tonic-gate int flag; 178*7c478bd9Sstevel@tonic-gate struct mountent *next; 179*7c478bd9Sstevel@tonic-gate } mountent_t; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate #define MSORTED 0x1 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate static vfsent_t **make_vfsarray(char **, int); 184*7c478bd9Sstevel@tonic-gate static vfsent_t *new_vfsent(struct vfstab *, int); 185*7c478bd9Sstevel@tonic-gate static vfsent_t *getvfsall(char *, int); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate static void doexec(char *, char **); 188*7c478bd9Sstevel@tonic-gate static void nomem(); 189*7c478bd9Sstevel@tonic-gate static void cleanup(int); 190*7c478bd9Sstevel@tonic-gate static char *setrpath(vfsent_t *); 191*7c478bd9Sstevel@tonic-gate static int dowait(); 192*7c478bd9Sstevel@tonic-gate static int setup_iopipe(vfsent_t *); 193*7c478bd9Sstevel@tonic-gate static void setup_output(vfsent_t *); 194*7c478bd9Sstevel@tonic-gate static void doio(vfsent_t *); 195*7c478bd9Sstevel@tonic-gate static void do_mounts(); 196*7c478bd9Sstevel@tonic-gate static int parmount(char **, int, char *); 197*7c478bd9Sstevel@tonic-gate static int mlevelcmp(const void *, const void *); 198*7c478bd9Sstevel@tonic-gate static int mordercmp(const void *, const void *); 199*7c478bd9Sstevel@tonic-gate static int check_fields(char *, char *); 200*7c478bd9Sstevel@tonic-gate static int cleanupkid(pid_t, int); 201*7c478bd9Sstevel@tonic-gate static void print_mnttab(int, int); 202*7c478bd9Sstevel@tonic-gate static void vfserror(int, char *); 203*7c478bd9Sstevel@tonic-gate static void mnterror(int); 204*7c478bd9Sstevel@tonic-gate static int ignore(char *); 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* 207*7c478bd9Sstevel@tonic-gate * This is /usr/sbin/mount: the generic command that in turn 208*7c478bd9Sstevel@tonic-gate * execs the appropriate /usr/lib/fs/{fstype}/mount. 209*7c478bd9Sstevel@tonic-gate * The -F flag and argument are NOT passed. 210*7c478bd9Sstevel@tonic-gate * If the usr file system is not mounted a duplicate copy 211*7c478bd9Sstevel@tonic-gate * can be found in /sbin and this version execs the 212*7c478bd9Sstevel@tonic-gate * appropriate /etc/fs/{fstype}/mount 213*7c478bd9Sstevel@tonic-gate * 214*7c478bd9Sstevel@tonic-gate * If the -F fstype, special or directory are missing, 215*7c478bd9Sstevel@tonic-gate * /etc/vfstab is searched to fill in the missing arguments. 216*7c478bd9Sstevel@tonic-gate * 217*7c478bd9Sstevel@tonic-gate * -V will print the built command on the stdout. 218*7c478bd9Sstevel@tonic-gate * It isn't passed either. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate void 221*7c478bd9Sstevel@tonic-gate main(argc, argv) 222*7c478bd9Sstevel@tonic-gate int argc; 223*7c478bd9Sstevel@tonic-gate char *argv[]; 224*7c478bd9Sstevel@tonic-gate { 225*7c478bd9Sstevel@tonic-gate char *special, /* argument of special/resource */ 226*7c478bd9Sstevel@tonic-gate *mountp, /* argument of mount directory */ 227*7c478bd9Sstevel@tonic-gate *fstype, /* wherein the fstype name is filled */ 228*7c478bd9Sstevel@tonic-gate *newargv[ARGV_MAX], /* arg list for specific command */ 229*7c478bd9Sstevel@tonic-gate *farg = NULL, *Farg = NULL; 230*7c478bd9Sstevel@tonic-gate int ii, ret, cc, fscnt; 231*7c478bd9Sstevel@tonic-gate struct stat64 stbuf; 232*7c478bd9Sstevel@tonic-gate struct vfstab vget, vref; 233*7c478bd9Sstevel@tonic-gate mode_t mode; 234*7c478bd9Sstevel@tonic-gate FILE *fd; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 239*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 240*7c478bd9Sstevel@tonic-gate #endif 241*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate myname = strrchr(argv[0], '/'); 244*7c478bd9Sstevel@tonic-gate if (myname) 245*7c478bd9Sstevel@tonic-gate myname++; 246*7c478bd9Sstevel@tonic-gate else 247*7c478bd9Sstevel@tonic-gate myname = argv[0]; 248*7c478bd9Sstevel@tonic-gate if (myname == 0) myname = "path unknown"; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* Process the args. */ 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate while ((cc = getopt(argc, argv, "?acd:f:F:gmno:pqrvVO")) != -1) 253*7c478bd9Sstevel@tonic-gate switch (cc) { 254*7c478bd9Sstevel@tonic-gate case 'a': 255*7c478bd9Sstevel@tonic-gate aflg++; 256*7c478bd9Sstevel@tonic-gate break; 257*7c478bd9Sstevel@tonic-gate case 'c': 258*7c478bd9Sstevel@tonic-gate cflg++; 259*7c478bd9Sstevel@tonic-gate break; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 262*7c478bd9Sstevel@tonic-gate case 'd': 263*7c478bd9Sstevel@tonic-gate dflg = atoi(optarg); 264*7c478bd9Sstevel@tonic-gate break; 265*7c478bd9Sstevel@tonic-gate #endif 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate case 'f': 268*7c478bd9Sstevel@tonic-gate fflg++; 269*7c478bd9Sstevel@tonic-gate farg = optarg; 270*7c478bd9Sstevel@tonic-gate break; 271*7c478bd9Sstevel@tonic-gate case 'F': 272*7c478bd9Sstevel@tonic-gate Fflg++; 273*7c478bd9Sstevel@tonic-gate Farg = optarg; 274*7c478bd9Sstevel@tonic-gate break; 275*7c478bd9Sstevel@tonic-gate case 'g': 276*7c478bd9Sstevel@tonic-gate gflg++; 277*7c478bd9Sstevel@tonic-gate break; 278*7c478bd9Sstevel@tonic-gate case 'm': 279*7c478bd9Sstevel@tonic-gate mflg++; 280*7c478bd9Sstevel@tonic-gate break; /* do not update /etc/mnttab */ 281*7c478bd9Sstevel@tonic-gate case 'o': 282*7c478bd9Sstevel@tonic-gate oflg++; 283*7c478bd9Sstevel@tonic-gate if ((specific_opts = strdup(optarg)) == NULL) 284*7c478bd9Sstevel@tonic-gate nomem(); 285*7c478bd9Sstevel@tonic-gate break; /* fstype dependent options */ 286*7c478bd9Sstevel@tonic-gate case 'O': 287*7c478bd9Sstevel@tonic-gate Oflg++; 288*7c478bd9Sstevel@tonic-gate break; 289*7c478bd9Sstevel@tonic-gate case 'p': 290*7c478bd9Sstevel@tonic-gate pflg++; 291*7c478bd9Sstevel@tonic-gate break; 292*7c478bd9Sstevel@tonic-gate case 'q': 293*7c478bd9Sstevel@tonic-gate qflg++; 294*7c478bd9Sstevel@tonic-gate break; 295*7c478bd9Sstevel@tonic-gate case 'r': 296*7c478bd9Sstevel@tonic-gate rflg++; 297*7c478bd9Sstevel@tonic-gate generic_opts = "ro"; 298*7c478bd9Sstevel@tonic-gate break; 299*7c478bd9Sstevel@tonic-gate case 'v': 300*7c478bd9Sstevel@tonic-gate vflg++; 301*7c478bd9Sstevel@tonic-gate break; 302*7c478bd9Sstevel@tonic-gate case 'V': 303*7c478bd9Sstevel@tonic-gate Vflg++; 304*7c478bd9Sstevel@tonic-gate break; 305*7c478bd9Sstevel@tonic-gate case '?': 306*7c478bd9Sstevel@tonic-gate questflg++; 307*7c478bd9Sstevel@tonic-gate break; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* copy '--' to specific */ 311*7c478bd9Sstevel@tonic-gate if (strcmp(argv[optind-1], "--") == 0) 312*7c478bd9Sstevel@tonic-gate dashflg++; 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /* option checking */ 315*7c478bd9Sstevel@tonic-gate /* more than two args not allowed if !aflg */ 316*7c478bd9Sstevel@tonic-gate if (!aflg && (argc - optind > 2)) 317*7c478bd9Sstevel@tonic-gate usage(); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* pv mututally exclusive */ 320*7c478bd9Sstevel@tonic-gate if (pflg + vflg + aflg > 1) { 321*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext 322*7c478bd9Sstevel@tonic-gate ("%s: -a, -p, and -v are mutually exclusive\n"), 323*7c478bd9Sstevel@tonic-gate myname); 324*7c478bd9Sstevel@tonic-gate usage(); 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * Can't have overlaying mounts on the same mount point during 329*7c478bd9Sstevel@tonic-gate * a parallel mount. 330*7c478bd9Sstevel@tonic-gate */ 331*7c478bd9Sstevel@tonic-gate if (aflg && Oflg) { 332*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext 333*7c478bd9Sstevel@tonic-gate ("%s: -a and -O are mutually exclusive\n"), myname); 334*7c478bd9Sstevel@tonic-gate usage(); 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* dfF mutually exclusive */ 338*7c478bd9Sstevel@tonic-gate if (fflg + Fflg > 1) { 339*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext 340*7c478bd9Sstevel@tonic-gate ("%s: More than one FSType specified\n"), myname); 341*7c478bd9Sstevel@tonic-gate usage(); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* no arguments, only allow p,v,V or [F]? */ 345*7c478bd9Sstevel@tonic-gate if (!aflg && optind == argc) { 346*7c478bd9Sstevel@tonic-gate if (cflg || fflg || mflg || oflg || rflg || qflg) 347*7c478bd9Sstevel@tonic-gate usage(); 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate if (Fflg && !questflg) 350*7c478bd9Sstevel@tonic-gate usage(); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate if (questflg) { 353*7c478bd9Sstevel@tonic-gate if (Fflg) { 354*7c478bd9Sstevel@tonic-gate newargv[2] = "-?"; 355*7c478bd9Sstevel@tonic-gate newargv[3] = NULL; 356*7c478bd9Sstevel@tonic-gate doexec(Farg, newargv); 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate usage(); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate if (questflg) 363*7c478bd9Sstevel@tonic-gate usage(); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* one or two args, allow any but p,v */ 366*7c478bd9Sstevel@tonic-gate if (optind != argc && (pflg || vflg)) { 367*7c478bd9Sstevel@tonic-gate fprintf(stderr, 368*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot use -p and -v with arguments\n"), myname); 369*7c478bd9Sstevel@tonic-gate usage(); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate /* if only reporting mnttab, generic prints mnttab and exits */ 374*7c478bd9Sstevel@tonic-gate if (!aflg && optind == argc) { 375*7c478bd9Sstevel@tonic-gate if (Vflg) { 376*7c478bd9Sstevel@tonic-gate printf("%s", myname); 377*7c478bd9Sstevel@tonic-gate if (pflg) 378*7c478bd9Sstevel@tonic-gate printf(" -p"); 379*7c478bd9Sstevel@tonic-gate if (vflg) 380*7c478bd9Sstevel@tonic-gate printf(" -v"); 381*7c478bd9Sstevel@tonic-gate printf("\n"); 382*7c478bd9Sstevel@tonic-gate exit(0); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate print_mnttab(vflg, pflg); 386*7c478bd9Sstevel@tonic-gate exit(0); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* 390*7c478bd9Sstevel@tonic-gate * Get filesystem type here. If "-F FStype" is specified, use 391*7c478bd9Sstevel@tonic-gate * that fs type. Otherwise, determine the fs type from /etc/vfstab 392*7c478bd9Sstevel@tonic-gate * if the entry exists. Otherwise, determine the local or remote 393*7c478bd9Sstevel@tonic-gate * fs type from /etc/default/df or /etc/dfs/fstypes respectively. 394*7c478bd9Sstevel@tonic-gate */ 395*7c478bd9Sstevel@tonic-gate if (fflg) { 396*7c478bd9Sstevel@tonic-gate if ((strcmp(farg, "S51K") != 0) && 397*7c478bd9Sstevel@tonic-gate (strcmp(farg, "S52K") != 0)) { 398*7c478bd9Sstevel@tonic-gate fstype = farg; 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate else 401*7c478bd9Sstevel@tonic-gate fstype = "ufs"; 402*7c478bd9Sstevel@tonic-gate } else /* if (Fflg) */ 403*7c478bd9Sstevel@tonic-gate fstype = Farg; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate fscnt = argc - optind; 406*7c478bd9Sstevel@tonic-gate if (aflg && (fscnt != 1)) 407*7c478bd9Sstevel@tonic-gate exit(parmount(argv + optind, fscnt, fstype)); 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * Then don't bother with the parallel over head. Everything 411*7c478bd9Sstevel@tonic-gate * from this point is simple/normal single execution. 412*7c478bd9Sstevel@tonic-gate */ 413*7c478bd9Sstevel@tonic-gate aflg = 0; 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate /* get special and/or mount-point from arg(s) */ 416*7c478bd9Sstevel@tonic-gate if (fscnt == 2) 417*7c478bd9Sstevel@tonic-gate special = argv[optind++]; 418*7c478bd9Sstevel@tonic-gate else 419*7c478bd9Sstevel@tonic-gate special = NULL; 420*7c478bd9Sstevel@tonic-gate if (optind < argc) 421*7c478bd9Sstevel@tonic-gate mountp = argv[optind++]; 422*7c478bd9Sstevel@tonic-gate else 423*7c478bd9Sstevel@tonic-gate mountp = NULL; 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate /* lookup only if we need to */ 426*7c478bd9Sstevel@tonic-gate if (fstype == NULL || specific_opts == NULL || special == NULL || 427*7c478bd9Sstevel@tonic-gate mountp == NULL) { 428*7c478bd9Sstevel@tonic-gate if ((fd = fopen(vfstab, "r")) == NULL) { 429*7c478bd9Sstevel@tonic-gate if (fstype == NULL || special == NULL || 430*7c478bd9Sstevel@tonic-gate mountp == NULL) { 431*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 432*7c478bd9Sstevel@tonic-gate "%s: Cannot open %s\n"), 433*7c478bd9Sstevel@tonic-gate myname, vfstab); 434*7c478bd9Sstevel@tonic-gate exit(1); 435*7c478bd9Sstevel@tonic-gate } else { 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * No vfstab, but we know what we want 438*7c478bd9Sstevel@tonic-gate * to mount. 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate goto out; 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate vfsnull(&vref); 444*7c478bd9Sstevel@tonic-gate vref.vfs_special = special; 445*7c478bd9Sstevel@tonic-gate vref.vfs_mountp = mountp; 446*7c478bd9Sstevel@tonic-gate vref.vfs_fstype = fstype; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate /* get a vfstab entry matching mountp or special */ 449*7c478bd9Sstevel@tonic-gate while ((ret = getvfsany(fd, &vget, &vref)) > 0) 450*7c478bd9Sstevel@tonic-gate vfserror(ret, vget.vfs_special); 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* if no entry and there was only one argument */ 453*7c478bd9Sstevel@tonic-gate /* then the argument could be the special */ 454*7c478bd9Sstevel@tonic-gate /* and not mount point as we thought earlier */ 455*7c478bd9Sstevel@tonic-gate if (ret == -1 && special == NULL) { 456*7c478bd9Sstevel@tonic-gate rewind(fd); 457*7c478bd9Sstevel@tonic-gate special = vref.vfs_special = mountp; 458*7c478bd9Sstevel@tonic-gate mountp = vref.vfs_mountp = NULL; 459*7c478bd9Sstevel@tonic-gate /* skip erroneous lines; they were reported above */ 460*7c478bd9Sstevel@tonic-gate while ((ret = getvfsany(fd, &vget, &vref)) > 0); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate fclose(fd); 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate if (ret == 0) { 466*7c478bd9Sstevel@tonic-gate if (fstype == NULL) 467*7c478bd9Sstevel@tonic-gate fstype = vget.vfs_fstype; 468*7c478bd9Sstevel@tonic-gate if (special == NULL) 469*7c478bd9Sstevel@tonic-gate special = vget.vfs_special; 470*7c478bd9Sstevel@tonic-gate if (mountp == NULL) 471*7c478bd9Sstevel@tonic-gate mountp = vget.vfs_mountp; 472*7c478bd9Sstevel@tonic-gate if (oflg == 0 && vget.vfs_mntopts) { 473*7c478bd9Sstevel@tonic-gate oflg++; 474*7c478bd9Sstevel@tonic-gate specific_opts = vget.vfs_mntopts; 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate } else if (special == NULL) { 477*7c478bd9Sstevel@tonic-gate if (stat64(mountp, &stbuf) == -1) { 478*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: cannot stat %s\n"), 479*7c478bd9Sstevel@tonic-gate myname, mountp); 480*7c478bd9Sstevel@tonic-gate exit(2); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate if (((mode = (stbuf.st_mode & S_IFMT)) == S_IFBLK) || 483*7c478bd9Sstevel@tonic-gate (mode == S_IFCHR)) { 484*7c478bd9Sstevel@tonic-gate fprintf(stderr, 485*7c478bd9Sstevel@tonic-gate gettext("%s: mount point cannot be determined\n"), 486*7c478bd9Sstevel@tonic-gate myname); 487*7c478bd9Sstevel@tonic-gate exit(1); 488*7c478bd9Sstevel@tonic-gate } else 489*7c478bd9Sstevel@tonic-gate { 490*7c478bd9Sstevel@tonic-gate fprintf(stderr, 491*7c478bd9Sstevel@tonic-gate gettext("%s: special cannot be determined\n"), 492*7c478bd9Sstevel@tonic-gate myname); 493*7c478bd9Sstevel@tonic-gate exit(1); 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate } else if (fstype == NULL) 496*7c478bd9Sstevel@tonic-gate fstype = default_fstype(special); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate out: 500*7c478bd9Sstevel@tonic-gate if (check_fields(fstype, mountp)) 501*7c478bd9Sstevel@tonic-gate exit(1); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate if (realpath(mountp, realdir) == NULL) { 504*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "mount: "); 505*7c478bd9Sstevel@tonic-gate perror(mountp); 506*7c478bd9Sstevel@tonic-gate exit(1); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate if ((mountp = strdup(realdir)) == NULL) 510*7c478bd9Sstevel@tonic-gate nomem(); 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* create the new arg list, and end the list with a null pointer */ 513*7c478bd9Sstevel@tonic-gate ii = 2; 514*7c478bd9Sstevel@tonic-gate if (cflg) 515*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-c"; 516*7c478bd9Sstevel@tonic-gate if (gflg) 517*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-g"; 518*7c478bd9Sstevel@tonic-gate if (mflg) 519*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-m"; 520*7c478bd9Sstevel@tonic-gate /* 521*7c478bd9Sstevel@tonic-gate * The q option needs to go before the -o option as some 522*7c478bd9Sstevel@tonic-gate * filesystems complain during first pass option parsing. 523*7c478bd9Sstevel@tonic-gate */ 524*7c478bd9Sstevel@tonic-gate if (qflg) 525*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-q"; 526*7c478bd9Sstevel@tonic-gate if (oflg) { 527*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-o"; 528*7c478bd9Sstevel@tonic-gate newargv[ii++] = specific_opts; 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate if (Oflg) 531*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-O"; 532*7c478bd9Sstevel@tonic-gate if (rflg) 533*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-r"; 534*7c478bd9Sstevel@tonic-gate if (dashflg) 535*7c478bd9Sstevel@tonic-gate newargv[ii++] = "--"; 536*7c478bd9Sstevel@tonic-gate newargv[ii++] = special; 537*7c478bd9Sstevel@tonic-gate newargv[ii++] = mountp; 538*7c478bd9Sstevel@tonic-gate newargv[ii] = NULL; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate doexec(fstype, newargv); 541*7c478bd9Sstevel@tonic-gate exit(0); 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate void 545*7c478bd9Sstevel@tonic-gate usage() 546*7c478bd9Sstevel@tonic-gate { 547*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Usage:\n%s [-v | -p]\n"), myname); 548*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 549*7c478bd9Sstevel@tonic-gate "%s [-F FSType] [-V] [current_options] [-o specific_options]"), 550*7c478bd9Sstevel@tonic-gate myname); 551*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\n\t{special | mount_point}\n")); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 554*7c478bd9Sstevel@tonic-gate "%s [-F FSType] [-V] [current_options] [-o specific_options]"), 555*7c478bd9Sstevel@tonic-gate myname); 556*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\n\tspecial mount_point\n")); 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 559*7c478bd9Sstevel@tonic-gate "%s -a [-F FSType ] [-V] [current_options] [-o specific_options]\n"), 560*7c478bd9Sstevel@tonic-gate myname); 561*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\t[mount_point ...]\n")); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate exit(1); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate /* 567*7c478bd9Sstevel@tonic-gate * Get rid of "dev=[hex string]" clause, if any. It's not legal 568*7c478bd9Sstevel@tonic-gate * when printing in vfstab format. 569*7c478bd9Sstevel@tonic-gate */ 570*7c478bd9Sstevel@tonic-gate void 571*7c478bd9Sstevel@tonic-gate elide_dev(char *mntopts) 572*7c478bd9Sstevel@tonic-gate { 573*7c478bd9Sstevel@tonic-gate char *dev, *other; 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate if (mntopts != NULL) { 576*7c478bd9Sstevel@tonic-gate dev = strstr(mntopts, "dev="); 577*7c478bd9Sstevel@tonic-gate if (dev != NULL) { 578*7c478bd9Sstevel@tonic-gate other = strpbrk(dev, ","); 579*7c478bd9Sstevel@tonic-gate if (other == NULL) { 580*7c478bd9Sstevel@tonic-gate /* last option */ 581*7c478bd9Sstevel@tonic-gate if (dev != mntopts) { 582*7c478bd9Sstevel@tonic-gate *--dev = '\0'; 583*7c478bd9Sstevel@tonic-gate } else { 584*7c478bd9Sstevel@tonic-gate *dev = '\0'; 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate } else { 587*7c478bd9Sstevel@tonic-gate /* first or intermediate option */ 588*7c478bd9Sstevel@tonic-gate memmove(dev, other+1, strlen(other+1)+1); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate void 595*7c478bd9Sstevel@tonic-gate print_mnttab(vflg, pflg) 596*7c478bd9Sstevel@tonic-gate int vflg, pflg; 597*7c478bd9Sstevel@tonic-gate { 598*7c478bd9Sstevel@tonic-gate FILE *fd; 599*7c478bd9Sstevel@tonic-gate FILE *rfp; /* this will be NULL if fopen fails */ 600*7c478bd9Sstevel@tonic-gate int ret; 601*7c478bd9Sstevel@tonic-gate char time_buf[TIME_MAX]; /* array to hold date and time */ 602*7c478bd9Sstevel@tonic-gate struct extmnttab mget; 603*7c478bd9Sstevel@tonic-gate time_t ltime; 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate if ((fd = fopen(mnttab, "r")) == NULL) { 606*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot open mnttab\n"), myname); 607*7c478bd9Sstevel@tonic-gate exit(1); 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate rfp = fopen(REMOTE, "r"); 610*7c478bd9Sstevel@tonic-gate while ((ret = getextmntent(fd, &mget, sizeof (struct extmnttab))) 611*7c478bd9Sstevel@tonic-gate == 0) { 612*7c478bd9Sstevel@tonic-gate if (ignore(mget.mnt_mntopts)) 613*7c478bd9Sstevel@tonic-gate continue; 614*7c478bd9Sstevel@tonic-gate if (mget.mnt_special && mget.mnt_mountp && 615*7c478bd9Sstevel@tonic-gate mget.mnt_fstype && mget.mnt_time) { 616*7c478bd9Sstevel@tonic-gate ltime = atol(mget.mnt_time); 617*7c478bd9Sstevel@tonic-gate cftime(time_buf, FORMAT, <ime); 618*7c478bd9Sstevel@tonic-gate if (pflg) { 619*7c478bd9Sstevel@tonic-gate elide_dev(mget.mnt_mntopts); 620*7c478bd9Sstevel@tonic-gate printf("%s - %s %s - no %s\n", 621*7c478bd9Sstevel@tonic-gate mget.mnt_special, 622*7c478bd9Sstevel@tonic-gate mget.mnt_mountp, 623*7c478bd9Sstevel@tonic-gate mget.mnt_fstype, 624*7c478bd9Sstevel@tonic-gate mget.mnt_mntopts != NULL ? 625*7c478bd9Sstevel@tonic-gate mget.mnt_mntopts : "-"); 626*7c478bd9Sstevel@tonic-gate } else if (vflg) { 627*7c478bd9Sstevel@tonic-gate printf("%s on %s type %s %s%s on %s", 628*7c478bd9Sstevel@tonic-gate mget.mnt_special, 629*7c478bd9Sstevel@tonic-gate mget.mnt_mountp, 630*7c478bd9Sstevel@tonic-gate mget.mnt_fstype, 631*7c478bd9Sstevel@tonic-gate remote(mget.mnt_fstype, rfp), 632*7c478bd9Sstevel@tonic-gate flags(mget.mnt_mntopts, NEW), 633*7c478bd9Sstevel@tonic-gate time_buf); 634*7c478bd9Sstevel@tonic-gate } else 635*7c478bd9Sstevel@tonic-gate printf("%s on %s %s%s on %s", 636*7c478bd9Sstevel@tonic-gate mget.mnt_mountp, 637*7c478bd9Sstevel@tonic-gate mget.mnt_special, 638*7c478bd9Sstevel@tonic-gate remote(mget.mnt_fstype, rfp), 639*7c478bd9Sstevel@tonic-gate flags(mget.mnt_mntopts, OLD), 640*7c478bd9Sstevel@tonic-gate time_buf); 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate if (ret > 0) 644*7c478bd9Sstevel@tonic-gate mnterror(ret); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate char * 648*7c478bd9Sstevel@tonic-gate flags(mntopts, flag) 649*7c478bd9Sstevel@tonic-gate char *mntopts; 650*7c478bd9Sstevel@tonic-gate int flag; 651*7c478bd9Sstevel@tonic-gate { 652*7c478bd9Sstevel@tonic-gate char opts[sizeof (mntflags)]; 653*7c478bd9Sstevel@tonic-gate char *value; 654*7c478bd9Sstevel@tonic-gate int rdwr = 1; 655*7c478bd9Sstevel@tonic-gate int suid = 1; 656*7c478bd9Sstevel@tonic-gate int devices = 1; 657*7c478bd9Sstevel@tonic-gate int setuid = 1; 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate if (mntopts == NULL || *mntopts == '\0') 660*7c478bd9Sstevel@tonic-gate return ("read/write/setuid/devices"); 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate strcpy(opts, ""); 663*7c478bd9Sstevel@tonic-gate while (*mntopts != '\0') { 664*7c478bd9Sstevel@tonic-gate switch (getsubopt(&mntopts, myopts, &value)) { 665*7c478bd9Sstevel@tonic-gate case READONLY: 666*7c478bd9Sstevel@tonic-gate rdwr = 0; 667*7c478bd9Sstevel@tonic-gate break; 668*7c478bd9Sstevel@tonic-gate case READWRITE: 669*7c478bd9Sstevel@tonic-gate rdwr = 1; 670*7c478bd9Sstevel@tonic-gate break; 671*7c478bd9Sstevel@tonic-gate case SUID: 672*7c478bd9Sstevel@tonic-gate suid = 1; 673*7c478bd9Sstevel@tonic-gate break; 674*7c478bd9Sstevel@tonic-gate case NOSUID: 675*7c478bd9Sstevel@tonic-gate suid = 0; 676*7c478bd9Sstevel@tonic-gate break; 677*7c478bd9Sstevel@tonic-gate case SETUID: 678*7c478bd9Sstevel@tonic-gate setuid = 1; 679*7c478bd9Sstevel@tonic-gate break; 680*7c478bd9Sstevel@tonic-gate case NOSETUID: 681*7c478bd9Sstevel@tonic-gate setuid = 0; 682*7c478bd9Sstevel@tonic-gate break; 683*7c478bd9Sstevel@tonic-gate case DEVICES: 684*7c478bd9Sstevel@tonic-gate devices = 1; 685*7c478bd9Sstevel@tonic-gate break; 686*7c478bd9Sstevel@tonic-gate case NODEVICES: 687*7c478bd9Sstevel@tonic-gate devices = 0; 688*7c478bd9Sstevel@tonic-gate break; 689*7c478bd9Sstevel@tonic-gate default: 690*7c478bd9Sstevel@tonic-gate /* cat '/' separator to mntflags */ 691*7c478bd9Sstevel@tonic-gate if (*opts != '\0' && value != NULL) 692*7c478bd9Sstevel@tonic-gate strcat(opts, "/"); 693*7c478bd9Sstevel@tonic-gate strcat(opts, value); 694*7c478bd9Sstevel@tonic-gate break; 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate strcpy(mntflags, ""); 699*7c478bd9Sstevel@tonic-gate if (rdwr) 700*7c478bd9Sstevel@tonic-gate strcat(mntflags, "read/write"); 701*7c478bd9Sstevel@tonic-gate else if (flag == OLD) 702*7c478bd9Sstevel@tonic-gate strcat(mntflags, "read only"); 703*7c478bd9Sstevel@tonic-gate else 704*7c478bd9Sstevel@tonic-gate strcat(mntflags, "read-only"); 705*7c478bd9Sstevel@tonic-gate if (suid) { 706*7c478bd9Sstevel@tonic-gate if (setuid) 707*7c478bd9Sstevel@tonic-gate strcat(mntflags, "/setuid"); 708*7c478bd9Sstevel@tonic-gate else 709*7c478bd9Sstevel@tonic-gate strcat(mntflags, "/nosetuid"); 710*7c478bd9Sstevel@tonic-gate if (devices) 711*7c478bd9Sstevel@tonic-gate strcat(mntflags, "/devices"); 712*7c478bd9Sstevel@tonic-gate else 713*7c478bd9Sstevel@tonic-gate strcat(mntflags, "/nodevices"); 714*7c478bd9Sstevel@tonic-gate } else { 715*7c478bd9Sstevel@tonic-gate strcat(mntflags, "/nosetuid/nodevices"); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate if (*opts != '\0') { 718*7c478bd9Sstevel@tonic-gate strcat(mntflags, "/"); 719*7c478bd9Sstevel@tonic-gate strcat(mntflags, opts); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate /* 723*7c478bd9Sstevel@tonic-gate * The assumed assertion 724*7c478bd9Sstevel@tonic-gate * assert (strlen(mntflags) < sizeof mntflags); 725*7c478bd9Sstevel@tonic-gate * is valid at this point in the code. Note that a call to "assert" 726*7c478bd9Sstevel@tonic-gate * is not appropriate in production code since it halts the program. 727*7c478bd9Sstevel@tonic-gate */ 728*7c478bd9Sstevel@tonic-gate return (mntflags); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate char * 732*7c478bd9Sstevel@tonic-gate remote(fstype, rfp) 733*7c478bd9Sstevel@tonic-gate char *fstype; 734*7c478bd9Sstevel@tonic-gate FILE *rfp; 735*7c478bd9Sstevel@tonic-gate { 736*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 737*7c478bd9Sstevel@tonic-gate char *fs; 738*7c478bd9Sstevel@tonic-gate extern char *strtok(); 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate if (rfp == NULL || fstype == NULL || 741*7c478bd9Sstevel@tonic-gate strlen(fstype) > (size_t)FSTYPE_MAX) 742*7c478bd9Sstevel@tonic-gate return (""); /* not a remote */ 743*7c478bd9Sstevel@tonic-gate rewind(rfp); 744*7c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), rfp) != NULL) { 745*7c478bd9Sstevel@tonic-gate fs = strtok(buf, " \t\n"); 746*7c478bd9Sstevel@tonic-gate if (strcmp(fstype, fs) == 0) 747*7c478bd9Sstevel@tonic-gate return ("remote/"); /* is a remote fs */ 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate return (""); /* not a remote */ 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate void 754*7c478bd9Sstevel@tonic-gate vfserror(int flag, char *special) 755*7c478bd9Sstevel@tonic-gate { 756*7c478bd9Sstevel@tonic-gate if (special == NULL) 757*7c478bd9Sstevel@tonic-gate special = "<null>"; 758*7c478bd9Sstevel@tonic-gate switch (flag) { 759*7c478bd9Sstevel@tonic-gate case VFS_TOOLONG: 760*7c478bd9Sstevel@tonic-gate fprintf(stderr, 761*7c478bd9Sstevel@tonic-gate gettext("%s: Warning: Line in vfstab for \"%s\" exceeds %d characters\n"), 762*7c478bd9Sstevel@tonic-gate myname, special, VFS_LINE_MAX-1); 763*7c478bd9Sstevel@tonic-gate break; 764*7c478bd9Sstevel@tonic-gate case VFS_TOOFEW: 765*7c478bd9Sstevel@tonic-gate fprintf(stderr, 766*7c478bd9Sstevel@tonic-gate gettext("%s: Warning: Line for \"%s\" in vfstab has too few entries\n"), 767*7c478bd9Sstevel@tonic-gate myname, special); 768*7c478bd9Sstevel@tonic-gate break; 769*7c478bd9Sstevel@tonic-gate case VFS_TOOMANY: 770*7c478bd9Sstevel@tonic-gate fprintf(stderr, 771*7c478bd9Sstevel@tonic-gate gettext("%s: Warning: Line for \"%s\" in vfstab has too many entries\n"), 772*7c478bd9Sstevel@tonic-gate myname, special); 773*7c478bd9Sstevel@tonic-gate break; 774*7c478bd9Sstevel@tonic-gate default: 775*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 776*7c478bd9Sstevel@tonic-gate "%s: Warning: Error in line for \"%s\" in vfstab\n"), 777*7c478bd9Sstevel@tonic-gate myname, special); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate void 782*7c478bd9Sstevel@tonic-gate mnterror(flag) 783*7c478bd9Sstevel@tonic-gate int flag; 784*7c478bd9Sstevel@tonic-gate { 785*7c478bd9Sstevel@tonic-gate switch (flag) { 786*7c478bd9Sstevel@tonic-gate case MNT_TOOLONG: 787*7c478bd9Sstevel@tonic-gate fprintf(stderr, 788*7c478bd9Sstevel@tonic-gate gettext("%s: Line in mnttab exceeds %d characters\n"), 789*7c478bd9Sstevel@tonic-gate myname, MNT_LINE_MAX-2); 790*7c478bd9Sstevel@tonic-gate break; 791*7c478bd9Sstevel@tonic-gate case MNT_TOOFEW: 792*7c478bd9Sstevel@tonic-gate fprintf(stderr, 793*7c478bd9Sstevel@tonic-gate gettext("%s: Line in mnttab has too few entries\n"), 794*7c478bd9Sstevel@tonic-gate myname); 795*7c478bd9Sstevel@tonic-gate break; 796*7c478bd9Sstevel@tonic-gate case MNT_TOOMANY: 797*7c478bd9Sstevel@tonic-gate fprintf(stderr, 798*7c478bd9Sstevel@tonic-gate gettext("%s: Line in mnttab has too many entries\n"), 799*7c478bd9Sstevel@tonic-gate myname); 800*7c478bd9Sstevel@tonic-gate break; 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate exit(1); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate void 806*7c478bd9Sstevel@tonic-gate doexec(fstype, newargv) 807*7c478bd9Sstevel@tonic-gate char *fstype, *newargv[]; 808*7c478bd9Sstevel@tonic-gate { 809*7c478bd9Sstevel@tonic-gate char full_path[PATH_MAX]; 810*7c478bd9Sstevel@tonic-gate char alter_path[PATH_MAX]; 811*7c478bd9Sstevel@tonic-gate char *vfs_path = VFS_PATH; 812*7c478bd9Sstevel@tonic-gate char *alt_path = ALT_PATH; 813*7c478bd9Sstevel@tonic-gate int i; 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate /* build the full pathname of the fstype dependent command. */ 816*7c478bd9Sstevel@tonic-gate sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname); 817*7c478bd9Sstevel@tonic-gate sprintf(alter_path, "%s/%s/%s", alt_path, fstype, myname); 818*7c478bd9Sstevel@tonic-gate newargv[1] = myname; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate if (Vflg) { 821*7c478bd9Sstevel@tonic-gate printf("%s -F %s", newargv[1], fstype); 822*7c478bd9Sstevel@tonic-gate for (i = 2; newargv[i]; i++) 823*7c478bd9Sstevel@tonic-gate printf(" %s", newargv[i]); 824*7c478bd9Sstevel@tonic-gate printf("\n"); 825*7c478bd9Sstevel@tonic-gate fflush(stdout); 826*7c478bd9Sstevel@tonic-gate exit(0); 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate /* 830*7c478bd9Sstevel@tonic-gate * Try to exec the fstype dependent portion of the mount. 831*7c478bd9Sstevel@tonic-gate * See if the directory is there before trying to exec dependent 832*7c478bd9Sstevel@tonic-gate * portion. This is only useful for eliminating the 833*7c478bd9Sstevel@tonic-gate * '..mount: not found' message when '/usr' is mounted 834*7c478bd9Sstevel@tonic-gate */ 835*7c478bd9Sstevel@tonic-gate if (access(full_path, 0) == 0) { 836*7c478bd9Sstevel@tonic-gate execv(full_path, &newargv[1]); 837*7c478bd9Sstevel@tonic-gate if (errno == EACCES) { 838*7c478bd9Sstevel@tonic-gate fprintf(stderr, 839*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot execute %s - permission denied\n"), 840*7c478bd9Sstevel@tonic-gate myname, full_path); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) { 843*7c478bd9Sstevel@tonic-gate newargv[0] = "sh"; 844*7c478bd9Sstevel@tonic-gate newargv[1] = full_path; 845*7c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate execv(alter_path, &newargv[1]); 849*7c478bd9Sstevel@tonic-gate if (errno == EACCES) { 850*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 851*7c478bd9Sstevel@tonic-gate "%s: Cannot execute %s - permission denied\n"), 852*7c478bd9Sstevel@tonic-gate myname, alter_path); 853*7c478bd9Sstevel@tonic-gate exit(1); 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) { 856*7c478bd9Sstevel@tonic-gate newargv[0] = "sh"; 857*7c478bd9Sstevel@tonic-gate newargv[1] = alter_path; 858*7c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate fprintf(stderr, 861*7c478bd9Sstevel@tonic-gate gettext("%s: Operation not applicable to FSType %s\n"), 862*7c478bd9Sstevel@tonic-gate myname, fstype); 863*7c478bd9Sstevel@tonic-gate exit(1); 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate char *mntopts[] = { MNTOPT_IGNORE, NULL }; 867*7c478bd9Sstevel@tonic-gate #define IGNORE 0 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * Return 1 if "ignore" appears in the options string 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate int 873*7c478bd9Sstevel@tonic-gate ignore(opts) 874*7c478bd9Sstevel@tonic-gate char *opts; 875*7c478bd9Sstevel@tonic-gate { 876*7c478bd9Sstevel@tonic-gate char *value; 877*7c478bd9Sstevel@tonic-gate char *saveptr, *my_opts; 878*7c478bd9Sstevel@tonic-gate int rval = 0; 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate if (opts == NULL || *opts == NULL) 881*7c478bd9Sstevel@tonic-gate return (0); 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate /* 884*7c478bd9Sstevel@tonic-gate * we make a copy of the option string to pass to getsubopt(), 885*7c478bd9Sstevel@tonic-gate * because getsubopt() modifies the string. We also save 886*7c478bd9Sstevel@tonic-gate * the original pointer returned by strdup, because getsubopt 887*7c478bd9Sstevel@tonic-gate * changes the pointer passed into it. If strdup fails (unlikely), 888*7c478bd9Sstevel@tonic-gate * we act as if the "ignore" option isn't set rather than fail. 889*7c478bd9Sstevel@tonic-gate */ 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate if ((saveptr = my_opts = strdup(opts)) == NULL) 892*7c478bd9Sstevel@tonic-gate nomem(); 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate while (*my_opts != '\0') { 895*7c478bd9Sstevel@tonic-gate if (getsubopt(&my_opts, mntopts, &value) == IGNORE) 896*7c478bd9Sstevel@tonic-gate rval = 1; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate free(saveptr); 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate return (rval); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate /* 905*7c478bd9Sstevel@tonic-gate * Perform the parallel version of mount. If count == 0, mount all 906*7c478bd9Sstevel@tonic-gate * vfstab filesystems with the automnt field == "yes". Use fstype if 907*7c478bd9Sstevel@tonic-gate * supplied. If mntlist supplied, then attempt to only mount those. 908*7c478bd9Sstevel@tonic-gate */ 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate int 911*7c478bd9Sstevel@tonic-gate parmount(char **mntlist, int count, char *fstype) 912*7c478bd9Sstevel@tonic-gate { 913*7c478bd9Sstevel@tonic-gate int maxfd = OPEN_MAX; 914*7c478bd9Sstevel@tonic-gate struct rlimit rl; 915*7c478bd9Sstevel@tonic-gate vfsent_t **vl, *vp; 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate /* 918*7c478bd9Sstevel@tonic-gate * Process scaling. After running a series 919*7c478bd9Sstevel@tonic-gate * of tests based on the number of simultaneous processes and 920*7c478bd9Sstevel@tonic-gate * processors available, optimum performance was achieved near or 921*7c478bd9Sstevel@tonic-gate * at (PROCN * 2). 922*7c478bd9Sstevel@tonic-gate */ 923*7c478bd9Sstevel@tonic-gate if ((maxrun = sysconf(_SC_NPROCESSORS_ONLN)) == -1) 924*7c478bd9Sstevel@tonic-gate maxrun = 4; 925*7c478bd9Sstevel@tonic-gate else 926*7c478bd9Sstevel@tonic-gate maxrun = maxrun * 2 + 1; 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 929*7c478bd9Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max; 930*7c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rl) == 0) 931*7c478bd9Sstevel@tonic-gate maxfd = (int)rl.rlim_cur; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate /* 935*7c478bd9Sstevel@tonic-gate * The parent needs to maintain 3 of its own fd's, plus 2 for 936*7c478bd9Sstevel@tonic-gate * each child (the stdout and stderr pipes). 937*7c478bd9Sstevel@tonic-gate */ 938*7c478bd9Sstevel@tonic-gate maxfd = (maxfd / 2) - 6; /* 6 takes care of temporary */ 939*7c478bd9Sstevel@tonic-gate /* periods of open fds */ 940*7c478bd9Sstevel@tonic-gate if (maxfd < maxrun) 941*7c478bd9Sstevel@tonic-gate maxrun = maxfd; 942*7c478bd9Sstevel@tonic-gate if (maxrun < 4) 943*7c478bd9Sstevel@tonic-gate maxrun = 4; /* sanity check */ 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate if (count == 0) 946*7c478bd9Sstevel@tonic-gate mntlist = NULL; /* used as a flag later */ 947*7c478bd9Sstevel@tonic-gate else 948*7c478bd9Sstevel@tonic-gate fstype = NULL; /* mount points supplied: */ 949*7c478bd9Sstevel@tonic-gate /* ignore fstype */ 950*7c478bd9Sstevel@tonic-gate /* 951*7c478bd9Sstevel@tonic-gate * Read the whole vfstab into a linked list for quick processing. 952*7c478bd9Sstevel@tonic-gate * On average, this is the most efficient way to collect and 953*7c478bd9Sstevel@tonic-gate * manipulate the vfstab data. 954*7c478bd9Sstevel@tonic-gate */ 955*7c478bd9Sstevel@tonic-gate vfsll = getvfsall(fstype, mntlist == NULL); 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate /* 958*7c478bd9Sstevel@tonic-gate * Make an array out of the vfs linked list for sorting purposes. 959*7c478bd9Sstevel@tonic-gate */ 960*7c478bd9Sstevel@tonic-gate if (vfsll == NULL || 961*7c478bd9Sstevel@tonic-gate (vfsarray = make_vfsarray(mntlist, count)) == NULL) { 962*7c478bd9Sstevel@tonic-gate if (mntlist == NULL) /* not an error - just none found */ 963*7c478bd9Sstevel@tonic-gate return (0); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: No valid entries found in %s\n"), 966*7c478bd9Sstevel@tonic-gate myname, vfstab); 967*7c478bd9Sstevel@tonic-gate return (1); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * Sort the entries based on their resolved path names 972*7c478bd9Sstevel@tonic-gate * 973*7c478bd9Sstevel@tonic-gate * If an lofs is encountered, then the original order of the vfstab 974*7c478bd9Sstevel@tonic-gate * file needs to be maintained until we are done mounting lofs's. 975*7c478bd9Sstevel@tonic-gate */ 976*7c478bd9Sstevel@tonic-gate if (!lofscnt) 977*7c478bd9Sstevel@tonic-gate qsort((void *)vfsarray, vfsarraysize, sizeof (vfsent_t *), 978*7c478bd9Sstevel@tonic-gate mlevelcmp); 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate /* 981*7c478bd9Sstevel@tonic-gate * Shrink the vfsll linked list down to the new list. This will 982*7c478bd9Sstevel@tonic-gate * speed up the pid search in cleanupkid() later. 983*7c478bd9Sstevel@tonic-gate */ 984*7c478bd9Sstevel@tonic-gate vfsll = vfsarray[0]; 985*7c478bd9Sstevel@tonic-gate for (vl = vfsarray; vp = *vl; ) 986*7c478bd9Sstevel@tonic-gate vp->next = *++vl; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate /* 989*7c478bd9Sstevel@tonic-gate * Try to handle interrupts in a reasonable way. 990*7c478bd9Sstevel@tonic-gate */ 991*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, cleanup); 992*7c478bd9Sstevel@tonic-gate sigset(SIGQUIT, cleanup); 993*7c478bd9Sstevel@tonic-gate sigset(SIGINT, cleanup); 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate do_mounts(); /* do the mounts */ 996*7c478bd9Sstevel@tonic-gate return (exitcode); 997*7c478bd9Sstevel@tonic-gate } 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* 1000*7c478bd9Sstevel@tonic-gate * Read all vstab (fp) entries into memory if fstype == NULL. 1001*7c478bd9Sstevel@tonic-gate * If fstype is specified, than read all those that match it. 1002*7c478bd9Sstevel@tonic-gate * 1003*7c478bd9Sstevel@tonic-gate * Returns a linked list. 1004*7c478bd9Sstevel@tonic-gate */ 1005*7c478bd9Sstevel@tonic-gate vfsent_t * 1006*7c478bd9Sstevel@tonic-gate getvfsall(char *fstype, int takeall) 1007*7c478bd9Sstevel@tonic-gate { 1008*7c478bd9Sstevel@tonic-gate vfsent_t *vhead, *vtail; 1009*7c478bd9Sstevel@tonic-gate struct vfstab vget; 1010*7c478bd9Sstevel@tonic-gate FILE *fp; 1011*7c478bd9Sstevel@tonic-gate int cnt = 0, ret; 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate if ((fp = fopen(vfstab, "r")) == NULL) { 1014*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot open %s\n"), 1015*7c478bd9Sstevel@tonic-gate myname, vfstab); 1016*7c478bd9Sstevel@tonic-gate exit(1); 1017*7c478bd9Sstevel@tonic-gate } 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate vhead = vtail = NULL; 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate while ((ret = getvfsent(fp, &vget)) != -1) { 1022*7c478bd9Sstevel@tonic-gate vfsent_t *vp; 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate if (ret > 0) { 1025*7c478bd9Sstevel@tonic-gate vfserror(ret, vget.vfs_mountp); 1026*7c478bd9Sstevel@tonic-gate continue; 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate /* 1030*7c478bd9Sstevel@tonic-gate * If mount points were not specified, then we ignore 1031*7c478bd9Sstevel@tonic-gate * entries that aren't marked "yes". 1032*7c478bd9Sstevel@tonic-gate */ 1033*7c478bd9Sstevel@tonic-gate if (takeall && 1034*7c478bd9Sstevel@tonic-gate (vget.vfs_automnt == NULL || 1035*7c478bd9Sstevel@tonic-gate strcmp(vget.vfs_automnt, "yes"))) 1036*7c478bd9Sstevel@tonic-gate continue; 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate if (fstype && vget.vfs_fstype && 1039*7c478bd9Sstevel@tonic-gate strcmp(fstype, vget.vfs_fstype)) 1040*7c478bd9Sstevel@tonic-gate continue; 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate if (vget.vfs_mountp == NULL || 1043*7c478bd9Sstevel@tonic-gate (vget.vfs_fstype && (strcmp(vget.vfs_fstype, "swap") == 0))) 1044*7c478bd9Sstevel@tonic-gate continue; 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate if (check_fields(vget.vfs_fstype, vget.vfs_mountp)) { 1047*7c478bd9Sstevel@tonic-gate exitcode = 1; 1048*7c478bd9Sstevel@tonic-gate continue; 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate vp = new_vfsent(&vget, cnt); /* create new vfs entry */ 1052*7c478bd9Sstevel@tonic-gate if (vhead == NULL) 1053*7c478bd9Sstevel@tonic-gate vhead = vp; 1054*7c478bd9Sstevel@tonic-gate else 1055*7c478bd9Sstevel@tonic-gate vtail->next = vp; 1056*7c478bd9Sstevel@tonic-gate vtail = vp; 1057*7c478bd9Sstevel@tonic-gate cnt++; 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate fclose(fp); 1060*7c478bd9Sstevel@tonic-gate if (vtail == NULL) { 1061*7c478bd9Sstevel@tonic-gate vfsarraysize = 0; 1062*7c478bd9Sstevel@tonic-gate vfslltail = NULL; 1063*7c478bd9Sstevel@tonic-gate return (NULL); 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate vtail->next = NULL; 1066*7c478bd9Sstevel@tonic-gate vfslltail = vtail; /* save it in the global variable */ 1067*7c478bd9Sstevel@tonic-gate vfsarraysize = cnt; 1068*7c478bd9Sstevel@tonic-gate return (vhead); 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate /* 1073*7c478bd9Sstevel@tonic-gate * Returns an array of vfsent_t's based on vfsll & mntlist. 1074*7c478bd9Sstevel@tonic-gate */ 1075*7c478bd9Sstevel@tonic-gate vfsent_t ** 1076*7c478bd9Sstevel@tonic-gate make_vfsarray(char **mntlist, int count) 1077*7c478bd9Sstevel@tonic-gate { 1078*7c478bd9Sstevel@tonic-gate vfsent_t *vp, *vmark, *vpprev, **vpp; 1079*7c478bd9Sstevel@tonic-gate int ndx, found; 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate if (vfsll == NULL) 1082*7c478bd9Sstevel@tonic-gate return (NULL); 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate if (count > 0) 1085*7c478bd9Sstevel@tonic-gate vfsarraysize = count; 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate vpp = (vfsent_t **)malloc(sizeof (*vpp) * (vfsarraysize + 1)); 1088*7c478bd9Sstevel@tonic-gate if (vpp == NULL) 1089*7c478bd9Sstevel@tonic-gate nomem(); 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate if (mntlist == NULL) { 1092*7c478bd9Sstevel@tonic-gate /* 1093*7c478bd9Sstevel@tonic-gate * No mount list specified: take all vfstab mount points. 1094*7c478bd9Sstevel@tonic-gate */ 1095*7c478bd9Sstevel@tonic-gate for (ndx = 0, vp = vfsll; vp; vp = vp->next) { 1096*7c478bd9Sstevel@tonic-gate (void) setrpath(vp); 1097*7c478bd9Sstevel@tonic-gate /* 1098*7c478bd9Sstevel@tonic-gate * Sigh. lofs entries can complicate matters so much 1099*7c478bd9Sstevel@tonic-gate * that the best way to avoid problems is to 1100*7c478bd9Sstevel@tonic-gate * stop parallel mounting when an lofs is 1101*7c478bd9Sstevel@tonic-gate * encountered, so we keep a count of how many 1102*7c478bd9Sstevel@tonic-gate * there are. 1103*7c478bd9Sstevel@tonic-gate * Fortunately this is rare. 1104*7c478bd9Sstevel@tonic-gate */ 1105*7c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && 1106*7c478bd9Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, MNTTYPE_LOFS) == 0)) 1107*7c478bd9Sstevel@tonic-gate lofscnt++; 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate vpp[ndx++] = vp; 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate vpp[ndx] = NULL; 1112*7c478bd9Sstevel@tonic-gate return (vpp); 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate /* 1116*7c478bd9Sstevel@tonic-gate * A list of mount points was specified on the command line 1117*7c478bd9Sstevel@tonic-gate * and we need to search for each one. 1118*7c478bd9Sstevel@tonic-gate */ 1119*7c478bd9Sstevel@tonic-gate vpprev = vfslltail; 1120*7c478bd9Sstevel@tonic-gate vpprev->next = vfsll; /* make a circle out of it */ 1121*7c478bd9Sstevel@tonic-gate vmark = vp = vfsll; 1122*7c478bd9Sstevel@tonic-gate /* 1123*7c478bd9Sstevel@tonic-gate * For each specified mount point: 1124*7c478bd9Sstevel@tonic-gate */ 1125*7c478bd9Sstevel@tonic-gate for (ndx = 0; *mntlist; mntlist++) { 1126*7c478bd9Sstevel@tonic-gate found = 0; 1127*7c478bd9Sstevel@tonic-gate /* 1128*7c478bd9Sstevel@tonic-gate * Circle our entire linked list, looking for *mntlist. 1129*7c478bd9Sstevel@tonic-gate */ 1130*7c478bd9Sstevel@tonic-gate while (vp) { 1131*7c478bd9Sstevel@tonic-gate if (strcmp(*mntlist, vp->v.vfs_mountp) == 0) { 1132*7c478bd9Sstevel@tonic-gate vpp[ndx++] = vp; /* found it. */ 1133*7c478bd9Sstevel@tonic-gate (void) setrpath(vp); 1134*7c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && 1135*7c478bd9Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, 1136*7c478bd9Sstevel@tonic-gate MNTTYPE_LOFS) == 0)) 1137*7c478bd9Sstevel@tonic-gate lofscnt++; 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate if (vp == vpprev) { /* list exhausted */ 1140*7c478bd9Sstevel@tonic-gate vp = NULL; 1141*7c478bd9Sstevel@tonic-gate found++; 1142*7c478bd9Sstevel@tonic-gate break; 1143*7c478bd9Sstevel@tonic-gate } 1144*7c478bd9Sstevel@tonic-gate /* 1145*7c478bd9Sstevel@tonic-gate * Remove it from the circular list. vpprev 1146*7c478bd9Sstevel@tonic-gate * remains unchanged. 1147*7c478bd9Sstevel@tonic-gate */ 1148*7c478bd9Sstevel@tonic-gate vp = vp->next; 1149*7c478bd9Sstevel@tonic-gate vpprev->next->next = NULL; 1150*7c478bd9Sstevel@tonic-gate vpprev->next = vp; 1151*7c478bd9Sstevel@tonic-gate /* 1152*7c478bd9Sstevel@tonic-gate * Set vmark to the first elem that we check 1153*7c478bd9Sstevel@tonic-gate * each time. 1154*7c478bd9Sstevel@tonic-gate */ 1155*7c478bd9Sstevel@tonic-gate vmark = vp; 1156*7c478bd9Sstevel@tonic-gate found++; 1157*7c478bd9Sstevel@tonic-gate break; 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate vpprev = vp; 1160*7c478bd9Sstevel@tonic-gate vp = vp->next; 1161*7c478bd9Sstevel@tonic-gate if (vp == vmark) /* break out if we completed */ 1162*7c478bd9Sstevel@tonic-gate /* the circle */ 1163*7c478bd9Sstevel@tonic-gate break; 1164*7c478bd9Sstevel@tonic-gate } 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate if (!found) { 1167*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1168*7c478bd9Sstevel@tonic-gate "%s: Warning: %s not found in %s\n"), 1169*7c478bd9Sstevel@tonic-gate myname, *mntlist, vfstab); 1170*7c478bd9Sstevel@tonic-gate exitcode = 1; 1171*7c478bd9Sstevel@tonic-gate } 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate if (ndx == 0) 1174*7c478bd9Sstevel@tonic-gate return (NULL); 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate vpp[ndx] = NULL; /* null terminate the list */ 1177*7c478bd9Sstevel@tonic-gate vfsarraysize = ndx; /* adjust vfsarraysize */ 1178*7c478bd9Sstevel@tonic-gate return (vpp); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate /* 1182*7c478bd9Sstevel@tonic-gate * Performs the exec argument processing, all of the child forking and 1183*7c478bd9Sstevel@tonic-gate * execing, and child cleanup. 1184*7c478bd9Sstevel@tonic-gate * Sets exitcode to non-zero if any errors occurred. 1185*7c478bd9Sstevel@tonic-gate */ 1186*7c478bd9Sstevel@tonic-gate void 1187*7c478bd9Sstevel@tonic-gate do_mounts() 1188*7c478bd9Sstevel@tonic-gate { 1189*7c478bd9Sstevel@tonic-gate int i, isave, cnt; 1190*7c478bd9Sstevel@tonic-gate vfsent_t *vp, *vpprev, **vl; 1191*7c478bd9Sstevel@tonic-gate char *newargv[ARGV_MAX]; 1192*7c478bd9Sstevel@tonic-gate pid_t child; 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate /* 1195*7c478bd9Sstevel@tonic-gate * create the arg list once; the only differences among 1196*7c478bd9Sstevel@tonic-gate * the calls are the options, special and mountp fields. 1197*7c478bd9Sstevel@tonic-gate */ 1198*7c478bd9Sstevel@tonic-gate i = 2; 1199*7c478bd9Sstevel@tonic-gate if (cflg) 1200*7c478bd9Sstevel@tonic-gate newargv[i++] = "-c"; 1201*7c478bd9Sstevel@tonic-gate if (gflg) 1202*7c478bd9Sstevel@tonic-gate newargv[i++] = "-g"; 1203*7c478bd9Sstevel@tonic-gate if (mflg) 1204*7c478bd9Sstevel@tonic-gate newargv[i++] = "-m"; 1205*7c478bd9Sstevel@tonic-gate if (Oflg) 1206*7c478bd9Sstevel@tonic-gate newargv[i++] = "-O"; 1207*7c478bd9Sstevel@tonic-gate if (qflg) 1208*7c478bd9Sstevel@tonic-gate newargv[i++] = "-q"; 1209*7c478bd9Sstevel@tonic-gate if (rflg) 1210*7c478bd9Sstevel@tonic-gate newargv[i++] = "-r"; 1211*7c478bd9Sstevel@tonic-gate if (dashflg) 1212*7c478bd9Sstevel@tonic-gate newargv[i++] = "--"; 1213*7c478bd9Sstevel@tonic-gate if (oflg) { 1214*7c478bd9Sstevel@tonic-gate newargv[i++] = "-o"; 1215*7c478bd9Sstevel@tonic-gate newargv[i++] = specific_opts; 1216*7c478bd9Sstevel@tonic-gate } 1217*7c478bd9Sstevel@tonic-gate isave = i; 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate /* 1220*7c478bd9Sstevel@tonic-gate * Main loop for the mount processes 1221*7c478bd9Sstevel@tonic-gate */ 1222*7c478bd9Sstevel@tonic-gate vl = vfsarray; 1223*7c478bd9Sstevel@tonic-gate cnt = vfsarraysize; 1224*7c478bd9Sstevel@tonic-gate for (vpprev = *vl; vp = *vl; vpprev = vp, vl++, cnt--) { 1225*7c478bd9Sstevel@tonic-gate /* 1226*7c478bd9Sstevel@tonic-gate * Check to see if we cross a mount level: e.g., 1227*7c478bd9Sstevel@tonic-gate * /a/b -> /a/b/c. If so, we need to wait for all current 1228*7c478bd9Sstevel@tonic-gate * mounts to finish, rerun realpath on the remaining mount 1229*7c478bd9Sstevel@tonic-gate * points, and resort the list. 1230*7c478bd9Sstevel@tonic-gate * 1231*7c478bd9Sstevel@tonic-gate * Also, we mount serially as long as there are lofs's 1232*7c478bd9Sstevel@tonic-gate * to mount to avoid improper mount ordering. 1233*7c478bd9Sstevel@tonic-gate */ 1234*7c478bd9Sstevel@tonic-gate if (vp->mlevel > vpprev->mlevel || lofscnt > 0) { 1235*7c478bd9Sstevel@tonic-gate vfsent_t **vlp; 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 1238*7c478bd9Sstevel@tonic-gate ; 1239*7c478bd9Sstevel@tonic-gate /* 1240*7c478bd9Sstevel@tonic-gate * Gads! It's possible for real path mounts points to 1241*7c478bd9Sstevel@tonic-gate * change after mounts are done at a lower mount 1242*7c478bd9Sstevel@tonic-gate * level. 1243*7c478bd9Sstevel@tonic-gate * Thus, we need to recalculate mount levels and 1244*7c478bd9Sstevel@tonic-gate * resort the list from this point. 1245*7c478bd9Sstevel@tonic-gate */ 1246*7c478bd9Sstevel@tonic-gate for (vlp = vl; *vlp; vlp++) 1247*7c478bd9Sstevel@tonic-gate (void) setrpath(*vlp); 1248*7c478bd9Sstevel@tonic-gate /* 1249*7c478bd9Sstevel@tonic-gate * Sort the remaining entries based on their newly 1250*7c478bd9Sstevel@tonic-gate * resolved path names. 1251*7c478bd9Sstevel@tonic-gate * Do not sort if we still have lofs's to mount. 1252*7c478bd9Sstevel@tonic-gate */ 1253*7c478bd9Sstevel@tonic-gate if (lofscnt == 0) { 1254*7c478bd9Sstevel@tonic-gate qsort((void *)vl, cnt, sizeof (vfsent_t *), 1255*7c478bd9Sstevel@tonic-gate mlevelcmp); 1256*7c478bd9Sstevel@tonic-gate vp = *vl; 1257*7c478bd9Sstevel@tonic-gate } 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate if (vp->flag & VRPFAILED) { 1261*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1262*7c478bd9Sstevel@tonic-gate "%s: Nonexistent mount point: %s\n"), 1263*7c478bd9Sstevel@tonic-gate myname, vp->v.vfs_mountp); 1264*7c478bd9Sstevel@tonic-gate vp->flag |= VNOTMOUNTED; 1265*7c478bd9Sstevel@tonic-gate exitcode = 1; 1266*7c478bd9Sstevel@tonic-gate continue; 1267*7c478bd9Sstevel@tonic-gate } 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate /* 1270*7c478bd9Sstevel@tonic-gate * If mount options were not specified on the command 1271*7c478bd9Sstevel@tonic-gate * line, then use the ones found in the vfstab entry, 1272*7c478bd9Sstevel@tonic-gate * if any. 1273*7c478bd9Sstevel@tonic-gate */ 1274*7c478bd9Sstevel@tonic-gate i = isave; 1275*7c478bd9Sstevel@tonic-gate if (!oflg && vp->v.vfs_mntopts) { 1276*7c478bd9Sstevel@tonic-gate newargv[i++] = "-o"; 1277*7c478bd9Sstevel@tonic-gate newargv[i++] = vp->v.vfs_mntopts; 1278*7c478bd9Sstevel@tonic-gate } 1279*7c478bd9Sstevel@tonic-gate newargv[i++] = vp->v.vfs_special; 1280*7c478bd9Sstevel@tonic-gate newargv[i++] = vp->rpath; 1281*7c478bd9Sstevel@tonic-gate newargv[i] = NULL; 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate /* 1284*7c478bd9Sstevel@tonic-gate * This should never really fail. 1285*7c478bd9Sstevel@tonic-gate */ 1286*7c478bd9Sstevel@tonic-gate while (setup_iopipe(vp) == -1 && (dowait() != -1)) 1287*7c478bd9Sstevel@tonic-gate ; 1288*7c478bd9Sstevel@tonic-gate 1289*7c478bd9Sstevel@tonic-gate while (nrun >= maxrun && (dowait() != -1)) /* throttle */ 1290*7c478bd9Sstevel@tonic-gate ; 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 1293*7c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && 1294*7c478bd9Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, "cachefs") == 0)) { 1295*7c478bd9Sstevel@tonic-gate while (cachefs_running && (dowait() != -1)) 1296*7c478bd9Sstevel@tonic-gate ; 1297*7c478bd9Sstevel@tonic-gate cachefs_running = 1; 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate #endif 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate if ((child = fork()) == -1) { 1302*7c478bd9Sstevel@tonic-gate perror("fork"); 1303*7c478bd9Sstevel@tonic-gate cleanup(-1); 1304*7c478bd9Sstevel@tonic-gate /* not reached */ 1305*7c478bd9Sstevel@tonic-gate } 1306*7c478bd9Sstevel@tonic-gate if (child == 0) { /* child */ 1307*7c478bd9Sstevel@tonic-gate signal(SIGHUP, SIG_IGN); 1308*7c478bd9Sstevel@tonic-gate signal(SIGQUIT, SIG_IGN); 1309*7c478bd9Sstevel@tonic-gate signal(SIGINT, SIG_IGN); 1310*7c478bd9Sstevel@tonic-gate setup_output(vp); 1311*7c478bd9Sstevel@tonic-gate doexec(vp->v.vfs_fstype, newargv); 1312*7c478bd9Sstevel@tonic-gate perror("exec"); 1313*7c478bd9Sstevel@tonic-gate exit(1); 1314*7c478bd9Sstevel@tonic-gate } 1315*7c478bd9Sstevel@tonic-gate 1316*7c478bd9Sstevel@tonic-gate /* parent */ 1317*7c478bd9Sstevel@tonic-gate (void) close(vp->sopipe[WRPIPE]); 1318*7c478bd9Sstevel@tonic-gate (void) close(vp->sepipe[WRPIPE]); 1319*7c478bd9Sstevel@tonic-gate vp->pid = child; 1320*7c478bd9Sstevel@tonic-gate nrun++; 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate /* 1323*7c478bd9Sstevel@tonic-gate * Mostly done by now - wait and clean up the stragglers. 1324*7c478bd9Sstevel@tonic-gate */ 1325*7c478bd9Sstevel@tonic-gate cleanup(0); 1326*7c478bd9Sstevel@tonic-gate } 1327*7c478bd9Sstevel@tonic-gate 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate /* 1330*7c478bd9Sstevel@tonic-gate * Setup stdout and stderr pipes for the children's output. 1331*7c478bd9Sstevel@tonic-gate */ 1332*7c478bd9Sstevel@tonic-gate int 1333*7c478bd9Sstevel@tonic-gate setup_iopipe(vfsent_t *mp) 1334*7c478bd9Sstevel@tonic-gate { 1335*7c478bd9Sstevel@tonic-gate /* 1336*7c478bd9Sstevel@tonic-gate * Make a stdout and stderr pipe. This should never fail. 1337*7c478bd9Sstevel@tonic-gate */ 1338*7c478bd9Sstevel@tonic-gate if (pipe(mp->sopipe) == -1) 1339*7c478bd9Sstevel@tonic-gate return (-1); 1340*7c478bd9Sstevel@tonic-gate if (pipe(mp->sepipe) == -1) { 1341*7c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[RDPIPE]); 1342*7c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[WRPIPE]); 1343*7c478bd9Sstevel@tonic-gate return (-1); 1344*7c478bd9Sstevel@tonic-gate } 1345*7c478bd9Sstevel@tonic-gate /* 1346*7c478bd9Sstevel@tonic-gate * Don't block on an empty pipe. 1347*7c478bd9Sstevel@tonic-gate */ 1348*7c478bd9Sstevel@tonic-gate (void) fcntl(mp->sopipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 1349*7c478bd9Sstevel@tonic-gate (void) fcntl(mp->sepipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 1350*7c478bd9Sstevel@tonic-gate /* 1351*7c478bd9Sstevel@tonic-gate * Don't pass extra fds into children. 1352*7c478bd9Sstevel@tonic-gate */ 1353*7c478bd9Sstevel@tonic-gate (void) fcntl(mp->sopipe[RDPIPE], F_SETFD, FD_CLOEXEC); 1354*7c478bd9Sstevel@tonic-gate (void) fcntl(mp->sepipe[RDPIPE], F_SETFD, FD_CLOEXEC); 1355*7c478bd9Sstevel@tonic-gate 1356*7c478bd9Sstevel@tonic-gate return (0); 1357*7c478bd9Sstevel@tonic-gate } 1358*7c478bd9Sstevel@tonic-gate 1359*7c478bd9Sstevel@tonic-gate /* 1360*7c478bd9Sstevel@tonic-gate * Called by a child to attach its stdout and stderr to the write side of 1361*7c478bd9Sstevel@tonic-gate * the pipes. 1362*7c478bd9Sstevel@tonic-gate */ 1363*7c478bd9Sstevel@tonic-gate void 1364*7c478bd9Sstevel@tonic-gate setup_output(vfsent_t *vp) 1365*7c478bd9Sstevel@tonic-gate { 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate (void) close(fileno(stdout)); 1368*7c478bd9Sstevel@tonic-gate (void) dup(vp->sopipe[WRPIPE]); 1369*7c478bd9Sstevel@tonic-gate (void) close(vp->sopipe[WRPIPE]); 1370*7c478bd9Sstevel@tonic-gate 1371*7c478bd9Sstevel@tonic-gate (void) close(fileno(stderr)); 1372*7c478bd9Sstevel@tonic-gate (void) dup(vp->sepipe[WRPIPE]); 1373*7c478bd9Sstevel@tonic-gate (void) close(vp->sepipe[WRPIPE]); 1374*7c478bd9Sstevel@tonic-gate } 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate /* 1377*7c478bd9Sstevel@tonic-gate * Parent uses this to print any stdout or stderr output issued by 1378*7c478bd9Sstevel@tonic-gate * the child. 1379*7c478bd9Sstevel@tonic-gate */ 1380*7c478bd9Sstevel@tonic-gate static void 1381*7c478bd9Sstevel@tonic-gate doio(vfsent_t *vp) 1382*7c478bd9Sstevel@tonic-gate { 1383*7c478bd9Sstevel@tonic-gate int bytes; 1384*7c478bd9Sstevel@tonic-gate char ibuf[BUFSIZ]; 1385*7c478bd9Sstevel@tonic-gate 1386*7c478bd9Sstevel@tonic-gate while ((bytes = read(vp->sepipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 1387*7c478bd9Sstevel@tonic-gate write(fileno(stderr), ibuf, bytes); 1388*7c478bd9Sstevel@tonic-gate while ((bytes = read(vp->sopipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 1389*7c478bd9Sstevel@tonic-gate write(fileno(stdout), ibuf, bytes); 1390*7c478bd9Sstevel@tonic-gate 1391*7c478bd9Sstevel@tonic-gate (void) close(vp->sopipe[RDPIPE]); 1392*7c478bd9Sstevel@tonic-gate (void) close(vp->sepipe[RDPIPE]); 1393*7c478bd9Sstevel@tonic-gate } 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate /* 1396*7c478bd9Sstevel@tonic-gate * Waits for 1 child to die. 1397*7c478bd9Sstevel@tonic-gate * 1398*7c478bd9Sstevel@tonic-gate * Returns -1 if no children are left to wait for. 1399*7c478bd9Sstevel@tonic-gate * Returns 0 if a child died without an error. 1400*7c478bd9Sstevel@tonic-gate * Returns 1 if a child died with an error. 1401*7c478bd9Sstevel@tonic-gate */ 1402*7c478bd9Sstevel@tonic-gate int 1403*7c478bd9Sstevel@tonic-gate dowait() 1404*7c478bd9Sstevel@tonic-gate { 1405*7c478bd9Sstevel@tonic-gate int child, wstat; 1406*7c478bd9Sstevel@tonic-gate 1407*7c478bd9Sstevel@tonic-gate if ((child = wait(&wstat)) == -1) 1408*7c478bd9Sstevel@tonic-gate return (-1); 1409*7c478bd9Sstevel@tonic-gate nrun--; 1410*7c478bd9Sstevel@tonic-gate return (cleanupkid(child, wstat) != 0); 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate /* 1414*7c478bd9Sstevel@tonic-gate * Locates the child mount process represented by pid, outputs any io 1415*7c478bd9Sstevel@tonic-gate * it may have, and returns its exit code. 1416*7c478bd9Sstevel@tonic-gate * Sets the global exitcode if an error occurred. 1417*7c478bd9Sstevel@tonic-gate */ 1418*7c478bd9Sstevel@tonic-gate int 1419*7c478bd9Sstevel@tonic-gate cleanupkid(pid_t pid, int wstat) 1420*7c478bd9Sstevel@tonic-gate { 1421*7c478bd9Sstevel@tonic-gate vfsent_t *vp, *prevp; 1422*7c478bd9Sstevel@tonic-gate int ret; 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate if (WIFEXITED(wstat)) /* this should always be true */ 1425*7c478bd9Sstevel@tonic-gate ret = WEXITSTATUS(wstat); 1426*7c478bd9Sstevel@tonic-gate else 1427*7c478bd9Sstevel@tonic-gate ret = 1; /* assume some kind of error */ 1428*7c478bd9Sstevel@tonic-gate if (ret) 1429*7c478bd9Sstevel@tonic-gate exitcode = 1; 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate /* 1432*7c478bd9Sstevel@tonic-gate * Find our child. 1433*7c478bd9Sstevel@tonic-gate * This search gets smaller and smaller as children are cleaned 1434*7c478bd9Sstevel@tonic-gate * up. 1435*7c478bd9Sstevel@tonic-gate */ 1436*7c478bd9Sstevel@tonic-gate for (prevp = NULL, vp = vfsll; vp; vp = vp->next) { 1437*7c478bd9Sstevel@tonic-gate if (vp->pid != pid) { 1438*7c478bd9Sstevel@tonic-gate prevp = vp; 1439*7c478bd9Sstevel@tonic-gate continue; 1440*7c478bd9Sstevel@tonic-gate } 1441*7c478bd9Sstevel@tonic-gate /* 1442*7c478bd9Sstevel@tonic-gate * Found: let's remove it from this linked list. 1443*7c478bd9Sstevel@tonic-gate */ 1444*7c478bd9Sstevel@tonic-gate if (prevp) { 1445*7c478bd9Sstevel@tonic-gate prevp->next = vp->next; 1446*7c478bd9Sstevel@tonic-gate vp->next = NULL; 1447*7c478bd9Sstevel@tonic-gate } 1448*7c478bd9Sstevel@tonic-gate break; 1449*7c478bd9Sstevel@tonic-gate } 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate if (vp == NULL) { 1452*7c478bd9Sstevel@tonic-gate /* 1453*7c478bd9Sstevel@tonic-gate * This should never happen. 1454*7c478bd9Sstevel@tonic-gate */ 1455*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1456*7c478bd9Sstevel@tonic-gate "%s: Unknown child %d\n"), myname, pid); 1457*7c478bd9Sstevel@tonic-gate exitcode = 1; 1458*7c478bd9Sstevel@tonic-gate return (ret); 1459*7c478bd9Sstevel@tonic-gate } 1460*7c478bd9Sstevel@tonic-gate doio(vp); /* Any output? */ 1461*7c478bd9Sstevel@tonic-gate 1462*7c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && (strcmp(vp->v.vfs_fstype, MNTTYPE_LOFS) == 0)) 1463*7c478bd9Sstevel@tonic-gate lofscnt--; 1464*7c478bd9Sstevel@tonic-gate 1465*7c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 1466*7c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && (strcmp(vp->v.vfs_fstype, "cachefs") == 0)) 1467*7c478bd9Sstevel@tonic-gate cachefs_running = 0; 1468*7c478bd9Sstevel@tonic-gate #endif 1469*7c478bd9Sstevel@tonic-gate 1470*7c478bd9Sstevel@tonic-gate vp->exitcode = ret; 1471*7c478bd9Sstevel@tonic-gate return (ret); 1472*7c478bd9Sstevel@tonic-gate } 1473*7c478bd9Sstevel@tonic-gate 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate static vfsent_t zvmount = { 0 }; 1476*7c478bd9Sstevel@tonic-gate 1477*7c478bd9Sstevel@tonic-gate vfsent_t * 1478*7c478bd9Sstevel@tonic-gate new_vfsent(struct vfstab *vin, int order) 1479*7c478bd9Sstevel@tonic-gate { 1480*7c478bd9Sstevel@tonic-gate vfsent_t *new; 1481*7c478bd9Sstevel@tonic-gate 1482*7c478bd9Sstevel@tonic-gate new = (vfsent_t *)malloc(sizeof (*new)); 1483*7c478bd9Sstevel@tonic-gate if (new == NULL) 1484*7c478bd9Sstevel@tonic-gate nomem(); 1485*7c478bd9Sstevel@tonic-gate 1486*7c478bd9Sstevel@tonic-gate *new = zvmount; 1487*7c478bd9Sstevel@tonic-gate if (vin->vfs_special && 1488*7c478bd9Sstevel@tonic-gate (new->v.vfs_special = strdup(vin->vfs_special)) == NULL) 1489*7c478bd9Sstevel@tonic-gate nomem(); 1490*7c478bd9Sstevel@tonic-gate if (vin->vfs_mountp && 1491*7c478bd9Sstevel@tonic-gate (new->v.vfs_mountp = strdup(vin->vfs_mountp)) == NULL) 1492*7c478bd9Sstevel@tonic-gate nomem(); 1493*7c478bd9Sstevel@tonic-gate if (vin->vfs_fstype && 1494*7c478bd9Sstevel@tonic-gate (new->v.vfs_fstype = strdup(vin->vfs_fstype)) == NULL) 1495*7c478bd9Sstevel@tonic-gate nomem(); 1496*7c478bd9Sstevel@tonic-gate /* 1497*7c478bd9Sstevel@tonic-gate * If specific mount options were specified on the command 1498*7c478bd9Sstevel@tonic-gate * line, then use those. Else, use the ones on the vfstab 1499*7c478bd9Sstevel@tonic-gate * line, if any. In other words, specific options on the 1500*7c478bd9Sstevel@tonic-gate * command line override those in /etc/vfstab. 1501*7c478bd9Sstevel@tonic-gate */ 1502*7c478bd9Sstevel@tonic-gate if (oflg) { 1503*7c478bd9Sstevel@tonic-gate if ((new->v.vfs_mntopts = strdup(specific_opts)) == NULL) 1504*7c478bd9Sstevel@tonic-gate nomem(); 1505*7c478bd9Sstevel@tonic-gate } else if (vin->vfs_mntopts && 1506*7c478bd9Sstevel@tonic-gate (new->v.vfs_mntopts = strdup(vin->vfs_mntopts)) == NULL) 1507*7c478bd9Sstevel@tonic-gate nomem(); 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate new->order = order; 1510*7c478bd9Sstevel@tonic-gate return (new); 1511*7c478bd9Sstevel@tonic-gate } 1512*7c478bd9Sstevel@tonic-gate 1513*7c478bd9Sstevel@tonic-gate /* 1514*7c478bd9Sstevel@tonic-gate * Runs realpath on vp's mount point, records success or failure, 1515*7c478bd9Sstevel@tonic-gate * resets the mount level based on the new realpath, and returns 1516*7c478bd9Sstevel@tonic-gate * realpath()'s return value. 1517*7c478bd9Sstevel@tonic-gate */ 1518*7c478bd9Sstevel@tonic-gate char * 1519*7c478bd9Sstevel@tonic-gate setrpath(vfsent_t *vp) 1520*7c478bd9Sstevel@tonic-gate { 1521*7c478bd9Sstevel@tonic-gate char *rp; 1522*7c478bd9Sstevel@tonic-gate 1523*7c478bd9Sstevel@tonic-gate if ((rp = realpath(vp->v.vfs_mountp, realdir)) == NULL) 1524*7c478bd9Sstevel@tonic-gate vp->flag |= VRPFAILED; 1525*7c478bd9Sstevel@tonic-gate else 1526*7c478bd9Sstevel@tonic-gate vp->flag &= ~VRPFAILED; 1527*7c478bd9Sstevel@tonic-gate 1528*7c478bd9Sstevel@tonic-gate if (vp->rpath) 1529*7c478bd9Sstevel@tonic-gate free(vp->rpath); 1530*7c478bd9Sstevel@tonic-gate if ((vp->rpath = strdup(realdir)) == NULL) 1531*7c478bd9Sstevel@tonic-gate nomem(); 1532*7c478bd9Sstevel@tonic-gate vp->mlevel = fsgetmlevel(vp->rpath); 1533*7c478bd9Sstevel@tonic-gate return (rp); 1534*7c478bd9Sstevel@tonic-gate } 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate 1537*7c478bd9Sstevel@tonic-gate /* 1538*7c478bd9Sstevel@tonic-gate * sort first by mlevel (1...N), then by vfstab order. 1539*7c478bd9Sstevel@tonic-gate */ 1540*7c478bd9Sstevel@tonic-gate int 1541*7c478bd9Sstevel@tonic-gate mlevelcmp(const void *a, const void *b) 1542*7c478bd9Sstevel@tonic-gate { 1543*7c478bd9Sstevel@tonic-gate vfsent_t *a1, *b1; 1544*7c478bd9Sstevel@tonic-gate int lcmp; 1545*7c478bd9Sstevel@tonic-gate 1546*7c478bd9Sstevel@tonic-gate a1 = *(vfsent_t **)a; 1547*7c478bd9Sstevel@tonic-gate b1 = *(vfsent_t **)b; 1548*7c478bd9Sstevel@tonic-gate 1549*7c478bd9Sstevel@tonic-gate lcmp = a1->mlevel - b1->mlevel; 1550*7c478bd9Sstevel@tonic-gate if (lcmp == 0) 1551*7c478bd9Sstevel@tonic-gate lcmp = a1->order - b1->order; 1552*7c478bd9Sstevel@tonic-gate return (lcmp); 1553*7c478bd9Sstevel@tonic-gate } 1554*7c478bd9Sstevel@tonic-gate 1555*7c478bd9Sstevel@tonic-gate /* sort by vfstab order. 0..N */ 1556*7c478bd9Sstevel@tonic-gate mordercmp(const void *a, const void *b) 1557*7c478bd9Sstevel@tonic-gate { 1558*7c478bd9Sstevel@tonic-gate vfsent_t *a1, *b1; 1559*7c478bd9Sstevel@tonic-gate 1560*7c478bd9Sstevel@tonic-gate a1 = *(vfsent_t **)a; 1561*7c478bd9Sstevel@tonic-gate b1 = *(vfsent_t **)b; 1562*7c478bd9Sstevel@tonic-gate return (a1->order - b1->order); 1563*7c478bd9Sstevel@tonic-gate } 1564*7c478bd9Sstevel@tonic-gate 1565*7c478bd9Sstevel@tonic-gate /* 1566*7c478bd9Sstevel@tonic-gate * cleanup the existing children and exit with an error 1567*7c478bd9Sstevel@tonic-gate * if asig != 0. 1568*7c478bd9Sstevel@tonic-gate */ 1569*7c478bd9Sstevel@tonic-gate void 1570*7c478bd9Sstevel@tonic-gate cleanup(int asig) 1571*7c478bd9Sstevel@tonic-gate { 1572*7c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 1573*7c478bd9Sstevel@tonic-gate ; 1574*7c478bd9Sstevel@tonic-gate 1575*7c478bd9Sstevel@tonic-gate if (asig != 0) 1576*7c478bd9Sstevel@tonic-gate exit(1); 1577*7c478bd9Sstevel@tonic-gate } 1578*7c478bd9Sstevel@tonic-gate 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate int 1581*7c478bd9Sstevel@tonic-gate check_fields(char *fstype, char *mountp) 1582*7c478bd9Sstevel@tonic-gate { 1583*7c478bd9Sstevel@tonic-gate struct stat64 stbuf; 1584*7c478bd9Sstevel@tonic-gate 1585*7c478bd9Sstevel@tonic-gate if (strlen(fstype) > (size_t)FSTYPE_MAX) { 1586*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1587*7c478bd9Sstevel@tonic-gate gettext("%s: FSType %s exceeds %d characters\n"), 1588*7c478bd9Sstevel@tonic-gate myname, fstype, FSTYPE_MAX); 1589*7c478bd9Sstevel@tonic-gate return (1); 1590*7c478bd9Sstevel@tonic-gate } 1591*7c478bd9Sstevel@tonic-gate 1592*7c478bd9Sstevel@tonic-gate if (mountp == NULL) { 1593*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1594*7c478bd9Sstevel@tonic-gate gettext("%s: Mount point cannot be determined\n"), 1595*7c478bd9Sstevel@tonic-gate myname); 1596*7c478bd9Sstevel@tonic-gate return (1); 1597*7c478bd9Sstevel@tonic-gate } 1598*7c478bd9Sstevel@tonic-gate if (*mountp != '/') { 1599*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1600*7c478bd9Sstevel@tonic-gate "%s: Mount point %s is not an absolute pathname.\n"), 1601*7c478bd9Sstevel@tonic-gate myname, mountp); 1602*7c478bd9Sstevel@tonic-gate return (1); 1603*7c478bd9Sstevel@tonic-gate } 1604*7c478bd9Sstevel@tonic-gate /* 1605*7c478bd9Sstevel@tonic-gate * Don't do some of these checks if aflg because a mount point may 1606*7c478bd9Sstevel@tonic-gate * not exist now, but will be mounted before we get to it. 1607*7c478bd9Sstevel@tonic-gate * This is one of the quirks of "secondary mounting". 1608*7c478bd9Sstevel@tonic-gate */ 1609*7c478bd9Sstevel@tonic-gate if (!aflg && stat64(mountp, &stbuf) < 0) { 1610*7c478bd9Sstevel@tonic-gate if (errno == ENOENT || errno == ENOTDIR) 1611*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1612*7c478bd9Sstevel@tonic-gate gettext("%s: Mount point %s does not exist.\n"), 1613*7c478bd9Sstevel@tonic-gate myname, mountp); 1614*7c478bd9Sstevel@tonic-gate else { 1615*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1616*7c478bd9Sstevel@tonic-gate gettext("%s: Cannot stat mount point %s.\n"), 1617*7c478bd9Sstevel@tonic-gate myname, mountp); 1618*7c478bd9Sstevel@tonic-gate perror(myname); 1619*7c478bd9Sstevel@tonic-gate } 1620*7c478bd9Sstevel@tonic-gate return (1); 1621*7c478bd9Sstevel@tonic-gate } 1622*7c478bd9Sstevel@tonic-gate return (0); 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate void 1626*7c478bd9Sstevel@tonic-gate nomem() 1627*7c478bd9Sstevel@tonic-gate { 1628*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Out of memory\n"), myname); 1629*7c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 1630*7c478bd9Sstevel@tonic-gate ; 1631*7c478bd9Sstevel@tonic-gate exit(1); 1632*7c478bd9Sstevel@tonic-gate } 1633