/* * Make a pass over the file system info in ``mntbuf'' filtering out * file system types not in vfslist and possibly re-stating to get * current (not cached) info. Returns the new count of valid statfs bufs. */ static size_t regetmntinfo(struct statfs **mntbufp, long mntsize, const char **vfslist) { int error, i, j; struct statfs *mntbuf; if (vfslist == NULL) return (nflag ? mntsize : getmntinfo(mntbufp, MNT_WAIT)); mntbuf = *mntbufp; for (j = 0, i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; /* * XXX statfs(2) can fail for various reasons. It may be * possible that the user does not have access to the * pathname, if this happens, we will fall back on * "stale" filesystem statistics. */ error = statfs(mntbuf[i].f_mntonname, &mntbuf[j]); if (nflag || error < 0) if (i != j) { if (error < 0) warnx("%s stats possibly stale", mntbuf[i].f_mntonname); mntbuf[j] = mntbuf[i]; } j++; } return (j); }
/* * Make a pass over the filesystem info in ``mntbuf'' filtering out * filesystem types not in vfslist and possibly re-stating to get * current (not cached) info. Returns the new count of valid statfs bufs. */ long regetmntinfo(struct statfs **mntbufp, struct statvfs **mntvbufp, long mntsize, char **vfslist) { int i, j; struct statfs *mntbuf; struct statvfs *mntvbuf; if (vfslist == NULL) return (nflag ? mntsize : getmntvinfo(mntbufp, mntvbufp, MNT_WAIT)); mntbuf = *mntbufp; mntvbuf = *mntvbufp; for (j = 0, i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; if (!nflag) { statfs(mntbuf[i].f_mntonname,&mntbuf[j]); statvfs(mntbuf[i].f_mntonname,&mntvbuf[j]); } else if (i != j) { mntbuf[j] = mntbuf[i]; mntvbuf[j] = mntvbuf[i]; } j++; } return (j); }
int umountall(char **typelist) { struct vfsconf vfc; struct fstab *fs; int rval; char *cp; static int firstcall = 1; if ((fs = getfsent()) != NULL) firstcall = 0; else if (firstcall) errx(1, "fstab reading failure"); else return (0); do { /* Ignore the root. */ if (strcmp(fs->fs_file, "/") == 0) continue; /* * !!! * Historic practice: ignore unknown FSTAB_* fields. */ if (strcmp(fs->fs_type, FSTAB_RW) && strcmp(fs->fs_type, FSTAB_RO) && strcmp(fs->fs_type, FSTAB_RQ)) continue; /* If an unknown file system type, complain. */ if (getvfsbyname(fs->fs_vfstype, &vfc) == -1) { warnx("%s: unknown mount type", fs->fs_vfstype); continue; } if (checkvfsname(fs->fs_vfstype, typelist)) continue; /* * We want to unmount the file systems in the reverse order * that they were mounted. So, we save off the file name * in some allocated memory, and then call recursively. */ if ((cp = malloc((size_t)strlen(fs->fs_file) + 1)) == NULL) err(1, "malloc failed"); (void)strcpy(cp, fs->fs_file); rval = umountall(typelist); rval = umountfs(cp, typelist) || rval; free(cp); return (rval); } while ((fs = getfsent()) != NULL); return (0); }
/*_________________---------------------------__________________ _________________ regetmntinfo __________________ -----------------___________________________------------------ */ static size_t regetmntinfo(struct statfs **mntbufp, long mntsize, const char **vfslist) { int i, j; struct statfs *mntbuf; if (vfslist == NULL) return (getmntinfo(mntbufp, MNT_WAIT)); mntbuf = *mntbufp; for (j = 0, i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; (void)statfs(mntbuf[i].f_mntonname,&mntbuf[j]); j++; } return (j); }
int main(int argc, char *argv[]) { struct stat stbuf; struct statfs statfsbuf, totalbuf; struct maxwidths maxwidths; struct statfs *mntbuf; const char *fstype; char *mntpath, *mntpt; const char **vfslist; int i, mntsize; int ch, rv; fstype = "ufs"; memset(&totalbuf, 0, sizeof(totalbuf)); totalbuf.f_bsize = DEV_BSIZE; strlcpy(totalbuf.f_mntfromname, "total", MNAMELEN); vfslist = NULL; while ((ch = getopt(argc, argv, "abcgHhiklmnPt:T")) != -1) switch (ch) { case 'a': aflag = 1; break; case 'b': /* FALLTHROUGH */ case 'P': /* * POSIX specifically discusses the behavior of * both -k and -P. It states that the blocksize should * be set to 1024. Thus, if this occurs, simply break * rather than clobbering the old blocksize. */ if (kflag) break; setenv("BLOCKSIZE", "512", 1); hflag = 0; break; case 'c': cflag = 1; break; case 'g': setenv("BLOCKSIZE", "1g", 1); hflag = 0; break; case 'H': hflag = UNITS_SI; break; case 'h': hflag = UNITS_2; break; case 'i': iflag = 1; break; case 'k': kflag++; setenv("BLOCKSIZE", "1024", 1); hflag = 0; break; case 'l': if (vfslist != NULL) errx(1, "-l and -t are mutually exclusive."); vfslist = makevfslist(makenetvfslist()); lflag = 1; break; case 'm': setenv("BLOCKSIZE", "1m", 1); hflag = 0; break; case 'n': nflag = 1; break; case 't': if (lflag) errx(1, "-l and -t are mutually exclusive."); if (vfslist != NULL) errx(1, "only one -t option may be specified"); fstype = optarg; vfslist = makevfslist(optarg); break; case 'T': Tflag = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; rv = 0; if (!*argv) { /* everything (modulo -t) */ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); mntsize = regetmntinfo(&mntbuf, mntsize, vfslist); } else { /* just the filesystems specified on the command line */ mntbuf = malloc(argc * sizeof(*mntbuf)); if (mntbuf == 0) err(1, "malloc()"); mntsize = 0; /* continued in for loop below */ } /* iterate through specified filesystems */ for (; *argv; argv++) { if (stat(*argv, &stbuf) < 0) { if ((mntpt = getmntpt(*argv)) == 0) { warn("%s", *argv); rv = 1; continue; } } else if (S_ISCHR(stbuf.st_mode)) { if ((mntpt = getmntpt(*argv)) == 0) { mdev.fspec = *argv; mntpath = strdup("/tmp/df.XXXXXX"); if (mntpath == NULL) { warn("strdup failed"); rv = 1; continue; } mntpt = mkdtemp(mntpath); if (mntpt == NULL) { warn("mkdtemp(\"%s\") failed", mntpath); rv = 1; free(mntpath); continue; } if (mount(fstype, mntpt, MNT_RDONLY, &mdev) != 0) { warn("%s", *argv); rv = 1; (void)rmdir(mntpt); free(mntpath); continue; } else if (statfs(mntpt, &statfsbuf) == 0) { statfsbuf.f_mntonname[0] = '\0'; prtstat(&statfsbuf, &maxwidths); if (cflag) addstat(&totalbuf, &statfsbuf); } else { warn("%s", *argv); rv = 1; } (void)unmount(mntpt, 0); (void)rmdir(mntpt); free(mntpath); continue; } } else mntpt = *argv; /* * Statfs does not take a `wait' flag, so we cannot * implement nflag here. */ if (statfs(mntpt, &statfsbuf) < 0) { warn("%s", mntpt); rv = 1; continue; } /* * Check to make sure the arguments we've been given are * satisfied. Return an error if we have been asked to * list a mount point that does not match the other args * we've been given (-l, -t, etc.). */ if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { rv = 1; continue; } /* the user asked for it, so ignore the ignore flag */ statfsbuf.f_flags &= ~MNT_IGNORE; /* add to list */ mntbuf[mntsize++] = statfsbuf; } bzero(&maxwidths, sizeof(maxwidths)); for (i = 0; i < mntsize; i++) { if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) { update_maxwidths(&maxwidths, &mntbuf[i]); if (cflag) addstat(&totalbuf, &mntbuf[i]); } } for (i = 0; i < mntsize; i++) if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) prtstat(&mntbuf[i], &maxwidths); if (cflag) prtstat(&totalbuf, &maxwidths); return (rv); }
int main(int argc, char *argv[]) { struct stat stbuf; struct statfs statfsbuf, *mntbuf; struct maxwidths maxwidths; char *mntpt, **vfslist; long mntsize; int ch, i, rv, tflag = 0, kludge_tflag = 0; int kflag = 0; const char *options = "abgHhiklmnPt:T:"; if (COMPAT_MODE("bin/df", "unix2003")) { /* Unix2003 requires -t be "include total capacity". which df already does, but it conflicts with the old -t so we need to *not* expect a string after -t (we provide -T in both cases to cover the old use of -t) */ options = "abgHhiklmnPtT:"; iflag = 1; } vfslist = NULL; while ((ch = getopt(argc, argv, options)) != -1) switch (ch) { case 'a': aflag = 1; break; case 'b': /* FALLTHROUGH */ case 'P': if (COMPAT_MODE("bin/df", "unix2003")) { if (!kflag) { /* -k overrides -P */ putenv("BLOCKSIZE=512"); } iflag = 0; } else { putenv("BLOCKSIZE=512"); } hflag = 0; break; case 'g': putenv("BLOCKSIZE=1g"); hflag = 0; break; case 'H': hflag = UNITS_SI; valp = vals_si; break; case 'h': hflag = UNITS_2; valp = vals_base2; break; case 'i': iflag = 1; break; case 'k': if (COMPAT_MODE("bin/df", "unix2003")) { putenv("BLOCKSIZE=1024"); } else { putenv("BLOCKSIZE=1k"); } kflag = 1; hflag = 0; break; case 'l': if (tflag) errx(1, "-l and -T are mutually exclusive."); if (vfslist != NULL) break; vfslist = makevfslist(makenetvfslist()); break; case 'm': putenv("BLOCKSIZE=1m"); hflag = 0; break; case 'n': nflag = 1; break; case 't': /* Unix2003 uses -t for something we do by default */ if (COMPAT_MODE("bin/df", "unix2003")) { kludge_tflag = 1; break; } case 'T': if (vfslist != NULL) { if (tflag) errx(1, "only one -%c option may be specified", ch); else errx(1, "-l and -%c are mutually exclusive.", ch); } tflag++; vfslist = makevfslist(optarg); break; case '?': default: usage(); } argc -= optind; argv += optind; /* If we are in unix2003 mode, have seen a -t but no -T and the first non switch arg isn't a file, let's pretend they used -T on it. This makes the Lexmark printer installer happy (PR-3918471) */ if (tflag == 0 && kludge_tflag && *argv && stat(*argv, &stbuf) < 0 && errno == ENOENT) { vfslist = makevfslist(*argv++); } mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); bzero(&maxwidths, sizeof(maxwidths)); for (i = 0; i < mntsize; i++) update_maxwidths(&maxwidths, &mntbuf[i]); rv = 0; if (!*argv) { mntsize = regetmntinfo(&mntbuf, mntsize, vfslist); bzero(&maxwidths, sizeof(maxwidths)); for (i = 0; i < mntsize; i++) update_maxwidths(&maxwidths, &mntbuf[i]); for (i = 0; i < mntsize; i++) { if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) prtstat(&mntbuf[i], &maxwidths); } exit(rv); } for (; *argv; argv++) { if (stat(*argv, &stbuf) < 0) { if ((mntpt = getmntpt(*argv)) == 0) { warn("%s", *argv); rv = 1; continue; } } else if (S_ISCHR(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) { warnx("%s: Raw devices not supported", *argv); rv = 1; continue; } else mntpt = *argv; /* * Statfs does not take a `wait' flag, so we cannot * implement nflag here. */ if (statfs(mntpt, &statfsbuf) < 0) { warn("%s", mntpt); rv = 1; continue; } /* Check to make sure the arguments we've been * given are satisfied. Return an error if we * have been asked to list a mount point that does * not match the other args we've been given (-l, -t, etc.) */ if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { rv++; continue; } if (argc == 1) { bzero(&maxwidths, sizeof(maxwidths)); update_maxwidths(&maxwidths, &statfsbuf); } prtstat(&statfsbuf, &maxwidths); } return (rv); }
int main(int argc, char *argv[]) { const char *mntfromname, **vfslist, *vfstype; struct fstab *fs; struct statfs *mntbuf; int all, ch, i, init_flags, late, failok, mntsize, rval, have_fstab, ro; int onlylate; char *cp, *ep, *options; all = init_flags = late = onlylate = 0; ro = 0; options = NULL; vfslist = NULL; vfstype = "ufs"; while ((ch = getopt(argc, argv, "adF:fLlno:prt:uvw")) != -1) switch (ch) { case 'a': all = 1; break; case 'd': debug = 1; break; case 'F': setfstab(optarg); break; case 'f': init_flags |= MNT_FORCE; break; case 'L': onlylate = 1; late = 1; break; case 'l': late = 1; break; case 'n': /* For compatibility with the Linux version of mount. */ break; case 'o': if (*optarg) { options = catopt(options, optarg); if (specified_ro(optarg)) ro = 1; } break; case 'p': fstab_style = 1; verbose = 1; break; case 'r': options = catopt(options, "ro"); ro = 1; break; case 't': if (vfslist != NULL) errx(1, "only one -t option may be specified"); vfslist = makevfslist(optarg); vfstype = optarg; break; case 'u': init_flags |= MNT_UPDATE; break; case 'v': verbose = 1; break; case 'w': options = catopt(options, "noro"); break; case '?': default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; #define BADTYPE(type) \ (strcmp(type, FSTAB_RO) && \ strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) if ((init_flags & MNT_UPDATE) && (ro == 0)) options = catopt(options, "noro"); rval = 0; switch (argc) { case 0: if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) err(1, "getmntinfo"); if (all) { while ((fs = getfsent()) != NULL) { if (BADTYPE(fs->fs_type)) continue; if (checkvfsname(fs->fs_vfstype, vfslist)) continue; if (hasopt(fs->fs_mntops, "noauto")) continue; if (!hasopt(fs->fs_mntops, "late") && onlylate) continue; if (hasopt(fs->fs_mntops, "late") && !late) continue; if (hasopt(fs->fs_mntops, "failok")) failok = 1; else failok = 0; if (!(init_flags & MNT_UPDATE) && ismounted(fs, mntbuf, mntsize)) continue; options = update_options(options, fs->fs_mntops, mntbuf->f_flags); if (mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, init_flags, options, fs->fs_mntops) && !failok) rval = 1; } } else if (fstab_style) { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; putfsent(&mntbuf[i]); } } else { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; if (!verbose && (mntbuf[i].f_flags & MNT_IGNORE) != 0) continue; prmount(&mntbuf[i]); } } exit(rval); case 1: if (vfslist != NULL) usage(); rmslashes(*argv, *argv); if (init_flags & MNT_UPDATE) { mntfromname = NULL; have_fstab = 0; if ((mntbuf = getmntpt(*argv)) == NULL) errx(1, "not currently mounted %s", *argv); /* * Only get the mntflags from fstab if both mntpoint * and mntspec are identical. Also handle the special * case where just '/' is mounted and 'spec' is not * identical with the one from fstab ('/dev' is missing * in the spec-string at boot-time). */ if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { if (strcmp(fs->fs_spec, mntbuf->f_mntfromname) == 0 && strcmp(fs->fs_file, mntbuf->f_mntonname) == 0) { have_fstab = 1; mntfromname = mntbuf->f_mntfromname; } else if (argv[0][0] == '/' && argv[0][1] == '\0') { fs = getfsfile("/"); have_fstab = 1; mntfromname = fs->fs_spec; } } if (have_fstab) { options = update_options(options, fs->fs_mntops, mntbuf->f_flags); } else { mntfromname = mntbuf->f_mntfromname; options = update_options(options, NULL, mntbuf->f_flags); } rval = mountfs(mntbuf->f_fstypename, mntfromname, mntbuf->f_mntonname, init_flags, options, 0); break; } if ((fs = getfsfile(*argv)) == NULL && (fs = getfsspec(*argv)) == NULL) errx(1, "%s: unknown special file or file system", *argv); if (BADTYPE(fs->fs_type)) errx(1, "%s has unknown file system type", *argv); rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, init_flags, options, fs->fs_mntops); break; case 2: /* * If -t flag has not been specified, the path cannot be * found, spec contains either a ':' or a '@', then assume * that an NFS file system is being specified ala Sun. * Check if the hostname contains only allowed characters * to reduce false positives. IPv6 addresses containing * ':' will be correctly parsed only if the separator is '@'. * The definition of a valid hostname is taken from RFC 1034. */ if (vfslist == NULL && ((ep = strchr(argv[0], '@')) != NULL || (ep = strchr(argv[0], ':')) != NULL)) { if (*ep == '@') { cp = ep + 1; ep = cp + strlen(cp); } else cp = argv[0]; while (cp != ep) { if (!isdigit(*cp) && !isalpha(*cp) && *cp != '.' && *cp != '-' && *cp != ':') break; cp++; } if (cp == ep) vfstype = "nfs"; } rval = mountfs(vfstype, argv[0], argv[1], init_flags, options, NULL); break; default: usage(); /* NOTREACHED */ } /* * If the mount was successfully, and done by root, tell mountd the * good news. */ if (rval == 0 && getuid() == 0) restart_mountd(); exit(rval); }
int mntlistmain() { /* NCurses Stuff */ app_init(); /* INIT Ncurses Stuff not needed when becomes part of SMIT*/ const char **vfslist, *vfstype; struct fstab *fs; struct statfs *mntbuf; int all, i, init_flags, late, failok, mntsize, rval, ro; int onlylate; char *options; all = init_flags = late = onlylate = 0; ro = 0; options = NULL; vfslist = NULL; vfstype = "ufs"; // Leave there #define BADTYPE(type) \ (strcmp(type, FSTAB_RO) && \ strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) rval = 0; /* Might be what I want */ if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) err(1, "getmntinfo"); if (all) { while ((fs = getfsent()) != NULL) { if (BADTYPE(fs->fs_type)) continue; if (checkvfsname(fs->fs_vfstype, vfslist)) continue; if (hasopt(fs->fs_mntops, "noauto")) continue; if (!hasopt(fs->fs_mntops, "late") && onlylate) continue; if (hasopt(fs->fs_mntops, "late") && !late) continue; if (hasopt(fs->fs_mntops, "failok")) failok = 1; else failok = 0; if (!(init_flags & MNT_UPDATE) && ismounted(fs, mntbuf, mntsize)) continue; } } else if (fstab_style) { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; } } else { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; prmount(&mntbuf[i]); wmove(FS_LIST, ctr++, 2); } } wgetch(FS_LIST); ctr = 1; // Reset the Counter return (rval); }
int main(int argc, char **argv) { const char *mntfromname, **vfslist, *vfstype; struct fstab *fs; struct statfs *mntbuf; FILE *mountdfp; pid_t pid; int all, ch, i, init_flags, mntsize, rval, have_fstab; char *options; all = init_flags = 0; options = NULL; vfslist = NULL; vfstype = "ufs"; while ((ch = getopt(argc, argv, "adF:fo:prwt:uv")) != -1) { switch (ch) { case 'a': all = 1; break; case 'd': debug = 1; break; case 'F': setfstab(optarg); break; case 'f': init_flags |= MNT_FORCE; break; case 'o': if (*optarg) options = catopt(options, optarg); break; case 'p': fstab_style = 1; verbose = 1; break; case 'r': options = catopt(options, "ro"); break; case 't': if (vfslist != NULL) errx(1, "only one -t option may be specified"); vfslist = makevfslist(optarg); vfstype = optarg; break; case 'u': init_flags |= MNT_UPDATE; break; case 'v': verbose = 1; break; case 'w': options = catopt(options, "noro"); break; case '?': default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; #define BADTYPE(type) \ (strcmp(type, FSTAB_RO) && \ strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) rval = 0; switch (argc) { case 0: if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) err(1, "getmntinfo"); if (all) { while ((fs = getfsent()) != NULL) { if (BADTYPE(fs->fs_type)) continue; if (checkvfsname(fs->fs_vfstype, vfslist)) continue; if (hasopt(fs->fs_mntops, "noauto")) continue; if (!(init_flags & MNT_UPDATE) && ismounted(fs, mntbuf, mntsize)) continue; options = update_options(options, fs->fs_mntops, mntbuf->f_flags); if (mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, init_flags, options, fs->fs_mntops)) rval = 1; } } else if (fstab_style) { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; putfsent(&mntbuf[i]); } } else { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; prmount(&mntbuf[i]); } } exit(rval); case 1: if (vfslist != NULL) usage(); rmslashes(*argv, *argv); if (init_flags & MNT_UPDATE) { mntfromname = NULL; have_fstab = 0; if ((mntbuf = getmntpt(*argv)) == NULL) errx(1, "not currently mounted %s", *argv); /* * Only get the mntflags from fstab if both mntpoint * and mntspec are identical. Also handle the special * case where just '/' is mounted and 'spec' is not * identical with the one from fstab ('/dev' is missing * in the spec-string at boot-time). */ if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { if (strcmp(fs->fs_spec, mntbuf->f_mntfromname) == 0 && strcmp(fs->fs_file, mntbuf->f_mntonname) == 0) { have_fstab = 1; mntfromname = mntbuf->f_mntfromname; } else if (argv[0][0] == '/' && argv[0][1] == '\0') { fs = getfsfile("/"); have_fstab = 1; mntfromname = fs->fs_spec; } } if (have_fstab) { options = update_options(options, fs->fs_mntops, mntbuf->f_flags); } else { mntfromname = mntbuf->f_mntfromname; options = update_options(options, NULL, mntbuf->f_flags); } rval = mountfs(mntbuf->f_fstypename, mntfromname, mntbuf->f_mntonname, init_flags, options, 0); break; } if ((fs = getfsfile(*argv)) == NULL && (fs = getfsspec(*argv)) == NULL) errx(1, "%s: unknown special file or file system", *argv); if (BADTYPE(fs->fs_type)) errx(1, "%s has unknown file system type", *argv); rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, init_flags, options, fs->fs_mntops); break; case 2: /* * If -t flag has not been specified, the path cannot be * found. * * If the spec is not a file and contains a ':' then assume * NFS. * * If the spec is a cdev attempt to extract the fstype from * the label. * * When all else fails ufs is assumed. */ if (vfslist == NULL) { if (strpbrk(argv[0], ":") != NULL && access(argv[0], 0) == -1) { vfstype = "nfs"; } else { checkdisklabel(argv[0], &vfstype); } } rval = mountfs(vfstype, getdevpath(argv[0], 0), argv[1], init_flags, options, NULL); break; default: usage(); /* NOTREACHED */ } /* * If the mount was successfully, and done by root, tell mountd the * good news. Pid checks are probably unnecessary, but don't hurt. */ if (rval == 0 && getuid() == 0 && (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) { if (fscanf(mountdfp, "%d", &pid) == 1 && pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH) err(1, "signal mountd"); fclose(mountdfp); } exit(rval); }
int main(int argc, char *argv[]) { int all, errs, ch, mntsize, error; char **typelist = NULL; struct statfs *mntbuf, *sfs; struct addrinfo hints; all = errs = 0; while ((ch = getopt(argc, argv, "AaF:fh:t:v")) != -1) switch (ch) { case 'A': all = 2; break; case 'a': all = 1; break; case 'F': setfstab(optarg); break; case 'f': fflag = MNT_FORCE; break; case 'h': /* -h implies -A. */ all = 2; nfshost = optarg; break; case 't': if (typelist != NULL) err(1, "only one -t option may be specified"); typelist = makevfslist(optarg); break; case 'v': vflag = 1; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; /* Start disks transferring immediately. */ if ((fflag & MNT_FORCE) == 0) sync(); if ((argc == 0 && !all) || (argc != 0 && all)) usage(); /* -h implies "-t nfs" if no -t flag. */ if ((nfshost != NULL) && (typelist == NULL)) typelist = makevfslist("nfs"); if (nfshost != NULL) { memset(&hints, 0, sizeof hints); error = getaddrinfo(nfshost, NULL, &hints, &nfshost_ai); if (error) errx(1, "%s: %s", nfshost, gai_strerror(error)); } switch (all) { case 2: if ((mntsize = mntinfo(&mntbuf)) <= 0) break; /* * We unmount the nfs-mounts in the reverse order * that they were mounted. */ for (errs = 0, mntsize--; mntsize > 0; mntsize--) { sfs = &mntbuf[mntsize]; if (checkvfsname(sfs->f_fstypename, typelist)) continue; if (strcmp(sfs->f_mntonname, "/dev") == 0) continue; if (umountfs(sfs) != 0) errs = 1; } free(mntbuf); break; case 1: if (setfsent() == 0) err(1, "%s", getfstab()); errs = umountall(typelist); break; case 0: for (errs = 0; *argv != NULL; ++argv) if (checkname(*argv, typelist) != 0) errs = 1; break; } exit(errs); }
/* * Do magic checks on mountpoint/device/fsid, and then call unmount(2). */ int checkname(char *mntname, char **typelist) { char buf[MAXPATHLEN]; struct statfs sfsbuf; struct stat sb; struct statfs *sfs; char *delimp; dev_t dev; int len; /* * 1. Check if the name exists in the mounttable. */ sfs = checkmntlist(mntname); /* * 2. Remove trailing slashes if there are any. After that * we look up the name in the mounttable again. */ if (sfs == NULL) { len = strlen(mntname); while (len > 1 && mntname[len - 1] == '/') mntname[--len] = '\0'; sfs = checkmntlist(mntname); } /* * 3. Check if the deprecated NFS syntax with an '@' has been used * and translate it to the ':' syntax. Look up the name in the * mount table again. */ if (sfs == NULL && (delimp = strrchr(mntname, '@')) != NULL) { snprintf(buf, sizeof(buf), "%s:%.*s", delimp + 1, (int)(delimp - mntname), mntname); len = strlen(buf); while (len > 1 && buf[len - 1] == '/') buf[--len] = '\0'; sfs = checkmntlist(buf); } /* * 4. Resort to a statfs(2) call. This is the last check so that * hung NFS filesystems for example can be unmounted without * potentially blocking forever in statfs() as long as the * filesystem is specified unambiguously. This covers all the * hard cases such as symlinks and mismatches between the * mount list and reality. * We also do this if an ambiguous mount point was specified. */ if (sfs == NULL || (getmntentry(NULL, mntname, NULL, FIND) != NULL && getmntentry(NULL, mntname, NULL, CHECKUNIQUE) == NULL)) { if (statfs(mntname, &sfsbuf) != 0) { warn("%s: statfs", mntname); } else if (stat(mntname, &sb) != 0) { warn("%s: stat", mntname); } else if (S_ISDIR(sb.st_mode)) { /* Check that `mntname' is the root directory. */ dev = sb.st_dev; snprintf(buf, sizeof(buf), "%s/..", mntname); if (stat(buf, &sb) != 0) { warn("%s: stat", buf); } else if (sb.st_dev == dev) { warnx("%s: not a file system root directory", mntname); return (1); } else sfs = &sfsbuf; } } if (sfs == NULL) { warnx("%s: unknown file system", mntname); return (1); } if (checkvfsname(sfs->f_fstypename, typelist)) return (1); return (umountfs(sfs)); }
int main(int argc, char **argv) { struct stat stbuf; struct statfs statfsbuf, *mntbuf; struct statvfs statvfsbuf, *mntvbuf; struct maxwidths maxwidths; const char *fstype; char *mntpath, *mntpt, **vfslist; long mntsize; int ch, i, rv; fstype = "ufs"; vfslist = NULL; while ((ch = getopt(argc, argv, "abgHhiklmnPt:")) != -1) switch (ch) { case 'a': aflag = 1; break; case 'b': /* FALLTHROUGH */ case 'P': if (setenv("BLOCKSIZE", "512", 1) != 0) warn("setenv: cannot set BLOCKSIZE=512"); hflag = 0; break; case 'g': if (setenv("BLOCKSIZE", "1g", 1) != 0) warn("setenv: cannot set BLOCKSIZE=1g"); hflag = 0; break; case 'H': hflag = UNITS_SI; break; case 'h': hflag = UNITS_2; break; case 'i': iflag = 1; break; case 'k': if (setenv("BLOCKSIZE", "1k", 1) != 0) warn("setenv: cannot set BLOCKSIZE=1k"); hflag = 0; break; case 'l': if (vfslist != NULL) errx(1, "-l and -t are mutually exclusive."); vfslist = makevfslist(makenetvfslist()); break; case 'm': if (setenv("BLOCKSIZE", "1m", 1) != 0) warn("setenv: cannot set BLOCKSIZE=1m"); hflag = 0; break; case 'n': nflag = 1; break; case 't': if (vfslist != NULL) errx(1, "only one -t option may be specified"); fstype = optarg; vfslist = makevfslist(optarg); break; case '?': default: usage(); } argc -= optind; argv += optind; mntsize = getmntvinfo(&mntbuf, &mntvbuf, MNT_NOWAIT); bzero(&maxwidths, sizeof(maxwidths)); for (i = 0; i < mntsize; i++) update_maxwidths(&maxwidths, &mntbuf[i], &mntvbuf[i]); rv = 0; if (!*argv) { mntsize = regetmntinfo(&mntbuf, &mntvbuf, mntsize, vfslist); bzero(&maxwidths, sizeof(maxwidths)); for (i = 0; i < mntsize; i++) update_maxwidths(&maxwidths, &mntbuf[i], &mntvbuf[i]); for (i = 0; i < mntsize; i++) { if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) prtstat(&mntbuf[i], &mntvbuf[i], &maxwidths); } exit(rv); } for (; *argv; argv++) { if (stat(*argv, &stbuf) < 0) { if ((mntpt = getmntpt(*argv)) == NULL) { warn("%s", *argv); rv = 1; continue; } } else if (S_ISCHR(stbuf.st_mode)) { if ((mntpt = getmntpt(*argv)) == NULL) { mdev.fspec = *argv; mntpath = strdup("/tmp/df.XXXXXX"); if (mntpath == NULL) { warn("strdup failed"); rv = 1; continue; } mntpt = mkdtemp(mntpath); if (mntpt == NULL) { warn("mkdtemp(\"%s\") failed", mntpath); rv = 1; free(mntpath); continue; } if (mount(fstype, mntpt, MNT_RDONLY, &mdev) != 0) { rv = ufs_df(*argv, &maxwidths) || rv; rmdir(mntpt); free(mntpath); continue; } else if (statfs(mntpt, &statfsbuf) == 0 && statvfs(mntpt, &statvfsbuf) == 0) { statfsbuf.f_mntonname[0] = '\0'; prtstat(&statfsbuf, &statvfsbuf, &maxwidths); } else { warn("%s", *argv); rv = 1; } unmount(mntpt, 0); rmdir(mntpt); free(mntpath); continue; } } else mntpt = *argv; /* * Statfs does not take a `wait' flag, so we cannot * implement nflag here. */ if (statfs(mntpt, &statfsbuf) < 0) { warn("%s", mntpt); rv = 1; continue; } if (statvfs(mntpt, &statvfsbuf) < 0) { warn("%s", mntpt); rv = 1; continue; } /* * Check to make sure the arguments we've been given are * satisfied. Return an error if we have been asked to * list a mount point that does not match the other args * we've been given (-l, -t, etc.). */ if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { rv = 1; continue; } if (argc == 1) { bzero(&maxwidths, sizeof(maxwidths)); update_maxwidths(&maxwidths, &statfsbuf, &statvfsbuf); } prtstat(&statfsbuf, &statvfsbuf, &maxwidths); } return (rv); }
int main(int argc, char *argv[]) { int all, errs, ch, mntsize, error, nfsforce, ret; char **typelist = NULL; struct statfs *mntbuf, *sfs; struct addrinfo hints; nfsforce = all = errs = 0; while ((ch = getopt(argc, argv, "AaF:fh:Nnt:v")) != -1) switch (ch) { case 'A': all = 2; break; case 'a': all = 1; break; case 'F': setfstab(optarg); break; case 'f': fflag |= MNT_FORCE; break; case 'h': /* -h implies -A. */ all = 2; nfshost = optarg; break; case 'N': nfsforce = 1; break; case 'n': fflag |= MNT_NONBUSY; break; case 't': if (typelist != NULL) err(1, "only one -t option may be specified"); typelist = makevfslist(optarg); break; case 'v': vflag = 1; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if ((fflag & MNT_FORCE) != 0 && (fflag & MNT_NONBUSY) != 0) err(1, "-f and -n are mutually exclusive"); /* Start disks transferring immediately. */ if ((fflag & (MNT_FORCE | MNT_NONBUSY)) == 0 && nfsforce == 0) sync(); if ((argc == 0 && !all) || (argc != 0 && all)) usage(); if (nfsforce != 0 && (argc == 0 || nfshost != NULL || typelist != NULL)) usage(); /* -h implies "-t nfs" if no -t flag. */ if ((nfshost != NULL) && (typelist == NULL)) typelist = makevfslist("nfs"); if (nfshost != NULL) { memset(&hints, 0, sizeof hints); error = getaddrinfo(nfshost, NULL, &hints, &nfshost_ai); if (error) errx(1, "%s: %s", nfshost, gai_strerror(error)); } switch (all) { case 2: if ((mntsize = mntinfo(&mntbuf)) <= 0) break; /* * We unmount the nfs-mounts in the reverse order * that they were mounted. */ for (errs = 0, mntsize--; mntsize > 0; mntsize--) { sfs = &mntbuf[mntsize]; if (checkvfsname(sfs->f_fstypename, typelist)) continue; if (strcmp(sfs->f_mntonname, "/dev") == 0) continue; if (umountfs(sfs) != 0) errs = 1; } free(mntbuf); break; case 1: if (setfsent() == 0) err(1, "%s", getfstab()); errs = umountall(typelist); break; case 0: for (errs = 0; *argv != NULL; ++argv) if (nfsforce != 0) { /* * First do the nfssvc() syscall to shut down * the mount point and then do the forced * dismount. */ ret = nfssvc(NFSSVC_FORCEDISM, *argv); if (ret >= 0) ret = unmount(*argv, MNT_FORCE); if (ret < 0) { warn("%s", *argv); errs = 1; } } else if (checkname(*argv, typelist) != 0) errs = 1; break; } exit(errs); }
int main(int argc, char *argv[]) { int all, errs, ch, mntsize; char **typelist = NULL, *mntonname, *mntfromname; char *type, *mntfromnamerev, *mntonnamerev; struct statfs *mntbuf; /* Start disks transferring immediately. */ sync(); all = errs = 0; while ((ch = getopt(argc, argv, "Aafh:t:v")) != -1) switch (ch) { case 'A': all = 2; break; case 'a': all = 1; break; case 'f': fflag = MNT_FORCE; break; case 'h': /* -h implies -A. */ all = 2; nfshost = optarg; break; case 't': if (typelist != NULL) err(1, "only one -t option may be specified"); typelist = makevfslist(optarg); break; case 'v': vflag = 1; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if ((argc == 0 && !all) || (argc != 0 && all)) usage(); /* -h implies "-t nfs" if no -t flag. */ if ((nfshost != NULL) && (typelist == NULL)) typelist = makevfslist("nfs"); switch (all) { case 2: if ((mntsize = mntinfo(&mntbuf)) <= 0) break; /* * We unmount the nfs-mounts in the reverse order * that they were mounted. */ for (errs = 0, mntsize--; mntsize > 0; mntsize--) { if (checkvfsname(mntbuf[mntsize].f_fstypename, typelist)) continue; /* * Check if a mountpoint is laid over by another mount. * A warning will be printed to stderr if this is * the case. The laid over mount remains unmounted. */ mntonname = mntbuf[mntsize].f_mntonname; mntfromname = mntbuf[mntsize].f_mntfromname; mntonnamerev = getmntname(getmntname(mntonname, NULL, MNTFROM, &type, NAME), NULL, MNTON, &type, NAME); mntfromnamerev = getmntname(mntonnamerev, NULL, MNTFROM, &type, NAME); if (strcmp(mntonnamerev, mntonname) == 0 && strcmp(mntfromnamerev, mntfromname ) != 0) warnx("cannot umount %s, %s\n " "is mounted there, umount it first", mntonname, mntfromnamerev); if (umountfs(mntbuf[mntsize].f_mntonname, typelist) != 0) errs = 1; } free(mntbuf); break; case 1: if (setfsent() == 0) err(1, "%s", _PATH_FSTAB); errs = umountall(typelist); break; case 0: for (errs = 0; *argv != NULL; ++argv) if (umountfs(*argv, typelist) != 0) errs = 1; break; } (void)getmntname(NULL, NULL, NOTHING, NULL, FREE); exit(errs); }
int umountfs(char *name, char **typelist) { enum clnt_stat clnt_stat; struct hostent *hp; struct mtablist *mtab; struct sockaddr_in saddr; struct timeval pertry, try; CLIENT *clp; size_t len; int so, speclen, do_rpc; char *mntonname, *mntfromname; char *mntfromnamerev; char *nfsdirname, *orignfsdirname; char *resolved, realname[MAXPATHLEN]; char *type, *delimp, *hostp, *origname; len = 0; mtab = NULL; mntfromname = mntonname = delimp = hostp = orignfsdirname = NULL; /* * 1. Check if the name exists in the mounttable. */ (void)checkmntlist(name, &mntfromname, &mntonname, &type); /* * 2. Remove trailing slashes if there are any. After that * we look up the name in the mounttable again. */ if (mntfromname == NULL && mntonname == NULL) { speclen = strlen(name); for (speclen = strlen(name); speclen > 1 && name[speclen - 1] == '/'; speclen--) name[speclen - 1] = '\0'; (void)checkmntlist(name, &mntfromname, &mntonname, &type); resolved = name; /* Save off original name in origname */ if ((origname = strdup(name)) == NULL) err(1, "strdup"); /* * 3. Check if the deprecated nfs-syntax with an '@' * has been used and translate it to the ':' syntax. * Look up the name in the mounttable again. */ if (mntfromname == NULL && mntonname == NULL) { if ((delimp = strrchr(name, '@')) != NULL) { hostp = delimp + 1; if (*hostp != '\0') { /* * Make both '@' and ':' * notations equal */ char *host = strdup(hostp); len = strlen(hostp); if (host == NULL) err(1, "strdup"); memmove(name + len + 1, name, (size_t)(delimp - name)); name[len] = ':'; memmove(name, host, len); free(host); } for (speclen = strlen(name); speclen > 1 && name[speclen - 1] == '/'; speclen--) name[speclen - 1] = '\0'; name[len + speclen + 1] = '\0'; (void)checkmntlist(name, &mntfromname, &mntonname, &type); resolved = name; } /* * 4. Check if a relative mountpoint has been * specified. This should happen as last check, * the order is important. To prevent possible * nfs-hangs, we just call realpath(3) on the * basedir of mountpoint and add the dirname again. * Check the name in mounttable one last time. */ if (mntfromname == NULL && mntonname == NULL) { (void)strcpy(name, origname); if ((getrealname(name, realname)) != NULL) { (void)checkmntlist(realname, &mntfromname, &mntonname, &type); resolved = realname; } /* * All tests failed, return to main() */ if (mntfromname == NULL && mntonname == NULL) { (void)strcpy(name, origname); warnx("%s: not currently mounted", origname); free(origname); return (1); } } } free(origname); } else resolved = name; if (checkvfsname(type, typelist)) return (1); hp = NULL; nfsdirname = NULL; if (!strcmp(type, "nfs")) { if ((nfsdirname = strdup(mntfromname)) == NULL) err(1, "strdup"); orignfsdirname = nfsdirname; if ((delimp = strchr(nfsdirname, ':')) != NULL) { *delimp = '\0'; hostp = nfsdirname; if ((hp = gethostbyname(hostp)) == NULL) { warnx("can't get net id for host"); } nfsdirname = delimp + 1; } } /* * Check if the reverse entrys of the mounttable are really the * same as the normal ones. */ if ((mntfromnamerev = strdup(getmntname(getmntname(mntfromname, NULL, MNTON, &type, NAME), NULL, MNTFROM, &type, NAME))) == NULL) err(1, "strdup"); /* * Mark the uppermost mount as unmounted. */ (void)getmntname(mntfromname, mntonname, NOTHING, &type, MARK); /* * If several equal mounts are in the mounttable, check the order * and warn the user if necessary. */ if (strcmp(mntfromnamerev, mntfromname ) != 0 && strcmp(resolved, mntonname) != 0) { warnx("cannot umount %s, %s\n " "is mounted there, umount it first", mntonname, mntfromnamerev); /* call getmntname again to set mntcheck[i] to 0 */ (void)getmntname(mntfromname, mntonname, NOTHING, &type, UNMARK); return (1); } free(mntfromnamerev); /* * Check if we have to start the rpc-call later. * If there are still identical nfs-names mounted, * we skip the rpc-call. Obviously this has to * happen before unmount(2), but it should happen * after the previous namecheck. */ if (strcmp(type, "nfs") == 0 && getmntname(mntfromname, NULL, NOTHING, &type, COUNT) != NULL) do_rpc = 1; else do_rpc = 0; if (!namematch(hp)) return (1); if (unmount(mntonname, fflag) != 0 ) { warn("unmount of %s failed", mntonname); return (1); } if (vflag) (void)printf("%s: unmount from %s\n", mntfromname, mntonname); /* * Report to mountd-server which nfsname * has been unmounted. */ if (hp != NULL && !(fflag & MNT_FORCE) && do_rpc) { memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = 0; memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length, sizeof(saddr.sin_addr))); pertry.tv_sec = 3; pertry.tv_usec = 0; so = RPC_ANYSOCK; if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, pertry, &so)) == NULL) { clnt_pcreateerror("Cannot MNT PRC"); return (1); } clp->cl_auth = authunix_create_default(); try.tv_sec = 20; try.tv_usec = 0; clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, nfsdirname, xdr_void, (caddr_t)0, try); if (clnt_stat != RPC_SUCCESS) { clnt_perror(clp, "Bad MNT RPC"); return (1); } /* * Remove the unmounted entry from /var/db/mounttab. */ if (read_mtab(mtab)) { mtab = mtabhead; clean_mtab(hostp, nfsdirname); if(!write_mtab()) warnx("cannot remove entry %s:%s", hostp, nfsdirname); free_mtab(); } free(orignfsdirname); auth_destroy(clp->cl_auth); clnt_destroy(clp); }