1241806Suqs/* $NetBSD: fsck.c,v 1.30 2003/08/07 10:04:15 agc Exp $ */ 266868Sadrian 3331722Seadler/* 466868Sadrian * Copyright (c) 1996 Christos Zoulas. All rights reserved. 566868Sadrian * Copyright (c) 1980, 1989, 1993, 1994 666868Sadrian * The Regents of the University of California. All rights reserved. 766868Sadrian * 866868Sadrian * Redistribution and use in source and binary forms, with or without 966868Sadrian * modification, are permitted provided that the following conditions 1066868Sadrian * are met: 1166868Sadrian * 1. Redistributions of source code must retain the above copyright 1266868Sadrian * notice, this list of conditions and the following disclaimer. 1366868Sadrian * 2. Redistributions in binary form must reproduce the above copyright 1466868Sadrian * notice, this list of conditions and the following disclaimer in the 1566868Sadrian * documentation and/or other materials provided with the distribution. 16241806Suqs * 3. Neither the name of the University nor the names of its contributors 1766868Sadrian * may be used to endorse or promote products derived from this software 1866868Sadrian * without specific prior written permission. 1966868Sadrian * 2066868Sadrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2166868Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2266868Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2366868Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2466868Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2566868Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2666868Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2766868Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2866868Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2966868Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3066868Sadrian * SUCH DAMAGE. 3166868Sadrian * 3266868Sadrian * From: @(#)mount.c 8.19 (Berkeley) 4/19/94 3366918Sobrien * From: $NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp 34241806Suqs * $NetBSD: fsck.c,v 1.30 2003/08/07 10:04:15 agc Exp $ 3566868Sadrian */ 3666868Sadrian 3766868Sadrian#include <sys/cdefs.h> 3893102Smarkm__FBSDID("$FreeBSD: stable/11/sbin/fsck/fsck.c 315546 2017-03-19 14:05:56Z trasz $"); 3966868Sadrian 4066868Sadrian#include <sys/param.h> 4166868Sadrian#include <sys/mount.h> 4266868Sadrian#include <sys/queue.h> 4366868Sadrian#include <sys/wait.h> 44274770Simp#include <sys/disk.h> 4566868Sadrian#include <sys/ioctl.h> 4666868Sadrian 4793102Smarkm#include <ctype.h> 4866868Sadrian#include <err.h> 4966868Sadrian#include <errno.h> 5066868Sadrian#include <fstab.h> 5166868Sadrian#include <fcntl.h> 5266868Sadrian#include <paths.h> 5366868Sadrian#include <signal.h> 5466868Sadrian#include <stdio.h> 5566868Sadrian#include <stdlib.h> 5666868Sadrian#include <string.h> 5766868Sadrian#include <unistd.h> 5866868Sadrian 5966868Sadrian#include "fsutil.h" 6066868Sadrian 6166868Sadrianstatic enum { IN_LIST, NOT_IN_LIST } which = NOT_IN_LIST; 6266868Sadrian 63227081Sedstatic TAILQ_HEAD(fstypelist, entry) opthead, selhead; 6466868Sadrian 6566868Sadrianstruct entry { 6666868Sadrian char *type; 6766868Sadrian char *options; 6866868Sadrian TAILQ_ENTRY(entry) entries; 6966868Sadrian}; 7066868Sadrian 7166868Sadrianstatic char *options = NULL; 7266868Sadrianstatic int flags = 0; 7375936Smckusickstatic int forceflag = 0; 7466868Sadrian 75241807Suqsstatic int checkfs(const char *, const char *, const char *, const char *, pid_t *); 7692839Simpstatic int selected(const char *); 7792839Simpstatic void addoption(char *); 7892839Simpstatic const char *getoptions(const char *); 7992839Simpstatic void addentry(struct fstypelist *, const char *, const char *); 8092839Simpstatic void maketypelist(char *); 8192839Simpstatic void catopt(char **, const char *); 82241807Suqsstatic void mangle(char *, int *, const char ** volatile *, int *); 83274770Simpstatic const char *getfstype(const char *); 8492839Simpstatic void usage(void) __dead2; 8592839Simpstatic int isok(struct fstab *); 8666868Sadrian 87274770Simpstatic struct { 88274770Simp const char *ptype; 89274770Simp const char *name; 90274770Simp} ptype_map[] = { 91274770Simp { "ufs", "ffs" }, 92274770Simp { "ffs", "ffs" }, 93274770Simp { "fat", "msdosfs" }, 94274770Simp { "efi", "msdosfs" }, 95274770Simp { NULL, NULL }, 96274770Simp}; 97274770Simp 9866868Sadrianint 9992839Simpmain(int argc, char *argv[]) 10066868Sadrian{ 10166868Sadrian struct fstab *fs; 10266868Sadrian int i, rval = 0; 10366868Sadrian const char *vfstype = NULL; 10466868Sadrian char globopt[3]; 105226711Ssobomax const char *etc_fstab; 10666868Sadrian 10766868Sadrian globopt[0] = '-'; 10866868Sadrian globopt[2] = '\0'; 10966868Sadrian 11066868Sadrian TAILQ_INIT(&selhead); 11166868Sadrian TAILQ_INIT(&opthead); 11266868Sadrian 113226711Ssobomax etc_fstab = NULL; 114226711Ssobomax while ((i = getopt(argc, argv, "BCdvpfFnyl:t:T:c:")) != -1) 11566868Sadrian switch (i) { 11675936Smckusick case 'B': 11775936Smckusick if (flags & CHECK_BACKGRD) 11875936Smckusick errx(1, "Cannot specify -B and -F."); 11975936Smckusick flags |= DO_BACKGRD; 12075936Smckusick break; 12175936Smckusick 12266868Sadrian case 'd': 12366868Sadrian flags |= CHECK_DEBUG; 12466868Sadrian break; 12566868Sadrian 12666868Sadrian case 'v': 12766868Sadrian flags |= CHECK_VERBOSE; 12866868Sadrian break; 12966868Sadrian 13075936Smckusick case 'F': 13175936Smckusick if (flags & DO_BACKGRD) 13275936Smckusick errx(1, "Cannot specify -B and -F."); 13375936Smckusick flags |= CHECK_BACKGRD; 13475936Smckusick break; 13575936Smckusick 13666868Sadrian case 'p': 13766868Sadrian flags |= CHECK_PREEN; 13866868Sadrian /*FALLTHROUGH*/ 139187931Sobrien case 'C': 140187931Sobrien flags |= CHECK_CLEAN; 141187931Sobrien /*FALLTHROUGH*/ 14266868Sadrian case 'n': 14366868Sadrian case 'y': 14466868Sadrian globopt[1] = i; 14566868Sadrian catopt(&options, globopt); 14666868Sadrian break; 14766868Sadrian 14875936Smckusick case 'f': 14975936Smckusick forceflag = 1; 15075936Smckusick globopt[1] = i; 15175936Smckusick catopt(&options, globopt); 15275936Smckusick break; 15375936Smckusick 15466868Sadrian case 'l': 15575015Sphk warnx("Ignoring obsolete -l option\n"); 15666868Sadrian break; 15766868Sadrian 15866868Sadrian case 'T': 15966868Sadrian if (*optarg) 16066868Sadrian addoption(optarg); 16166868Sadrian break; 16266868Sadrian 16366868Sadrian case 't': 16470522Sphk if (!TAILQ_EMPTY(&selhead)) 16566868Sadrian errx(1, "only one -t option may be specified."); 16666868Sadrian 16766868Sadrian maketypelist(optarg); 16866868Sadrian vfstype = optarg; 16966868Sadrian break; 17066868Sadrian 171226711Ssobomax case 'c': 172226711Ssobomax etc_fstab = optarg; 173226711Ssobomax break; 174226711Ssobomax 17566868Sadrian case '?': 17666868Sadrian default: 17766868Sadrian usage(); 17866868Sadrian /* NOTREACHED */ 17966868Sadrian } 18066868Sadrian 18166868Sadrian argc -= optind; 18266868Sadrian argv += optind; 18366868Sadrian 184226711Ssobomax if (etc_fstab != NULL) 185226711Ssobomax setfstab(etc_fstab); 186226711Ssobomax 18766868Sadrian if (argc == 0) 18875015Sphk return checkfstab(flags, isok, checkfs); 18966868Sadrian 19066868Sadrian#define BADTYPE(type) \ 19166868Sadrian (strcmp(type, FSTAB_RO) && \ 19266868Sadrian strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) 19366868Sadrian 19466868Sadrian 19566868Sadrian for (; argc--; argv++) { 19675936Smckusick const char *spec, *mntpt, *type, *cp; 19775936Smckusick char device[MAXPATHLEN]; 19875936Smckusick struct statfs *mntp; 19966868Sadrian 200241807Suqs mntpt = NULL; 20166868Sadrian spec = *argv; 20266868Sadrian cp = strrchr(spec, '/'); 203298194Saraujo if (cp == NULL) { 20466868Sadrian (void)snprintf(device, sizeof(device), "%s%s", 20566868Sadrian _PATH_DEV, spec); 20666868Sadrian spec = device; 20766868Sadrian } 20875936Smckusick mntp = getmntpt(spec); 20975936Smckusick if (mntp != NULL) { 21075936Smckusick spec = mntp->f_mntfromname; 21175936Smckusick mntpt = mntp->f_mntonname; 21275936Smckusick } 21366868Sadrian if ((fs = getfsfile(spec)) == NULL && 21466868Sadrian (fs = getfsspec(spec)) == NULL) { 21566868Sadrian if (vfstype == NULL) 216274770Simp vfstype = getfstype(spec); 217106254Sphk if (vfstype == NULL) 218315546Strasz vfstype = "ufs"; 21966868Sadrian type = vfstype; 22075936Smckusick devcheck(spec); 22175936Smckusick } else { 22266868Sadrian spec = fs->fs_spec; 22366868Sadrian type = fs->fs_vfstype; 22475936Smckusick mntpt = fs->fs_file; 22566868Sadrian if (BADTYPE(fs->fs_type)) 226102231Strhodes errx(1, "%s has unknown file system type.", 22766868Sadrian spec); 22866868Sadrian } 22975936Smckusick if ((flags & CHECK_BACKGRD) && 23075936Smckusick checkfs(type, spec, mntpt, "-F", NULL) == 0) { 23175936Smckusick printf("%s: DEFER FOR BACKGROUND CHECKING\n", *argv); 23275936Smckusick continue; 23375936Smckusick } 23475936Smckusick if ((flags & DO_BACKGRD) && forceflag == 0 && 23575936Smckusick checkfs(type, spec, mntpt, "-F", NULL) != 0) 23675936Smckusick continue; 23766868Sadrian 23875936Smckusick rval |= checkfs(type, spec, mntpt, NULL, NULL); 23966868Sadrian } 24066868Sadrian 24166868Sadrian return rval; 24266868Sadrian} 24366868Sadrian 24466868Sadrian 24575936Smckusickstatic int 24692839Simpisok(struct fstab *fs) 24766868Sadrian{ 24875936Smckusick int i; 24975936Smckusick 25066868Sadrian if (fs->fs_passno == 0) 25175936Smckusick return (0); 25266868Sadrian if (BADTYPE(fs->fs_type)) 25375936Smckusick return (0); 25466868Sadrian if (!selected(fs->fs_vfstype)) 25575936Smckusick return (0); 25675936Smckusick /* 25775936Smckusick * If the -B flag has been given, then process the needed 25875936Smckusick * background checks. Background checks cannot be run on 259102231Strhodes * file systems that will be mounted read-only or that were 26075936Smckusick * not mounted at boot time (typically those marked `noauto'). 261102231Strhodes * If these basic tests are passed, check with the file system 26275936Smckusick * itself to see if it is willing to do background checking 26375936Smckusick * by invoking its check program with the -F flag. 26475936Smckusick */ 26575936Smckusick if (flags & DO_BACKGRD) { 26675936Smckusick if (!strcmp(fs->fs_type, FSTAB_RO)) 26775936Smckusick return (0); 26875936Smckusick if (getmntpt(fs->fs_spec) == NULL) 26975936Smckusick return (0); 27075936Smckusick if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", 0)) 27175936Smckusick return (0); 27275936Smckusick return (1); 27375936Smckusick } 27475936Smckusick /* 27575936Smckusick * If the -F flag has been given, then consider deferring the 27675936Smckusick * check to background. Background checks cannot be run on 277102231Strhodes * file systems that will be mounted read-only or that will 27875936Smckusick * not be mounted at boot time (e.g., marked `noauto'). If 279102231Strhodes * these basic tests are passed, check with the file system 28075936Smckusick * itself to see if it is willing to defer to background 28175936Smckusick * checking by invoking its check program with the -F flag. 28275936Smckusick */ 28375936Smckusick if ((flags & CHECK_BACKGRD) == 0 || !strcmp(fs->fs_type, FSTAB_RO)) 28475936Smckusick return (1); 28575936Smckusick for (i = strlen(fs->fs_mntops) - 6; i >= 0; i--) 28675936Smckusick if (!strncmp(&fs->fs_mntops[i], "noauto", 6)) 28775936Smckusick break; 28875936Smckusick if (i >= 0) 28975936Smckusick return (1); 29075936Smckusick if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", NULL) != 0) 29175936Smckusick return (1); 29275936Smckusick printf("%s: DEFER FOR BACKGROUND CHECKING\n", fs->fs_spec); 29375936Smckusick return (0); 29466868Sadrian} 29566868Sadrian 29666868Sadrian 29766868Sadrianstatic int 298113994Sjmallettcheckfs(const char *pvfstype, const char *spec, const char *mntpt, 299241807Suqs const char *auxopt, pid_t *pidp) 30066868Sadrian{ 301241807Suqs const char ** volatile argv; 30266868Sadrian pid_t pid; 30366868Sadrian int argc, i, status, maxargc; 304117031Sgordon char *optbuf, execbase[MAXPATHLEN]; 305113994Sjmallett char *vfstype = NULL; 30666868Sadrian const char *extra = NULL; 30766868Sadrian 30866868Sadrian#ifdef __GNUC__ 30966868Sadrian /* Avoid vfork clobbering */ 31066868Sadrian (void) &optbuf; 31166868Sadrian (void) &vfstype; 31266868Sadrian#endif 313113994Sjmallett /* 314113994Sjmallett * We convert the vfstype to lowercase and any spaces to underscores 315113994Sjmallett * to not confuse the issue 316113994Sjmallett * 317113994Sjmallett * XXX This is a kludge to make automatic filesystem type guessing 318113994Sjmallett * from the disklabel work for "4.2BSD" filesystems. It does a 319113994Sjmallett * very limited subset of transliteration to a normalised form of 320113994Sjmallett * filesystem name, and we do not seem to enforce a filesystem 321113994Sjmallett * name character set. 322113994Sjmallett */ 323113994Sjmallett vfstype = strdup(pvfstype); 324113994Sjmallett if (vfstype == NULL) 325241806Suqs perr("strdup(pvfstype)"); 326241807Suqs for (i = 0; i < (int)strlen(vfstype); i++) { 327113994Sjmallett vfstype[i] = tolower(vfstype[i]); 328113994Sjmallett if (vfstype[i] == ' ') 329113994Sjmallett vfstype[i] = '_'; 330113994Sjmallett } 33166868Sadrian 33266868Sadrian extra = getoptions(vfstype); 33366868Sadrian optbuf = NULL; 33466868Sadrian if (options) 33566868Sadrian catopt(&optbuf, options); 33666868Sadrian if (extra) 33766868Sadrian catopt(&optbuf, extra); 33875936Smckusick if (auxopt) 33975936Smckusick catopt(&optbuf, auxopt); 34075936Smckusick else if (flags & DO_BACKGRD) 34175936Smckusick catopt(&optbuf, "-B"); 34266868Sadrian 34366868Sadrian maxargc = 64; 34466868Sadrian argv = emalloc(sizeof(char *) * maxargc); 34566868Sadrian 34666868Sadrian (void) snprintf(execbase, sizeof(execbase), "fsck_%s", vfstype); 34766868Sadrian argc = 0; 34866868Sadrian argv[argc++] = execbase; 34966868Sadrian if (optbuf) 35066868Sadrian mangle(optbuf, &argc, &argv, &maxargc); 35166868Sadrian argv[argc++] = spec; 35266868Sadrian argv[argc] = NULL; 35366868Sadrian 35466868Sadrian if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) { 35566868Sadrian (void)printf("start %s %swait", mntpt, 35666868Sadrian pidp ? "no" : ""); 35766868Sadrian for (i = 0; i < argc; i++) 35866868Sadrian (void)printf(" %s", argv[i]); 35966868Sadrian (void)printf("\n"); 36066868Sadrian } 36166868Sadrian 36266868Sadrian switch (pid = vfork()) { 36366868Sadrian case -1: /* Error. */ 36466868Sadrian warn("vfork"); 36566868Sadrian if (optbuf) 36666868Sadrian free(optbuf); 367113994Sjmallett free(vfstype); 36866868Sadrian return (1); 36966868Sadrian 37066868Sadrian case 0: /* Child. */ 37175936Smckusick if ((flags & CHECK_DEBUG) && auxopt == NULL) 37266868Sadrian _exit(0); 37366868Sadrian 37466868Sadrian /* Go find an executable. */ 375241807Suqs execvP(execbase, _PATH_SYSPATH, __DECONST(char * const *, argv)); 376117031Sgordon if (spec) 377117031Sgordon warn("exec %s for %s in %s", execbase, spec, _PATH_SYSPATH); 378117031Sgordon else 379117031Sgordon warn("exec %s in %s", execbase, _PATH_SYSPATH); 38066868Sadrian _exit(1); 38166868Sadrian /* NOTREACHED */ 38266868Sadrian 38366868Sadrian default: /* Parent. */ 38466868Sadrian if (optbuf) 38566868Sadrian free(optbuf); 38666868Sadrian 387113994Sjmallett free(vfstype); 388113994Sjmallett 38966868Sadrian if (pidp) { 39066868Sadrian *pidp = pid; 39166868Sadrian return 0; 39266868Sadrian } 39366868Sadrian 39466868Sadrian if (waitpid(pid, &status, 0) < 0) { 39566868Sadrian warn("waitpid"); 39666868Sadrian return (1); 39766868Sadrian } 39866868Sadrian 39966868Sadrian if (WIFEXITED(status)) { 40066868Sadrian if (WEXITSTATUS(status) != 0) 40166868Sadrian return (WEXITSTATUS(status)); 40266868Sadrian } 40366868Sadrian else if (WIFSIGNALED(status)) { 40466868Sadrian warnx("%s: %s", spec, strsignal(WTERMSIG(status))); 40566868Sadrian return (1); 40666868Sadrian } 40766868Sadrian break; 40866868Sadrian } 40966868Sadrian 41066868Sadrian return (0); 41166868Sadrian} 41266868Sadrian 41366868Sadrian 41466868Sadrianstatic int 41592839Simpselected(const char *type) 41666868Sadrian{ 41766868Sadrian struct entry *e; 41866868Sadrian 41966868Sadrian /* If no type specified, it's always selected. */ 42070522Sphk TAILQ_FOREACH(e, &selhead, entries) 42166868Sadrian if (!strncmp(e->type, type, MFSNAMELEN)) 42266868Sadrian return which == IN_LIST ? 1 : 0; 42366868Sadrian 42466868Sadrian return which == IN_LIST ? 0 : 1; 42566868Sadrian} 42666868Sadrian 42766868Sadrian 42866868Sadrianstatic const char * 42992839Simpgetoptions(const char *type) 43066868Sadrian{ 43166868Sadrian struct entry *e; 43266868Sadrian 43370522Sphk TAILQ_FOREACH(e, &opthead, entries) 43466868Sadrian if (!strncmp(e->type, type, MFSNAMELEN)) 43566868Sadrian return e->options; 43666868Sadrian return ""; 43766868Sadrian} 43866868Sadrian 43966868Sadrian 44066868Sadrianstatic void 44192839Simpaddoption(char *optstr) 44266868Sadrian{ 44366868Sadrian char *newoptions; 44466868Sadrian struct entry *e; 44566868Sadrian 44666868Sadrian if ((newoptions = strchr(optstr, ':')) == NULL) 44766868Sadrian errx(1, "Invalid option string"); 44866868Sadrian 44966868Sadrian *newoptions++ = '\0'; 45066868Sadrian 45170522Sphk TAILQ_FOREACH(e, &opthead, entries) 45266868Sadrian if (!strncmp(e->type, optstr, MFSNAMELEN)) { 45366868Sadrian catopt(&e->options, newoptions); 45466868Sadrian return; 45566868Sadrian } 45666868Sadrian addentry(&opthead, optstr, newoptions); 45766868Sadrian} 45866868Sadrian 45966868Sadrian 46066868Sadrianstatic void 46192839Simpaddentry(struct fstypelist *list, const char *type, const char *opts) 46266868Sadrian{ 46366868Sadrian struct entry *e; 46466868Sadrian 46566868Sadrian e = emalloc(sizeof(struct entry)); 46666868Sadrian e->type = estrdup(type); 46766868Sadrian e->options = estrdup(opts); 46866868Sadrian TAILQ_INSERT_TAIL(list, e, entries); 46966868Sadrian} 47066868Sadrian 47166868Sadrian 47266868Sadrianstatic void 47392839Simpmaketypelist(char *fslist) 47466868Sadrian{ 47566868Sadrian char *ptr; 47666868Sadrian 47766868Sadrian if ((fslist == NULL) || (fslist[0] == '\0')) 47866868Sadrian errx(1, "empty type list"); 47966868Sadrian 48066868Sadrian if (fslist[0] == 'n' && fslist[1] == 'o') { 48166868Sadrian fslist += 2; 48266868Sadrian which = NOT_IN_LIST; 48366868Sadrian } 48466868Sadrian else 48566868Sadrian which = IN_LIST; 48666868Sadrian 48766868Sadrian while ((ptr = strsep(&fslist, ",")) != NULL) 48866868Sadrian addentry(&selhead, ptr, ""); 48966868Sadrian 49066868Sadrian} 49166868Sadrian 49266868Sadrian 49366868Sadrianstatic void 49492839Simpcatopt(char **sp, const char *o) 49566868Sadrian{ 49666868Sadrian char *s; 49766868Sadrian size_t i, j; 49866868Sadrian 49966868Sadrian s = *sp; 50066868Sadrian if (s) { 50166868Sadrian i = strlen(s); 50266868Sadrian j = i + 1 + strlen(o) + 1; 50366868Sadrian s = erealloc(s, j); 50466868Sadrian (void)snprintf(s + i, j, ",%s", o); 50566868Sadrian } else 50666868Sadrian s = estrdup(o); 50766868Sadrian *sp = s; 50866868Sadrian} 50966868Sadrian 51066868Sadrian 51166868Sadrianstatic void 512241807Suqsmangle(char *opts, int *argcp, const char ** volatile *argvp, int *maxargcp) 51366868Sadrian{ 51466868Sadrian char *p, *s; 51566868Sadrian int argc, maxargc; 51666868Sadrian const char **argv; 51766868Sadrian 51866868Sadrian argc = *argcp; 51966868Sadrian argv = *argvp; 52066868Sadrian maxargc = *maxargcp; 52166868Sadrian 522241806Suqs for (s = opts; (p = strsep(&s, ",")) != NULL;) { 52366868Sadrian /* Always leave space for one more argument and the NULL. */ 52466868Sadrian if (argc >= maxargc - 3) { 52566868Sadrian maxargc <<= 1; 52666868Sadrian argv = erealloc(argv, maxargc * sizeof(char *)); 52766868Sadrian } 52866868Sadrian if (*p != '\0') { 52966868Sadrian if (*p == '-') { 53066868Sadrian argv[argc++] = p; 53166868Sadrian p = strchr(p, '='); 53266868Sadrian if (p) { 53366868Sadrian *p = '\0'; 53466868Sadrian argv[argc++] = p+1; 53566868Sadrian } 53666868Sadrian } else { 53766868Sadrian argv[argc++] = "-o"; 53866868Sadrian argv[argc++] = p; 53966868Sadrian } 54066868Sadrian } 54166868Sadrian } 54266868Sadrian 54366868Sadrian *argcp = argc; 54466868Sadrian *argvp = argv; 54566868Sadrian *maxargcp = maxargc; 54666868Sadrian} 54766868Sadrian 548241807Suqsstatic const char * 549274770Simpgetfstype(const char *str) 55066868Sadrian{ 551274770Simp struct diocgattr_arg attr; 552274770Simp int fd, i; 55366868Sadrian 55466868Sadrian if ((fd = open(str, O_RDONLY)) == -1) 55566868Sadrian err(1, "cannot open `%s'", str); 55666868Sadrian 557274770Simp strncpy(attr.name, "PART::type", sizeof(attr.name)); 558274770Simp memset(&attr.value, 0, sizeof(attr.value)); 559274770Simp attr.len = sizeof(attr.value); 560274770Simp if (ioctl(fd, DIOCGATTR, &attr) == -1) { 561199582Snetchild (void) close(fd); 562106254Sphk return(NULL); 563199582Snetchild } 56466868Sadrian (void) close(fd); 565274770Simp for (i = 0; ptype_map[i].ptype != NULL; i++) 566274770Simp if (strstr(attr.value.str, ptype_map[i].ptype) != NULL) 567274770Simp return (ptype_map[i].name); 568274770Simp return (NULL); 56966868Sadrian} 57066868Sadrian 57166868Sadrian 57266868Sadrianstatic void 57392839Simpusage(void) 57466868Sadrian{ 57566868Sadrian static const char common[] = 576226711Ssobomax "[-Cdfnpvy] [-B | -F] [-T fstype:fsoptions] [-t fstype] [-c fstab]"; 57766868Sadrian 578141611Sru (void)fprintf(stderr, "usage: %s %s [special | node] ...\n", 57993102Smarkm getprogname(), common); 58066868Sadrian exit(1); 58166868Sadrian} 582