Home | History | Annotate | Line # | Download | only in fsck
fsck.c revision 1.9
      1  1.9  christos /*	$NetBSD: fsck.c,v 1.9 1996/12/07 19:09:11 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * Copyright (c) 1996 Christos Zoulas. All rights reserved.
      5  1.1  christos  * Copyright (c) 1980, 1989, 1993, 1994
      6  1.1  christos  *	The Regents of the University of California.  All rights reserved.
      7  1.1  christos  *
      8  1.1  christos  * Redistribution and use in source and binary forms, with or without
      9  1.1  christos  * modification, are permitted provided that the following conditions
     10  1.1  christos  * are met:
     11  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     12  1.1  christos  *    notice, this list of conditions and the following disclaimer.
     13  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     15  1.1  christos  *    documentation and/or other materials provided with the distribution.
     16  1.1  christos  * 3. All advertising materials mentioning features or use of this software
     17  1.1  christos  *    must display the following acknowledgement:
     18  1.1  christos  *	This product includes software developed by the University of
     19  1.1  christos  *	California, Berkeley and its contributors.
     20  1.1  christos  * 4. Neither the name of the University nor the names of its contributors
     21  1.1  christos  *    may be used to endorse or promote products derived from this software
     22  1.1  christos  *    without specific prior written permission.
     23  1.1  christos  *
     24  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  1.1  christos  * SUCH DAMAGE.
     35  1.1  christos  *
     36  1.1  christos  * From: @(#)mount.c	8.19 (Berkeley) 4/19/94
     37  1.1  christos  * From: NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp
     38  1.1  christos  *
     39  1.1  christos  */
     40  1.1  christos 
     41  1.9  christos static char rcsid[] = "$NetBSD: fsck.c,v 1.9 1996/12/07 19:09:11 christos Exp $";
     42  1.1  christos 
     43  1.1  christos #include <sys/param.h>
     44  1.1  christos #include <sys/mount.h>
     45  1.1  christos #include <sys/queue.h>
     46  1.1  christos #include <sys/wait.h>
     47  1.8  christos #define DKTYPENAMES
     48  1.8  christos #include <sys/disklabel.h>
     49  1.8  christos #include <sys/ioctl.h>
     50  1.1  christos 
     51  1.1  christos #include <err.h>
     52  1.1  christos #include <errno.h>
     53  1.1  christos #include <fstab.h>
     54  1.8  christos #include <fcntl.h>
     55  1.1  christos #include <signal.h>
     56  1.1  christos #include <stdio.h>
     57  1.1  christos #include <stdlib.h>
     58  1.1  christos #include <string.h>
     59  1.1  christos #include <unistd.h>
     60  1.1  christos 
     61  1.1  christos #include "pathnames.h"
     62  1.4  christos #include "fsutil.h"
     63  1.1  christos 
     64  1.2  christos static enum { IN_LIST, NOT_IN_LIST } which = NOT_IN_LIST;
     65  1.1  christos 
     66  1.2  christos TAILQ_HEAD(fstypelist, entry) opthead, selhead;
     67  1.1  christos 
     68  1.1  christos struct entry {
     69  1.1  christos 	char *type;
     70  1.2  christos 	char *options;
     71  1.1  christos 	TAILQ_ENTRY(entry) entries;
     72  1.1  christos };
     73  1.1  christos 
     74  1.4  christos static int maxrun = 0;
     75  1.2  christos static char *options = NULL;
     76  1.4  christos static int flags = 0;
     77  1.2  christos 
     78  1.2  christos int main __P((int, char *[]));
     79  1.1  christos 
     80  1.5  christos static int checkfs __P((const char *, const char *, const char *, void *,
     81  1.5  christos     pid_t *));
     82  1.1  christos static int selected __P((const char *));
     83  1.2  christos static void addoption __P((char *));
     84  1.2  christos static const char *getoptions __P((const char *));
     85  1.2  christos static void addentry __P((struct fstypelist *, const char *, const char *));
     86  1.1  christos static void maketypelist __P((char *));
     87  1.2  christos static char *catopt __P((char *, const char *, int));
     88  1.7  christos static void mangle __P((char *, int *, const char ***, int *));
     89  1.8  christos static char *getfslab __P((const char *));
     90  1.1  christos static void usage __P((void));
     91  1.4  christos static void *isok __P((struct fstab *));
     92  1.1  christos 
     93  1.1  christos int
     94  1.1  christos main(argc, argv)
     95  1.1  christos 	int argc;
     96  1.2  christos 	char *argv[];
     97  1.1  christos {
     98  1.1  christos 	struct fstab *fs;
     99  1.1  christos 	int i, rval = 0;
    100  1.1  christos 	char *vfstype = NULL;
    101  1.7  christos 	char globopt[3];
    102  1.7  christos 
    103  1.7  christos 	globopt[0] = '-';
    104  1.7  christos 	globopt[2] = '\0';
    105  1.1  christos 
    106  1.2  christos 	TAILQ_INIT(&selhead);
    107  1.2  christos 	TAILQ_INIT(&opthead);
    108  1.2  christos 
    109  1.7  christos 	while ((i = getopt(argc, argv, "dvpfnyl:t:T:")) != -1)
    110  1.1  christos 		switch (i) {
    111  1.1  christos 		case 'd':
    112  1.4  christos 			flags |= CHECK_DEBUG;
    113  1.1  christos 			break;
    114  1.1  christos 
    115  1.1  christos 		case 'v':
    116  1.4  christos 			flags |= CHECK_VERBOSE;
    117  1.1  christos 			break;
    118  1.1  christos 
    119  1.7  christos 		case 'p':
    120  1.7  christos 			flags |= CHECK_PREEN;
    121  1.7  christos 			/*FALLTHROUGH*/
    122  1.7  christos 		case 'n':
    123  1.7  christos 		case 'f':
    124  1.1  christos 		case 'y':
    125  1.7  christos 			globopt[1] = i;
    126  1.7  christos 			options = catopt(options, globopt, 1);
    127  1.2  christos 			break;
    128  1.2  christos 
    129  1.2  christos 		case 'l':
    130  1.2  christos 			maxrun = atoi(optarg);
    131  1.1  christos 			break;
    132  1.1  christos 
    133  1.2  christos 		case 'T':
    134  1.1  christos 			if (*optarg)
    135  1.2  christos 				addoption(optarg);
    136  1.1  christos 			break;
    137  1.1  christos 
    138  1.1  christos 		case 't':
    139  1.2  christos 			if (selhead.tqh_first != NULL)
    140  1.1  christos 				errx(1, "only one -t option may be specified.");
    141  1.2  christos 
    142  1.1  christos 			maketypelist(optarg);
    143  1.1  christos 			vfstype = optarg;
    144  1.1  christos 			break;
    145  1.1  christos 
    146  1.1  christos 		case '?':
    147  1.1  christos 		default:
    148  1.1  christos 			usage();
    149  1.1  christos 			/* NOTREACHED */
    150  1.1  christos 		}
    151  1.1  christos 
    152  1.1  christos 	argc -= optind;
    153  1.1  christos 	argv += optind;
    154  1.1  christos 
    155  1.2  christos 	if (argc == 0)
    156  1.4  christos 		return checkfstab(flags, maxrun, isok, checkfs);
    157  1.2  christos 
    158  1.1  christos #define	BADTYPE(type)							\
    159  1.1  christos 	(strcmp(type, FSTAB_RO) &&					\
    160  1.1  christos 	    strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
    161  1.1  christos 
    162  1.1  christos 
    163  1.1  christos 	for (; argc--; argv++) {
    164  1.1  christos 		char *spec, *type;
    165  1.1  christos 
    166  1.1  christos 		if ((fs = getfsfile(*argv)) == NULL &&
    167  1.1  christos 		    (fs = getfsspec(*argv)) == NULL) {
    168  1.1  christos 			if (vfstype == NULL)
    169  1.8  christos 				vfstype = getfslab(*argv);
    170  1.1  christos 			spec = *argv;
    171  1.1  christos 			type = vfstype;
    172  1.1  christos 		}
    173  1.1  christos 		else {
    174  1.1  christos 			spec = fs->fs_spec;
    175  1.1  christos 			type = fs->fs_vfstype;
    176  1.1  christos 			if (BADTYPE(fs->fs_type))
    177  1.1  christos 				errx(1, "%s has unknown file system type.",
    178  1.1  christos 				    *argv);
    179  1.1  christos 		}
    180  1.1  christos 
    181  1.6  christos 		rval |= checkfs(type, blockcheck(spec), *argv, NULL, NULL);
    182  1.1  christos 	}
    183  1.1  christos 
    184  1.1  christos 	return rval;
    185  1.1  christos }
    186  1.1  christos 
    187  1.2  christos 
    188  1.4  christos static void *
    189  1.2  christos isok(fs)
    190  1.2  christos 	struct fstab *fs;
    191  1.2  christos {
    192  1.2  christos 	if (fs->fs_passno == 0)
    193  1.4  christos 		return NULL;
    194  1.2  christos 
    195  1.2  christos 	if (BADTYPE(fs->fs_type))
    196  1.4  christos 		return NULL;
    197  1.2  christos 
    198  1.2  christos 	if (!selected(fs->fs_vfstype))
    199  1.4  christos 		return NULL;
    200  1.2  christos 
    201  1.4  christos 	return fs;
    202  1.2  christos }
    203  1.2  christos 
    204  1.2  christos 
    205  1.1  christos static int
    206  1.6  christos checkfs(vfstype, spec, mntpt, auxarg, pidp)
    207  1.4  christos 	const char *vfstype, *spec, *mntpt;
    208  1.5  christos 	void *auxarg;
    209  1.5  christos 	pid_t *pidp;
    210  1.1  christos {
    211  1.1  christos 	/* List of directories containing fsck_xxx subcommands. */
    212  1.1  christos 	static const char *edirs[] = {
    213  1.1  christos 		_PATH_SBIN,
    214  1.1  christos 		_PATH_USRSBIN,
    215  1.1  christos 		NULL
    216  1.1  christos 	};
    217  1.8  christos 	char execbase[MAXPATHLEN];
    218  1.7  christos 	const char **argv, **edir;
    219  1.1  christos 	pid_t pid;
    220  1.8  christos 	int argc = 1, i, status, maxargc;
    221  1.1  christos 	char *optbuf = NULL, execname[MAXPATHLEN + 1];
    222  1.2  christos 	const char *extra = getoptions(vfstype);
    223  1.1  christos 
    224  1.8  christos 
    225  1.1  christos #ifdef __GNUC__
    226  1.1  christos 	/* Avoid vfork clobbering */
    227  1.1  christos 	(void) &optbuf;
    228  1.8  christos 	(void) &vfstype;
    229  1.1  christos #endif
    230  1.1  christos 
    231  1.3       cgd 	if (strcmp(vfstype, "ufs") == 0)
    232  1.3       cgd 		vfstype = MOUNT_UFS;
    233  1.3       cgd 
    234  1.7  christos 	maxargc = 100;
    235  1.7  christos 	argv = emalloc(sizeof(char *) * maxargc);
    236  1.7  christos 
    237  1.8  christos 	/* construct basename of executable and argv[0] simultaneously */
    238  1.9  christos 	(void) snprintf(execbase, sizeof(execbase), "fsck_%s", vfstype);
    239  1.8  christos 	argv[0] = vfstype;
    240  1.2  christos 
    241  1.2  christos 	if (options) {
    242  1.2  christos 		if (extra != NULL)
    243  1.2  christos 			optbuf = catopt(options, extra, 0);
    244  1.2  christos 		else
    245  1.2  christos 			optbuf = estrdup(options);
    246  1.2  christos 	}
    247  1.2  christos 	else if (extra)
    248  1.2  christos 		optbuf = estrdup(extra);
    249  1.2  christos 
    250  1.2  christos 	if (optbuf)
    251  1.7  christos 		mangle(optbuf, &argc, &argv, &maxargc);
    252  1.2  christos 
    253  1.2  christos 	argv[argc++] = spec;
    254  1.7  christos 	argv[argc] = NULL;
    255  1.1  christos 
    256  1.4  christos 	if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) {
    257  1.8  christos 		(void)printf("start %s %swait", mntpt,
    258  1.8  christos 			pidp ? "no" : "");
    259  1.8  christos 		for (i = 0; i < argc; i++)
    260  1.1  christos 			(void)printf(" %s", argv[i]);
    261  1.1  christos 		(void)printf("\n");
    262  1.1  christos 	}
    263  1.1  christos 
    264  1.1  christos 	switch (pid = vfork()) {
    265  1.1  christos 	case -1:				/* Error. */
    266  1.1  christos 		warn("vfork");
    267  1.1  christos 		if (optbuf)
    268  1.1  christos 			free(optbuf);
    269  1.1  christos 		return (1);
    270  1.1  christos 
    271  1.1  christos 	case 0:					/* Child. */
    272  1.4  christos 		if (flags & CHECK_DEBUG)
    273  1.2  christos 			_exit(0);
    274  1.2  christos 
    275  1.1  christos 		/* Go find an executable. */
    276  1.1  christos 		edir = edirs;
    277  1.1  christos 		do {
    278  1.1  christos 			(void)snprintf(execname,
    279  1.8  christos 			    sizeof(execname), "%s/%s", *edir, execbase);
    280  1.1  christos 			execv(execname, (char * const *)argv);
    281  1.1  christos 			if (errno != ENOENT)
    282  1.1  christos 				if (spec)
    283  1.1  christos 					warn("exec %s for %s", execname, spec);
    284  1.1  christos 				else
    285  1.1  christos 					warn("exec %s", execname);
    286  1.1  christos 		} while (*++edir != NULL);
    287  1.1  christos 
    288  1.1  christos 		if (errno == ENOENT)
    289  1.1  christos 			if (spec)
    290  1.1  christos 				warn("exec %s for %s", execname, spec);
    291  1.1  christos 			else
    292  1.1  christos 				warn("exec %s", execname);
    293  1.8  christos 		_exit(1);
    294  1.1  christos 		/* NOTREACHED */
    295  1.1  christos 
    296  1.1  christos 	default:				/* Parent. */
    297  1.1  christos 		if (optbuf)
    298  1.1  christos 			free(optbuf);
    299  1.1  christos 
    300  1.2  christos 		if (pidp) {
    301  1.2  christos 			*pidp = pid;
    302  1.2  christos 			return 0;
    303  1.2  christos 		}
    304  1.2  christos 
    305  1.1  christos 		if (waitpid(pid, &status, 0) < 0) {
    306  1.1  christos 			warn("waitpid");
    307  1.1  christos 			return (1);
    308  1.1  christos 		}
    309  1.1  christos 
    310  1.1  christos 		if (WIFEXITED(status)) {
    311  1.1  christos 			if (WEXITSTATUS(status) != 0)
    312  1.1  christos 				return (WEXITSTATUS(status));
    313  1.1  christos 		}
    314  1.1  christos 		else if (WIFSIGNALED(status)) {
    315  1.1  christos 			warnx("%s: %s", spec, strsignal(WTERMSIG(status)));
    316  1.1  christos 			return (1);
    317  1.1  christos 		}
    318  1.1  christos 		break;
    319  1.1  christos 	}
    320  1.1  christos 
    321  1.1  christos 	return (0);
    322  1.1  christos }
    323  1.1  christos 
    324  1.1  christos 
    325  1.1  christos static int
    326  1.1  christos selected(type)
    327  1.1  christos 	const char *type;
    328  1.1  christos {
    329  1.1  christos 	struct entry *e;
    330  1.1  christos 
    331  1.1  christos 	/* If no type specified, it's always selected. */
    332  1.2  christos 	for (e = selhead.tqh_first; e != NULL; e = e->entries.tqe_next)
    333  1.1  christos 		if (!strncmp(e->type, type, MFSNAMELEN))
    334  1.1  christos 			return which == IN_LIST ? 1 : 0;
    335  1.1  christos 
    336  1.1  christos 	return which == IN_LIST ? 0 : 1;
    337  1.1  christos }
    338  1.1  christos 
    339  1.1  christos 
    340  1.2  christos static const char *
    341  1.2  christos getoptions(type)
    342  1.1  christos 	const char *type;
    343  1.1  christos {
    344  1.1  christos 	struct entry *e;
    345  1.1  christos 
    346  1.2  christos 	for (e = opthead.tqh_first; e != NULL; e = e->entries.tqe_next)
    347  1.2  christos 		if (!strncmp(e->type, type, MFSNAMELEN))
    348  1.2  christos 			return e->options;
    349  1.2  christos 	return "";
    350  1.1  christos }
    351  1.1  christos 
    352  1.1  christos 
    353  1.1  christos static void
    354  1.2  christos addoption(optstr)
    355  1.2  christos 	char *optstr;
    356  1.1  christos {
    357  1.2  christos 	char *newoptions;
    358  1.1  christos 	struct entry *e;
    359  1.1  christos 
    360  1.2  christos 	if ((newoptions = strchr(optstr, ':')) == NULL)
    361  1.2  christos 		errx(1, "Invalid option string");
    362  1.2  christos 
    363  1.2  christos 	*newoptions++ = '\0';
    364  1.2  christos 
    365  1.2  christos 	for (e = opthead.tqh_first; e != NULL; e = e->entries.tqe_next)
    366  1.2  christos 		if (!strncmp(e->type, optstr, MFSNAMELEN)) {
    367  1.2  christos 			e->options = catopt(e->options, newoptions, 1);
    368  1.1  christos 			return;
    369  1.1  christos 		}
    370  1.2  christos 	addentry(&opthead, optstr, newoptions);
    371  1.1  christos }
    372  1.1  christos 
    373  1.1  christos 
    374  1.1  christos static void
    375  1.2  christos addentry(list, type, opts)
    376  1.2  christos 	struct fstypelist *list;
    377  1.1  christos 	const char *type;
    378  1.2  christos 	const char *opts;
    379  1.1  christos {
    380  1.2  christos 	struct entry *e;
    381  1.2  christos 
    382  1.2  christos 	e = emalloc(sizeof(struct entry));
    383  1.2  christos 	e->type = estrdup(type);
    384  1.2  christos 	e->options = estrdup(opts);
    385  1.2  christos 	TAILQ_INSERT_TAIL(list, e, entries);
    386  1.1  christos }
    387  1.1  christos 
    388  1.1  christos 
    389  1.1  christos static void
    390  1.1  christos maketypelist(fslist)
    391  1.1  christos 	char *fslist;
    392  1.1  christos {
    393  1.1  christos 	char *ptr;
    394  1.1  christos 
    395  1.1  christos 	if ((fslist == NULL) || (fslist[0] == '\0'))
    396  1.1  christos 		errx(1, "empty type list");
    397  1.1  christos 
    398  1.1  christos 	if (fslist[0] == 'n' && fslist[1] == 'o') {
    399  1.1  christos 		fslist += 2;
    400  1.1  christos 		which = NOT_IN_LIST;
    401  1.1  christos 	}
    402  1.1  christos 	else
    403  1.1  christos 		which = IN_LIST;
    404  1.1  christos 
    405  1.1  christos 	while ((ptr = strsep(&fslist, ",")) != NULL)
    406  1.2  christos 		addentry(&selhead, ptr, "");
    407  1.1  christos 
    408  1.1  christos }
    409  1.1  christos 
    410  1.1  christos 
    411  1.1  christos static char *
    412  1.2  christos catopt(s0, s1, fr)
    413  1.1  christos 	char *s0;
    414  1.1  christos 	const char *s1;
    415  1.2  christos 	int fr;
    416  1.1  christos {
    417  1.1  christos 	size_t i;
    418  1.1  christos 	char *cp;
    419  1.1  christos 
    420  1.1  christos 	if (s0 && *s0) {
    421  1.1  christos 		i = strlen(s0) + strlen(s1) + 1 + 1;
    422  1.1  christos 		cp = emalloc(i);
    423  1.1  christos 		(void)snprintf(cp, i, "%s,%s", s0, s1);
    424  1.1  christos 	}
    425  1.1  christos 	else
    426  1.1  christos 		cp = estrdup(s1);
    427  1.1  christos 
    428  1.2  christos 	if (s0 && fr)
    429  1.1  christos 		free(s0);
    430  1.1  christos 	return (cp);
    431  1.1  christos }
    432  1.1  christos 
    433  1.1  christos 
    434  1.1  christos static void
    435  1.7  christos mangle(opts, argcp, argvp, maxargcp)
    436  1.2  christos 	char *opts;
    437  1.1  christos 	int *argcp;
    438  1.7  christos 	const char ***argvp;
    439  1.7  christos 	int *maxargcp;
    440  1.1  christos {
    441  1.1  christos 	char *p, *s;
    442  1.7  christos 	int argc = *argcp, maxargc = *maxargcp;
    443  1.7  christos 	const char **argv = *argvp;
    444  1.1  christos 
    445  1.1  christos 	argc = *argcp;
    446  1.7  christos 	maxargc = *maxargcp;
    447  1.7  christos 
    448  1.7  christos 	for (s = opts; (p = strsep(&s, ",")) != NULL;) {
    449  1.7  christos 		/* always leave space for one more argument and the NULL */
    450  1.7  christos 		if (argc >= maxargc - 3) {
    451  1.7  christos 			maxargc += 50;
    452  1.7  christos 			argv = erealloc(argv, maxargc * sizeof(char *));
    453  1.7  christos 		}
    454  1.1  christos 		if (*p != '\0')
    455  1.1  christos 			if (*p == '-') {
    456  1.1  christos 				argv[argc++] = p;
    457  1.1  christos 				p = strchr(p, '=');
    458  1.1  christos 				if (p) {
    459  1.1  christos 					*p = '\0';
    460  1.1  christos 					argv[argc++] = p+1;
    461  1.1  christos 				}
    462  1.1  christos 			}
    463  1.1  christos 			else {
    464  1.1  christos 				argv[argc++] = "-o";
    465  1.1  christos 				argv[argc++] = p;
    466  1.1  christos 			}
    467  1.7  christos 	}
    468  1.1  christos 
    469  1.1  christos 	*argcp = argc;
    470  1.7  christos 	*argvp = argv;
    471  1.7  christos 	*maxargcp = maxargc;
    472  1.1  christos }
    473  1.8  christos 
    474  1.8  christos 
    475  1.8  christos /* Maybe this belongs to <sys/disklabel.h> */
    476  1.8  christos static char *fscknames[] = {
    477  1.8  christos 	NULL,
    478  1.8  christos 	NULL,
    479  1.8  christos 	NULL,
    480  1.8  christos 	NULL,
    481  1.8  christos 	NULL,
    482  1.8  christos 	NULL,
    483  1.8  christos 	NULL,
    484  1.8  christos 	"ffs",
    485  1.8  christos 	"msdos",
    486  1.8  christos 	NULL,
    487  1.8  christos 	NULL,
    488  1.8  christos 	NULL,
    489  1.8  christos 	NULL,
    490  1.8  christos 	NULL,
    491  1.8  christos 	NULL,
    492  1.8  christos 	NULL,
    493  1.8  christos 	NULL,
    494  1.8  christos 	NULL
    495  1.8  christos };
    496  1.8  christos 
    497  1.8  christos 
    498  1.8  christos static char *
    499  1.8  christos getfslab(str)
    500  1.8  christos 	const char *str;
    501  1.8  christos {
    502  1.8  christos 	struct disklabel dl;
    503  1.8  christos 	int fd;
    504  1.8  christos 	char p, *vfstype;
    505  1.8  christos 	u_char t;
    506  1.8  christos 
    507  1.8  christos 	/* deduce the filesystem type from the disk label */
    508  1.8  christos 	if ((fd = open(str, O_RDONLY)) == -1)
    509  1.8  christos 		err(1, "cannot open `%s'", str);
    510  1.8  christos 
    511  1.8  christos 	if (ioctl(fd, DIOCGDINFO, &dl) == -1)
    512  1.8  christos 		err(1, "cannot get disklabel for `%s'", str);
    513  1.8  christos 
    514  1.8  christos 	(void) close(fd);
    515  1.8  christos 
    516  1.8  christos 	p = str[strlen(str) - 1];
    517  1.8  christos 
    518  1.8  christos 	if ((p - 'a') >= dl.d_npartitions)
    519  1.8  christos 		errx(1, "partition `%s' is not defined on disk", str);
    520  1.8  christos 
    521  1.8  christos 	if ((t = dl.d_partitions[p - 'a'].p_fstype) >= DKMAXTYPES)
    522  1.8  christos 		errx(1, "partition `%s' is not of a legal vfstype",
    523  1.8  christos 		    p, str);
    524  1.8  christos 
    525  1.8  christos 	if ((vfstype = fscknames[t]) == NULL)
    526  1.8  christos 		errx(1, "vfstype `%s' on partition `%s' is not supported",
    527  1.8  christos 		    fstypenames[t], str);
    528  1.8  christos 
    529  1.8  christos 	return vfstype;
    530  1.8  christos }
    531  1.8  christos 
    532  1.1  christos 
    533  1.1  christos 
    534  1.1  christos static void
    535  1.1  christos usage()
    536  1.1  christos {
    537  1.1  christos 	extern char *__progname;
    538  1.2  christos 	static const char common[] =
    539  1.4  christos 	    "[-dpvlyn] [-T fstype:fsoptions] [-t fstype]";
    540  1.1  christos 
    541  1.4  christos 	(void)fprintf(stderr, "Usage: %s %s [special|node]...\n",
    542  1.4  christos 	    __progname, common);
    543  1.1  christos 	exit(1);
    544  1.1  christos }
    545