[BACK]Return to mount.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / mount

Annotation of src/sbin/mount/mount.c, Revision 1.103

1.103   ! mlelstv     1: /*     $NetBSD: mount.c,v 1.102 2016/10/09 21:03:43 christos Exp $     */
1.16      cgd         2:
1.1       cgd         3: /*
1.12      mycroft     4:  * Copyright (c) 1980, 1989, 1993, 1994
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
1.66      agc        15:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
1.29      christos   32: #include <sys/cdefs.h>
1.1       cgd        33: #ifndef lint
1.85      lukem      34: __COPYRIGHT("@(#) Copyright (c) 1980, 1989, 1993, 1994\
                     35:  The Regents of the University of California.  All rights reserved.");
1.1       cgd        36: #endif /* not lint */
                     37:
                     38: #ifndef lint
1.16      cgd        39: #if 0
1.32      lukem      40: static char sccsid[] = "@(#)mount.c    8.25 (Berkeley) 5/8/95";
1.16      cgd        41: #else
1.103   ! mlelstv    42: __RCSID("$NetBSD: mount.c,v 1.102 2016/10/09 21:03:43 christos Exp $");
1.16      cgd        43: #endif
1.1       cgd        44: #endif /* not lint */
                     45:
                     46: #include <sys/param.h>
1.12      mycroft    47: #include <sys/mount.h>
1.1       cgd        48: #include <sys/wait.h>
1.12      mycroft    49:
1.90      pooka      50: #include <fs/puffs/puffs_msgif.h>
                     51:
1.12      mycroft    52: #include <err.h>
                     53: #include <errno.h>
1.1       cgd        54: #include <fstab.h>
1.32      lukem      55: #include <pwd.h>
1.12      mycroft    56: #include <signal.h>
1.1       cgd        57: #include <stdio.h>
                     58: #include <stdlib.h>
1.12      mycroft    59: #include <string.h>
                     60: #include <unistd.h>
1.94      christos   61: #include <util.h>
1.12      mycroft    62:
1.48      abs        63: #define MOUNTNAMES
                     64: #include <fcntl.h>
1.73      thorpej    65: #include <sys/disk.h>
1.48      abs        66: #include <sys/disklabel.h>
                     67: #include <sys/ioctl.h>
                     68:
1.1       cgd        69: #include "pathnames.h"
1.86      pooka      70: #include "mountprog.h"
1.1       cgd        71:
1.52      jdolecek   72: static int     debug, verbose;
1.1       cgd        73:
1.76      xtraeme    74: static void    catopt(char **, const char *);
1.53      enami      75: static const char *
1.76      xtraeme    76:                getfslab(const char *str);
1.69      christos   77: static struct statvfs *
1.76      xtraeme    78:                getmntpt(const char *);
                     79: static int     getmntargs(struct statvfs *, char *, size_t);
                     80: static int     hasopt(const char *, const char *);
1.82      christos   81: static void    mangle(char *, int *, const char ** volatile *, int *);
1.76      xtraeme    82: static int     mountfs(const char *, const char *, const char *,
                     83:                    int, const char *, const char *, int, char *, size_t);
                     84: static void    prmount(struct statvfs *);
1.93      joerg      85: __dead static void     usage(void);
1.53      enami      86:
1.12      mycroft    87:
1.99      ast        88: /* Map from mount options to printable formats. */
1.52      jdolecek   89: static const struct opt {
1.12      mycroft    90:        int o_opt;
1.24      cgd        91:        int o_silent;
1.12      mycroft    92:        const char *o_name;
                     93: } optnames[] = {
1.58      christos   94:        __MNT_FLAGS
1.1       cgd        95: };
                     96:
1.103   ! mlelstv    97: #define FLG_UPDATE     1
        !            98: #define FLG_RDONLY     2
        !            99: #define FLG_RDWRITE    4
        !           100: #define FLG_FORCE      8
        !           101:
