17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 227c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 26*4bff34e3Sthurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 277c478bd9Sstevel@tonic-gate * Use is subject to license terms. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.82 */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stdio.h> 33004388ebScasper #include <stdio_ext.h> 347c478bd9Sstevel@tonic-gate #include <limits.h> 357c478bd9Sstevel@tonic-gate #include <fcntl.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <stdarg.h> 407c478bd9Sstevel@tonic-gate #include <sys/types.h> 417c478bd9Sstevel@tonic-gate #include <sys/stat.h> 427c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 437c478bd9Sstevel@tonic-gate #include <errno.h> 447c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 457c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 467c478bd9Sstevel@tonic-gate #include <sys/mount.h> 477c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 487c478bd9Sstevel@tonic-gate #include <sys/param.h> 497c478bd9Sstevel@tonic-gate #include <sys/wait.h> 507c478bd9Sstevel@tonic-gate #include <sys/signal.h> 517c478bd9Sstevel@tonic-gate #include <sys/resource.h> 527c478bd9Sstevel@tonic-gate #include <stropts.h> 537c478bd9Sstevel@tonic-gate #include <sys/conf.h> 547c478bd9Sstevel@tonic-gate #include <locale.h> 557c478bd9Sstevel@tonic-gate #include "fslib.h" 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #define VFS_PATH "/usr/lib/fs" 587c478bd9Sstevel@tonic-gate #define ALT_PATH "/etc/fs" 597c478bd9Sstevel@tonic-gate #define REMOTE "/etc/dfs/fstypes" 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define ARGV_MAX 16 627c478bd9Sstevel@tonic-gate #define TIME_MAX 50 637c478bd9Sstevel@tonic-gate #define FSTYPE_MAX 8 647c478bd9Sstevel@tonic-gate #define REMOTE_MAX 64 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #define OLD 0 677c478bd9Sstevel@tonic-gate #define NEW 1 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #define READONLY 0 707c478bd9Sstevel@tonic-gate #define READWRITE 1 717c478bd9Sstevel@tonic-gate #define SUID 2 727c478bd9Sstevel@tonic-gate #define NOSUID 3 737c478bd9Sstevel@tonic-gate #define SETUID 4 747c478bd9Sstevel@tonic-gate #define NOSETUID 5 757c478bd9Sstevel@tonic-gate #define DEVICES 6 767c478bd9Sstevel@tonic-gate #define NODEVICES 7 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #define FORMAT "%a %b %e %H:%M:%S %Y\n" /* date time format */ 797c478bd9Sstevel@tonic-gate /* a - abbreviated weekday name */ 807c478bd9Sstevel@tonic-gate /* b - abbreviated month name */ 817c478bd9Sstevel@tonic-gate /* e - day of month */ 827c478bd9Sstevel@tonic-gate /* H - hour */ 837c478bd9Sstevel@tonic-gate /* M - minute */ 847c478bd9Sstevel@tonic-gate /* S - second */ 857c478bd9Sstevel@tonic-gate /* Y - Year */ 867c478bd9Sstevel@tonic-gate /* n - newline */ 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate extern int optind; 897c478bd9Sstevel@tonic-gate extern char *optarg; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate extern void usage(void); 927c478bd9Sstevel@tonic-gate extern char *flags(char *, int); 937c478bd9Sstevel@tonic-gate extern char *remote(char *, FILE *); 947c478bd9Sstevel@tonic-gate extern char *default_fstype(char *); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate char *myopts[] = { 977c478bd9Sstevel@tonic-gate MNTOPT_RO, 987c478bd9Sstevel@tonic-gate MNTOPT_RW, 997c478bd9Sstevel@tonic-gate MNTOPT_SUID, 1007c478bd9Sstevel@tonic-gate MNTOPT_NOSUID, 1017c478bd9Sstevel@tonic-gate MNTOPT_SETUID, 1027c478bd9Sstevel@tonic-gate MNTOPT_NOSETUID, 1037c478bd9Sstevel@tonic-gate MNTOPT_DEVICES, 1047c478bd9Sstevel@tonic-gate MNTOPT_NODEVICES, 1057c478bd9Sstevel@tonic-gate NULL 1067c478bd9Sstevel@tonic-gate }; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static char *myname; /* point to argv[0] */ 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 1117c478bd9Sstevel@tonic-gate * Set the limit to double the number of characters a user should be allowed to 1127c478bd9Sstevel@tonic-gate * type in one line. 1137c478bd9Sstevel@tonic-gate * This should cover the different shells, which don't use POSIX_MAX_INPUT, 1147c478bd9Sstevel@tonic-gate * and should cover the case where a long option string can be in 1157c478bd9Sstevel@tonic-gate * the /etc/vfstab file. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate char mntflags[(_POSIX_MAX_INPUT+1) * 2]; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate char realdir[MAXPATHLEN]; /* buffer for realpath() calls */ 1207c478bd9Sstevel@tonic-gate char *vfstab = VFSTAB; 1217c478bd9Sstevel@tonic-gate char *mnttab = MNTTAB; 1227c478bd9Sstevel@tonic-gate char *specific_opts; /* holds specific mount options */ 1237c478bd9Sstevel@tonic-gate char *generic_opts; /* holds generic mount options */ 1247c478bd9Sstevel@tonic-gate int maxrun; 1257c478bd9Sstevel@tonic-gate int nrun; 1267c478bd9Sstevel@tonic-gate int lofscnt; /* presence of lofs prohibits parallel */ 1277c478bd9Sstevel@tonic-gate /* mounting */ 1287c478bd9Sstevel@tonic-gate int exitcode; 1297c478bd9Sstevel@tonic-gate int aflg, cflg, fflg, Fflg, gflg, oflg, pflg, rflg, vflg, Vflg, mflg, Oflg, 1307c478bd9Sstevel@tonic-gate dashflg, questflg, dflg, qflg; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * Currently, mounting cachefs instances simultaneously uncovers various 1347c478bd9Sstevel@tonic-gate * problems. For the short term, we serialize cachefs activity while we fix 1357c478bd9Sstevel@tonic-gate * these cachefs bugs. 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate #define CACHEFS_BUG 1387c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 1397c478bd9Sstevel@tonic-gate int cachefs_running; /* parallel cachefs not supported yet */ 1407c478bd9Sstevel@tonic-gate #endif 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Each vfsent_t describes a vfstab entry. It is used to manage and cleanup 1447c478bd9Sstevel@tonic-gate * each child that performs the particular mount for the entry. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate typedef struct vfsent { 1487c478bd9Sstevel@tonic-gate struct vfstab v; /* the vfstab entry */ 1497c478bd9Sstevel@tonic-gate char *rpath; /* resolved pathname so far */ 1507c478bd9Sstevel@tonic-gate int mlevel; /* how deep is this mount point */ 1517c478bd9Sstevel@tonic-gate int order; /* vfstab serial order of this vfs */ 1527c478bd9Sstevel@tonic-gate int flag; 1537c478bd9Sstevel@tonic-gate pid_t pid; /* the pid of this mount process */ 1547c478bd9Sstevel@tonic-gate int exitcode; /* process's exitcode */ 1557c478bd9Sstevel@tonic-gate #define RDPIPE 0 1567c478bd9Sstevel@tonic-gate #define WRPIPE 1 1577c478bd9Sstevel@tonic-gate int sopipe[2]; /* pipe attached to child's stdout */ 1587c478bd9Sstevel@tonic-gate int sepipe[2]; /* pipe attached to child's stderr */ 1597c478bd9Sstevel@tonic-gate struct vfsent *next; /* used when in linked list */ 1607c478bd9Sstevel@tonic-gate } vfsent_t; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate #define VRPFAILED 0x01 /* most recent realpath failed on */ 1637c478bd9Sstevel@tonic-gate /* this mount point */ 1647c478bd9Sstevel@tonic-gate #define VNOTMOUNTED 0x02 /* mount point could not be mounted */ 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate vfsent_t *vfsll, *vfslltail; /* head and tail of the global */ 1677c478bd9Sstevel@tonic-gate /* linked list of vfstab entries */ 1687c478bd9Sstevel@tonic-gate vfsent_t **vfsarray; /* global array of vfsent_t's */ 1697c478bd9Sstevel@tonic-gate int vfsarraysize; /* length of the list */ 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * This structure is used to build a linked list of 1737c478bd9Sstevel@tonic-gate * mnttab structures from /etc/mnttab. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate typedef struct mountent { 1767c478bd9Sstevel@tonic-gate struct extmnttab *ment; 1777c478bd9Sstevel@tonic-gate int flag; 1787c478bd9Sstevel@tonic-gate struct mountent *next; 1797c478bd9Sstevel@tonic-gate } mountent_t; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate #define MSORTED 0x1 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate static vfsent_t **make_vfsarray(char **, int); 1847c478bd9Sstevel@tonic-gate static vfsent_t *new_vfsent(struct vfstab *, int); 1857c478bd9Sstevel@tonic-gate static vfsent_t *getvfsall(char *, int); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate static void doexec(char *, char **); 1887c478bd9Sstevel@tonic-gate static void nomem(); 1897c478bd9Sstevel@tonic-gate static void cleanup(int); 1907c478bd9Sstevel@tonic-gate static char *setrpath(vfsent_t *); 1917c478bd9Sstevel@tonic-gate static int dowait(); 1927c478bd9Sstevel@tonic-gate static int setup_iopipe(vfsent_t *); 1937c478bd9Sstevel@tonic-gate static void setup_output(vfsent_t *); 1947c478bd9Sstevel@tonic-gate static void doio(vfsent_t *); 1957c478bd9Sstevel@tonic-gate static void do_mounts(); 1967c478bd9Sstevel@tonic-gate static int parmount(char **, int, char *); 1977c478bd9Sstevel@tonic-gate static int mlevelcmp(const void *, const void *); 1987c478bd9Sstevel@tonic-gate static int mordercmp(const void *, const void *); 1997c478bd9Sstevel@tonic-gate static int check_fields(char *, char *); 2007c478bd9Sstevel@tonic-gate static int cleanupkid(pid_t, int); 2017c478bd9Sstevel@tonic-gate static void print_mnttab(int, int); 2027c478bd9Sstevel@tonic-gate static void vfserror(int, char *); 2037c478bd9Sstevel@tonic-gate static void mnterror(int); 2047c478bd9Sstevel@tonic-gate static int ignore(char *); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* 2077c478bd9Sstevel@tonic-gate * This is /usr/sbin/mount: the generic command that in turn 2087c478bd9Sstevel@tonic-gate * execs the appropriate /usr/lib/fs/{fstype}/mount. 2097c478bd9Sstevel@tonic-gate * The -F flag and argument are NOT passed. 2107c478bd9Sstevel@tonic-gate * If the usr file system is not mounted a duplicate copy 2117c478bd9Sstevel@tonic-gate * can be found in /sbin and this version execs the 2127c478bd9Sstevel@tonic-gate * appropriate /etc/fs/{fstype}/mount 2137c478bd9Sstevel@tonic-gate * 2147c478bd9Sstevel@tonic-gate * If the -F fstype, special or directory are missing, 2157c478bd9Sstevel@tonic-gate * /etc/vfstab is searched to fill in the missing arguments. 2167c478bd9Sstevel@tonic-gate * 2177c478bd9Sstevel@tonic-gate * -V will print the built command on the stdout. 2187c478bd9Sstevel@tonic-gate * It isn't passed either. 2197c478bd9Sstevel@tonic-gate */ 22008190127Sdh int 22108190127Sdh main(int argc, char *argv[]) 2227c478bd9Sstevel@tonic-gate { 223*4bff34e3Sthurlow char *special, /* argument of special/resource */ 224*4bff34e3Sthurlow *mountp, /* argument of mount directory */ 225*4bff34e3Sthurlow *fstype, /* wherein the fstype name is filled */ 226*4bff34e3Sthurlow *newargv[ARGV_MAX], /* arg list for specific command */ 227*4bff34e3Sthurlow *farg = NULL, *Farg = NULL; 2287c478bd9Sstevel@tonic-gate int ii, ret, cc, fscnt; 2297c478bd9Sstevel@tonic-gate struct stat64 stbuf; 2307c478bd9Sstevel@tonic-gate struct vfstab vget, vref; 2317c478bd9Sstevel@tonic-gate mode_t mode; 2327c478bd9Sstevel@tonic-gate FILE *fd; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 2377c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 2387c478bd9Sstevel@tonic-gate #endif 2397c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate myname = strrchr(argv[0], '/'); 2427c478bd9Sstevel@tonic-gate if (myname) 2437c478bd9Sstevel@tonic-gate myname++; 2447c478bd9Sstevel@tonic-gate else 2457c478bd9Sstevel@tonic-gate myname = argv[0]; 2467c478bd9Sstevel@tonic-gate if (myname == 0) myname = "path unknown"; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* Process the args. */ 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate while ((cc = getopt(argc, argv, "?acd:f:F:gmno:pqrvVO")) != -1) 2517c478bd9Sstevel@tonic-gate switch (cc) { 2527c478bd9Sstevel@tonic-gate case 'a': 2537c478bd9Sstevel@tonic-gate aflg++; 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate case 'c': 2567c478bd9Sstevel@tonic-gate cflg++; 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate #ifdef DEBUG 2607c478bd9Sstevel@tonic-gate case 'd': 2617c478bd9Sstevel@tonic-gate dflg = atoi(optarg); 2627c478bd9Sstevel@tonic-gate break; 2637c478bd9Sstevel@tonic-gate #endif 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate case 'f': 2667c478bd9Sstevel@tonic-gate fflg++; 2677c478bd9Sstevel@tonic-gate farg = optarg; 2687c478bd9Sstevel@tonic-gate break; 2697c478bd9Sstevel@tonic-gate case 'F': 2707c478bd9Sstevel@tonic-gate Fflg++; 2717c478bd9Sstevel@tonic-gate Farg = optarg; 2727c478bd9Sstevel@tonic-gate break; 2737c478bd9Sstevel@tonic-gate case 'g': 2747c478bd9Sstevel@tonic-gate gflg++; 2757c478bd9Sstevel@tonic-gate break; 2767c478bd9Sstevel@tonic-gate case 'm': 2777c478bd9Sstevel@tonic-gate mflg++; 2787c478bd9Sstevel@tonic-gate break; /* do not update /etc/mnttab */ 2797c478bd9Sstevel@tonic-gate case 'o': 2807c478bd9Sstevel@tonic-gate oflg++; 2817c478bd9Sstevel@tonic-gate if ((specific_opts = strdup(optarg)) == NULL) 2827c478bd9Sstevel@tonic-gate nomem(); 2837c478bd9Sstevel@tonic-gate break; /* fstype dependent options */ 2847c478bd9Sstevel@tonic-gate case 'O': 2857c478bd9Sstevel@tonic-gate Oflg++; 2867c478bd9Sstevel@tonic-gate break; 2877c478bd9Sstevel@tonic-gate case 'p': 2887c478bd9Sstevel@tonic-gate pflg++; 2897c478bd9Sstevel@tonic-gate break; 2907c478bd9Sstevel@tonic-gate case 'q': 2917c478bd9Sstevel@tonic-gate qflg++; 2927c478bd9Sstevel@tonic-gate break; 2937c478bd9Sstevel@tonic-gate case 'r': 2947c478bd9Sstevel@tonic-gate rflg++; 2957c478bd9Sstevel@tonic-gate generic_opts = "ro"; 2967c478bd9Sstevel@tonic-gate break; 2977c478bd9Sstevel@tonic-gate case 'v': 2987c478bd9Sstevel@tonic-gate vflg++; 2997c478bd9Sstevel@tonic-gate break; 3007c478bd9Sstevel@tonic-gate case 'V': 3017c478bd9Sstevel@tonic-gate Vflg++; 3027c478bd9Sstevel@tonic-gate break; 3037c478bd9Sstevel@tonic-gate case '?': 3047c478bd9Sstevel@tonic-gate questflg++; 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* copy '--' to specific */ 3097c478bd9Sstevel@tonic-gate if (strcmp(argv[optind-1], "--") == 0) 3107c478bd9Sstevel@tonic-gate dashflg++; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* option checking */ 3137c478bd9Sstevel@tonic-gate /* more than two args not allowed if !aflg */ 3147c478bd9Sstevel@tonic-gate if (!aflg && (argc - optind > 2)) 3157c478bd9Sstevel@tonic-gate usage(); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* pv mututally exclusive */ 3187c478bd9Sstevel@tonic-gate if (pflg + vflg + aflg > 1) { 3197c478bd9Sstevel@tonic-gate fprintf(stderr, gettext 320*4bff34e3Sthurlow ("%s: -a, -p, and -v are mutually exclusive\n"), 321*4bff34e3Sthurlow myname); 3227c478bd9Sstevel@tonic-gate usage(); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * Can't have overlaying mounts on the same mount point during 3277c478bd9Sstevel@tonic-gate * a parallel mount. 3287c478bd9Sstevel@tonic-gate */ 3297c478bd9Sstevel@tonic-gate if (aflg && Oflg) { 3307c478bd9Sstevel@tonic-gate fprintf(stderr, gettext 331*4bff34e3Sthurlow ("%s: -a and -O are mutually exclusive\n"), myname); 3327c478bd9Sstevel@tonic-gate usage(); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* dfF mutually exclusive */ 3367c478bd9Sstevel@tonic-gate if (fflg + Fflg > 1) { 3377c478bd9Sstevel@tonic-gate fprintf(stderr, gettext 338*4bff34e3Sthurlow ("%s: More than one FSType specified\n"), myname); 3397c478bd9Sstevel@tonic-gate usage(); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* no arguments, only allow p,v,V or [F]? */ 3437c478bd9Sstevel@tonic-gate if (!aflg && optind == argc) { 3447c478bd9Sstevel@tonic-gate if (cflg || fflg || mflg || oflg || rflg || qflg) 3457c478bd9Sstevel@tonic-gate usage(); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate if (Fflg && !questflg) 3487c478bd9Sstevel@tonic-gate usage(); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (questflg) { 3517c478bd9Sstevel@tonic-gate if (Fflg) { 3527c478bd9Sstevel@tonic-gate newargv[2] = "-?"; 3537c478bd9Sstevel@tonic-gate newargv[3] = NULL; 3547c478bd9Sstevel@tonic-gate doexec(Farg, newargv); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate usage(); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (questflg) 3617c478bd9Sstevel@tonic-gate usage(); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* one or two args, allow any but p,v */ 3647c478bd9Sstevel@tonic-gate if (optind != argc && (pflg || vflg)) { 3657c478bd9Sstevel@tonic-gate fprintf(stderr, 3667c478bd9Sstevel@tonic-gate gettext("%s: Cannot use -p and -v with arguments\n"), myname); 3677c478bd9Sstevel@tonic-gate usage(); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* if only reporting mnttab, generic prints mnttab and exits */ 3727c478bd9Sstevel@tonic-gate if (!aflg && optind == argc) { 3737c478bd9Sstevel@tonic-gate if (Vflg) { 3747c478bd9Sstevel@tonic-gate printf("%s", myname); 3757c478bd9Sstevel@tonic-gate if (pflg) 3767c478bd9Sstevel@tonic-gate printf(" -p"); 3777c478bd9Sstevel@tonic-gate if (vflg) 3787c478bd9Sstevel@tonic-gate printf(" -v"); 3797c478bd9Sstevel@tonic-gate printf("\n"); 3807c478bd9Sstevel@tonic-gate exit(0); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate print_mnttab(vflg, pflg); 3847c478bd9Sstevel@tonic-gate exit(0); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate /* 3887c478bd9Sstevel@tonic-gate * Get filesystem type here. If "-F FStype" is specified, use 3897c478bd9Sstevel@tonic-gate * that fs type. Otherwise, determine the fs type from /etc/vfstab 3907c478bd9Sstevel@tonic-gate * if the entry exists. Otherwise, determine the local or remote 3917c478bd9Sstevel@tonic-gate * fs type from /etc/default/df or /etc/dfs/fstypes respectively. 3927c478bd9Sstevel@tonic-gate */ 3937c478bd9Sstevel@tonic-gate if (fflg) { 3947c478bd9Sstevel@tonic-gate if ((strcmp(farg, "S51K") != 0) && 3957c478bd9Sstevel@tonic-gate (strcmp(farg, "S52K") != 0)) { 3967c478bd9Sstevel@tonic-gate fstype = farg; 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate else 3997c478bd9Sstevel@tonic-gate fstype = "ufs"; 4007c478bd9Sstevel@tonic-gate } else /* if (Fflg) */ 4017c478bd9Sstevel@tonic-gate fstype = Farg; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate fscnt = argc - optind; 4047c478bd9Sstevel@tonic-gate if (aflg && (fscnt != 1)) 4057c478bd9Sstevel@tonic-gate exit(parmount(argv + optind, fscnt, fstype)); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Then don't bother with the parallel over head. Everything 4097c478bd9Sstevel@tonic-gate * from this point is simple/normal single execution. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate aflg = 0; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* get special and/or mount-point from arg(s) */ 4147c478bd9Sstevel@tonic-gate if (fscnt == 2) 4157c478bd9Sstevel@tonic-gate special = argv[optind++]; 4167c478bd9Sstevel@tonic-gate else 4177c478bd9Sstevel@tonic-gate special = NULL; 4187c478bd9Sstevel@tonic-gate if (optind < argc) 4197c478bd9Sstevel@tonic-gate mountp = argv[optind++]; 4207c478bd9Sstevel@tonic-gate else 4217c478bd9Sstevel@tonic-gate mountp = NULL; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* lookup only if we need to */ 4247c478bd9Sstevel@tonic-gate if (fstype == NULL || specific_opts == NULL || special == NULL || 4257c478bd9Sstevel@tonic-gate mountp == NULL) { 4267c478bd9Sstevel@tonic-gate if ((fd = fopen(vfstab, "r")) == NULL) { 4277c478bd9Sstevel@tonic-gate if (fstype == NULL || special == NULL || 428*4bff34e3Sthurlow mountp == NULL) { 4297c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 430*4bff34e3Sthurlow "%s: Cannot open %s\n"), 431*4bff34e3Sthurlow myname, vfstab); 4327c478bd9Sstevel@tonic-gate exit(1); 4337c478bd9Sstevel@tonic-gate } else { 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate * No vfstab, but we know what we want 4367c478bd9Sstevel@tonic-gate * to mount. 4377c478bd9Sstevel@tonic-gate */ 4387c478bd9Sstevel@tonic-gate goto out; 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate vfsnull(&vref); 4427c478bd9Sstevel@tonic-gate vref.vfs_special = special; 4437c478bd9Sstevel@tonic-gate vref.vfs_mountp = mountp; 4447c478bd9Sstevel@tonic-gate vref.vfs_fstype = fstype; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* get a vfstab entry matching mountp or special */ 4477c478bd9Sstevel@tonic-gate while ((ret = getvfsany(fd, &vget, &vref)) > 0) 4487c478bd9Sstevel@tonic-gate vfserror(ret, vget.vfs_special); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* if no entry and there was only one argument */ 4517c478bd9Sstevel@tonic-gate /* then the argument could be the special */ 4527c478bd9Sstevel@tonic-gate /* and not mount point as we thought earlier */ 4537c478bd9Sstevel@tonic-gate if (ret == -1 && special == NULL) { 4547c478bd9Sstevel@tonic-gate rewind(fd); 4557c478bd9Sstevel@tonic-gate special = vref.vfs_special = mountp; 4567c478bd9Sstevel@tonic-gate mountp = vref.vfs_mountp = NULL; 4577c478bd9Sstevel@tonic-gate /* skip erroneous lines; they were reported above */ 458*4bff34e3Sthurlow while ((ret = getvfsany(fd, &vget, &vref)) > 0) 459*4bff34e3Sthurlow ; 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate fclose(fd); 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate if (ret == 0) { 4657c478bd9Sstevel@tonic-gate if (fstype == NULL) 4667c478bd9Sstevel@tonic-gate fstype = vget.vfs_fstype; 4677c478bd9Sstevel@tonic-gate if (special == NULL) 4687c478bd9Sstevel@tonic-gate special = vget.vfs_special; 4697c478bd9Sstevel@tonic-gate if (mountp == NULL) 4707c478bd9Sstevel@tonic-gate mountp = vget.vfs_mountp; 4717c478bd9Sstevel@tonic-gate if (oflg == 0 && vget.vfs_mntopts) { 4727c478bd9Sstevel@tonic-gate oflg++; 4737c478bd9Sstevel@tonic-gate specific_opts = vget.vfs_mntopts; 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate } else if (special == NULL) { 4767c478bd9Sstevel@tonic-gate if (stat64(mountp, &stbuf) == -1) { 4777c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: cannot stat %s\n"), 478*4bff34e3Sthurlow myname, mountp); 4797c478bd9Sstevel@tonic-gate exit(2); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate if (((mode = (stbuf.st_mode & S_IFMT)) == S_IFBLK) || 482*4bff34e3Sthurlow (mode == S_IFCHR)) { 4837c478bd9Sstevel@tonic-gate fprintf(stderr, 4847c478bd9Sstevel@tonic-gate gettext("%s: mount point cannot be determined\n"), 485*4bff34e3Sthurlow myname); 4867c478bd9Sstevel@tonic-gate exit(1); 4877c478bd9Sstevel@tonic-gate } else 4887c478bd9Sstevel@tonic-gate { 4897c478bd9Sstevel@tonic-gate fprintf(stderr, 4907c478bd9Sstevel@tonic-gate gettext("%s: special cannot be determined\n"), 491*4bff34e3Sthurlow myname); 4927c478bd9Sstevel@tonic-gate exit(1); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate } else if (fstype == NULL) 4957c478bd9Sstevel@tonic-gate fstype = default_fstype(special); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate out: 4997c478bd9Sstevel@tonic-gate if (check_fields(fstype, mountp)) 5007c478bd9Sstevel@tonic-gate exit(1); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate if (realpath(mountp, realdir) == NULL) { 5037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "mount: "); 5047c478bd9Sstevel@tonic-gate perror(mountp); 5057c478bd9Sstevel@tonic-gate exit(1); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate if ((mountp = strdup(realdir)) == NULL) 5097c478bd9Sstevel@tonic-gate nomem(); 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* create the new arg list, and end the list with a null pointer */ 5127c478bd9Sstevel@tonic-gate ii = 2; 5137c478bd9Sstevel@tonic-gate if (cflg) 5147c478bd9Sstevel@tonic-gate newargv[ii++] = "-c"; 5157c478bd9Sstevel@tonic-gate if (gflg) 5167c478bd9Sstevel@tonic-gate newargv[ii++] = "-g"; 5177c478bd9Sstevel@tonic-gate if (mflg) 5187c478bd9Sstevel@tonic-gate newargv[ii++] = "-m"; 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * The q option needs to go before the -o option as some 5217c478bd9Sstevel@tonic-gate * filesystems complain during first pass option parsing. 5227c478bd9Sstevel@tonic-gate */ 5237c478bd9Sstevel@tonic-gate if (qflg) 5247c478bd9Sstevel@tonic-gate newargv[ii++] = "-q"; 5257c478bd9Sstevel@tonic-gate if (oflg) { 5267c478bd9Sstevel@tonic-gate newargv[ii++] = "-o"; 5277c478bd9Sstevel@tonic-gate newargv[ii++] = specific_opts; 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate if (Oflg) 5307c478bd9Sstevel@tonic-gate newargv[ii++] = "-O"; 5317c478bd9Sstevel@tonic-gate if (rflg) 5327c478bd9Sstevel@tonic-gate newargv[ii++] = "-r"; 5337c478bd9Sstevel@tonic-gate if (dashflg) 5347c478bd9Sstevel@tonic-gate newargv[ii++] = "--"; 5357c478bd9Sstevel@tonic-gate newargv[ii++] = special; 5367c478bd9Sstevel@tonic-gate newargv[ii++] = mountp; 5377c478bd9Sstevel@tonic-gate newargv[ii] = NULL; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate doexec(fstype, newargv); 54008190127Sdh return (0); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate void 54408190127Sdh usage(void) 5457c478bd9Sstevel@tonic-gate { 5467c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Usage:\n%s [-v | -p]\n"), myname); 5477c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 548*4bff34e3Sthurlow "%s [-F FSType] [-V] [current_options] [-o specific_options]"), 549*4bff34e3Sthurlow myname); 5507c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\n\t{special | mount_point}\n")); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 553*4bff34e3Sthurlow "%s [-F FSType] [-V] [current_options] [-o specific_options]"), 554*4bff34e3Sthurlow myname); 5557c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\n\tspecial mount_point\n")); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 5587c478bd9Sstevel@tonic-gate "%s -a [-F FSType ] [-V] [current_options] [-o specific_options]\n"), 559*4bff34e3Sthurlow myname); 5607c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\t[mount_point ...]\n")); 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate exit(1); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * Get rid of "dev=[hex string]" clause, if any. It's not legal 5677c478bd9Sstevel@tonic-gate * when printing in vfstab format. 5687c478bd9Sstevel@tonic-gate */ 5697c478bd9Sstevel@tonic-gate void 5707c478bd9Sstevel@tonic-gate elide_dev(char *mntopts) 5717c478bd9Sstevel@tonic-gate { 5727c478bd9Sstevel@tonic-gate char *dev, *other; 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate if (mntopts != NULL) { 5757c478bd9Sstevel@tonic-gate dev = strstr(mntopts, "dev="); 5767c478bd9Sstevel@tonic-gate if (dev != NULL) { 5777c478bd9Sstevel@tonic-gate other = strpbrk(dev, ","); 5787c478bd9Sstevel@tonic-gate if (other == NULL) { 5797c478bd9Sstevel@tonic-gate /* last option */ 5807c478bd9Sstevel@tonic-gate if (dev != mntopts) { 5817c478bd9Sstevel@tonic-gate *--dev = '\0'; 5827c478bd9Sstevel@tonic-gate } else { 5837c478bd9Sstevel@tonic-gate *dev = '\0'; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate } else { 5867c478bd9Sstevel@tonic-gate /* first or intermediate option */ 5877c478bd9Sstevel@tonic-gate memmove(dev, other+1, strlen(other+1)+1); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate void 59408190127Sdh print_mnttab(int vflg, int pflg) 5957c478bd9Sstevel@tonic-gate { 5967c478bd9Sstevel@tonic-gate FILE *fd; 5977c478bd9Sstevel@tonic-gate FILE *rfp; /* this will be NULL if fopen fails */ 5987c478bd9Sstevel@tonic-gate int ret; 5997c478bd9Sstevel@tonic-gate char time_buf[TIME_MAX]; /* array to hold date and time */ 6007c478bd9Sstevel@tonic-gate struct extmnttab mget; 6017c478bd9Sstevel@tonic-gate time_t ltime; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if ((fd = fopen(mnttab, "r")) == NULL) { 6047c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot open mnttab\n"), myname); 6057c478bd9Sstevel@tonic-gate exit(1); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate rfp = fopen(REMOTE, "r"); 6087c478bd9Sstevel@tonic-gate while ((ret = getextmntent(fd, &mget, sizeof (struct extmnttab))) 609*4bff34e3Sthurlow == 0) { 6107c478bd9Sstevel@tonic-gate if (ignore(mget.mnt_mntopts)) 6117c478bd9Sstevel@tonic-gate continue; 6127c478bd9Sstevel@tonic-gate if (mget.mnt_special && mget.mnt_mountp && 6137c478bd9Sstevel@tonic-gate mget.mnt_fstype && mget.mnt_time) { 6147c478bd9Sstevel@tonic-gate ltime = atol(mget.mnt_time); 6157c478bd9Sstevel@tonic-gate cftime(time_buf, FORMAT, <ime); 6167c478bd9Sstevel@tonic-gate if (pflg) { 6177c478bd9Sstevel@tonic-gate elide_dev(mget.mnt_mntopts); 6187c478bd9Sstevel@tonic-gate printf("%s - %s %s - no %s\n", 619*4bff34e3Sthurlow mget.mnt_special, 620*4bff34e3Sthurlow mget.mnt_mountp, 621*4bff34e3Sthurlow mget.mnt_fstype, 622*4bff34e3Sthurlow mget.mnt_mntopts != NULL ? 623*4bff34e3Sthurlow mget.mnt_mntopts : "-"); 6247c478bd9Sstevel@tonic-gate } else if (vflg) { 6257c478bd9Sstevel@tonic-gate printf("%s on %s type %s %s%s on %s", 626*4bff34e3Sthurlow mget.mnt_special, 627*4bff34e3Sthurlow mget.mnt_mountp, 628*4bff34e3Sthurlow mget.mnt_fstype, 629*4bff34e3Sthurlow remote(mget.mnt_fstype, rfp), 630*4bff34e3Sthurlow flags(mget.mnt_mntopts, NEW), 631*4bff34e3Sthurlow time_buf); 6327c478bd9Sstevel@tonic-gate } else 6337c478bd9Sstevel@tonic-gate printf("%s on %s %s%s on %s", 634*4bff34e3Sthurlow mget.mnt_mountp, 635*4bff34e3Sthurlow mget.mnt_special, 636*4bff34e3Sthurlow remote(mget.mnt_fstype, rfp), 637*4bff34e3Sthurlow flags(mget.mnt_mntopts, OLD), 638*4bff34e3Sthurlow time_buf); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate if (ret > 0) 6427c478bd9Sstevel@tonic-gate mnterror(ret); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate char * 64608190127Sdh flags(char *mntopts, int flag) 6477c478bd9Sstevel@tonic-gate { 6487c478bd9Sstevel@tonic-gate char opts[sizeof (mntflags)]; 6497c478bd9Sstevel@tonic-gate char *value; 6507c478bd9Sstevel@tonic-gate int rdwr = 1; 6517c478bd9Sstevel@tonic-gate int suid = 1; 6527c478bd9Sstevel@tonic-gate int devices = 1; 6537c478bd9Sstevel@tonic-gate int setuid = 1; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate if (mntopts == NULL || *mntopts == '\0') 6567c478bd9Sstevel@tonic-gate return ("read/write/setuid/devices"); 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate strcpy(opts, ""); 6597c478bd9Sstevel@tonic-gate while (*mntopts != '\0') { 6607c478bd9Sstevel@tonic-gate switch (getsubopt(&mntopts, myopts, &value)) { 6617c478bd9Sstevel@tonic-gate case READONLY: 6627c478bd9Sstevel@tonic-gate rdwr = 0; 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate case READWRITE: 6657c478bd9Sstevel@tonic-gate rdwr = 1; 6667c478bd9Sstevel@tonic-gate break; 6677c478bd9Sstevel@tonic-gate case SUID: 6687c478bd9Sstevel@tonic-gate suid = 1; 6697c478bd9Sstevel@tonic-gate break; 6707c478bd9Sstevel@tonic-gate case NOSUID: 6717c478bd9Sstevel@tonic-gate suid = 0; 6727c478bd9Sstevel@tonic-gate break; 6737c478bd9Sstevel@tonic-gate case SETUID: 6747c478bd9Sstevel@tonic-gate setuid = 1; 6757c478bd9Sstevel@tonic-gate break; 6767c478bd9Sstevel@tonic-gate case NOSETUID: 6777c478bd9Sstevel@tonic-gate setuid = 0; 6787c478bd9Sstevel@tonic-gate break; 6797c478bd9Sstevel@tonic-gate case DEVICES: 6807c478bd9Sstevel@tonic-gate devices = 1; 6817c478bd9Sstevel@tonic-gate break; 6827c478bd9Sstevel@tonic-gate case NODEVICES: 6837c478bd9Sstevel@tonic-gate devices = 0; 6847c478bd9Sstevel@tonic-gate break; 6857c478bd9Sstevel@tonic-gate default: 6867c478bd9Sstevel@tonic-gate /* cat '/' separator to mntflags */ 6877c478bd9Sstevel@tonic-gate if (*opts != '\0' && value != NULL) 6887c478bd9Sstevel@tonic-gate strcat(opts, "/"); 6897c478bd9Sstevel@tonic-gate strcat(opts, value); 6907c478bd9Sstevel@tonic-gate break; 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate strcpy(mntflags, ""); 6957c478bd9Sstevel@tonic-gate if (rdwr) 6967c478bd9Sstevel@tonic-gate strcat(mntflags, "read/write"); 6977c478bd9Sstevel@tonic-gate else if (flag == OLD) 6987c478bd9Sstevel@tonic-gate strcat(mntflags, "read only"); 6997c478bd9Sstevel@tonic-gate else 7007c478bd9Sstevel@tonic-gate strcat(mntflags, "read-only"); 7017c478bd9Sstevel@tonic-gate if (suid) { 7027c478bd9Sstevel@tonic-gate if (setuid) 7037c478bd9Sstevel@tonic-gate strcat(mntflags, "/setuid"); 7047c478bd9Sstevel@tonic-gate else 7057c478bd9Sstevel@tonic-gate strcat(mntflags, "/nosetuid"); 7067c478bd9Sstevel@tonic-gate if (devices) 7077c478bd9Sstevel@tonic-gate strcat(mntflags, "/devices"); 7087c478bd9Sstevel@tonic-gate else 7097c478bd9Sstevel@tonic-gate strcat(mntflags, "/nodevices"); 7107c478bd9Sstevel@tonic-gate } else { 7117c478bd9Sstevel@tonic-gate strcat(mntflags, "/nosetuid/nodevices"); 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate if (*opts != '\0') { 7147c478bd9Sstevel@tonic-gate strcat(mntflags, "/"); 7157c478bd9Sstevel@tonic-gate strcat(mntflags, opts); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate /* 7197c478bd9Sstevel@tonic-gate * The assumed assertion 7207c478bd9Sstevel@tonic-gate * assert (strlen(mntflags) < sizeof mntflags); 7217c478bd9Sstevel@tonic-gate * is valid at this point in the code. Note that a call to "assert" 7227c478bd9Sstevel@tonic-gate * is not appropriate in production code since it halts the program. 7237c478bd9Sstevel@tonic-gate */ 7247c478bd9Sstevel@tonic-gate return (mntflags); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate char * 72808190127Sdh remote(char *fstype, FILE *rfp) 7297c478bd9Sstevel@tonic-gate { 7307c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 7317c478bd9Sstevel@tonic-gate char *fs; 7327c478bd9Sstevel@tonic-gate extern char *strtok(); 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate if (rfp == NULL || fstype == NULL || 735*4bff34e3Sthurlow strlen(fstype) > (size_t)FSTYPE_MAX) 7367c478bd9Sstevel@tonic-gate return (""); /* not a remote */ 7377c478bd9Sstevel@tonic-gate rewind(rfp); 7387c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), rfp) != NULL) { 7397c478bd9Sstevel@tonic-gate fs = strtok(buf, " \t\n"); 7407c478bd9Sstevel@tonic-gate if (strcmp(fstype, fs) == 0) 7417c478bd9Sstevel@tonic-gate return ("remote/"); /* is a remote fs */ 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate return (""); /* not a remote */ 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate void 7487c478bd9Sstevel@tonic-gate vfserror(int flag, char *special) 7497c478bd9Sstevel@tonic-gate { 7507c478bd9Sstevel@tonic-gate if (special == NULL) 7517c478bd9Sstevel@tonic-gate special = "<null>"; 7527c478bd9Sstevel@tonic-gate switch (flag) { 7537c478bd9Sstevel@tonic-gate case VFS_TOOLONG: 7547c478bd9Sstevel@tonic-gate fprintf(stderr, 7557c478bd9Sstevel@tonic-gate gettext("%s: Warning: Line in vfstab for \"%s\" exceeds %d characters\n"), 756*4bff34e3Sthurlow myname, special, VFS_LINE_MAX-1); 7577c478bd9Sstevel@tonic-gate break; 7587c478bd9Sstevel@tonic-gate case VFS_TOOFEW: 7597c478bd9Sstevel@tonic-gate fprintf(stderr, 7607c478bd9Sstevel@tonic-gate gettext("%s: Warning: Line for \"%s\" in vfstab has too few entries\n"), 761*4bff34e3Sthurlow myname, special); 7627c478bd9Sstevel@tonic-gate break; 7637c478bd9Sstevel@tonic-gate case VFS_TOOMANY: 7647c478bd9Sstevel@tonic-gate fprintf(stderr, 7657c478bd9Sstevel@tonic-gate gettext("%s: Warning: Line for \"%s\" in vfstab has too many entries\n"), 766*4bff34e3Sthurlow myname, special); 7677c478bd9Sstevel@tonic-gate break; 7687c478bd9Sstevel@tonic-gate default: 7697c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 770*4bff34e3Sthurlow "%s: Warning: Error in line for \"%s\" in vfstab\n"), 771*4bff34e3Sthurlow myname, special); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate void 77608190127Sdh mnterror(int flag) 7777c478bd9Sstevel@tonic-gate { 7787c478bd9Sstevel@tonic-gate switch (flag) { 7797c478bd9Sstevel@tonic-gate case MNT_TOOLONG: 7807c478bd9Sstevel@tonic-gate fprintf(stderr, 781*4bff34e3Sthurlow gettext("%s: Line in mnttab exceeds %d characters\n"), 782*4bff34e3Sthurlow myname, MNT_LINE_MAX-2); 7837c478bd9Sstevel@tonic-gate break; 7847c478bd9Sstevel@tonic-gate case MNT_TOOFEW: 7857c478bd9Sstevel@tonic-gate fprintf(stderr, 786*4bff34e3Sthurlow gettext("%s: Line in mnttab has too few entries\n"), 787*4bff34e3Sthurlow myname); 7887c478bd9Sstevel@tonic-gate break; 7897c478bd9Sstevel@tonic-gate case MNT_TOOMANY: 7907c478bd9Sstevel@tonic-gate fprintf(stderr, 791*4bff34e3Sthurlow gettext("%s: Line in mnttab has too many entries\n"), 792*4bff34e3Sthurlow myname); 7937c478bd9Sstevel@tonic-gate break; 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate exit(1); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate void 79908190127Sdh doexec(char *fstype, char *newargv[]) 8007c478bd9Sstevel@tonic-gate { 8017c478bd9Sstevel@tonic-gate char full_path[PATH_MAX]; 8027c478bd9Sstevel@tonic-gate char alter_path[PATH_MAX]; 8037c478bd9Sstevel@tonic-gate char *vfs_path = VFS_PATH; 8047c478bd9Sstevel@tonic-gate char *alt_path = ALT_PATH; 8057c478bd9Sstevel@tonic-gate int i; 806*4bff34e3Sthurlow int smbfs; 807*4bff34e3Sthurlow 808*4bff34e3Sthurlow /* 809*4bff34e3Sthurlow * Special case smbfs file system. 810*4bff34e3Sthurlow * Execute command in profile if possible. 811*4bff34e3Sthurlow */ 812*4bff34e3Sthurlow smbfs = strcmp(fstype, "smbfs") == 0; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* build the full pathname of the fstype dependent command. */ 8157c478bd9Sstevel@tonic-gate sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname); 8167c478bd9Sstevel@tonic-gate sprintf(alter_path, "%s/%s/%s", alt_path, fstype, myname); 8177c478bd9Sstevel@tonic-gate newargv[1] = myname; 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate if (Vflg) { 8207c478bd9Sstevel@tonic-gate printf("%s -F %s", newargv[1], fstype); 8217c478bd9Sstevel@tonic-gate for (i = 2; newargv[i]; i++) 8227c478bd9Sstevel@tonic-gate printf(" %s", newargv[i]); 8237c478bd9Sstevel@tonic-gate printf("\n"); 8247c478bd9Sstevel@tonic-gate fflush(stdout); 8257c478bd9Sstevel@tonic-gate exit(0); 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate /* 8297c478bd9Sstevel@tonic-gate * Try to exec the fstype dependent portion of the mount. 8307c478bd9Sstevel@tonic-gate * See if the directory is there before trying to exec dependent 8317c478bd9Sstevel@tonic-gate * portion. This is only useful for eliminating the 8327c478bd9Sstevel@tonic-gate * '..mount: not found' message when '/usr' is mounted 8337c478bd9Sstevel@tonic-gate */ 8347c478bd9Sstevel@tonic-gate if (access(full_path, 0) == 0) { 835*4bff34e3Sthurlow if (smbfs) { 836*4bff34e3Sthurlow /* 837*4bff34e3Sthurlow * Run mount_smbfs(1m) with pfexec so that we can 838*4bff34e3Sthurlow * add sys_mount privilege, (via exec_attr, etc.) 839*4bff34e3Sthurlow * allowing normal users to mount on any directory 840*4bff34e3Sthurlow * they own. 841*4bff34e3Sthurlow */ 842*4bff34e3Sthurlow newargv[0] = "pfexec"; 843*4bff34e3Sthurlow newargv[1] = full_path; 844*4bff34e3Sthurlow execv("/usr/bin/pfexec", &newargv[0]); 845*4bff34e3Sthurlow newargv[1] = myname; 846*4bff34e3Sthurlow } 8477c478bd9Sstevel@tonic-gate execv(full_path, &newargv[1]); 8487c478bd9Sstevel@tonic-gate if (errno == EACCES) { 8497c478bd9Sstevel@tonic-gate fprintf(stderr, 8507c478bd9Sstevel@tonic-gate gettext("%s: Cannot execute %s - permission denied\n"), 851*4bff34e3Sthurlow myname, full_path); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) { 8547c478bd9Sstevel@tonic-gate newargv[0] = "sh"; 8557c478bd9Sstevel@tonic-gate newargv[1] = full_path; 8567c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate } 859*4bff34e3Sthurlow if (smbfs) { 860*4bff34e3Sthurlow newargv[0] = "pfexec"; 861*4bff34e3Sthurlow newargv[1] = alter_path; 862*4bff34e3Sthurlow execv("/usr/bin/pfexec", &newargv[0]); 863*4bff34e3Sthurlow newargv[1] = myname; 864*4bff34e3Sthurlow } 8657c478bd9Sstevel@tonic-gate execv(alter_path, &newargv[1]); 8667c478bd9Sstevel@tonic-gate if (errno == EACCES) { 8677c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 868*4bff34e3Sthurlow "%s: Cannot execute %s - permission denied\n"), 869*4bff34e3Sthurlow myname, alter_path); 8707c478bd9Sstevel@tonic-gate exit(1); 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) { 8737c478bd9Sstevel@tonic-gate newargv[0] = "sh"; 8747c478bd9Sstevel@tonic-gate newargv[1] = alter_path; 8757c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate fprintf(stderr, 878*4bff34e3Sthurlow gettext("%s: Operation not applicable to FSType %s\n"), 879*4bff34e3Sthurlow myname, fstype); 8807c478bd9Sstevel@tonic-gate exit(1); 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate char *mntopts[] = { MNTOPT_IGNORE, NULL }; 8847c478bd9Sstevel@tonic-gate #define IGNORE 0 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate /* 8877c478bd9Sstevel@tonic-gate * Return 1 if "ignore" appears in the options string 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate int 89008190127Sdh ignore(char *opts) 8917c478bd9Sstevel@tonic-gate { 8927c478bd9Sstevel@tonic-gate char *value; 8937c478bd9Sstevel@tonic-gate char *saveptr, *my_opts; 8947c478bd9Sstevel@tonic-gate int rval = 0; 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate if (opts == NULL || *opts == NULL) 8977c478bd9Sstevel@tonic-gate return (0); 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate /* 9007c478bd9Sstevel@tonic-gate * we make a copy of the option string to pass to getsubopt(), 9017c478bd9Sstevel@tonic-gate * because getsubopt() modifies the string. We also save 9027c478bd9Sstevel@tonic-gate * the original pointer returned by strdup, because getsubopt 9037c478bd9Sstevel@tonic-gate * changes the pointer passed into it. If strdup fails (unlikely), 9047c478bd9Sstevel@tonic-gate * we act as if the "ignore" option isn't set rather than fail. 9057c478bd9Sstevel@tonic-gate */ 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate if ((saveptr = my_opts = strdup(opts)) == NULL) 9087c478bd9Sstevel@tonic-gate nomem(); 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate while (*my_opts != '\0') { 9117c478bd9Sstevel@tonic-gate if (getsubopt(&my_opts, mntopts, &value) == IGNORE) 9127c478bd9Sstevel@tonic-gate rval = 1; 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate free(saveptr); 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate return (rval); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate /* 9217c478bd9Sstevel@tonic-gate * Perform the parallel version of mount. If count == 0, mount all 9227c478bd9Sstevel@tonic-gate * vfstab filesystems with the automnt field == "yes". Use fstype if 9237c478bd9Sstevel@tonic-gate * supplied. If mntlist supplied, then attempt to only mount those. 9247c478bd9Sstevel@tonic-gate */ 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate int 9277c478bd9Sstevel@tonic-gate parmount(char **mntlist, int count, char *fstype) 9287c478bd9Sstevel@tonic-gate { 9297c478bd9Sstevel@tonic-gate int maxfd = OPEN_MAX; 9307c478bd9Sstevel@tonic-gate struct rlimit rl; 9317c478bd9Sstevel@tonic-gate vfsent_t **vl, *vp; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* 9347c478bd9Sstevel@tonic-gate * Process scaling. After running a series 9357c478bd9Sstevel@tonic-gate * of tests based on the number of simultaneous processes and 9367c478bd9Sstevel@tonic-gate * processors available, optimum performance was achieved near or 9377c478bd9Sstevel@tonic-gate * at (PROCN * 2). 9387c478bd9Sstevel@tonic-gate */ 9397c478bd9Sstevel@tonic-gate if ((maxrun = sysconf(_SC_NPROCESSORS_ONLN)) == -1) 9407c478bd9Sstevel@tonic-gate maxrun = 4; 9417c478bd9Sstevel@tonic-gate else 9427c478bd9Sstevel@tonic-gate maxrun = maxrun * 2 + 1; 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 9457c478bd9Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max; 9467c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rl) == 0) 9477c478bd9Sstevel@tonic-gate maxfd = (int)rl.rlim_cur; 9487c478bd9Sstevel@tonic-gate } 949004388ebScasper (void) enable_extended_FILE_stdio(-1, -1); 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate /* 9527c478bd9Sstevel@tonic-gate * The parent needs to maintain 3 of its own fd's, plus 2 for 9537c478bd9Sstevel@tonic-gate * each child (the stdout and stderr pipes). 9547c478bd9Sstevel@tonic-gate */ 9557c478bd9Sstevel@tonic-gate maxfd = (maxfd / 2) - 6; /* 6 takes care of temporary */ 9567c478bd9Sstevel@tonic-gate /* periods of open fds */ 9577c478bd9Sstevel@tonic-gate if (maxfd < maxrun) 9587c478bd9Sstevel@tonic-gate maxrun = maxfd; 9597c478bd9Sstevel@tonic-gate if (maxrun < 4) 9607c478bd9Sstevel@tonic-gate maxrun = 4; /* sanity check */ 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate if (count == 0) 9637c478bd9Sstevel@tonic-gate mntlist = NULL; /* used as a flag later */ 9647c478bd9Sstevel@tonic-gate else 9657c478bd9Sstevel@tonic-gate fstype = NULL; /* mount points supplied: */ 9667c478bd9Sstevel@tonic-gate /* ignore fstype */ 9677c478bd9Sstevel@tonic-gate /* 9687c478bd9Sstevel@tonic-gate * Read the whole vfstab into a linked list for quick processing. 9697c478bd9Sstevel@tonic-gate * On average, this is the most efficient way to collect and 9707c478bd9Sstevel@tonic-gate * manipulate the vfstab data. 9717c478bd9Sstevel@tonic-gate */ 9727c478bd9Sstevel@tonic-gate vfsll = getvfsall(fstype, mntlist == NULL); 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate /* 9757c478bd9Sstevel@tonic-gate * Make an array out of the vfs linked list for sorting purposes. 9767c478bd9Sstevel@tonic-gate */ 9777c478bd9Sstevel@tonic-gate if (vfsll == NULL || 9787c478bd9Sstevel@tonic-gate (vfsarray = make_vfsarray(mntlist, count)) == NULL) { 9797c478bd9Sstevel@tonic-gate if (mntlist == NULL) /* not an error - just none found */ 9807c478bd9Sstevel@tonic-gate return (0); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: No valid entries found in %s\n"), 983*4bff34e3Sthurlow myname, vfstab); 9847c478bd9Sstevel@tonic-gate return (1); 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate /* 9887c478bd9Sstevel@tonic-gate * Sort the entries based on their resolved path names 9897c478bd9Sstevel@tonic-gate * 9907c478bd9Sstevel@tonic-gate * If an lofs is encountered, then the original order of the vfstab 9917c478bd9Sstevel@tonic-gate * file needs to be maintained until we are done mounting lofs's. 9927c478bd9Sstevel@tonic-gate */ 9937c478bd9Sstevel@tonic-gate if (!lofscnt) 9947c478bd9Sstevel@tonic-gate qsort((void *)vfsarray, vfsarraysize, sizeof (vfsent_t *), 995*4bff34e3Sthurlow mlevelcmp); 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate /* 9987c478bd9Sstevel@tonic-gate * Shrink the vfsll linked list down to the new list. This will 9997c478bd9Sstevel@tonic-gate * speed up the pid search in cleanupkid() later. 10007c478bd9Sstevel@tonic-gate */ 10017c478bd9Sstevel@tonic-gate vfsll = vfsarray[0]; 10027c478bd9Sstevel@tonic-gate for (vl = vfsarray; vp = *vl; ) 10037c478bd9Sstevel@tonic-gate vp->next = *++vl; 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * Try to handle interrupts in a reasonable way. 10077c478bd9Sstevel@tonic-gate */ 10087c478bd9Sstevel@tonic-gate sigset(SIGHUP, cleanup); 10097c478bd9Sstevel@tonic-gate sigset(SIGQUIT, cleanup); 10107c478bd9Sstevel@tonic-gate sigset(SIGINT, cleanup); 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate do_mounts(); /* do the mounts */ 10137c478bd9Sstevel@tonic-gate return (exitcode); 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate /* 10177c478bd9Sstevel@tonic-gate * Read all vstab (fp) entries into memory if fstype == NULL. 10187c478bd9Sstevel@tonic-gate * If fstype is specified, than read all those that match it. 10197c478bd9Sstevel@tonic-gate * 10207c478bd9Sstevel@tonic-gate * Returns a linked list. 10217c478bd9Sstevel@tonic-gate */ 10227c478bd9Sstevel@tonic-gate vfsent_t * 10237c478bd9Sstevel@tonic-gate getvfsall(char *fstype, int takeall) 10247c478bd9Sstevel@tonic-gate { 10257c478bd9Sstevel@tonic-gate vfsent_t *vhead, *vtail; 10267c478bd9Sstevel@tonic-gate struct vfstab vget; 10277c478bd9Sstevel@tonic-gate FILE *fp; 10287c478bd9Sstevel@tonic-gate int cnt = 0, ret; 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate if ((fp = fopen(vfstab, "r")) == NULL) { 10317c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot open %s\n"), 1032*4bff34e3Sthurlow myname, vfstab); 10337c478bd9Sstevel@tonic-gate exit(1); 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate vhead = vtail = NULL; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate while ((ret = getvfsent(fp, &vget)) != -1) { 10397c478bd9Sstevel@tonic-gate vfsent_t *vp; 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate if (ret > 0) { 10427c478bd9Sstevel@tonic-gate vfserror(ret, vget.vfs_mountp); 10437c478bd9Sstevel@tonic-gate continue; 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate /* 10477c478bd9Sstevel@tonic-gate * If mount points were not specified, then we ignore 10487c478bd9Sstevel@tonic-gate * entries that aren't marked "yes". 10497c478bd9Sstevel@tonic-gate */ 10507c478bd9Sstevel@tonic-gate if (takeall && 10517c478bd9Sstevel@tonic-gate (vget.vfs_automnt == NULL || 10527c478bd9Sstevel@tonic-gate strcmp(vget.vfs_automnt, "yes"))) 10537c478bd9Sstevel@tonic-gate continue; 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate if (fstype && vget.vfs_fstype && 10567c478bd9Sstevel@tonic-gate strcmp(fstype, vget.vfs_fstype)) 10577c478bd9Sstevel@tonic-gate continue; 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate if (vget.vfs_mountp == NULL || 10607c478bd9Sstevel@tonic-gate (vget.vfs_fstype && (strcmp(vget.vfs_fstype, "swap") == 0))) 10617c478bd9Sstevel@tonic-gate continue; 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate if (check_fields(vget.vfs_fstype, vget.vfs_mountp)) { 10647c478bd9Sstevel@tonic-gate exitcode = 1; 10657c478bd9Sstevel@tonic-gate continue; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate vp = new_vfsent(&vget, cnt); /* create new vfs entry */ 10697c478bd9Sstevel@tonic-gate if (vhead == NULL) 10707c478bd9Sstevel@tonic-gate vhead = vp; 10717c478bd9Sstevel@tonic-gate else 10727c478bd9Sstevel@tonic-gate vtail->next = vp; 10737c478bd9Sstevel@tonic-gate vtail = vp; 10747c478bd9Sstevel@tonic-gate cnt++; 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate fclose(fp); 10777c478bd9Sstevel@tonic-gate if (vtail == NULL) { 10787c478bd9Sstevel@tonic-gate vfsarraysize = 0; 10797c478bd9Sstevel@tonic-gate vfslltail = NULL; 10807c478bd9Sstevel@tonic-gate return (NULL); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate vtail->next = NULL; 10837c478bd9Sstevel@tonic-gate vfslltail = vtail; /* save it in the global variable */ 10847c478bd9Sstevel@tonic-gate vfsarraysize = cnt; 10857c478bd9Sstevel@tonic-gate return (vhead); 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate /* 10907c478bd9Sstevel@tonic-gate * Returns an array of vfsent_t's based on vfsll & mntlist. 10917c478bd9Sstevel@tonic-gate */ 10927c478bd9Sstevel@tonic-gate vfsent_t ** 10937c478bd9Sstevel@tonic-gate make_vfsarray(char **mntlist, int count) 10947c478bd9Sstevel@tonic-gate { 10957c478bd9Sstevel@tonic-gate vfsent_t *vp, *vmark, *vpprev, **vpp; 10967c478bd9Sstevel@tonic-gate int ndx, found; 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate if (vfsll == NULL) 10997c478bd9Sstevel@tonic-gate return (NULL); 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate if (count > 0) 11027c478bd9Sstevel@tonic-gate vfsarraysize = count; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate vpp = (vfsent_t **)malloc(sizeof (*vpp) * (vfsarraysize + 1)); 11057c478bd9Sstevel@tonic-gate if (vpp == NULL) 11067c478bd9Sstevel@tonic-gate nomem(); 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate if (mntlist == NULL) { 11097c478bd9Sstevel@tonic-gate /* 11107c478bd9Sstevel@tonic-gate * No mount list specified: take all vfstab mount points. 11117c478bd9Sstevel@tonic-gate */ 11127c478bd9Sstevel@tonic-gate for (ndx = 0, vp = vfsll; vp; vp = vp->next) { 11137c478bd9Sstevel@tonic-gate (void) setrpath(vp); 11147c478bd9Sstevel@tonic-gate /* 11157c478bd9Sstevel@tonic-gate * Sigh. lofs entries can complicate matters so much 11167c478bd9Sstevel@tonic-gate * that the best way to avoid problems is to 11177c478bd9Sstevel@tonic-gate * stop parallel mounting when an lofs is 11187c478bd9Sstevel@tonic-gate * encountered, so we keep a count of how many 11197c478bd9Sstevel@tonic-gate * there are. 11207c478bd9Sstevel@tonic-gate * Fortunately this is rare. 11217c478bd9Sstevel@tonic-gate */ 11227c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && 11237c478bd9Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, MNTTYPE_LOFS) == 0)) 11247c478bd9Sstevel@tonic-gate lofscnt++; 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate vpp[ndx++] = vp; 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate vpp[ndx] = NULL; 11297c478bd9Sstevel@tonic-gate return (vpp); 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate /* 11337c478bd9Sstevel@tonic-gate * A list of mount points was specified on the command line 11347c478bd9Sstevel@tonic-gate * and we need to search for each one. 11357c478bd9Sstevel@tonic-gate */ 11367c478bd9Sstevel@tonic-gate vpprev = vfslltail; 11377c478bd9Sstevel@tonic-gate vpprev->next = vfsll; /* make a circle out of it */ 11387c478bd9Sstevel@tonic-gate vmark = vp = vfsll; 11397c478bd9Sstevel@tonic-gate /* 11407c478bd9Sstevel@tonic-gate * For each specified mount point: 11417c478bd9Sstevel@tonic-gate */ 11427c478bd9Sstevel@tonic-gate for (ndx = 0; *mntlist; mntlist++) { 11437c478bd9Sstevel@tonic-gate found = 0; 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate * Circle our entire linked list, looking for *mntlist. 11467c478bd9Sstevel@tonic-gate */ 11477c478bd9Sstevel@tonic-gate while (vp) { 11487c478bd9Sstevel@tonic-gate if (strcmp(*mntlist, vp->v.vfs_mountp) == 0) { 11497c478bd9Sstevel@tonic-gate vpp[ndx++] = vp; /* found it. */ 11507c478bd9Sstevel@tonic-gate (void) setrpath(vp); 11517c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && 11527c478bd9Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, 11537c478bd9Sstevel@tonic-gate MNTTYPE_LOFS) == 0)) 11547c478bd9Sstevel@tonic-gate lofscnt++; 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate if (vp == vpprev) { /* list exhausted */ 11577c478bd9Sstevel@tonic-gate vp = NULL; 11587c478bd9Sstevel@tonic-gate found++; 11597c478bd9Sstevel@tonic-gate break; 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate /* 11627c478bd9Sstevel@tonic-gate * Remove it from the circular list. vpprev 11637c478bd9Sstevel@tonic-gate * remains unchanged. 11647c478bd9Sstevel@tonic-gate */ 11657c478bd9Sstevel@tonic-gate vp = vp->next; 11667c478bd9Sstevel@tonic-gate vpprev->next->next = NULL; 11677c478bd9Sstevel@tonic-gate vpprev->next = vp; 11687c478bd9Sstevel@tonic-gate /* 11697c478bd9Sstevel@tonic-gate * Set vmark to the first elem that we check 11707c478bd9Sstevel@tonic-gate * each time. 11717c478bd9Sstevel@tonic-gate */ 11727c478bd9Sstevel@tonic-gate vmark = vp; 11737c478bd9Sstevel@tonic-gate found++; 11747c478bd9Sstevel@tonic-gate break; 11757c478bd9Sstevel@tonic-gate } 11767c478bd9Sstevel@tonic-gate vpprev = vp; 11777c478bd9Sstevel@tonic-gate vp = vp->next; 11787c478bd9Sstevel@tonic-gate if (vp == vmark) /* break out if we completed */ 11797c478bd9Sstevel@tonic-gate /* the circle */ 11807c478bd9Sstevel@tonic-gate break; 11817c478bd9Sstevel@tonic-gate } 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate if (!found) { 11847c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1185*4bff34e3Sthurlow "%s: Warning: %s not found in %s\n"), 1186*4bff34e3Sthurlow myname, *mntlist, vfstab); 11877c478bd9Sstevel@tonic-gate exitcode = 1; 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate } 11907c478bd9Sstevel@tonic-gate if (ndx == 0) 11917c478bd9Sstevel@tonic-gate return (NULL); 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate vpp[ndx] = NULL; /* null terminate the list */ 11947c478bd9Sstevel@tonic-gate vfsarraysize = ndx; /* adjust vfsarraysize */ 11957c478bd9Sstevel@tonic-gate return (vpp); 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate /* 11997c478bd9Sstevel@tonic-gate * Performs the exec argument processing, all of the child forking and 12007c478bd9Sstevel@tonic-gate * execing, and child cleanup. 12017c478bd9Sstevel@tonic-gate * Sets exitcode to non-zero if any errors occurred. 12027c478bd9Sstevel@tonic-gate */ 12037c478bd9Sstevel@tonic-gate void 120408190127Sdh do_mounts(void) 12057c478bd9Sstevel@tonic-gate { 12067c478bd9Sstevel@tonic-gate int i, isave, cnt; 12077c478bd9Sstevel@tonic-gate vfsent_t *vp, *vpprev, **vl; 12087c478bd9Sstevel@tonic-gate char *newargv[ARGV_MAX]; 12097c478bd9Sstevel@tonic-gate pid_t child; 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate /* 12127c478bd9Sstevel@tonic-gate * create the arg list once; the only differences among 12137c478bd9Sstevel@tonic-gate * the calls are the options, special and mountp fields. 12147c478bd9Sstevel@tonic-gate */ 12157c478bd9Sstevel@tonic-gate i = 2; 12167c478bd9Sstevel@tonic-gate if (cflg) 12177c478bd9Sstevel@tonic-gate newargv[i++] = "-c"; 12187c478bd9Sstevel@tonic-gate if (gflg) 12197c478bd9Sstevel@tonic-gate newargv[i++] = "-g"; 12207c478bd9Sstevel@tonic-gate if (mflg) 12217c478bd9Sstevel@tonic-gate newargv[i++] = "-m"; 12227c478bd9Sstevel@tonic-gate if (Oflg) 12237c478bd9Sstevel@tonic-gate newargv[i++] = "-O"; 12247c478bd9Sstevel@tonic-gate if (qflg) 12257c478bd9Sstevel@tonic-gate newargv[i++] = "-q"; 12267c478bd9Sstevel@tonic-gate if (rflg) 12277c478bd9Sstevel@tonic-gate newargv[i++] = "-r"; 12287c478bd9Sstevel@tonic-gate if (dashflg) 12297c478bd9Sstevel@tonic-gate newargv[i++] = "--"; 12307c478bd9Sstevel@tonic-gate if (oflg) { 12317c478bd9Sstevel@tonic-gate newargv[i++] = "-o"; 12327c478bd9Sstevel@tonic-gate newargv[i++] = specific_opts; 12337c478bd9Sstevel@tonic-gate } 12347c478bd9Sstevel@tonic-gate isave = i; 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate /* 12377c478bd9Sstevel@tonic-gate * Main loop for the mount processes 12387c478bd9Sstevel@tonic-gate */ 12397c478bd9Sstevel@tonic-gate vl = vfsarray; 12407c478bd9Sstevel@tonic-gate cnt = vfsarraysize; 12417c478bd9Sstevel@tonic-gate for (vpprev = *vl; vp = *vl; vpprev = vp, vl++, cnt--) { 12427c478bd9Sstevel@tonic-gate /* 12437c478bd9Sstevel@tonic-gate * Check to see if we cross a mount level: e.g., 12447c478bd9Sstevel@tonic-gate * /a/b -> /a/b/c. If so, we need to wait for all current 12457c478bd9Sstevel@tonic-gate * mounts to finish, rerun realpath on the remaining mount 12467c478bd9Sstevel@tonic-gate * points, and resort the list. 12477c478bd9Sstevel@tonic-gate * 12487c478bd9Sstevel@tonic-gate * Also, we mount serially as long as there are lofs's 12497c478bd9Sstevel@tonic-gate * to mount to avoid improper mount ordering. 12507c478bd9Sstevel@tonic-gate */ 12517c478bd9Sstevel@tonic-gate if (vp->mlevel > vpprev->mlevel || lofscnt > 0) { 12527c478bd9Sstevel@tonic-gate vfsent_t **vlp; 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 12557c478bd9Sstevel@tonic-gate ; 12567c478bd9Sstevel@tonic-gate /* 12577c478bd9Sstevel@tonic-gate * Gads! It's possible for real path mounts points to 12587c478bd9Sstevel@tonic-gate * change after mounts are done at a lower mount 12597c478bd9Sstevel@tonic-gate * level. 12607c478bd9Sstevel@tonic-gate * Thus, we need to recalculate mount levels and 12617c478bd9Sstevel@tonic-gate * resort the list from this point. 12627c478bd9Sstevel@tonic-gate */ 12637c478bd9Sstevel@tonic-gate for (vlp = vl; *vlp; vlp++) 12647c478bd9Sstevel@tonic-gate (void) setrpath(*vlp); 12657c478bd9Sstevel@tonic-gate /* 12667c478bd9Sstevel@tonic-gate * Sort the remaining entries based on their newly 12677c478bd9Sstevel@tonic-gate * resolved path names. 12687c478bd9Sstevel@tonic-gate * Do not sort if we still have lofs's to mount. 12697c478bd9Sstevel@tonic-gate */ 12707c478bd9Sstevel@tonic-gate if (lofscnt == 0) { 12717c478bd9Sstevel@tonic-gate qsort((void *)vl, cnt, sizeof (vfsent_t *), 1272*4bff34e3Sthurlow mlevelcmp); 12737c478bd9Sstevel@tonic-gate vp = *vl; 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate if (vp->flag & VRPFAILED) { 12787c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1279*4bff34e3Sthurlow "%s: Nonexistent mount point: %s\n"), 1280*4bff34e3Sthurlow myname, vp->v.vfs_mountp); 12817c478bd9Sstevel@tonic-gate vp->flag |= VNOTMOUNTED; 12827c478bd9Sstevel@tonic-gate exitcode = 1; 12837c478bd9Sstevel@tonic-gate continue; 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate /* 12877c478bd9Sstevel@tonic-gate * If mount options were not specified on the command 12887c478bd9Sstevel@tonic-gate * line, then use the ones found in the vfstab entry, 12897c478bd9Sstevel@tonic-gate * if any. 12907c478bd9Sstevel@tonic-gate */ 12917c478bd9Sstevel@tonic-gate i = isave; 12927c478bd9Sstevel@tonic-gate if (!oflg && vp->v.vfs_mntopts) { 12937c478bd9Sstevel@tonic-gate newargv[i++] = "-o"; 12947c478bd9Sstevel@tonic-gate newargv[i++] = vp->v.vfs_mntopts; 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate newargv[i++] = vp->v.vfs_special; 12977c478bd9Sstevel@tonic-gate newargv[i++] = vp->rpath; 12987c478bd9Sstevel@tonic-gate newargv[i] = NULL; 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate /* 13017c478bd9Sstevel@tonic-gate * This should never really fail. 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate while (setup_iopipe(vp) == -1 && (dowait() != -1)) 13047c478bd9Sstevel@tonic-gate ; 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate while (nrun >= maxrun && (dowait() != -1)) /* throttle */ 13077c478bd9Sstevel@tonic-gate ; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 13107c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && 13117c478bd9Sstevel@tonic-gate (strcmp(vp->v.vfs_fstype, "cachefs") == 0)) { 13127c478bd9Sstevel@tonic-gate while (cachefs_running && (dowait() != -1)) 13137c478bd9Sstevel@tonic-gate ; 13147c478bd9Sstevel@tonic-gate cachefs_running = 1; 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate #endif 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate if ((child = fork()) == -1) { 13197c478bd9Sstevel@tonic-gate perror("fork"); 13207c478bd9Sstevel@tonic-gate cleanup(-1); 13217c478bd9Sstevel@tonic-gate /* not reached */ 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate if (child == 0) { /* child */ 13247c478bd9Sstevel@tonic-gate signal(SIGHUP, SIG_IGN); 13257c478bd9Sstevel@tonic-gate signal(SIGQUIT, SIG_IGN); 13267c478bd9Sstevel@tonic-gate signal(SIGINT, SIG_IGN); 13277c478bd9Sstevel@tonic-gate setup_output(vp); 13287c478bd9Sstevel@tonic-gate doexec(vp->v.vfs_fstype, newargv); 13297c478bd9Sstevel@tonic-gate perror("exec"); 13307c478bd9Sstevel@tonic-gate exit(1); 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate /* parent */ 13347c478bd9Sstevel@tonic-gate (void) close(vp->sopipe[WRPIPE]); 13357c478bd9Sstevel@tonic-gate (void) close(vp->sepipe[WRPIPE]); 13367c478bd9Sstevel@tonic-gate vp->pid = child; 13377c478bd9Sstevel@tonic-gate nrun++; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate /* 13407c478bd9Sstevel@tonic-gate * Mostly done by now - wait and clean up the stragglers. 13417c478bd9Sstevel@tonic-gate */ 13427c478bd9Sstevel@tonic-gate cleanup(0); 13437c478bd9Sstevel@tonic-gate } 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate /* 13477c478bd9Sstevel@tonic-gate * Setup stdout and stderr pipes for the children's output. 13487c478bd9Sstevel@tonic-gate */ 13497c478bd9Sstevel@tonic-gate int 13507c478bd9Sstevel@tonic-gate setup_iopipe(vfsent_t *mp) 13517c478bd9Sstevel@tonic-gate { 13527c478bd9Sstevel@tonic-gate /* 13537c478bd9Sstevel@tonic-gate * Make a stdout and stderr pipe. This should never fail. 13547c478bd9Sstevel@tonic-gate */ 13557c478bd9Sstevel@tonic-gate if (pipe(mp->sopipe) == -1) 13567c478bd9Sstevel@tonic-gate return (-1); 13577c478bd9Sstevel@tonic-gate if (pipe(mp->sepipe) == -1) { 13587c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[RDPIPE]); 13597c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[WRPIPE]); 13607c478bd9Sstevel@tonic-gate return (-1); 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate /* 13637c478bd9Sstevel@tonic-gate * Don't block on an empty pipe. 13647c478bd9Sstevel@tonic-gate */ 13657c478bd9Sstevel@tonic-gate (void) fcntl(mp->sopipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 13667c478bd9Sstevel@tonic-gate (void) fcntl(mp->sepipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 13677c478bd9Sstevel@tonic-gate /* 13687c478bd9Sstevel@tonic-gate * Don't pass extra fds into children. 13697c478bd9Sstevel@tonic-gate */ 13707c478bd9Sstevel@tonic-gate (void) fcntl(mp->sopipe[RDPIPE], F_SETFD, FD_CLOEXEC); 13717c478bd9Sstevel@tonic-gate (void) fcntl(mp->sepipe[RDPIPE], F_SETFD, FD_CLOEXEC); 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate return (0); 13747c478bd9Sstevel@tonic-gate } 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate /* 13777c478bd9Sstevel@tonic-gate * Called by a child to attach its stdout and stderr to the write side of 13787c478bd9Sstevel@tonic-gate * the pipes. 13797c478bd9Sstevel@tonic-gate */ 13807c478bd9Sstevel@tonic-gate void 13817c478bd9Sstevel@tonic-gate setup_output(vfsent_t *vp) 13827c478bd9Sstevel@tonic-gate { 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate (void) close(fileno(stdout)); 13857c478bd9Sstevel@tonic-gate (void) dup(vp->sopipe[WRPIPE]); 13867c478bd9Sstevel@tonic-gate (void) close(vp->sopipe[WRPIPE]); 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate (void) close(fileno(stderr)); 13897c478bd9Sstevel@tonic-gate (void) dup(vp->sepipe[WRPIPE]); 13907c478bd9Sstevel@tonic-gate (void) close(vp->sepipe[WRPIPE]); 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate /* 13947c478bd9Sstevel@tonic-gate * Parent uses this to print any stdout or stderr output issued by 13957c478bd9Sstevel@tonic-gate * the child. 13967c478bd9Sstevel@tonic-gate */ 13977c478bd9Sstevel@tonic-gate static void 13987c478bd9Sstevel@tonic-gate doio(vfsent_t *vp) 13997c478bd9Sstevel@tonic-gate { 14007c478bd9Sstevel@tonic-gate int bytes; 14017c478bd9Sstevel@tonic-gate char ibuf[BUFSIZ]; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate while ((bytes = read(vp->sepipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 14047c478bd9Sstevel@tonic-gate write(fileno(stderr), ibuf, bytes); 14057c478bd9Sstevel@tonic-gate while ((bytes = read(vp->sopipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 14067c478bd9Sstevel@tonic-gate write(fileno(stdout), ibuf, bytes); 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate (void) close(vp->sopipe[RDPIPE]); 14097c478bd9Sstevel@tonic-gate (void) close(vp->sepipe[RDPIPE]); 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * Waits for 1 child to die. 14147c478bd9Sstevel@tonic-gate * 14157c478bd9Sstevel@tonic-gate * Returns -1 if no children are left to wait for. 14167c478bd9Sstevel@tonic-gate * Returns 0 if a child died without an error. 14177c478bd9Sstevel@tonic-gate * Returns 1 if a child died with an error. 14187c478bd9Sstevel@tonic-gate */ 14197c478bd9Sstevel@tonic-gate int 142008190127Sdh dowait(void) 14217c478bd9Sstevel@tonic-gate { 14227c478bd9Sstevel@tonic-gate int child, wstat; 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate if ((child = wait(&wstat)) == -1) 14257c478bd9Sstevel@tonic-gate return (-1); 14267c478bd9Sstevel@tonic-gate nrun--; 14277c478bd9Sstevel@tonic-gate return (cleanupkid(child, wstat) != 0); 14287c478bd9Sstevel@tonic-gate } 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate /* 14317c478bd9Sstevel@tonic-gate * Locates the child mount process represented by pid, outputs any io 14327c478bd9Sstevel@tonic-gate * it may have, and returns its exit code. 14337c478bd9Sstevel@tonic-gate * Sets the global exitcode if an error occurred. 14347c478bd9Sstevel@tonic-gate */ 14357c478bd9Sstevel@tonic-gate int 14367c478bd9Sstevel@tonic-gate cleanupkid(pid_t pid, int wstat) 14377c478bd9Sstevel@tonic-gate { 14387c478bd9Sstevel@tonic-gate vfsent_t *vp, *prevp; 14397c478bd9Sstevel@tonic-gate int ret; 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate if (WIFEXITED(wstat)) /* this should always be true */ 14427c478bd9Sstevel@tonic-gate ret = WEXITSTATUS(wstat); 14437c478bd9Sstevel@tonic-gate else 14447c478bd9Sstevel@tonic-gate ret = 1; /* assume some kind of error */ 14457c478bd9Sstevel@tonic-gate if (ret) 14467c478bd9Sstevel@tonic-gate exitcode = 1; 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate /* 14497c478bd9Sstevel@tonic-gate * Find our child. 14507c478bd9Sstevel@tonic-gate * This search gets smaller and smaller as children are cleaned 14517c478bd9Sstevel@tonic-gate * up. 14527c478bd9Sstevel@tonic-gate */ 14537c478bd9Sstevel@tonic-gate for (prevp = NULL, vp = vfsll; vp; vp = vp->next) { 14547c478bd9Sstevel@tonic-gate if (vp->pid != pid) { 14557c478bd9Sstevel@tonic-gate prevp = vp; 14567c478bd9Sstevel@tonic-gate continue; 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate /* 14597c478bd9Sstevel@tonic-gate * Found: let's remove it from this linked list. 14607c478bd9Sstevel@tonic-gate */ 14617c478bd9Sstevel@tonic-gate if (prevp) { 14627c478bd9Sstevel@tonic-gate prevp->next = vp->next; 14637c478bd9Sstevel@tonic-gate vp->next = NULL; 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate break; 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate if (vp == NULL) { 14697c478bd9Sstevel@tonic-gate /* 14707c478bd9Sstevel@tonic-gate * This should never happen. 14717c478bd9Sstevel@tonic-gate */ 14727c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1473*4bff34e3Sthurlow "%s: Unknown child %d\n"), myname, pid); 14747c478bd9Sstevel@tonic-gate exitcode = 1; 14757c478bd9Sstevel@tonic-gate return (ret); 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate doio(vp); /* Any output? */ 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && (strcmp(vp->v.vfs_fstype, MNTTYPE_LOFS) == 0)) 14807c478bd9Sstevel@tonic-gate lofscnt--; 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 14837c478bd9Sstevel@tonic-gate if (vp->v.vfs_fstype && (strcmp(vp->v.vfs_fstype, "cachefs") == 0)) 14847c478bd9Sstevel@tonic-gate cachefs_running = 0; 14857c478bd9Sstevel@tonic-gate #endif 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate vp->exitcode = ret; 14887c478bd9Sstevel@tonic-gate return (ret); 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate static vfsent_t zvmount = { 0 }; 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate vfsent_t * 14957c478bd9Sstevel@tonic-gate new_vfsent(struct vfstab *vin, int order) 14967c478bd9Sstevel@tonic-gate { 14977c478bd9Sstevel@tonic-gate vfsent_t *new; 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate new = (vfsent_t *)malloc(sizeof (*new)); 15007c478bd9Sstevel@tonic-gate if (new == NULL) 15017c478bd9Sstevel@tonic-gate nomem(); 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate *new = zvmount; 15047c478bd9Sstevel@tonic-gate if (vin->vfs_special && 15057c478bd9Sstevel@tonic-gate (new->v.vfs_special = strdup(vin->vfs_special)) == NULL) 15067c478bd9Sstevel@tonic-gate nomem(); 15077c478bd9Sstevel@tonic-gate if (vin->vfs_mountp && 15087c478bd9Sstevel@tonic-gate (new->v.vfs_mountp = strdup(vin->vfs_mountp)) == NULL) 15097c478bd9Sstevel@tonic-gate nomem(); 15107c478bd9Sstevel@tonic-gate if (vin->vfs_fstype && 15117c478bd9Sstevel@tonic-gate (new->v.vfs_fstype = strdup(vin->vfs_fstype)) == NULL) 15127c478bd9Sstevel@tonic-gate nomem(); 15137c478bd9Sstevel@tonic-gate /* 15147c478bd9Sstevel@tonic-gate * If specific mount options were specified on the command 15157c478bd9Sstevel@tonic-gate * line, then use those. Else, use the ones on the vfstab 15167c478bd9Sstevel@tonic-gate * line, if any. In other words, specific options on the 15177c478bd9Sstevel@tonic-gate * command line override those in /etc/vfstab. 15187c478bd9Sstevel@tonic-gate */ 15197c478bd9Sstevel@tonic-gate if (oflg) { 15207c478bd9Sstevel@tonic-gate if ((new->v.vfs_mntopts = strdup(specific_opts)) == NULL) 15217c478bd9Sstevel@tonic-gate nomem(); 15227c478bd9Sstevel@tonic-gate } else if (vin->vfs_mntopts && 1523*4bff34e3Sthurlow (new->v.vfs_mntopts = strdup(vin->vfs_mntopts)) == NULL) 15247c478bd9Sstevel@tonic-gate nomem(); 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate new->order = order; 15277c478bd9Sstevel@tonic-gate return (new); 15287c478bd9Sstevel@tonic-gate } 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate /* 15317c478bd9Sstevel@tonic-gate * Runs realpath on vp's mount point, records success or failure, 15327c478bd9Sstevel@tonic-gate * resets the mount level based on the new realpath, and returns 15337c478bd9Sstevel@tonic-gate * realpath()'s return value. 15347c478bd9Sstevel@tonic-gate */ 15357c478bd9Sstevel@tonic-gate char * 15367c478bd9Sstevel@tonic-gate setrpath(vfsent_t *vp) 15377c478bd9Sstevel@tonic-gate { 15387c478bd9Sstevel@tonic-gate char *rp; 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate if ((rp = realpath(vp->v.vfs_mountp, realdir)) == NULL) 15417c478bd9Sstevel@tonic-gate vp->flag |= VRPFAILED; 15427c478bd9Sstevel@tonic-gate else 15437c478bd9Sstevel@tonic-gate vp->flag &= ~VRPFAILED; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate if (vp->rpath) 15467c478bd9Sstevel@tonic-gate free(vp->rpath); 15477c478bd9Sstevel@tonic-gate if ((vp->rpath = strdup(realdir)) == NULL) 15487c478bd9Sstevel@tonic-gate nomem(); 15497c478bd9Sstevel@tonic-gate vp->mlevel = fsgetmlevel(vp->rpath); 15507c478bd9Sstevel@tonic-gate return (rp); 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate /* 15557c478bd9Sstevel@tonic-gate * sort first by mlevel (1...N), then by vfstab order. 15567c478bd9Sstevel@tonic-gate */ 15577c478bd9Sstevel@tonic-gate int 15587c478bd9Sstevel@tonic-gate mlevelcmp(const void *a, const void *b) 15597c478bd9Sstevel@tonic-gate { 15607c478bd9Sstevel@tonic-gate vfsent_t *a1, *b1; 15617c478bd9Sstevel@tonic-gate int lcmp; 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate a1 = *(vfsent_t **)a; 15647c478bd9Sstevel@tonic-gate b1 = *(vfsent_t **)b; 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate lcmp = a1->mlevel - b1->mlevel; 15677c478bd9Sstevel@tonic-gate if (lcmp == 0) 15687c478bd9Sstevel@tonic-gate lcmp = a1->order - b1->order; 15697c478bd9Sstevel@tonic-gate return (lcmp); 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate /* sort by vfstab order. 0..N */ 157308190127Sdh static int 15747c478bd9Sstevel@tonic-gate mordercmp(const void *a, const void *b) 15757c478bd9Sstevel@tonic-gate { 15767c478bd9Sstevel@tonic-gate vfsent_t *a1, *b1; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate a1 = *(vfsent_t **)a; 15797c478bd9Sstevel@tonic-gate b1 = *(vfsent_t **)b; 15807c478bd9Sstevel@tonic-gate return (a1->order - b1->order); 15817c478bd9Sstevel@tonic-gate } 15827c478bd9Sstevel@tonic-gate 15837c478bd9Sstevel@tonic-gate /* 15847c478bd9Sstevel@tonic-gate * cleanup the existing children and exit with an error 15857c478bd9Sstevel@tonic-gate * if asig != 0. 15867c478bd9Sstevel@tonic-gate */ 15877c478bd9Sstevel@tonic-gate void 15887c478bd9Sstevel@tonic-gate cleanup(int asig) 15897c478bd9Sstevel@tonic-gate { 15907c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 15917c478bd9Sstevel@tonic-gate ; 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate if (asig != 0) 15947c478bd9Sstevel@tonic-gate exit(1); 15957c478bd9Sstevel@tonic-gate } 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate int 15997c478bd9Sstevel@tonic-gate check_fields(char *fstype, char *mountp) 16007c478bd9Sstevel@tonic-gate { 16017c478bd9Sstevel@tonic-gate struct stat64 stbuf; 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate if (strlen(fstype) > (size_t)FSTYPE_MAX) { 16047c478bd9Sstevel@tonic-gate fprintf(stderr, 1605*4bff34e3Sthurlow gettext("%s: FSType %s exceeds %d characters\n"), 1606*4bff34e3Sthurlow myname, fstype, FSTYPE_MAX); 16077c478bd9Sstevel@tonic-gate return (1); 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate if (mountp == NULL) { 16117c478bd9Sstevel@tonic-gate fprintf(stderr, 1612*4bff34e3Sthurlow gettext("%s: Mount point cannot be determined\n"), 1613*4bff34e3Sthurlow myname); 16147c478bd9Sstevel@tonic-gate return (1); 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate if (*mountp != '/') { 16177c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1618*4bff34e3Sthurlow "%s: Mount point %s is not an absolute pathname.\n"), 1619*4bff34e3Sthurlow myname, mountp); 16207c478bd9Sstevel@tonic-gate return (1); 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate /* 16237c478bd9Sstevel@tonic-gate * Don't do some of these checks if aflg because a mount point may 16247c478bd9Sstevel@tonic-gate * not exist now, but will be mounted before we get to it. 16257c478bd9Sstevel@tonic-gate * This is one of the quirks of "secondary mounting". 16267c478bd9Sstevel@tonic-gate */ 16277c478bd9Sstevel@tonic-gate if (!aflg && stat64(mountp, &stbuf) < 0) { 16287c478bd9Sstevel@tonic-gate if (errno == ENOENT || errno == ENOTDIR) 16297c478bd9Sstevel@tonic-gate fprintf(stderr, 1630*4bff34e3Sthurlow gettext("%s: Mount point %s does not exist.\n"), 1631*4bff34e3Sthurlow myname, mountp); 16327c478bd9Sstevel@tonic-gate else { 16337c478bd9Sstevel@tonic-gate fprintf(stderr, 1634*4bff34e3Sthurlow gettext("%s: Cannot stat mount point %s.\n"), 1635*4bff34e3Sthurlow myname, mountp); 16367c478bd9Sstevel@tonic-gate perror(myname); 16377c478bd9Sstevel@tonic-gate } 16387c478bd9Sstevel@tonic-gate return (1); 16397c478bd9Sstevel@tonic-gate } 16407c478bd9Sstevel@tonic-gate return (0); 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate void 164408190127Sdh nomem(void) 16457c478bd9Sstevel@tonic-gate { 16467c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Out of memory\n"), myname); 16477c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 16487c478bd9Sstevel@tonic-gate ; 16497c478bd9Sstevel@tonic-gate exit(1); 16507c478bd9Sstevel@tonic-gate } 1651