Home | History | Annotate | Line # | Download | only in fsck
fsck.c revision 1.8
      1  1.8  christos /*	$NetBSD: fsck.c,v 1.8 1996/12/05 18:30:23 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.8  christos static char rcsid[] = "$NetBSD: fsck.c,v 1.8 1996/12/05 18:30:23 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.8  christos 	(void) snprintf(execbase, sizeof(execbase), "fsck_%s", vfstype);
    235  1.8  christos 
    236  1.7  christos 	maxargc = 100;
    237  1.7  christos 	argv = emalloc(sizeof(char *) * maxargc);
    238  1.7  christos 
    239  1.8  christos 	/* construct basename of executable and argv[0] simultaneously */
    240  1.8  christos 	(void)strncat(execbase,
    241  1.8  christos 		     (const char *)vfstype,
    242  1.8  christos 		     sizeof(execbase) - 6); /* strlen("fsck_") + \0 */
    243  1.8  christos 	argv[0] = vfstype;
    244  1.2  christos 
    245  1.2  christos 	if (options) {
    246  1.2  christos 		if (extra != NULL)
    247  1.2  christos 			optbuf = catopt(options, extra, 0);
    248  1.2  christos 		else
    249  1.2  christos 			optbuf = estrdup(options);
    250  1.2  christos 	}
    251  1.2  christos 	else if (extra)
    252  1.2  christos 		optbuf = estrdup(extra);
    253  1.2  christos 
    254  1.2  christos 	if (optbuf)
    255  1.7  christos 		mangle(optbuf, &argc, &argv, &maxargc);
    256  1.2  christos 
    257  1.2  christos 	argv[argc++] = spec;
    258  1.7  christos 	argv[argc] = NULL;
    259  1.1  christos 
    260  1.4  christos 	if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) {
    261  1.8  christos 		(void)printf("start %s %swait", mntpt,
    262  1.8  christos 			pidp ? "no" : "");
    263  1.8  christos 		for (i = 0; i < argc; i++)
    264  1.1  christos 			(void)printf(" %s", argv[i]);
    265  1.1  christos 		(void)printf("\n");
    266  1.1  christos 	}
    267  1.1  christos 
    268  1.1  christos 	switch (pid = vfork()) {
    269  1.1  christos 	case -1:				/* Error. */
    270  1.1  christos 		warn("vfork");
    271  1.1  christos 		if (optbuf)
    272  1.1  christos 			free(optbuf);
    273  1.1  christos 		return (1);
    274  1.1  christos 
    275  1.1  christos 	case 0:					/* Child. */
    276  1.4  christos 		if (flags & CHECK_DEBUG)
    277  1.2  christos 			_exit(0);
    278  1.2  christos 
    279  1.1  christos 		/* Go find an executable. */
    280  1.1  christos 		edir = edirs;
    281  1.1  christos 		do {
    282  1.1  christos 			(void)snprintf(execname,
    283  1.8  christos 			    sizeof(execname), "%s/%s", *edir, execbase);
    284  1.1  christos 			execv(execname, (char * const *)argv);
    285  1.1  christos 			if (errno != ENOENT)
    286  1.1  christos 				if (spec)
    287  1.1  christos 					warn("exec %s for %s", execname, spec);
    288  1.1  christos 				else
    289  1.1  christos 					warn("exec %s", execname);
    290  1.1  christos 		} while (*++edir != NULL);
    291  1.1  christos 
    292  1.1  christos 		if (errno == ENOENT)
    293  1.1  christos 			if (spec)
    294  1.1  christos 				warn("exec %s for %s", execname, spec);
    295  1.1  christos 			else
    296  1.1  christos 				warn("exec %s", execname);
    297  1.8  christos 		_exit(1);
    298  1.1  christos 		/* NOTREACHED */
    299  1.1  christos 
    300  1.1  christos 	default:				/* Parent. */
    301  1.1  christos 		if (optbuf)
    302  1.1  christos 			free(optbuf);
    303  1.1  christos 
    304  1.2  christos 		if (pidp) {
    305  1.2  christos 			*pidp = pid;
    306  1.2  christos 			return 0;
    307  1.2  christos 		}
    308  1.2  christos 
    309  1.1  christos 		if (waitpid(pid, &status, 0) < 0) {
    310  1.1  christos 			warn("waitpid");
    311  1.1  christos 			return (1);
    312  1.1  christos 		}
    313  1.1  christos 
    314  1.1  christos 		if (WIFEXITED(status)) {
    315  1.1  christos 			if (WEXITSTATUS(status) != 0)
    316  1.1  christos 				return (WEXITSTATUS(status));
    317  1.1  christos 		}
    318  1.1  christos 		else if (WIFSIGNALED(status)) {
    319  1.1  christos 			warnx("%s: %s", spec, strsignal(WTERMSIG(status)));
    320  1.1  christos 			return (1);
    321  1.1  christos 		}
    322  1.1  christos 		break;
    323  1.1  christos 	}
    324  1.1  christos 
    325  1.1  christos 	return (0);
    326  1.1  christos }
    327  1.1  christos 
    328  1.1  christos 
    329  1.1  christos static int
    330  1.1  christos selected(type)
    331  1.1  christos 	const char *type;
    332  1.1  christos {
    333  1.1  christos 	struct entry *e;
    334  1.1  christos 
    335  1.1  christos 	/* If no type specified, it's always selected. */
    336  1.2  christos 	for (e = selhead.tqh_first; e != NULL; e = e->entries.tqe_next)
    337  1.1  christos 		if (!strncmp(e->type, type, MFSNAMELEN))
    338  1.1  christos 			return which == IN_LIST ? 1 : 0;
    339  1.1  christos 
    340  1.1  christos 	return which == IN_LIST ? 0 : 1;
    341  1.1  christos }
    342  1.1  christos 
    343  1.1  christos 
    344  1.2  christos static const char *
    345  1.2  christos getoptions(type)
    346  1.1  christos 	const char *type;
    347  1.1  christos {
    348  1.1  christos 	struct entry *e;
    349  1.1  christos 
    350  1.2  christos 	for (e = opthead.tqh_first; e != NULL; e = e->entries.tqe_next)
    351  1.2  christos 		if (!strncmp(e->type, type, MFSNAMELEN))
    352  1.2  christos 			return e->options;
    353  1.2  christos 	return "";
    354  1.1  christos }
    355  1.1  christos 
    356  1.1  christos 
    357  1.1  christos static void
    358  1.2  christos addoption(optstr)
    359  1.2  christos 	char *optstr;
    360  1.1  christos {
    361  1.2  christos 	char *newoptions;
    362  1.1  christos 	struct entry *e;
    363  1.1  christos 
    364  1.2  christos 	if ((newoptions = strchr(optstr, ':')) == NULL)
    365  1.2  christos 		errx(1, "Invalid option string");
    366  1.2  christos 
    367  1.2  christos 	*newoptions++ = '\0';
    368  1.2  christos 
    369  1.2  christos 	for (e = opthead.tqh_first; e != NULL; e = e->entries.tqe_next)
    370  1.2  christos 		if (!strncmp(e->type, optstr, MFSNAMELEN)) {
    371  1.2  christos 			e->options = catopt(e->options, newoptions, 1);
    372  1.1  christos 			return;
    373  1.1  christos 		}
    374  1.2  christos 	addentry(&opthead, optstr, newoptions);
    375  1.1  christos }
    376  1.1  christos 
    377  1.1  christos 
    378  1.1  christos static void
    379  1.2  christos addentry(list, type, opts)
    380  1.2  christos 	struct fstypelist *list;
    381  1.1  christos 	const char *type;
    382  1.2  christos 	const char *opts;
    383  1.1  christos {
    384  1.2  christos 	struct entry *e;
    385  1.2  christos 
    386  1.2  christos 	e = emalloc(sizeof(struct entry));
    387  1.2  christos 	e->type = estrdup(type);
    388  1.2  christos 	e->options = estrdup(opts);
    389  1.2  christos 	TAILQ_INSERT_TAIL(list, e, entries);
    390  1.1  christos }
    391  1.1  christos 
    392  1.1  christos 
    393  1.1  christos static void
    394  1.1  christos maketypelist(fslist)
    395  1.1  christos 	char *fslist;
    396  1.1  christos {
    397  1.1  christos 	char *ptr;
    398  1.1  christos 
    399  1.1  christos 	if ((fslist == NULL) || (fslist[0] == '\0'))
    400  1.1  christos 		errx(1, "empty type list");
    401  1.1  christos 
    402  1.1  christos 	if (fslist[0] == 'n' && fslist[1] == 'o') {
    403  1.1  christos 		fslist += 2;
    404  1.1  christos 		which = NOT_IN_LIST;
    405  1.1  christos 	}
    406  1.1  christos 	else
    407  1.1  christos 		which = IN_LIST;
    408  1.1  christos 
    409  1.1  christos 	while ((ptr = strsep(&fslist, ",")) != NULL)
    410  1.2  christos 		addentry(&selhead, ptr, "");
    411  1.1  christos 
    412  1.1  christos }
    413  1.1  christos 
    414  1.1  christos 
    415  1.1  christos static char *
    416  1.2  christos catopt(s0, s1, fr)
    417  1.1  christos 	char *s0;
    418  1.1  christos 	const char *s1;
    419  1.2  christos 	int fr;
    420  1.1  christos {
    421  1.1  christos 	size_t i;
    422  1.1  christos 	char *cp;
    423  1.1  christos 
    424  1.1  christos 	if (s0 && *s0) {
    425  1.1  christos 		i = strlen(s0) + strlen(s1) + 1 + 1;
    426  1.1  christos 		cp = emalloc(i);
    427  1.1  christos 		(void)snprintf(cp, i, "%s,%s", s0, s1);
    428  1.1  christos 	}
    429  1.1  christos 	else
    430  1.1  christos 		cp = estrdup(s1);
    431  1.1  christos 
    432  1.2  christos 	if (s0 && fr)
    433  1.1  christos 		free(s0);
    434  1.1  christos 	return (cp);
    435  1.1  christos }
    436  1.1  christos 
    437  1.1  christos 
    438  1.1  christos static void
    439  1.7  christos mangle(opts, argcp, argvp, maxargcp)
    440  1.2  christos 	char *opts;
    441  1.1  christos 	int *argcp;
    442  1.7  christos 	const char ***argvp;
    443  1.7  christos 	int *maxargcp;
    444  1.1  christos {
    445  1.1  christos 	char *p, *s;
    446  1.7  christos 	int argc = *argcp, maxargc = *maxargcp;
    447  1.7  christos 	const char **argv = *argvp;
    448  1.1  christos 
    449  1.1  christos 	argc = *argcp;
    450  1.7  christos 	maxargc = *maxargcp;
    451  1.7  christos 
    452  1.7  christos 	for (s = opts; (p = strsep(&s, ",")) != NULL;) {
    453  1.7  christos 		/* always leave space for one more argument and the NULL */
    454  1.7  christos 		if (argc >= maxargc - 3) {
    455  1.7  christos 			maxargc += 50;
    456  1.7  christos 			argv = erealloc(argv, maxargc * sizeof(char *));
    457  1.7  christos 		}
    458  1.1  christos 		if (*p != '\0')
    459  1.1  christos 			if (*p == '-') {
    460  1.1  christos 				argv[argc++] = p;
    461  1.1  christos 				p = strchr(p, '=');
    462  1.1  christos 				if (p) {
    463  1.1  christos 					*p = '\0';
    464  1.1  christos 					argv[argc++] = p+1;
    465  1.1  christos 				}
    466  1.1  christos 			}
    467  1.1  christos 			else {
    468  1.1  christos 				argv[argc++] = "-o";
    469  1.1  christos 				argv[argc++] = p;
    470  1.1  christos 			}
    471  1.7  christos 	}
    472  1.1  christos 
    473  1.1  christos 	*argcp = argc;
    474  1.7  christos 	*argvp = argv;
    475  1.7  christos 	*maxargcp = maxargc;
    476  1.1  christos }
    477  1.8  christos 
    478  1.8  christos 
    479  1.8  christos /* Maybe this belongs to <sys/disklabel.h> */
    480  1.8  christos static char *fscknames[] = {
    481  1.8  christos 	NULL,
    482  1.8  christos 	NULL,
    483  1.8  christos 	NULL,
    484  1.8  christos 	NULL,
    485  1.8  christos 	NULL,
    486  1.8  christos 	NULL,
    487  1.8  christos 	NULL,
    488  1.8  christos 	"ffs",
    489  1.8  christos 	"msdos",
    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 	NULL,
    496  1.8  christos 	NULL,
    497  1.8  christos 	NULL,
    498  1.8  christos 	NULL
    499  1.8  christos };
    500  1.8  christos 
    501  1.8  christos 
    502  1.8  christos static char *
    503  1.8  christos getfslab(str)
    504  1.8  christos 	const char *str;
    505  1.8  christos {
    506  1.8  christos 	struct disklabel dl;
    507  1.8  christos 	int fd;
    508  1.8  christos 	char p, *vfstype;
    509  1.8  christos 	u_char t;
    510  1.8  christos 
    511  1.8  christos 	/* deduce the filesystem type from the disk label */
    512  1.8  christos 	if ((fd = open(str, O_RDONLY)) == -1)
    513  1.8  christos 		err(1, "cannot open `%s'", str);
    514  1.8  christos 
    515  1.8  christos 	if (ioctl(fd, DIOCGDINFO, &dl) == -1)
    516  1.8  christos 		err(1, "cannot get disklabel for `%s'", str);
    517  1.8  christos 
    518  1.8  christos 	(void) close(fd);
    519  1.8  christos 
    520  1.8  christos 	p = str[strlen(str) - 1];
    521  1.8  christos 
    522  1.8  christos 	if ((p - 'a') >= dl.d_npartitions)
    523  1.8  christos 		errx(1, "partition `%s' is not defined on disk", str);
    524  1.8  christos 
    525  1.8  christos 	if ((t = dl.d_partitions[p - 'a'].p_fstype) >= DKMAXTYPES)
    526  1.8  christos 		errx(1, "partition `%s' is not of a legal vfstype",
    527  1.8  christos 		    p, str);
    528  1.8  christos 
    529  1.8  christos 	if ((vfstype = fscknames[t]) == NULL)
    530  1.8  christos 		errx(1, "vfstype `%s' on partition `%s' is not supported",
    531  1.8  christos 		    fstypenames[t], str);
    532  1.8  christos 
    533  1.8  christos 	return vfstype;
    534  1.8  christos }
    535  1.8  christos 
    536  1.1  christos 
    537  1.1  christos 
    538  1.1  christos static void
    539  1.1  christos usage()
    540  1.1  christos {
    541  1.1  christos 	extern char *__progname;
    542  1.2  christos 	static const char common[] =
    543  1.4  christos 	    "[-dpvlyn] [-T fstype:fsoptions] [-t fstype]";
    544  1.1  christos 
    545  1.4  christos 	(void)fprintf(stderr, "Usage: %s %s [special|node]...\n",
    546  1.4  christos 	    __progname, common);
    547  1.1  christos 	exit(1);
    548  1.1  christos }
    549