1.94      christos  102: static const char ffs_fstype[] = "ffs";
1.30      christos  103:
1.12      mycroft   104: int
1.76      xtraeme   105: main(int argc, char *argv[])
1.1       cgd       106: {
1.32      lukem     107:        const char *mntfromname, *mntonname, **vfslist, *vfstype;
1.12      mycroft   108:        struct fstab *fs;
1.69      christos  109:        struct statvfs *mntbuf;
1.89      yamt      110: #if 0
1.12      mycroft   111:        FILE *mountdfp;
1.89      yamt      112: #endif
1.22      cgd       113:        int all, ch, forceall, i, init_flags, mntsize, rval;
1.12      mycroft   114:        char *options;
1.43      mycroft   115:        const char *mountopts, *fstypename;
1.94      christos  116:        char canonical_path_buf[MAXPATHLEN], buf[MAXPATHLEN];
1.75      he        117:        char *canonical_path;
1.52      jdolecek  118:
                    119:        /* started as "mount" */
1.22      cgd       120:        all = forceall = init_flags = 0;
1.12      mycroft   121:        options = NULL;
1.32      lukem     122:        vfslist = NULL;
1.40      cgd       123:        vfstype = ffs_fstype;
1.31      lukem     124:        while ((ch = getopt(argc, argv, "Aadfo:rwt:uv")) != -1)
1.12      mycroft   125:                switch (ch) {
1.22      cgd       126:                case 'A':
                    127:                        all = forceall = 1;
                    128:                        break;
1.1       cgd       129:                case 'a':
                    130:                        all = 1;
                    131:                        break;
1.12      mycroft   132:                case 'd':
                    133:                        debug = 1;
                    134:                        break;
1.1       cgd       135:                case 'f':
1.103   ! mlelstv   136:                        init_flags |= FLG_FORCE;
1.12      mycroft   137:                        break;
                    138:                case 'o':
                    139:                        if (*optarg)
1.35      mycroft   140:                                catopt(&options, optarg);
1.1       cgd       141:                        break;
                    142:                case 'r':
1.103   ! mlelstv   143:                        init_flags |= FLG_RDONLY;
1.12      mycroft   144:                        break;
                    145:                case 't':
1.32      lukem     146:                        if (vfslist != NULL)
1.94      christos  147:                                errx(EXIT_FAILURE,
                    148:                                    "Only one -t option may be specified.");
1.32      lukem     149:                        vfslist = makevfslist(optarg);
1.12      mycroft   150:                        vfstype = optarg;
1.1       cgd       151:                        break;
                    152:                case 'u':
1.103   ! mlelstv   153:                        init_flags |= FLG_UPDATE;
1.1       cgd       154:                        break;
                    155:                case 'v':
1.61      christos  156:                        verbose++;
1.1       cgd       157:                        break;
                    158:                case 'w':
1.103   ! mlelstv   159:                        init_flags |= FLG_RDWRITE;
1.1       cgd       160:                        break;
                    161:                case '?':
                    162:                default:
                    163:                        usage();
                    164:                        /* NOTREACHED */
                    165:                }
                    166:        argc -= optind;
                    167:        argv += optind;
                    168:
1.12      mycroft   169: #define        BADTYPE(type)                                                   \
                    170:        (strcmp(type, FSTAB_RO) &&                                      \
                    171:            strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
                    172:
                    173:        rval = 0;
                    174:        switch (argc) {
                    175:        case 0:
                    176:                if (all)
                    177:                        while ((fs = getfsent()) != NULL) {
                    178:                                if (BADTYPE(fs->fs_type))
                    179:                                        continue;
1.32      lukem     180:                                if (checkvfsname(fs->fs_vfstype, vfslist))
1.12      mycroft   181:                                        continue;
                    182:                                if (hasopt(fs->fs_mntops, "noauto"))
                    183:                                        continue;
1.68      cgd       184:                                if (strcmp(fs->fs_spec, "from_mount") == 0) {
1.94      christos  185:                                        if ((mntbuf = getmntpt(fs->fs_file))
                    186:                                            == NULL)
                    187:                                                errx(EXIT_FAILURE,
                    188:                                                    "Unknown file system %s",
1.68      cgd       189:                                                    fs->fs_file);
                    190:                                        mntfromname = mntbuf->f_mntfromname;
                    191:                                } else
                    192:                                        mntfromname = fs->fs_spec;
1.95      christos  193:                                mntfromname = getfsspecname(buf, sizeof(buf),
                    194:                                    mntfromname);
                    195:                                if (mntfromname == NULL)
1.97      christos  196:                                        err(EXIT_FAILURE, "%s", buf);
1.68      cgd       197:                                if (mountfs(fs->fs_vfstype, mntfromname,
1.12      mycroft   198:                                    fs->fs_file, init_flags, options,
1.61      christos  199:                                    fs->fs_mntops, !forceall, NULL, 0))
1.12      mycroft   200:                                        rval = 1;
                    201:                        }
                    202:                else {
                    203:                        if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
1.94      christos  204:                                err(EXIT_FAILURE, "getmntinfo");
1.12      mycroft   205:                        for (i = 0; i < mntsize; i++) {
1.32      lukem     206:                                if (checkvfsname(mntbuf[i].f_fstypename,
                    207:                                    vfslist))
1.12      mycroft   208:                                        continue;
1.13      mycroft   209:                                prmount(&mntbuf[i]);
1.12      mycroft   210:                        }
1.1       cgd       211:                }
1.98      christos  212:                return rval;
1.12      mycroft   213:        case 1:
1.40      cgd       214:                if (vfslist != NULL) {
1.1       cgd       215:                        usage();
1.40      cgd       216:                        /* NOTREACHED */
                    217:                }
1.1       cgd       218:
1.74      erh       219:                /*
                    220:                 * Create a canonical version of the device or mount path
                    221:                 * passed to us.  It's ok for this to fail.  It's also ok
                    222:                 * for the result to be exactly the same as the original.
                    223:                 */
                    224:                canonical_path = realpath(*argv, canonical_path_buf);
                    225:
1.103   ! mlelstv   226:                if (init_flags & FLG_UPDATE) {
1.74      erh       227:                        /*
1.77      lukem     228:                         * Try looking up the canonical path first,
1.74      erh       229:                         * then try exactly what the user entered.
                    230:                         */
                    231:                        if ((canonical_path == NULL ||
1.94      christos  232:                            (mntbuf = getmntpt(canonical_path)) == NULL) &&
                    233:                            (mntbuf = getmntpt(*argv)) == NULL) {
                    234: out:
                    235:                                errx(EXIT_FAILURE,
                    236:                                    "Unknown special file or file system `%s'",
1.12      mycroft   237:                                    *argv);
1.74      erh       238:                        }
1.68      cgd       239:                        mntfromname = mntbuf->f_mntfromname;
1.42      ross      240:                        if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) {
1.68      cgd       241:                                if (strcmp(fs->fs_spec, "from_mount") != 0)
                    242:                                        mntfromname = fs->fs_spec;
1.42      ross      243:                                /* ignore the fstab file options.  */
                    244:                                fs->fs_mntops = NULL;
1.68      cgd       245:                        }
1.42      ross      246:                        mntonname  = mntbuf->f_mntonname;
                    247:                        fstypename = mntbuf->f_fstypename;
                    248:                        mountopts  = NULL;
1.12      mycroft   249:                } else {
1.74      erh       250:                        /*
1.77      lukem     251:                         * Try looking up the canonical path first,
1.74      erh       252:                         * then try exactly what the user entered.
                    253:                         */
1.77      lukem     254:                        if (canonical_path == NULL ||
                    255:                            ((fs = getfsfile(canonical_path)) == NULL &&
                    256:                             (fs = getfsspec(canonical_path)) == NULL))
1.74      erh       257:                        {
                    258:                                if ((fs = getfsfile(*argv)) == NULL &&
1.94      christos  259:                                    (fs = getfsspec(*argv)) == NULL) {
                    260:                                        goto out;
1.74      erh       261:                                }
                    262:                        }
1.12      mycroft   263:                        if (BADTYPE(fs->fs_type))
1.94      christos  264:                                errx(EXIT_FAILURE,
                    265:                                    "Unknown file system type for `%s'",
1.12      mycroft   266:                                    *argv);
1.68      cgd       267:                        if (strcmp(fs->fs_spec, "from_mount") == 0) {
1.74      erh       268:                                if ((canonical_path == NULL ||
1.94      christos  269:                                    (mntbuf = getmntpt(canonical_path))
                    270:                                     == NULL) &&
                    271:                                    (mntbuf = getmntpt(*argv)) == NULL)
                    272:                                        goto out;
1.68      cgd       273:                                mntfromname = mntbuf->f_mntfromname;
                    274:                        } else
                    275:                                mntfromname = fs->fs_spec;
1.42      ross      276:                        mntonname   = fs->fs_file;
                    277:                        fstypename  = fs->fs_vfstype;
                    278:                        mountopts   = fs->fs_mntops;
1.12      mycroft   279:                }
1.95      christos  280:                mntfromname = getfsspecname(buf, sizeof(buf), mntfromname);
                    281:                if (mntfromname == NULL)
                    282:                        err(EXIT_FAILURE, "%s", buf);
1.42      ross      283:                rval = mountfs(fstypename, mntfromname,
1.61      christos  284:                    mntonname, init_flags, options, mountopts, 0, NULL, 0);
1.12      mycroft   285:                break;
                    286:        case 2:
1.1       cgd       287:                /*
1.12      mycroft   288:                 * If -t flag has not been specified, and spec contains either
                    289:                 * a ':' or a '@' then assume that an NFS filesystem is being
                    290:                 * specified ala Sun.
1.1       cgd       291:                 */
1.95      christos  292:                mntfromname = getfsspecname(buf, sizeof(buf), argv[0]);
                    293:                if (mntfromname == NULL)
                    294:                        err(EXIT_FAILURE, "%s", buf);
1.48      abs       295:                if (vfslist == NULL) {
1.87      pooka     296:                        if (strpbrk(argv[0], ":@") != NULL) {
                    297:                                fprintf(stderr, "WARNING: autoselecting nfs "
                    298:                                    "based on : or @ in the device name is "
                    299:                                    "deprecated!\n"
                    300:                                    "WARNING: This behaviour will be removed "
                    301:                                    "in a future release\n");
1.48      abs       302:                                vfstype = "nfs";
1.87      pooka     303:                        } else {
1.94      christos  304:                                vfstype = getfslab(mntfromname);
1.48      abs       305:                                if (vfstype == NULL)
                    306:                                        vfstype = ffs_fstype;
                    307:                        }
                    308:                }
1.94      christos  309:                rval = mountfs(vfstype, mntfromname, argv[1], init_flags,
                    310:                    options, NULL, 0, NULL, 0);
1.12      mycroft   311:                break;
                    312:        default:
                    313:                usage();
1.1       cgd       314:        }
                    315:
1.89      yamt      316: #if 0  /* disabled because it interferes the service. */
1.12      mycroft   317:        /*
                    318:         * If the mount was successfully, and done by root, tell mountd the
                    319:         * good news.  Pid checks are probably unnecessary, but don't hurt.
                    320:         */
                    321:        if (rval == 0 && getuid() == 0 &&
                    322:            (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) {
1.29      christos  323:                int pid;
                    324:
                    325:                if (fscanf(mountdfp, "%d", &pid) == 1 &&
1.53      enami     326:                    pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH)
1.94      christos  327:                        err(EXIT_FAILURE, "signal mountd");
1.12      mycroft   328:                (void)fclose(mountdfp);
1.1       cgd       329:        }
1.89      yamt      330: #endif
1.1       cgd       331:
1.98      christos  332:        return rval;
1.1       cgd       333: }
                    334:
1.12      mycroft   335: int
1.76      xtraeme   336: hasopt(const char *mntopts, const char *option)
1.1       cgd       337: {
1.12      mycroft   338:        int negative, found;
                    339:        char *opt, *optbuf;
1.1       cgd       340:
1.12      mycroft   341:        if (option[0] == 'n' && option[1] == 'o') {
                    342:                negative = 1;
                    343:                option += 2;
                    344:        } else
                    345:                negative = 0;
1.94      christos  346:        optbuf = estrdup(mntopts);
1.12      mycroft   347:        found = 0;
                    348:        for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
                    349:                if (opt[0] == 'n' && opt[1] == 'o') {
                    350:                        if (!strcasecmp(opt + 2, option))
                    351:                                found = negative;
                    352:                } else if (!strcasecmp(opt, option))
                    353:                        found = !negative;
                    354:        }
                    355:        free(optbuf);
                    356:        return (found);
1.1       cgd       357: }
                    358:
