fsck.c revision 92839
166868Sadrian/* $NetBSD: fsck.c,v 1.21 1999/04/22 04:20:53 abs Exp $ */ 266868Sadrian 366868Sadrian/* 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. 1666868Sadrian * 3. All advertising materials mentioning features or use of this software 1766868Sadrian * must display the following acknowledgement: 1866868Sadrian * This product includes software developed by the University of 1966868Sadrian * California, Berkeley and its contributors. 2066868Sadrian * 4. Neither the name of the University nor the names of its contributors 2166868Sadrian * may be used to endorse or promote products derived from this software 2266868Sadrian * without specific prior written permission. 2366868Sadrian * 2466868Sadrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2566868Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2666868Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2766868Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2866868Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2966868Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3066868Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3166868Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3266868Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3366868Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3466868Sadrian * SUCH DAMAGE. 3566868Sadrian * 3666868Sadrian * From: @(#)mount.c 8.19 (Berkeley) 4/19/94 3766918Sobrien * From: $NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp 3866918Sobrien * $NetBSD: fsck.c,v 1.21 1999/04/22 04:20:53 abs Exp $ 3966868Sadrian */ 4066868Sadrian 4166868Sadrian#include <sys/cdefs.h> 4266868Sadrian#ifndef lint 4366918Sobrien__RCSID("$FreeBSD: head/sbin/fsck/fsck.c 92839 2002-03-20 22:57:10Z imp $"); 4466868Sadrian#endif /* not lint */ 4566868Sadrian 4666868Sadrian#include <sys/param.h> 4766868Sadrian#include <sys/mount.h> 4866868Sadrian#include <sys/queue.h> 4966868Sadrian#include <sys/wait.h> 5066868Sadrian#define FSTYPENAMES 5166868Sadrian#define DKTYPENAMES 5266868Sadrian#include <sys/disklabel.h> 5366868Sadrian#include <sys/ioctl.h> 5466868Sadrian 5566868Sadrian#include <err.h> 5666868Sadrian#include <errno.h> 5766868Sadrian#include <fstab.h> 5866868Sadrian#include <fcntl.h> 5966868Sadrian#include <paths.h> 6066868Sadrian#include <signal.h> 6166868Sadrian#include <stdio.h> 6266868Sadrian#include <stdlib.h> 6366868Sadrian#include <string.h> 6466868Sadrian#include <unistd.h> 6566868Sadrian 6666868Sadrian#include "pathnames.h" 6766868Sadrian#include "fsutil.h" 6866868Sadrian 6966868Sadrianstatic enum { IN_LIST, NOT_IN_LIST } which = NOT_IN_LIST; 7066868Sadrian 7166868SadrianTAILQ_HEAD(fstypelist, entry) opthead, selhead; 7266868Sadrian 7366868Sadrianstruct entry { 7466868Sadrian char *type; 7566868Sadrian char *options; 7666868Sadrian TAILQ_ENTRY(entry) entries; 7766868Sadrian}; 7866868Sadrian 7966868Sadrianstatic char *options = NULL; 8066868Sadrianstatic int flags = 0; 8175936Smckusickstatic int forceflag = 0; 8266868Sadrian 8392839Simpstatic int checkfs(const char *, const char *, const char *, char *, pid_t *); 8492839Simpstatic int selected(const char *); 8592839Simpstatic void addoption(char *); 8692839Simpstatic const char *getoptions(const char *); 8792839Simpstatic void addentry(struct fstypelist *, const char *, const char *); 8892839Simpstatic void maketypelist(char *); 8992839Simpstatic void catopt(char **, const char *); 9092839Simpstatic void mangle(char *, int *, const char ***, int *); 9192839Simpstatic const char *getfslab(const char *); 9292839Simpstatic void usage(void) __dead2; 9392839Simpstatic int isok(struct fstab *); 9466868Sadrian 9566868Sadrianint 9692839Simpmain(int argc, char *argv[]) 9766868Sadrian{ 9866868Sadrian struct fstab *fs; 9966868Sadrian int i, rval = 0; 10066868Sadrian const char *vfstype = NULL; 10166868Sadrian char globopt[3]; 10266868Sadrian 10366868Sadrian globopt[0] = '-'; 10466868Sadrian globopt[2] = '\0'; 10566868Sadrian 10666868Sadrian TAILQ_INIT(&selhead); 10766868Sadrian TAILQ_INIT(&opthead); 10866868Sadrian 10975936Smckusick while ((i = getopt(argc, argv, "BdvpfFnyl:t:T:")) != -1) 11066868Sadrian switch (i) { 11175936Smckusick case 'B': 11275936Smckusick if (flags & CHECK_BACKGRD) 11375936Smckusick errx(1, "Cannot specify -B and -F."); 11475936Smckusick flags |= DO_BACKGRD; 11575936Smckusick break; 11675936Smckusick 11766868Sadrian case 'd': 11866868Sadrian flags |= CHECK_DEBUG; 11966868Sadrian break; 12066868Sadrian 12166868Sadrian case 'v': 12266868Sadrian flags |= CHECK_VERBOSE; 12366868Sadrian break; 12466868Sadrian 12575936Smckusick case 'F': 12675936Smckusick if (flags & DO_BACKGRD) 12775936Smckusick errx(1, "Cannot specify -B and -F."); 12875936Smckusick flags |= CHECK_BACKGRD; 12975936Smckusick break; 13075936Smckusick 13166868Sadrian case 'p': 13266868Sadrian flags |= CHECK_PREEN; 13366868Sadrian /*FALLTHROUGH*/ 13466868Sadrian case 'n': 13566868Sadrian case 'y': 13666868Sadrian globopt[1] = i; 13766868Sadrian catopt(&options, globopt); 13866868Sadrian break; 13966868Sadrian 14075936Smckusick case 'f': 14175936Smckusick forceflag = 1; 14275936Smckusick globopt[1] = i; 14375936Smckusick catopt(&options, globopt); 14475936Smckusick break; 14575936Smckusick 14666868Sadrian case 'l': 14775015Sphk warnx("Ignoring obsolete -l option\n"); 14866868Sadrian break; 14966868Sadrian 15066868Sadrian case 'T': 15166868Sadrian if (*optarg) 15266868Sadrian addoption(optarg); 15366868Sadrian break; 15466868Sadrian 15566868Sadrian case 't': 15670522Sphk if (!TAILQ_EMPTY(&selhead)) 15766868Sadrian errx(1, "only one -t option may be specified."); 15866868Sadrian 15966868Sadrian maketypelist(optarg); 16066868Sadrian vfstype = optarg; 16166868Sadrian break; 16266868Sadrian 16366868Sadrian case '?': 16466868Sadrian default: 16566868Sadrian usage(); 16666868Sadrian /* NOTREACHED */ 16766868Sadrian } 16866868Sadrian 16966868Sadrian argc -= optind; 17066868Sadrian argv += optind; 17166868Sadrian 17266868Sadrian if (argc == 0) 17375015Sphk return checkfstab(flags, isok, checkfs); 17466868Sadrian 17566868Sadrian#define BADTYPE(type) \ 17666868Sadrian (strcmp(type, FSTAB_RO) && \ 17766868Sadrian strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) 17866868Sadrian 17966868Sadrian 18066868Sadrian for (; argc--; argv++) { 18175936Smckusick const char *spec, *mntpt, *type, *cp; 18275936Smckusick char device[MAXPATHLEN]; 18375936Smckusick struct statfs *mntp; 18466868Sadrian 18566868Sadrian spec = *argv; 18666868Sadrian cp = strrchr(spec, '/'); 18766868Sadrian if (cp == 0) { 18866868Sadrian (void)snprintf(device, sizeof(device), "%s%s", 18966868Sadrian _PATH_DEV, spec); 19066868Sadrian spec = device; 19166868Sadrian } 19275936Smckusick mntp = getmntpt(spec); 19375936Smckusick if (mntp != NULL) { 19475936Smckusick spec = mntp->f_mntfromname; 19575936Smckusick mntpt = mntp->f_mntonname; 19675936Smckusick } 19766868Sadrian if ((fs = getfsfile(spec)) == NULL && 19866868Sadrian (fs = getfsspec(spec)) == NULL) { 19966868Sadrian if (vfstype == NULL) 20066868Sadrian vfstype = getfslab(spec); 20166868Sadrian type = vfstype; 20275936Smckusick devcheck(spec); 20375936Smckusick } else { 20466868Sadrian spec = fs->fs_spec; 20566868Sadrian type = fs->fs_vfstype; 20675936Smckusick mntpt = fs->fs_file; 20766868Sadrian if (BADTYPE(fs->fs_type)) 20866868Sadrian errx(1, "%s has unknown file system type.", 20966868Sadrian spec); 21066868Sadrian } 21175936Smckusick if ((flags & CHECK_BACKGRD) && 21275936Smckusick checkfs(type, spec, mntpt, "-F", NULL) == 0) { 21375936Smckusick printf("%s: DEFER FOR BACKGROUND CHECKING\n", *argv); 21475936Smckusick continue; 21575936Smckusick } 21675936Smckusick if ((flags & DO_BACKGRD) && forceflag == 0 && 21775936Smckusick checkfs(type, spec, mntpt, "-F", NULL) != 0) 21875936Smckusick continue; 21966868Sadrian 22075936Smckusick rval |= checkfs(type, spec, mntpt, NULL, NULL); 22166868Sadrian } 22266868Sadrian 22366868Sadrian return rval; 22466868Sadrian} 22566868Sadrian 22666868Sadrian 22775936Smckusickstatic int 22892839Simpisok(struct fstab *fs) 22966868Sadrian{ 23075936Smckusick int i; 23175936Smckusick 23266868Sadrian if (fs->fs_passno == 0) 23375936Smckusick return (0); 23466868Sadrian if (BADTYPE(fs->fs_type)) 23575936Smckusick return (0); 23666868Sadrian if (!selected(fs->fs_vfstype)) 23775936Smckusick return (0); 23875936Smckusick /* 23975936Smckusick * If the -B flag has been given, then process the needed 24075936Smckusick * background checks. Background checks cannot be run on 24175936Smckusick * filesystems that will be mounted read-only or that were 24275936Smckusick * not mounted at boot time (typically those marked `noauto'). 24375936Smckusick * If these basic tests are passed, check with the filesystem 24475936Smckusick * itself to see if it is willing to do background checking 24575936Smckusick * by invoking its check program with the -F flag. 24675936Smckusick */ 24775936Smckusick if (flags & DO_BACKGRD) { 24875936Smckusick if (!strcmp(fs->fs_type, FSTAB_RO)) 24975936Smckusick return (0); 25075936Smckusick if (getmntpt(fs->fs_spec) == NULL) 25175936Smckusick return (0); 25275936Smckusick if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", 0)) 25375936Smckusick return (0); 25475936Smckusick return (1); 25575936Smckusick } 25675936Smckusick /* 25775936Smckusick * If the -F flag has been given, then consider deferring the 25875936Smckusick * check to background. Background checks cannot be run on 25975936Smckusick * filesystems that will be mounted read-only or that will 26075936Smckusick * not be mounted at boot time (e.g., marked `noauto'). If 26175936Smckusick * these basic tests are passed, check with the filesystem 26275936Smckusick * itself to see if it is willing to defer to background 26375936Smckusick * checking by invoking its check program with the -F flag. 26475936Smckusick */ 26575936Smckusick if ((flags & CHECK_BACKGRD) == 0 || !strcmp(fs->fs_type, FSTAB_RO)) 26675936Smckusick return (1); 26775936Smckusick for (i = strlen(fs->fs_mntops) - 6; i >= 0; i--) 26875936Smckusick if (!strncmp(&fs->fs_mntops[i], "noauto", 6)) 26975936Smckusick break; 27075936Smckusick if (i >= 0) 27175936Smckusick return (1); 27275936Smckusick if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", NULL) != 0) 27375936Smckusick return (1); 27475936Smckusick printf("%s: DEFER FOR BACKGROUND CHECKING\n", fs->fs_spec); 27575936Smckusick return (0); 27666868Sadrian} 27766868Sadrian 27866868Sadrian 27966868Sadrianstatic int 28092839Simpcheckfs(const char *pvfstype, const char *spec, const char *mntpt, 28192839Simp char *auxopt, pid_t *pidp) 28266868Sadrian{ 28366868Sadrian /* List of directories containing fsck_xxx subcommands. */ 28466868Sadrian static const char *edirs[] = { 28566868Sadrian _PATH_SBIN, 28666868Sadrian _PATH_USRSBIN, 28766868Sadrian NULL 28866868Sadrian }; 28966868Sadrian const char **argv, **edir; 29066868Sadrian pid_t pid; 29166868Sadrian int argc, i, status, maxargc; 29266868Sadrian char *optbuf, execname[MAXPATHLEN + 1], execbase[MAXPATHLEN]; 29366868Sadrian char *vfstype = NULL; 29466868Sadrian const char *extra = NULL; 29566868Sadrian 29666868Sadrian#ifdef __GNUC__ 29766868Sadrian /* Avoid vfork clobbering */ 29866868Sadrian (void) &optbuf; 29966868Sadrian (void) &vfstype; 30066868Sadrian#endif 30166868Sadrian /* 30266868Sadrian * We convert the vfstype to lowercase and any spaces to underscores 30366868Sadrian * to not confuse the issue 30466868Sadrian */ 30566868Sadrian vfstype = strdup(pvfstype); 30666868Sadrian if (vfstype == NULL) 30766868Sadrian perror("strdup(pvfstype)"); 30866868Sadrian for (i = 0; i < strlen(vfstype); i++) { 30966868Sadrian vfstype[i] = tolower(vfstype[i]); 31066868Sadrian if (vfstype[i] == ' ') 31166868Sadrian vfstype[i] = '_'; 31266868Sadrian } 31366868Sadrian 31466868Sadrian extra = getoptions(vfstype); 31566868Sadrian optbuf = NULL; 31666868Sadrian if (options) 31766868Sadrian catopt(&optbuf, options); 31866868Sadrian if (extra) 31966868Sadrian catopt(&optbuf, extra); 32075936Smckusick if (auxopt) 32175936Smckusick catopt(&optbuf, auxopt); 32275936Smckusick else if (flags & DO_BACKGRD) 32375936Smckusick catopt(&optbuf, "-B"); 32466868Sadrian 32566868Sadrian maxargc = 64; 32666868Sadrian argv = emalloc(sizeof(char *) * maxargc); 32766868Sadrian 32866868Sadrian (void) snprintf(execbase, sizeof(execbase), "fsck_%s", vfstype); 32966868Sadrian argc = 0; 33066868Sadrian argv[argc++] = execbase; 33166868Sadrian if (optbuf) 33266868Sadrian mangle(optbuf, &argc, &argv, &maxargc); 33366868Sadrian argv[argc++] = spec; 33466868Sadrian argv[argc] = NULL; 33566868Sadrian 33666868Sadrian if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) { 33766868Sadrian (void)printf("start %s %swait", mntpt, 33866868Sadrian pidp ? "no" : ""); 33966868Sadrian for (i = 0; i < argc; i++) 34066868Sadrian (void)printf(" %s", argv[i]); 34166868Sadrian (void)printf("\n"); 34266868Sadrian } 34366868Sadrian 34466868Sadrian switch (pid = vfork()) { 34566868Sadrian case -1: /* Error. */ 34666868Sadrian warn("vfork"); 34766868Sadrian if (optbuf) 34866868Sadrian free(optbuf); 34966868Sadrian free(vfstype); 35066868Sadrian return (1); 35166868Sadrian 35266868Sadrian case 0: /* Child. */ 35375936Smckusick if ((flags & CHECK_DEBUG) && auxopt == NULL) 35466868Sadrian _exit(0); 35566868Sadrian 35666868Sadrian /* Go find an executable. */ 35766868Sadrian edir = edirs; 35866868Sadrian do { 35966868Sadrian (void)snprintf(execname, 36066868Sadrian sizeof(execname), "%s/%s", *edir, execbase); 36166868Sadrian execv(execname, (char * const *)argv); 36266868Sadrian if (errno != ENOENT) { 36366868Sadrian if (spec) 36466868Sadrian warn("exec %s for %s", execname, spec); 36566868Sadrian else 36666868Sadrian warn("exec %s", execname); 36766868Sadrian } 36866868Sadrian } while (*++edir != NULL); 36966868Sadrian 37066868Sadrian if (errno == ENOENT) { 37166868Sadrian if (spec) 37266868Sadrian warn("exec %s for %s", execname, spec); 37366868Sadrian else 37466868Sadrian warn("exec %s", execname); 37566868Sadrian } 37666868Sadrian _exit(1); 37766868Sadrian /* NOTREACHED */ 37866868Sadrian 37966868Sadrian default: /* Parent. */ 38066868Sadrian if (optbuf) 38166868Sadrian free(optbuf); 38266868Sadrian 38366868Sadrian free(vfstype); 38466868Sadrian 38566868Sadrian if (pidp) { 38666868Sadrian *pidp = pid; 38766868Sadrian return 0; 38866868Sadrian } 38966868Sadrian 39066868Sadrian if (waitpid(pid, &status, 0) < 0) { 39166868Sadrian warn("waitpid"); 39266868Sadrian return (1); 39366868Sadrian } 39466868Sadrian 39566868Sadrian if (WIFEXITED(status)) { 39666868Sadrian if (WEXITSTATUS(status) != 0) 39766868Sadrian return (WEXITSTATUS(status)); 39866868Sadrian } 39966868Sadrian else if (WIFSIGNALED(status)) { 40066868Sadrian warnx("%s: %s", spec, strsignal(WTERMSIG(status))); 40166868Sadrian return (1); 40266868Sadrian } 40366868Sadrian break; 40466868Sadrian } 40566868Sadrian 40666868Sadrian return (0); 40766868Sadrian} 40866868Sadrian 40966868Sadrian 41066868Sadrianstatic int 41192839Simpselected(const char *type) 41266868Sadrian{ 41366868Sadrian struct entry *e; 41466868Sadrian 41566868Sadrian /* If no type specified, it's always selected. */ 41670522Sphk TAILQ_FOREACH(e, &selhead, entries) 41766868Sadrian if (!strncmp(e->type, type, MFSNAMELEN)) 41866868Sadrian return which == IN_LIST ? 1 : 0; 41966868Sadrian 42066868Sadrian return which == IN_LIST ? 0 : 1; 42166868Sadrian} 42266868Sadrian 42366868Sadrian 42466868Sadrianstatic const char * 42592839Simpgetoptions(const char *type) 42666868Sadrian{ 42766868Sadrian struct entry *e; 42866868Sadrian 42970522Sphk TAILQ_FOREACH(e, &opthead, entries) 43066868Sadrian if (!strncmp(e->type, type, MFSNAMELEN)) 43166868Sadrian return e->options; 43266868Sadrian return ""; 43366868Sadrian} 43466868Sadrian 43566868Sadrian 43666868Sadrianstatic void 43792839Simpaddoption(char *optstr) 43866868Sadrian{ 43966868Sadrian char *newoptions; 44066868Sadrian struct entry *e; 44166868Sadrian 44266868Sadrian if ((newoptions = strchr(optstr, ':')) == NULL) 44366868Sadrian errx(1, "Invalid option string"); 44466868Sadrian 44566868Sadrian *newoptions++ = '\0'; 44666868Sadrian 44770522Sphk TAILQ_FOREACH(e, &opthead, entries) 44866868Sadrian if (!strncmp(e->type, optstr, MFSNAMELEN)) { 44966868Sadrian catopt(&e->options, newoptions); 45066868Sadrian return; 45166868Sadrian } 45266868Sadrian addentry(&opthead, optstr, newoptions); 45366868Sadrian} 45466868Sadrian 45566868Sadrian 45666868Sadrianstatic void 45792839Simpaddentry(struct fstypelist *list, const char *type, const char *opts) 45866868Sadrian{ 45966868Sadrian struct entry *e; 46066868Sadrian 46166868Sadrian e = emalloc(sizeof(struct entry)); 46266868Sadrian e->type = estrdup(type); 46366868Sadrian e->options = estrdup(opts); 46466868Sadrian TAILQ_INSERT_TAIL(list, e, entries); 46566868Sadrian} 46666868Sadrian 46766868Sadrian 46866868Sadrianstatic void 46992839Simpmaketypelist(char *fslist) 47066868Sadrian{ 47166868Sadrian char *ptr; 47266868Sadrian 47366868Sadrian if ((fslist == NULL) || (fslist[0] == '\0')) 47466868Sadrian errx(1, "empty type list"); 47566868Sadrian 47666868Sadrian if (fslist[0] == 'n' && fslist[1] == 'o') { 47766868Sadrian fslist += 2; 47866868Sadrian which = NOT_IN_LIST; 47966868Sadrian } 48066868Sadrian else 48166868Sadrian which = IN_LIST; 48266868Sadrian 48366868Sadrian while ((ptr = strsep(&fslist, ",")) != NULL) 48466868Sadrian addentry(&selhead, ptr, ""); 48566868Sadrian 48666868Sadrian} 48766868Sadrian 48866868Sadrian 48966868Sadrianstatic void 49092839Simpcatopt(char **sp, const char *o) 49166868Sadrian{ 49266868Sadrian char *s; 49366868Sadrian size_t i, j; 49466868Sadrian 49566868Sadrian s = *sp; 49666868Sadrian if (s) { 49766868Sadrian i = strlen(s); 49866868Sadrian j = i + 1 + strlen(o) + 1; 49966868Sadrian s = erealloc(s, j); 50066868Sadrian (void)snprintf(s + i, j, ",%s", o); 50166868Sadrian } else 50266868Sadrian s = estrdup(o); 50366868Sadrian *sp = s; 50466868Sadrian} 50566868Sadrian 50666868Sadrian 50766868Sadrianstatic void 50892839Simpmangle(char *options, int *argcp, const char ***argvp, int *maxargcp) 50966868Sadrian{ 51066868Sadrian char *p, *s; 51166868Sadrian int argc, maxargc; 51266868Sadrian const char **argv; 51366868Sadrian 51466868Sadrian argc = *argcp; 51566868Sadrian argv = *argvp; 51666868Sadrian maxargc = *maxargcp; 51766868Sadrian 51866868Sadrian for (s = options; (p = strsep(&s, ",")) != NULL;) { 51966868Sadrian /* Always leave space for one more argument and the NULL. */ 52066868Sadrian if (argc >= maxargc - 3) { 52166868Sadrian maxargc <<= 1; 52266868Sadrian argv = erealloc(argv, maxargc * sizeof(char *)); 52366868Sadrian } 52466868Sadrian if (*p != '\0') { 52566868Sadrian if (*p == '-') { 52666868Sadrian argv[argc++] = p; 52766868Sadrian p = strchr(p, '='); 52866868Sadrian if (p) { 52966868Sadrian *p = '\0'; 53066868Sadrian argv[argc++] = p+1; 53166868Sadrian } 53266868Sadrian } else { 53366868Sadrian argv[argc++] = "-o"; 53466868Sadrian argv[argc++] = p; 53566868Sadrian } 53666868Sadrian } 53766868Sadrian } 53866868Sadrian 53966868Sadrian *argcp = argc; 54066868Sadrian *argvp = argv; 54166868Sadrian *maxargcp = maxargc; 54266868Sadrian} 54366868Sadrian 54466868Sadrian 54566868Sadrianconst static char * 54692839Simpgetfslab(const char *str) 54766868Sadrian{ 54866868Sadrian struct disklabel dl; 54966868Sadrian int fd; 55066868Sadrian char p; 55166868Sadrian const char *vfstype; 55266868Sadrian u_char t; 55366868Sadrian 55466868Sadrian /* deduce the filesystem type from the disk label */ 55566868Sadrian if ((fd = open(str, O_RDONLY)) == -1) 55666868Sadrian err(1, "cannot open `%s'", str); 55766868Sadrian 55866868Sadrian if (ioctl(fd, DIOCGDINFO, &dl) == -1) 55966868Sadrian err(1, "cannot get disklabel for `%s'", str); 56066868Sadrian 56166868Sadrian (void) close(fd); 56266868Sadrian 56366868Sadrian p = str[strlen(str) - 1]; 56466868Sadrian 56566868Sadrian if ((p - 'a') >= dl.d_npartitions) 56666868Sadrian errx(1, "partition `%s' is not defined on disk", str); 56766868Sadrian 56866868Sadrian if ((t = dl.d_partitions[p - 'a'].p_fstype) >= FSMAXTYPES) 56966868Sadrian errx(1, "partition `%s' is not of a legal vfstype", 57066868Sadrian str); 57166868Sadrian 57266868Sadrian if ((vfstype = fstypenames[t]) == NULL) 57366868Sadrian errx(1, "vfstype `%s' on partition `%s' is not supported", 57466868Sadrian fstypenames[t], str); 57566868Sadrian 57666868Sadrian return vfstype; 57766868Sadrian} 57866868Sadrian 57966868Sadrian 58066868Sadrianstatic void 58192839Simpusage(void) 58266868Sadrian{ 58366868Sadrian extern char *__progname; 58466868Sadrian static const char common[] = 58576143Smckusick "[-BFdpvlyn] [-T fstype:fsoptions] [-t fstype]"; 58666868Sadrian 58766868Sadrian (void)fprintf(stderr, "Usage: %s %s [special|node]...\n", 58866868Sadrian __progname, common); 58966868Sadrian exit(1); 59066868Sadrian} 591