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>