1.52      jdolecek  359: static int
1.99      ast       360: mountfs(const char *vfstype, const char *spec, const char *name,
1.94      christos  361:     int flags, const char *options, const char *mntopts,
                    362:     int skipmounted, char *buf, size_t buflen)
1.1       cgd       363: {
1.12      mycroft   364:        /* List of directories containing mount_xxx subcommands. */
                    365:        static const char *edirs[] = {
1.72      christos  366: #ifdef RESCUEDIR
                    367:                RESCUEDIR,
1.60      lukem     368: #endif
1.12      mycroft   369:                _PATH_SBIN,
                    370:                _PATH_USRSBIN,
                    371:                NULL
                    372:        };
1.82      christos  373:        const char ** volatile argv, **edir;
1.69      christos  374:        struct statvfs *sfp, sf;
1.12      mycroft   375:        pid_t pid;
1.61      christos  376:        int pfd[2];
1.36      drochner  377:        int argc, numfs, i, status, maxargc;
1.33      christos  378:        char *optbuf, execname[MAXPATHLEN + 1], execbase[MAXPATHLEN],
                    379:            mntpath[MAXPATHLEN];
1.82      christos  380:        volatile int getargs;
1.1       cgd       381:
1.12      mycroft   382:        if (realpath(name, mntpath) == NULL) {
1.94      christos  383:                warn("realpath `%s'", name);
1.12      mycroft   384:                return (1);
                    385:        }
1.1       cgd       386:
1.12      mycroft   387:        name = mntpath;
1.1       cgd       388:
1.35      mycroft   389:        optbuf = NULL;
                    390:        if (mntopts)
                    391:                catopt(&optbuf, mntopts);
1.81      christos  392:
                    393:        if (options) {
1.35      mycroft   394:                catopt(&optbuf, options);
1.81      christos  395:                getargs = strstr(options, "getargs") != NULL;
                    396:        } else
                    397:                getargs = 0;
                    398:
1.35      mycroft   399:        if (!mntopts && !options)
                    400:                catopt(&optbuf, "rw");
1.12      mycroft   401:
1.92      pooka     402:        if (getargs == 0 && strcmp(name, "/") == 0 && !hasopt(optbuf, "union"))
1.103   ! mlelstv   403:                flags |= FLG_UPDATE;
1.22      cgd       404:        else if (skipmounted) {
1.36      drochner  405:                if ((numfs = getmntinfo(&sfp, MNT_WAIT)) == 0) {
                    406:                        warn("getmntinfo");
1.21      cgd       407:                        return (1);
                    408:                }
1.36      drochner  409:                for(i = 0; i < numfs; i++) {
1.91      pooka     410:                        const char *mountedtype = sfp[i].f_fstypename;
                    411:                        size_t cmplen = sizeof(sfp[i].f_fstypename);
                    412:
                    413:                        /* remove "puffs|" from comparisons, if present */
                    414: #define TYPESIZE (sizeof(PUFFS_TYPEPREFIX)-1)
                    415:                        if (strncmp(mountedtype,
                    416:                            PUFFS_TYPEPREFIX, TYPESIZE) == 0) {
                    417:                                mountedtype += TYPESIZE;
                    418:                                cmplen -= TYPESIZE;
                    419:                        }
                    420:
1.53      enami     421:                        /*
                    422:                         * XXX can't check f_mntfromname,
                    423:                         * thanks to mfs, union, etc.
                    424:                         */
1.36      drochner  425:                        if (strncmp(name, sfp[i].f_mntonname, MNAMELEN) == 0 &&
1.91      pooka     426:                            strncmp(vfstype, mountedtype, cmplen) == 0) {
1.36      drochner  427:                                if (verbose)
1.53      enami     428:                                        (void)printf("%s on %s type %.*s: "
                    429:                                            "%s\n",
                    430:                                            sfp[i].f_mntfromname,
                    431:                                            sfp[i].f_mntonname,
1.84      christos  432:                                            (int)sizeof(sfp[i].f_fstypename),
1.53      enami     433:                                            sfp[i].f_fstypename,
                    434:                                            "already mounted");
1.36      drochner  435:                                return (0);
                    436:                        }
1.21      cgd       437:                }
                    438:        }
1.103   ! mlelstv   439:        if (flags & FLG_FORCE)
1.35      mycroft   440:                catopt(&optbuf, "force");
1.103   ! mlelstv   441:        if (flags & FLG_RDONLY)
1.35      mycroft   442:                catopt(&optbuf, "ro");
1.103   ! mlelstv   443:        /* make -w override -r */
        !           444:        if (flags & FLG_RDWRITE)
        !           445:                catopt(&optbuf, "rw");
1.33      christos  446:
1.103   ! mlelstv   447:        if (flags & FLG_UPDATE) {
1.35      mycroft   448:                catopt(&optbuf, "update");
1.30      christos  449:                /* Figure out the fstype only if we defaulted to ffs */
1.69      christos  450:                if (vfstype == ffs_fstype && statvfs(name, &sf) != -1)
1.30      christos  451:                        vfstype = sf.f_fstypename;
                    452:        }
1.12      mycroft   453:
1.35      mycroft   454:        maxargc = 64;
1.94      christos  455:        argv = ecalloc(maxargc, sizeof(*argv));
1.35      mycroft   456:
1.90      pooka     457:        if (getargs &&
                    458:            strncmp(vfstype, PUFFS_TYPEPREFIX, sizeof(PUFFS_TYPEPREFIX)-1) == 0)
                    459:                (void)snprintf(execbase, sizeof(execbase), "mount_puffs");
                    460:        else if (hasopt(optbuf, "rump"))
1.88      pooka     461:                (void)snprintf(execbase, sizeof(execbase), "rump_%s", vfstype);
                    462:        else
                    463:                (void)snprintf(execbase, sizeof(execbase), "mount_%s", vfstype);
1.12      mycroft   464:        argc = 0;
1.33      christos  465:        argv[argc++] = execbase;
1.35      mycroft   466:        if (optbuf)
                    467:                mangle(optbuf, &argc, &argv, &maxargc);
1.12      mycroft   468:        argv[argc++] = spec;
                    469:        argv[argc++] = name;
                    470:        argv[argc] = NULL;
                    471:
1.81      christos  472:        if ((verbose && buf == NULL) || debug) {
1.35      mycroft   473:                (void)printf("exec:");
                    474:                for (i = 0; i < argc; i++)
1.12      mycroft   475:                        (void)printf(" %s", argv[i]);
                    476:                (void)printf("\n");
                    477:        }
1.5       mycroft   478:
1.61      christos  479:        if (buf) {
                    480:                if (pipe(pfd) == -1)
                    481:                        warn("Cannot create pipe");
                    482:        }
                    483:
1.100     pooka     484:        switch (pid = fork()) {
1.12      mycroft   485:        case -1:                                /* Error. */
1.100     pooka     486:                warn("fork");
1.35      mycroft   487:                if (optbuf)
                    488:                        free(optbuf);
1.80      christos  489:                free(argv);
1.12      mycroft   490:                return (1);
1.35      mycroft   491:
1.12      mycroft   492:        case 0:                                 /* Child. */
1.34      christos  493:                if (debug)
                    494:                        _exit(0);
                    495:
1.61      christos  496:                if (buf) {
                    497:                        (void)close(pfd[0]);
                    498:                        (void)close(STDOUT_FILENO);
                    499:                        if (dup2(pfd[1], STDOUT_FILENO) == -1)
                    500:                                warn("Cannot open fd to mount program");
                    501:                }
                    502:
1.12      mycroft   503:                /* Go find an executable. */
                    504:                edir = edirs;
                    505:                do {
                    506:                        (void)snprintf(execname,
1.33      christos  507:                            sizeof(execname), "%s/%s", *edir, execbase);
1.78      christos  508:                        (void)execv(execname, __UNCONST(argv));
1.12      mycroft   509:                        if (errno != ENOENT)
                    510:                                warn("exec %s for %s", execname, name);
                    511:                } while (*++edir != NULL);
1.1       cgd       512:
1.12      mycroft   513:                if (errno == ENOENT)
1.102     christos  514:                        warn("exec %s for %s: %s", execbase, name, execbase);
1.34      christos  515:                _exit(1);
1.12      mycroft   516:                /* NOTREACHED */
1.35      mycroft   517:
1.12      mycroft   518:        default:                                /* Parent. */
1.35      mycroft   519:                if (optbuf)
                    520:                        free(optbuf);
1.80      christos  521:                free(argv);
1.1       cgd       522:
1.81      christos  523:                if (buf || getargs) {
1.61      christos  524:                        char tbuf[1024], *ptr;
                    525:                        int nread;
1.64      enami     526:
1.61      christos  527:                        if (buf == NULL) {
                    528:                                ptr = tbuf;
                    529:                                buflen = sizeof(tbuf) - 1;
                    530:                        } else {
                    531:                                ptr = buf;
                    532:                                buflen--;
                    533:                        }
                    534:                        (void)close(pfd[1]);
                    535:                        (void)signal(SIGPIPE, SIG_IGN);
                    536:                        while ((nread = read(pfd[0], ptr, buflen)) > 0) {
                    537:                                buflen -= nread;
                    538:                                ptr += nread;
                    539:                        }
                    540:                        *ptr = '\0';
                    541:                        if (buflen == 0) {
                    542:                                while (read(pfd[0], &nread, sizeof(nread)) > 0)
                    543:                                        continue;
                    544:                        }
                    545:                        if (buf == NULL)
1.64      enami     546:                                (void)fprintf(stdout, "%s", tbuf);
1.61      christos  547:                }
                    548:
1.94      christos  549:                if (waitpid(pid, &status, 0) == -1) {
1.12      mycroft   550:                        warn("waitpid");
                    551:                        return (1);
1.1       cgd       552:                }
1.12      mycroft   553:
                    554:                if (WIFEXITED(status)) {
                    555:                        if (WEXITSTATUS(status) != 0)
                    556:                                return (WEXITSTATUS(status));
                    557:                } else if (WIFSIGNALED(status)) {
1.17      jtc       558:                        warnx("%s: %s", name, strsignal(WTERMSIG(status)));
1.12      mycroft   559:                        return (1);
1.1       cgd       560:                }
1.12      mycroft   561:
1.61      christos  562:                if (buf == NULL) {
                    563:                        if (verbose) {
1.94      christos  564:                                if (statvfs(name, &sf) == -1) {
1.69      christos  565:                                        warn("statvfs %s", name);
1.61      christos  566:                                        return (1);
                    567:                                }
                    568:                                prmount(&sf);
1.12      mycroft   569:                        }
1.1       cgd       570:                }
1.12      mycroft   571:                break;
1.1       cgd       572:        }
1.12      mycroft   573:
                    574:        return (0);
1.1       cgd       575: }
                    576:
1.52      jdolecek  577: static void
1.76      xtraeme   578: prmount(struct statvfs *sfp)
1.13      mycroft   579: {
1.12      mycroft   580:        int flags;
1.52      jdolecek  581:        const struct opt *o;
1.32      lukem     582:        struct passwd *pw;
1.12      mycroft   583:        int f;
1.1       cgd       584:
1.53      enami     585:        (void)printf("%s on %s type %.*s", sfp->f_mntfromname,
1.84      christos  586:            sfp->f_mntonname, (int)sizeof(sfp->f_fstypename),
                    587:            sfp->f_fstypename);
1.1       cgd       588:
1.69      christos  589:        flags = sfp->f_flag & MNT_VISFLAGMASK;
1.99      ast       590:        for (f = 0, o = optnames; flags && o <
1.58      christos  591:            &optnames[sizeof(optnames)/sizeof(optnames[0])]; o++)
1.12      mycroft   592:                if (flags & o->o_opt) {
1.58      christos  593:                        if (!o->o_silent || verbose)
1.24      cgd       594:                                (void)printf("%s%s", !f++ ? " (" : ", ",
                    595:                                    o->o_name);
1.12      mycroft   596:                        flags &= ~o->o_opt;
                    597:                }
1.24      cgd       598:        if (flags)
1.27      pk        599:                (void)printf("%sunknown flag%s %#x", !f++ ? " (" : ", ",
1.24      cgd       600:                    flags & (flags - 1) ? "s" : "", flags);
1.32      lukem     601:        if (sfp->f_owner) {
                    602:                (void)printf("%smounted by ", !f++ ? " (" : ", ");
                    603:                if ((pw = getpwuid(sfp->f_owner)) != NULL)
                    604:                        (void)printf("%s", pw->pw_name);
                    605:                else
                    606:                        (void)printf("%d", sfp->f_owner);
                    607:        }
1.71      enami     608:        if (verbose)
                    609:                (void)printf("%sfsid: 0x%x/0x%x",
                    610:                    !f++ ? " (" /* ) */: ", ",
                    611:                    sfp->f_fsidx.__fsid_val[0], sfp->f_fsidx.__fsid_val[1]);
                    612:
1.61      christos  613:        if (verbose) {
1.69      christos  614:                (void)printf("%s", !f++ ? " (" : ", ");
1.70      hannken   615:                (void)printf("reads: sync %" PRIu64 " async %" PRIu64 "",
1.69      christos  616:                    sfp->f_syncreads, sfp->f_asyncreads);
1.70      hannken   617:                (void)printf(", writes: sync %" PRIu64 " async %" PRIu64 "",
1.69      christos  618:                    sfp->f_syncwrites, sfp->f_asyncwrites);
1.61      christos  619:                if (verbose > 1) {
                    620:                        char buf[2048];
1.63      enami     621:
1.61      christos  622:                        if (getmntargs(sfp, buf, sizeof(buf)))
1.63      enami     623:                                printf(", [%s: %s]", sfp->f_fstypename, buf);
1.61      christos  624:                }
1.63      enami     625:                printf(")\n");
1.61      christos  626:        } else
1.50      is        627:                (void)printf("%s", f ? ")\n" : "\n");
1.61      christos  628: }
                    629:
                    630: static int
1.76      xtraeme   631: getmntargs(struct statvfs *sfs, char *buf, size_t buflen)
1.61      christos  632: {
1.64      enami     633:
1.61      christos  634:        if (mountfs(sfs->f_fstypename, sfs->f_mntfromname, sfs->f_mntonname, 0,
                    635:            "getargs", NULL, 0, buf, buflen))
1.64      enami     636:                return (0);
1.61      christos  637:        else {
                    638:                if (*buf == '\0')
1.64      enami     639:                        return (0);
1.61      christos  640:                if ((buf = strchr(buf, '\n')) != NULL)
                    641:                        *buf = '\0';
1.64      enami     642:                return (1);
1.61      christos  643:        }
1.1       cgd       644: }
                    645:
1.69      christos  646: static struct statvfs *
1.76      xtraeme   647: getmntpt(const char *name)
1.1       cgd       648: {
1.69      christos  649:        struct statvfs *mntbuf;
1.12      mycroft   650:        int i, mntsize;
1.1       cgd       651:
                    652:        mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
1.12      mycroft   653:        for (i = 0; i < mntsize; i++)
                    654:                if (strcmp(mntbuf[i].f_mntfromname, name) == 0 ||
                    655:                    strcmp(mntbuf[i].f_mntonname, name) == 0)
1.1       cgd       656:                        return (&mntbuf[i]);
1.12      mycroft   657:        return (NULL);
1.1       cgd       658: }
                    659:
1.52      jdolecek  660: static void
1.76      xtraeme   661: catopt(char **sp, const char *o)
1.12      mycroft   662: {
1.67      itojun    663:        char *s, *n;
1.12      mycroft   664:
1.35      mycroft   665:        s = *sp;
                    666:        if (s) {
1.94      christos  667:                easprintf(&n, "%s,%s", s, o);
1.67      itojun    668:                free(s);
                    669:                s = n;
1.12      mycroft   670:        } else
1.94      christos  671:                s = estrdup(o);
1.35      mycroft   672:        *sp = s;
1.1       cgd       673: }
                    674:
1.35      mycroft   675: static void
1.82      christos  676: mangle(char *options, int *argcp, const char ** volatile *argvp, int *maxargcp)
1.1       cgd       677: {
1.12      mycroft   678:        char *p, *s;
1.35      mycroft   679:        int argc, maxargc;
1.67      itojun    680:        const char **argv, **nargv;
1.1       cgd       681:
1.12      mycroft   682:        argc = *argcp;
1.35      mycroft   683:        argv = *argvp;
                    684:        maxargc = *maxargcp;
                    685:
                    686:        for (s = options; (p = strsep(&s, ",")) != NULL;) {
                    687:                /* Always leave space for one more argument and the NULL. */
                    688:                if (argc >= maxargc - 4) {
1.94      christos  689:                        nargv = erealloc(argv, (maxargc << 1) * sizeof(nargv));
1.67      itojun    690:                        argv = nargv;
1.35      mycroft   691:                        maxargc <<= 1;
                    692:                }
1.44      ross      693:                if (*p != '\0') {
1.12      mycroft   694:                        if (*p == '-') {
                    695:                                argv[argc++] = p;
                    696:                                p = strchr(p, '=');
                    697:                                if (p) {
                    698:                                        *p = '\0';
                    699:                                        argv[argc++] = p+1;
1.1       cgd       700:                                }
1.103   ! mlelstv   701:                        } else {
1.12      mycroft   702:                                argv[argc++] = "-o";
                    703:                                argv[argc++] = p;
1.1       cgd       704:                        }
1.44      ross      705:                }
1.35      mycroft   706:        }
1.12      mycroft   707:
                    708:        *argcp = argc;
1.35      mycroft   709:        *argvp = argv;
                    710:        *maxargcp = maxargc;
1.48      abs       711: }
                    712:
1.53      enami     713: /* Deduce the filesystem type from the disk label. */
                    714: static const char *
1.76      xtraeme   715: getfslab(const char *str)
1.48      abs       716: {
1.73      thorpej   717:        static struct dkwedge_info dkw;
1.48      abs       718:        struct disklabel dl;
                    719:        int fd;
                    720:        int part;
                    721:        const char *vfstype;
                    722:        u_char fstype;
1.53      enami     723:        char buf[MAXPATHLEN + 1];
1.51      abs       724:        char *sp, *ep;
1.48      abs       725:
1.51      abs       726:        if ((fd = open(str, O_RDONLY)) == -1) {
                    727:                /*
                    728:                 * Iff we get EBUSY try the raw device. Since mount always uses
                    729:                 * the block device we know we are never passed a raw device.
                    730:                 */
                    731:                if (errno != EBUSY)
1.94      christos  732:                        err(EXIT_FAILURE, "cannot open `%s'", str);
1.51      abs       733:                strlcpy(buf, str, MAXPATHLEN);
                    734:                if ((sp = strrchr(buf, '/')) != NULL)
                    735:                        ++sp;
                    736:                else
                    737:                        sp = buf;
1.53      enami     738:                for (ep = sp + strlen(sp) + 1;  ep > sp; ep--)
                    739:                        *ep = *(ep - 1);
1.51      abs       740:                *sp = 'r';
                    741:
                    742:                /* Silently fail here - mount call can display error */
                    743:                if ((fd = open(buf, O_RDONLY)) == -1)
1.53      enami     744:                        return (NULL);
1.51      abs       745:        }
1.49      abs       746:
1.73      thorpej   747:        /* Check to see if this is a wedge. */
                    748:        if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
                    749:                /* Yup, this is easy. */
                    750:                (void) close(fd);
                    751:                return (dkw.dkw_ptype);
                    752:        }
                    753:
1.51      abs       754:        if (ioctl(fd, DIOCGDINFO, &dl) == -1) {
1.54      enami     755:                (void) close(fd);
1.53      enami     756:                return (NULL);
1.49      abs       757:        }
1.48      abs       758:
                    759:        (void) close(fd);
                    760:
                    761:        part = str[strlen(str) - 1] - 'a';
                    762:
                    763:        if (part < 0 || part >= dl.d_npartitions)
1.59      nathanw   764:                return (NULL);
1.48      abs       765:
                    766:        /* Return NULL for unknown types - caller can fall back to ffs */
                    767:        if ((fstype = dl.d_partitions[part].p_fstype) >= FSMAXMOUNTNAMES)
                    768:                vfstype = NULL;
                    769:        else
                    770:                vfstype = mountnames[fstype];
                    771:
1.53      enami     772:        return (vfstype);
1.1       cgd       773: }
                    774:
1.52      jdolecek  775: static void
1.76      xtraeme   776: usage(void)
1.1       cgd       777: {
                    778:
1.94      christos  779:        (void)fprintf(stderr, "Usage: %s [-Aadfruvw] [-t type]\n"
                    780:            "\t%s [-dfruvw] special | node\n"
                    781:            "\t%s [-dfruvw] [-o options] [-t type] special node\n",
                    782:            getprogname(), getprogname(), getprogname());
1.12      mycroft   783:        exit(1);
1.1       cgd       784: }

CVSweb <webmaster@jp.NetBSD.org>