xref: /onnv-gate/usr/src/cmd/fs.d/fsck.c (revision 9889:68d0fe4c716e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54271Srie  * Common Development and Distribution License (the "License").
64271Srie  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*9889SLarry.Liu@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include	<stdio.h>
300Sstevel@tonic-gate #include	<errno.h>
310Sstevel@tonic-gate #include	<limits.h>
320Sstevel@tonic-gate #include	<fcntl.h>
330Sstevel@tonic-gate #include	<string.h>
340Sstevel@tonic-gate #include	<sys/types.h>
350Sstevel@tonic-gate #include	<sys/stat.h>
360Sstevel@tonic-gate #include	<sys/wait.h>
370Sstevel@tonic-gate #include	<sys/vfstab.h>
380Sstevel@tonic-gate #include	<sys/mntent.h>
39*9889SLarry.Liu@Sun.COM #include	<sys/sysmacros.h>
400Sstevel@tonic-gate #include	<locale.h>
410Sstevel@tonic-gate #include	<libintl.h>
42*9889SLarry.Liu@Sun.COM #include	<sys/dkio.h>
430Sstevel@tonic-gate 
44*9889SLarry.Liu@Sun.COM #define	DEV_BSIZE	512
450Sstevel@tonic-gate #define	ARGV_MAX	16
460Sstevel@tonic-gate #define	FSTYPE_MAX	8
470Sstevel@tonic-gate #define	VFS_PATH	"/usr/lib/fs"
480Sstevel@tonic-gate #define	VFS_PATH2	"/etc/fs"
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #define	CHECK(xx, yy)\
510Sstevel@tonic-gate 	if (xx == (yy)-1) {\
520Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: too many arguments\n"), myname); \
530Sstevel@tonic-gate 		usage(); \
540Sstevel@tonic-gate 	}
550Sstevel@tonic-gate #define	OPTION(flag)\
560Sstevel@tonic-gate 		options++; \
570Sstevel@tonic-gate 		nargv[nargc++] = flag; \
580Sstevel@tonic-gate 		CHECK(nargc, ARGV_MAX); \
590Sstevel@tonic-gate 		break
600Sstevel@tonic-gate #define	OPTARG(flag)\
610Sstevel@tonic-gate 		nargv[nargc++] = flag; \
620Sstevel@tonic-gate 		CHECK(nargc, ARGV_MAX); \
630Sstevel@tonic-gate 		if (optarg) {\
640Sstevel@tonic-gate 			nargv[nargc++] = optarg; \
650Sstevel@tonic-gate 			CHECK(nargc, ARGV_MAX); \
660Sstevel@tonic-gate 		}\
670Sstevel@tonic-gate 		break
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 
700Sstevel@tonic-gate int	nrun, ndisks;
710Sstevel@tonic-gate int	maxrun = 8;	/* should be based on the machine resources */
720Sstevel@tonic-gate 
730Sstevel@tonic-gate extern char	*default_fstype();
740Sstevel@tonic-gate 
750Sstevel@tonic-gate int	nargc = 2;
760Sstevel@tonic-gate int	options = 0;
770Sstevel@tonic-gate int	mnt_passno = 0;
780Sstevel@tonic-gate int	exitstat = 0;
79392Sswilcox int	verbose = 0;
800Sstevel@tonic-gate char	*nargv[ARGV_MAX];
810Sstevel@tonic-gate char	*myname, *fstype;
820Sstevel@tonic-gate char	*malloc();
830Sstevel@tonic-gate char	vfstab[] = VFSTAB;
840Sstevel@tonic-gate char	pflg = 0, Vflg = 0;
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate  * Keep an idea of the last device arg type as a hint to the
880Sstevel@tonic-gate  * type of the next arg. In the case of mountall, it's very likely
890Sstevel@tonic-gate  * to be the same type and the next entry in the file. This should
900Sstevel@tonic-gate  * help speed vfstab lookups.
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate enum dev_arg_t { UNKNOWN, SPECIAL, FSCKDEV, MOUNTPT };
930Sstevel@tonic-gate enum dev_arg_t arg_hint = UNKNOWN;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate static struct devlist {
960Sstevel@tonic-gate 	char *name;
970Sstevel@tonic-gate 	char *fsname;
980Sstevel@tonic-gate 	pid_t pid;
990Sstevel@tonic-gate 	struct devlist *nxt;
1000Sstevel@tonic-gate } *newdev(), *getdev();
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate  * private copy vfstab functions
1040Sstevel@tonic-gate  */
1050Sstevel@tonic-gate static struct vfstab	vfsave = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1060Sstevel@tonic-gate 
107821Sdh145677 static void usage(void);
108821Sdh145677 static void fsck_dopreen(struct devlist **devp, int ndevs);
109821Sdh145677 static void waiter(struct devlist **blp, struct devlist **badlist);
110821Sdh145677 static void print_badlist(struct devlist *lp);
111821Sdh145677 static void startdisk(struct devlist *dp);
112821Sdh145677 static void do_exec(char *fstype, char *nargv[]);
113821Sdh145677 static void prnt_cmd(FILE *fd, char *fstype);
114821Sdh145677 static void vfserror(int flag);
115821Sdh145677 
1160Sstevel@tonic-gate static int
1170Sstevel@tonic-gate vfdup(struct vfstab *vp)
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 	if (vfsave.vfs_special != NULL) {
1200Sstevel@tonic-gate 		free(vfsave.vfs_special);
1210Sstevel@tonic-gate 		vfsave.vfs_special = NULL;
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate 	if ((vp->vfs_special != NULL) &&
1240Sstevel@tonic-gate 	    ((vfsave.vfs_special = strdup(vp->vfs_special)) == NULL)) {
1250Sstevel@tonic-gate 		perror(myname);
1260Sstevel@tonic-gate 		return (4);	/* XXX */
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	if (vfsave.vfs_fsckdev != NULL) {
1300Sstevel@tonic-gate 		free(vfsave.vfs_fsckdev);
1310Sstevel@tonic-gate 		vfsave.vfs_fsckdev = NULL;
1320Sstevel@tonic-gate 	}
1330Sstevel@tonic-gate 	if ((vp->vfs_fsckdev != NULL) &&
1340Sstevel@tonic-gate 	    ((vfsave.vfs_fsckdev = strdup(vp->vfs_fsckdev)) == NULL)) {
1350Sstevel@tonic-gate 		perror(myname);
1360Sstevel@tonic-gate 		return (4);	/* XXX */
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (vfsave.vfs_mountp != NULL) {
1400Sstevel@tonic-gate 		free(vfsave.vfs_mountp);
1410Sstevel@tonic-gate 		vfsave.vfs_mountp = NULL;
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate 	if ((vp->vfs_mountp != NULL) &&
1440Sstevel@tonic-gate 	    ((vfsave.vfs_mountp = strdup(vp->vfs_mountp)) == NULL)) {
1450Sstevel@tonic-gate 		perror(myname);
1460Sstevel@tonic-gate 		return (4);	/* XXX */
1470Sstevel@tonic-gate 	}
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	if (vfsave.vfs_fstype != NULL) {
1500Sstevel@tonic-gate 		free(vfsave.vfs_fstype);
1510Sstevel@tonic-gate 		vfsave.vfs_fstype = NULL;
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate 	if ((vp->vfs_fstype != NULL) &&
1540Sstevel@tonic-gate 	    ((vfsave.vfs_fstype = strdup(vp->vfs_fstype)) == NULL)) {
1550Sstevel@tonic-gate 		perror(myname);
1560Sstevel@tonic-gate 		return (4);	/* XXX */
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	if (vfsave.vfs_fsckpass != NULL) {
1600Sstevel@tonic-gate 		free(vfsave.vfs_fsckpass);
1610Sstevel@tonic-gate 		vfsave.vfs_fsckpass = NULL;
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate 	if ((vp->vfs_fsckpass != NULL) &&
1640Sstevel@tonic-gate 	    ((vfsave.vfs_fsckpass = strdup(vp->vfs_fsckpass)) == NULL)) {
1650Sstevel@tonic-gate 		perror(myname);
1660Sstevel@tonic-gate 		return (4);	/* XXX */
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	if (vfsave.vfs_automnt != NULL) {
1700Sstevel@tonic-gate 		free(vfsave.vfs_automnt);
1710Sstevel@tonic-gate 		vfsave.vfs_automnt = NULL;
1720Sstevel@tonic-gate 	}
1730Sstevel@tonic-gate 	if ((vp->vfs_automnt != NULL) &&
1740Sstevel@tonic-gate 	    ((vfsave.vfs_automnt = strdup(vp->vfs_automnt)) == NULL)) {
1750Sstevel@tonic-gate 		perror(myname);
1760Sstevel@tonic-gate 		return (4);	/* XXX */
1770Sstevel@tonic-gate 	}
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	if (vfsave.vfs_mntopts != NULL) {
1800Sstevel@tonic-gate 		free(vfsave.vfs_mntopts);
1810Sstevel@tonic-gate 		vfsave.vfs_mntopts = NULL;
1820Sstevel@tonic-gate 	}
1830Sstevel@tonic-gate 	if ((vp->vfs_mntopts != NULL) &&
1840Sstevel@tonic-gate 	    ((vfsave.vfs_mntopts = strdup(vp->vfs_mntopts)) == NULL)) {
1850Sstevel@tonic-gate 		perror(myname);
1860Sstevel@tonic-gate 		return (4);	/* XXX */
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	*vp = vfsave;
1900Sstevel@tonic-gate 	return (0);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate static int
1940Sstevel@tonic-gate mygetvfsent(FILE *fp, struct vfstab *vp)
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate 	int	error;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	if ((error = getvfsent(fp, vp)) != 0)
1990Sstevel@tonic-gate 		return (error);
2000Sstevel@tonic-gate 	return (vfdup(vp));
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate static int
2040Sstevel@tonic-gate mygetvfsany(FILE *fp, struct vfstab *vp, struct vfstab *vrefp)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate 	int	error;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	if ((error = getvfsany(fp, vp, vrefp)) != 0)
2090Sstevel@tonic-gate 		return (error);
2100Sstevel@tonic-gate 	return (vfdup(vp));
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
213821Sdh145677 int
214821Sdh145677 main(int argc, char *argv[])
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	int	cc, ret, other_than_ufs = 0;
2170Sstevel@tonic-gate 	int	questflg = 0, Fflg = 0, Vflg = 0, sanity = 0;
2180Sstevel@tonic-gate 	char	*subopt;
2190Sstevel@tonic-gate 	FILE	*fd = NULL;
220*9889SLarry.Liu@Sun.COM 	int	devfd;
2210Sstevel@tonic-gate 	struct vfstab	vget, vref;
222*9889SLarry.Liu@Sun.COM 	struct dk_minfo dkminfo;
2230Sstevel@tonic-gate 	int preencnt = 0;
2240Sstevel@tonic-gate 	struct devlist *dp, *devs = NULL;
2250Sstevel@tonic-gate 	int status;
226*9889SLarry.Liu@Sun.COM 	uint_t lbs;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2290Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
2300Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
2310Sstevel@tonic-gate #endif
2320Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	myname = strrchr(argv[0], '/');
2350Sstevel@tonic-gate 	if (myname)
2360Sstevel@tonic-gate 		myname++;
2370Sstevel@tonic-gate 	else
2380Sstevel@tonic-gate 		myname = argv[0];
2390Sstevel@tonic-gate 
240392Sswilcox 	while ((cc = getopt(argc, argv, "?F:mnNo:vVyY")) != -1) {
2410Sstevel@tonic-gate 		switch (cc) {
2420Sstevel@tonic-gate 		case '?':
2430Sstevel@tonic-gate 			questflg++;
2440Sstevel@tonic-gate 			if (questflg > 1)
2450Sstevel@tonic-gate 				usage();
2460Sstevel@tonic-gate 			nargv[nargc++] = "-?";
2470Sstevel@tonic-gate 			CHECK(nargc, ARGV_MAX);
2480Sstevel@tonic-gate 			break;
2490Sstevel@tonic-gate 		case 'F':
2500Sstevel@tonic-gate 			Fflg++;
2510Sstevel@tonic-gate 			/* check for more that one -F */
2520Sstevel@tonic-gate 			if (Fflg > 1) {
2530Sstevel@tonic-gate 				fprintf(stderr,
2540Sstevel@tonic-gate 				gettext("%s: more than one fstype specified\n"),
2550Sstevel@tonic-gate 					myname);
2560Sstevel@tonic-gate 				usage();
2570Sstevel@tonic-gate 			}
2580Sstevel@tonic-gate 			fstype = optarg;
259392Sswilcox 			if (strlen(fstype) > (size_t)FSTYPE_MAX) {
2600Sstevel@tonic-gate 				fprintf(stderr,
2610Sstevel@tonic-gate 			gettext("%s: Fstype %s exceeds %d characters\n"),
2620Sstevel@tonic-gate 					myname, fstype, FSTYPE_MAX);
2630Sstevel@tonic-gate 						exit(1);
2640Sstevel@tonic-gate 			}
2650Sstevel@tonic-gate 			break;
2660Sstevel@tonic-gate 		case 'm':
2670Sstevel@tonic-gate 			sanity++;
2680Sstevel@tonic-gate 			OPTION("-m");
2690Sstevel@tonic-gate 		case 'n':
2700Sstevel@tonic-gate 			OPTION("-n");
2710Sstevel@tonic-gate 		case 'N':
2720Sstevel@tonic-gate 			OPTION("-N");
2730Sstevel@tonic-gate 		case 'o':
2740Sstevel@tonic-gate 			subopt = optarg;
2750Sstevel@tonic-gate 			while (*subopt != '\0') {
2760Sstevel@tonic-gate 				if (*subopt == 'p') {
2770Sstevel@tonic-gate 					pflg++;
2780Sstevel@tonic-gate 					break;
2790Sstevel@tonic-gate 				}
2800Sstevel@tonic-gate 				subopt++;
2810Sstevel@tonic-gate 			}
2820Sstevel@tonic-gate 			OPTARG("-o");
283392Sswilcox 		case 'v':
284392Sswilcox 			OPTION("-v");
2850Sstevel@tonic-gate 		case 'V':
2860Sstevel@tonic-gate 			Vflg++;
2870Sstevel@tonic-gate 			if (Vflg > 1)
2880Sstevel@tonic-gate 				usage();
2890Sstevel@tonic-gate 			break;
2900Sstevel@tonic-gate 		case 'y':
2910Sstevel@tonic-gate 			OPTION("-y");
2920Sstevel@tonic-gate 		case 'Y':
2930Sstevel@tonic-gate 			OPTION("-Y");
2940Sstevel@tonic-gate 		}
2950Sstevel@tonic-gate 		optarg = NULL;
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	/* copy '--' to specific */
2990Sstevel@tonic-gate 	if (strcmp(argv[optind-1], "--") == 0) {
3000Sstevel@tonic-gate 		nargv[nargc++] = argv[optind-1];
3010Sstevel@tonic-gate 		CHECK(nargc, ARGV_MAX);
3020Sstevel@tonic-gate 	}
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	if (questflg) {
3050Sstevel@tonic-gate 		if (Fflg) {
3060Sstevel@tonic-gate 			nargc = 2;
3070Sstevel@tonic-gate 			nargv[nargc++] = "-?";
3080Sstevel@tonic-gate 			nargv[nargc] = NULL;
3090Sstevel@tonic-gate 			do_exec(fstype, nargv);
3100Sstevel@tonic-gate 		}
3110Sstevel@tonic-gate 		usage();
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	if ((sanity) && (options > 1)) {
3150Sstevel@tonic-gate 		usage();
3160Sstevel@tonic-gate 	}
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	if (optind == argc) {	/* no device name is specified */
3190Sstevel@tonic-gate 		if (fstype == NULL) {
3200Sstevel@tonic-gate 			if ((argc > 2) && (sanity)) {
3210Sstevel@tonic-gate 				usage();
3220Sstevel@tonic-gate 			}
3230Sstevel@tonic-gate 		}
3240Sstevel@tonic-gate 		/*
3250Sstevel@tonic-gate 		 * Try to check UFS filesystems first, then check other
3260Sstevel@tonic-gate 		 * filesystems if they exist.
3270Sstevel@tonic-gate 		 * Note: Parallel checking is only available in UFS for now.
3280Sstevel@tonic-gate 		 */
3290Sstevel@tonic-gate 		if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
3300Sstevel@tonic-gate 			if ((fd = fopen(vfstab, "r")) == NULL) {
3310Sstevel@tonic-gate 				fprintf(stderr,
3320Sstevel@tonic-gate 					gettext("%s: cannot open vfstab\n"),
3330Sstevel@tonic-gate 					myname);
3340Sstevel@tonic-gate 				exit(1);
3350Sstevel@tonic-gate 			}
3360Sstevel@tonic-gate 			while ((ret = mygetvfsent(fd, &vget)) == 0) {
3370Sstevel@tonic-gate 				if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) &&
3380Sstevel@tonic-gate 				    numbers(vget.vfs_fsckpass)) {
3390Sstevel@tonic-gate 					other_than_ufs ++;
3400Sstevel@tonic-gate 					continue;
3410Sstevel@tonic-gate 				}
3420Sstevel@tonic-gate 				if (numbers(vget.vfs_fsckpass))
3430Sstevel@tonic-gate 					mnt_passno = atoi(vget.vfs_fsckpass);
3440Sstevel@tonic-gate 				else
3450Sstevel@tonic-gate 					continue;
3460Sstevel@tonic-gate 				if (mnt_passno < 1)
3470Sstevel@tonic-gate 					continue;
3480Sstevel@tonic-gate 				if (pflg == 0 || mnt_passno == 1) {
3490Sstevel@tonic-gate 					status = execute(vget.vfs_fsckdev,
3500Sstevel@tonic-gate 					    MNTTYPE_UFS, Vflg, fd);
3510Sstevel@tonic-gate 					/* return the highest exit code */
3520Sstevel@tonic-gate 					if (status > exitstat)
3530Sstevel@tonic-gate 						exitstat = status;
3540Sstevel@tonic-gate 				} else if (preen_addev(vget.vfs_fsckdev) == 0) {
3550Sstevel@tonic-gate 					preencnt++;
3560Sstevel@tonic-gate 					dp = newdev(&vget);
3570Sstevel@tonic-gate 					dp->nxt = devs;
3580Sstevel@tonic-gate 					devs = dp;
3590Sstevel@tonic-gate 				} else {
3600Sstevel@tonic-gate 					/*
3610Sstevel@tonic-gate 					 * preening setup failed, so
3620Sstevel@tonic-gate 					 * execute serially here...
3630Sstevel@tonic-gate 					 */
3640Sstevel@tonic-gate 					fprintf(stderr,
3650Sstevel@tonic-gate 					gettext("%s: preen_addev error\n"),
3660Sstevel@tonic-gate 						myname);
3670Sstevel@tonic-gate 					status = execute(vget.vfs_fsckdev,
3680Sstevel@tonic-gate 					    MNTTYPE_UFS, Vflg, fd);
3690Sstevel@tonic-gate 					/* return the highest exit code */
3700Sstevel@tonic-gate 					if (status > exitstat)
3710Sstevel@tonic-gate 						exitstat = status;
3720Sstevel@tonic-gate 				}
3730Sstevel@tonic-gate 			}
3740Sstevel@tonic-gate 			fclose(fd);
3750Sstevel@tonic-gate 			if (ret > 0)
3760Sstevel@tonic-gate 				vfserror(ret);
3770Sstevel@tonic-gate 			if (pflg && exitstat == 0) {
3780Sstevel@tonic-gate 				fsck_dopreen(&devs, preencnt);
3790Sstevel@tonic-gate 			}
3800Sstevel@tonic-gate 		}
3810Sstevel@tonic-gate 		else
3820Sstevel@tonic-gate 			other_than_ufs = 1;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 		if (other_than_ufs) {
3850Sstevel@tonic-gate 			if ((fd = fopen(vfstab, "r")) == NULL) {
3860Sstevel@tonic-gate 				fprintf(stderr,
3870Sstevel@tonic-gate 					gettext("%s: cannot open vfstab\n"),
3880Sstevel@tonic-gate 					myname);
3890Sstevel@tonic-gate 				exit(1);
3900Sstevel@tonic-gate 			}
3910Sstevel@tonic-gate 			while ((ret = mygetvfsent(fd, &vget)) == 0)
3920Sstevel@tonic-gate 				if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) &&
3930Sstevel@tonic-gate 				    numbers(vget.vfs_fsckpass) &&
3940Sstevel@tonic-gate 				    vget.vfs_fsckdev != NULL &&
3950Sstevel@tonic-gate 				    (fstype == NULL ||
3960Sstevel@tonic-gate 				    strcmp(fstype, vget.vfs_fstype) == 0)) {
3970Sstevel@tonic-gate 					status = execute(vget.vfs_fsckdev,
3980Sstevel@tonic-gate 					    vget.vfs_fstype, Vflg, fd);
3990Sstevel@tonic-gate 					/* return the highest exit code */
4000Sstevel@tonic-gate 					if (status > exitstat)
4010Sstevel@tonic-gate 						exitstat = status;
4020Sstevel@tonic-gate 				}
4030Sstevel@tonic-gate 			fclose(fd);
4040Sstevel@tonic-gate 			if (ret > 0)
4050Sstevel@tonic-gate 				vfserror(ret);
4060Sstevel@tonic-gate 		}
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	} else {	/* device name is specified */
4090Sstevel@tonic-gate 		if (fstype == NULL && (fd = fopen(vfstab, "r")) == NULL) {
4100Sstevel@tonic-gate 			fprintf(stderr, gettext("%s: cannot open vfstab\n"),
4110Sstevel@tonic-gate 				myname);
4120Sstevel@tonic-gate 			exit(1);
4130Sstevel@tonic-gate 		}
414*9889SLarry.Liu@Sun.COM 
4150Sstevel@tonic-gate 		while (optind < argc) {
4160Sstevel@tonic-gate 			/*
4170Sstevel@tonic-gate 			 * If "-F FStype" is specified, use that fs type.
4180Sstevel@tonic-gate 			 * Otherwise, determine the fs type from /etc/vfstab
4190Sstevel@tonic-gate 			 * if the entry exists.  Otherwise, determine the
4200Sstevel@tonic-gate 			 * local or remote fs type from /etc/default/df
4210Sstevel@tonic-gate 			 * or /etc/dfs/fstypes respectively.
4220Sstevel@tonic-gate 			 */
4230Sstevel@tonic-gate 			if (fstype == NULL) {
4240Sstevel@tonic-gate 				if ((argc > 3) && (sanity)) {
4250Sstevel@tonic-gate 					usage();
4260Sstevel@tonic-gate 				}
4270Sstevel@tonic-gate 				/* must check for both special && raw devices */
4280Sstevel@tonic-gate 				vfsnull(&vref);
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 				/*
4310Sstevel@tonic-gate 				 * Find the vfstab entry for this device.
4320Sstevel@tonic-gate 				 * arg_hint tells us what to try to match,
4330Sstevel@tonic-gate 				 * based on the type of the last arg. If
4340Sstevel@tonic-gate 				 * arg_hint equals UNKNOWN, then we're not
4350Sstevel@tonic-gate 				 * sure of the type and need to fallthrough
4360Sstevel@tonic-gate 				 * all 3 possibilities for vfstab lookup.
4370Sstevel@tonic-gate 				 * Try it as a mountpt first, since that's
4380Sstevel@tonic-gate 				 * what mountall gives us.
4390Sstevel@tonic-gate 				 */
4400Sstevel@tonic-gate try_again:
4410Sstevel@tonic-gate 				switch (arg_hint) {
4420Sstevel@tonic-gate 				case UNKNOWN:
4430Sstevel@tonic-gate 					/* FALLTHROUGH */
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 				case MOUNTPT:
4460Sstevel@tonic-gate 					vref.vfs_mountp = argv[optind];
4470Sstevel@tonic-gate 					if ((ret = mygetvfsany(fd, &vget,
4480Sstevel@tonic-gate 						&vref)) == -1 ||
4490Sstevel@tonic-gate 						vget.vfs_fstype == NULL) {
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 						vref.vfs_mountp = NULL;
4520Sstevel@tonic-gate 						rewind(fd);
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 						if (arg_hint == MOUNTPT) {
4550Sstevel@tonic-gate 							arg_hint = UNKNOWN;
4560Sstevel@tonic-gate 							goto try_again;
4570Sstevel@tonic-gate 						}
4580Sstevel@tonic-gate 						/* FALLTHROUGH */
4590Sstevel@tonic-gate 					} else {
4600Sstevel@tonic-gate 						/* Found it */
4610Sstevel@tonic-gate 						if (vget.vfs_fsckdev != NULL) {
4620Sstevel@tonic-gate 							argv[optind] =
4630Sstevel@tonic-gate 							vget.vfs_fsckdev;
4640Sstevel@tonic-gate 						}
4650Sstevel@tonic-gate 						arg_hint = MOUNTPT;
4660Sstevel@tonic-gate 						break;
4670Sstevel@tonic-gate 					}
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 				case FSCKDEV:
4700Sstevel@tonic-gate 					vref.vfs_fsckdev = argv[optind];
471*9889SLarry.Liu@Sun.COM 
472*9889SLarry.Liu@Sun.COM 					/*
473*9889SLarry.Liu@Sun.COM 					 * Check the media sector size
474*9889SLarry.Liu@Sun.COM 					 */
475*9889SLarry.Liu@Sun.COM 					if (((devfd = open(vref.vfs_fsckdev,
476*9889SLarry.Liu@Sun.COM 					    O_RDWR)) >= 0) && (ioctl(devfd,
477*9889SLarry.Liu@Sun.COM 					    DKIOCGMEDIAINFO, &dkminfo) !=
478*9889SLarry.Liu@Sun.COM 					    -1)) {
479*9889SLarry.Liu@Sun.COM 						lbs =  dkminfo.dki_lbsize;
480*9889SLarry.Liu@Sun.COM 						if (lbs != 0 && ISP2(lbs /
481*9889SLarry.Liu@Sun.COM 						    DEV_BSIZE) &&
482*9889SLarry.Liu@Sun.COM 						    lbs != DEV_BSIZE) {
483*9889SLarry.Liu@Sun.COM 							fprintf(stderr,
484*9889SLarry.Liu@Sun.COM 							    gettext("The device"
485*9889SLarry.Liu@Sun.COM 							    " sector size is"
486*9889SLarry.Liu@Sun.COM 							    " not supported by"
487*9889SLarry.Liu@Sun.COM 							    " fsck\n"));
488*9889SLarry.Liu@Sun.COM 							(void) close(devfd);
489*9889SLarry.Liu@Sun.COM 							exit(1);
490*9889SLarry.Liu@Sun.COM 						}
491*9889SLarry.Liu@Sun.COM 					}
492*9889SLarry.Liu@Sun.COM 
493*9889SLarry.Liu@Sun.COM 					if (devfd >= 0) {
494*9889SLarry.Liu@Sun.COM 						(void) close(devfd);
495*9889SLarry.Liu@Sun.COM 					}
496*9889SLarry.Liu@Sun.COM 
4970Sstevel@tonic-gate 					if ((ret = mygetvfsany(fd, &vget,
4980Sstevel@tonic-gate 						&vref)) == -1 ||
4990Sstevel@tonic-gate 						vget.vfs_fstype == NULL) {
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 						vref.vfs_fsckdev = NULL;
5020Sstevel@tonic-gate 						rewind(fd);
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 						if (arg_hint == FSCKDEV) {
5050Sstevel@tonic-gate 							arg_hint = UNKNOWN;
5060Sstevel@tonic-gate 							goto try_again;
5070Sstevel@tonic-gate 						}
5080Sstevel@tonic-gate 						/* FALLTHROUGH */
5090Sstevel@tonic-gate 					} else {
5100Sstevel@tonic-gate 						/* Found it */
5110Sstevel@tonic-gate 						arg_hint = FSCKDEV;
5120Sstevel@tonic-gate 						break;
5130Sstevel@tonic-gate 					}
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 				case SPECIAL:
5160Sstevel@tonic-gate 					vref.vfs_special = argv[optind];
5170Sstevel@tonic-gate 					if ((ret = mygetvfsany(fd, &vget,
5180Sstevel@tonic-gate 						&vref)) == -1 ||
5190Sstevel@tonic-gate 						vget.vfs_fstype == NULL) {
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 						vref.vfs_special = NULL;
5220Sstevel@tonic-gate 						rewind(fd);
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 						if (arg_hint == SPECIAL) {
5250Sstevel@tonic-gate 							arg_hint = UNKNOWN;
5260Sstevel@tonic-gate 							goto try_again;
5270Sstevel@tonic-gate 						}
5280Sstevel@tonic-gate 						/* FALLTHROUGH */
5290Sstevel@tonic-gate 					} else {
5300Sstevel@tonic-gate 						/* Found it */
5310Sstevel@tonic-gate 						arg_hint = SPECIAL;
5320Sstevel@tonic-gate 						break;
5330Sstevel@tonic-gate 					}
5340Sstevel@tonic-gate 				}
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 				if (ret == 0 && vget.vfs_fstype) {
5370Sstevel@tonic-gate 					if ((pflg) && (strcmp(vget.vfs_fstype,
5380Sstevel@tonic-gate 					    MNTTYPE_UFS) == 0) && (preen_addev(
5390Sstevel@tonic-gate 					    vget.vfs_fsckdev) == 0)) {
5400Sstevel@tonic-gate 						preencnt++;
5410Sstevel@tonic-gate 						dp = newdev(&vget);
5420Sstevel@tonic-gate 						dp->nxt = devs;
5430Sstevel@tonic-gate 						devs = dp;
5440Sstevel@tonic-gate 					} else {
5450Sstevel@tonic-gate 						status = execute(argv[optind],
5460Sstevel@tonic-gate 						    vget.vfs_fstype, Vflg, fd);
5470Sstevel@tonic-gate 						if (status > exitstat)
5480Sstevel@tonic-gate 							exitstat = status;
5490Sstevel@tonic-gate 					}
5500Sstevel@tonic-gate 				} else if (ret == -1 ||
5510Sstevel@tonic-gate 				    vget.vfs_fstype == NULL) {
5520Sstevel@tonic-gate 					fstype =
5530Sstevel@tonic-gate 					    default_fstype(argv[optind]);
5540Sstevel@tonic-gate 					status = execute(argv[optind], fstype,
5550Sstevel@tonic-gate 					    Vflg, fd);
5560Sstevel@tonic-gate 					/* return the highest exit code */
5570Sstevel@tonic-gate 					if (status > exitstat)
5580Sstevel@tonic-gate 						exitstat = status;
5590Sstevel@tonic-gate 				} else
5600Sstevel@tonic-gate 					vfserror(ret);
5610Sstevel@tonic-gate 			} else {
5620Sstevel@tonic-gate 				status = execute(argv[optind], fstype,
5630Sstevel@tonic-gate 				    Vflg, NULL);
5640Sstevel@tonic-gate 				/* return the highest exit code */
5650Sstevel@tonic-gate 				if (status > exitstat)
5660Sstevel@tonic-gate 					exitstat = status;
5670Sstevel@tonic-gate 			}
5680Sstevel@tonic-gate 			optind++;
5690Sstevel@tonic-gate 		}
5700Sstevel@tonic-gate 		if (fd != NULL)
5710Sstevel@tonic-gate 			fclose(fd);
5720Sstevel@tonic-gate 		if ((pflg) && (exitstat == 0)) {
5730Sstevel@tonic-gate 			fsck_dopreen(&devs, preencnt);
5740Sstevel@tonic-gate 		}
5750Sstevel@tonic-gate 	}
576821Sdh145677 	return (exitstat);
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate 
579821Sdh145677 static void
580821Sdh145677 fsck_dopreen(struct devlist **devp, int ndevs)
5810Sstevel@tonic-gate {
5820Sstevel@tonic-gate 	char name[1024];
5830Sstevel@tonic-gate 	int rc;
584821Sdh145677 	int i;
5850Sstevel@tonic-gate 	struct devlist *bl, *bdp;
5860Sstevel@tonic-gate 	struct devlist *badlist;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	bl = badlist = NULL;
5890Sstevel@tonic-gate 	while (ndevs > 0) {
5900Sstevel@tonic-gate 		if (nrun > maxrun)
5910Sstevel@tonic-gate 			waiter(&bl, &badlist);
5920Sstevel@tonic-gate 		rc = preen_getdev(name);
5930Sstevel@tonic-gate 		switch (rc) {
5940Sstevel@tonic-gate 		case 0:
5950Sstevel@tonic-gate 			break;
5960Sstevel@tonic-gate 		case 1:
5970Sstevel@tonic-gate 			bdp = getdev(name, devp);
5980Sstevel@tonic-gate 			if (bdp == NULL) {
5990Sstevel@tonic-gate 				fprintf(stderr,
6000Sstevel@tonic-gate 					gettext("%s: unknown dev: `%s'\n"),
6010Sstevel@tonic-gate 					myname, name);
6020Sstevel@tonic-gate 				exit(1);
6030Sstevel@tonic-gate 			}
6040Sstevel@tonic-gate 			bdp->nxt = bl;
6050Sstevel@tonic-gate 			bl = bdp;
6060Sstevel@tonic-gate 			startdisk(bdp);
6070Sstevel@tonic-gate 			ndevs--;
6080Sstevel@tonic-gate 			break;
6090Sstevel@tonic-gate 		case 2:
6100Sstevel@tonic-gate 			waiter(&bl, &badlist);
6110Sstevel@tonic-gate 			break;
6120Sstevel@tonic-gate 		default:
6130Sstevel@tonic-gate 			fprintf(stderr,
6140Sstevel@tonic-gate 			gettext("%s: bad return `%d' from preen_getdev\n"),
6150Sstevel@tonic-gate 				myname, rc);
6160Sstevel@tonic-gate 			break;
6170Sstevel@tonic-gate 		}
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 	while (bl != NULL) {
6200Sstevel@tonic-gate 		waiter(&bl, &badlist);
6210Sstevel@tonic-gate 	}
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	if (badlist != NULL)
6240Sstevel@tonic-gate 		print_badlist(badlist);
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate 
627821Sdh145677 static void
628821Sdh145677 startdisk(struct devlist *dp)
6290Sstevel@tonic-gate {
6300Sstevel@tonic-gate 	pid_t pid;
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	nrun++;
6330Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
6340Sstevel@tonic-gate 		perror("fork");
6350Sstevel@tonic-gate 		exit(1);
6360Sstevel@tonic-gate 	} else if (pid == 0) {
6370Sstevel@tonic-gate 		exitstat = execute(dp->name, MNTTYPE_UFS, Vflg, NULL);
6380Sstevel@tonic-gate 		exit(exitstat);
6390Sstevel@tonic-gate 	} else {
6400Sstevel@tonic-gate 		dp->pid = pid;
6410Sstevel@tonic-gate 	}
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate 
644821Sdh145677 static void
645821Sdh145677 waiter(struct devlist **blp, struct devlist **badlist)
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate 	pid_t curpid;
6480Sstevel@tonic-gate 	int status;
649821Sdh145677 	struct devlist *bdp, *pbdp;
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate 	curpid = wait(&status);
6520Sstevel@tonic-gate 	if (curpid == -1) {
6530Sstevel@tonic-gate 		perror("wait");
6540Sstevel@tonic-gate 		exit(1);
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	for (pbdp = NULL, bdp = *blp; bdp != NULL; pbdp = bdp, bdp = bdp->nxt) {
6580Sstevel@tonic-gate 		if (bdp->pid == curpid) {
6590Sstevel@tonic-gate 			break;
6600Sstevel@tonic-gate 		}
6610Sstevel@tonic-gate 	}
6620Sstevel@tonic-gate 	if (bdp == NULL)
6630Sstevel@tonic-gate 		return;
6640Sstevel@tonic-gate 	nrun--;
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 	if (pbdp)
6670Sstevel@tonic-gate 		pbdp->nxt = bdp->nxt;
6680Sstevel@tonic-gate 	else
6690Sstevel@tonic-gate 		*blp = bdp->nxt;
6700Sstevel@tonic-gate 	preen_releasedev(bdp->name);
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 	if (WTERMSIG(status)) {
6730Sstevel@tonic-gate 		printf(gettext("%s (%s): EXITED WITH SIGNAL %d\n"),
6740Sstevel@tonic-gate 			bdp->name, bdp->fsname, WTERMSIG(status));
6750Sstevel@tonic-gate 		status = status&0377 | 8<<8;
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 	if (WHIBYTE(status) != 0) {
6780Sstevel@tonic-gate 		if (WHIBYTE(status) > exitstat)
6790Sstevel@tonic-gate 			exitstat = WHIBYTE(status);
6800Sstevel@tonic-gate 		while (*badlist != NULL)
6810Sstevel@tonic-gate 			badlist = &(*badlist)->nxt;
6820Sstevel@tonic-gate 		*badlist = bdp;
6830Sstevel@tonic-gate 		bdp->nxt = NULL;
6840Sstevel@tonic-gate 	}
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate 
687821Sdh145677 static void
688821Sdh145677 print_badlist(struct devlist *lp)
6890Sstevel@tonic-gate {
6900Sstevel@tonic-gate 	int x, len;
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 	printf(
6930Sstevel@tonic-gate gettext("\nTHE FOLLOWING FILE SYSTEM(S) HAD AN UNEXPECTED INCONSISTENCY:"));
6940Sstevel@tonic-gate 	for (x = 3; lp != NULL; lp = lp->nxt) {
6950Sstevel@tonic-gate 		len = strlen(lp->name) + strlen(lp->fsname) + 5;
6960Sstevel@tonic-gate 		x += len;
6970Sstevel@tonic-gate 		if (x >= 80) {
6980Sstevel@tonic-gate 			printf("\n   ");
6990Sstevel@tonic-gate 			x = len + 3;
7000Sstevel@tonic-gate 		} else {
7010Sstevel@tonic-gate 			printf(" ");
7020Sstevel@tonic-gate 		}
7030Sstevel@tonic-gate 		printf("%s (%s)%s", lp->name, lp->fsname,
7040Sstevel@tonic-gate 		    lp->nxt ? "," : "\n");
7050Sstevel@tonic-gate 	}
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate /*
7090Sstevel@tonic-gate  * allocate and initialize a `devlist' structure
7100Sstevel@tonic-gate  */
7110Sstevel@tonic-gate static
7120Sstevel@tonic-gate struct devlist *
713821Sdh145677 newdev(struct vfstab *vfsp)
7140Sstevel@tonic-gate {
7150Sstevel@tonic-gate 	struct devlist *dp;
7160Sstevel@tonic-gate 	extern char *strdup();
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	dp = (struct devlist *)malloc(sizeof (struct devlist));
7190Sstevel@tonic-gate 	if (dp == NULL) {
7200Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: out of memory\n"), myname);
7210Sstevel@tonic-gate 		exit(1);
7220Sstevel@tonic-gate 	}
7230Sstevel@tonic-gate 	dp->name = strdup(vfsp->vfs_fsckdev);
7240Sstevel@tonic-gate 	dp->fsname = strdup(vfsp->vfs_mountp);
7250Sstevel@tonic-gate 	if (dp->name == NULL || dp->fsname == NULL) {
7260Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: out of memory\n"), myname);
7270Sstevel@tonic-gate 		exit(1);
7280Sstevel@tonic-gate 	}
7290Sstevel@tonic-gate 	return (dp);
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate /*
7330Sstevel@tonic-gate  * locate the devlist structure in the given list that matches `name'.
7340Sstevel@tonic-gate  * If found, the structure is removed from the list, and a pointer to
7350Sstevel@tonic-gate  * it is returned.  If not, NULL is returned.
7360Sstevel@tonic-gate  */
7370Sstevel@tonic-gate static
7380Sstevel@tonic-gate struct devlist *
739821Sdh145677 getdev(char *name, struct devlist **list)
7400Sstevel@tonic-gate {
741821Sdh145677 	struct devlist *p, *lp;
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	for (lp = NULL, p = *list; p != NULL; lp = p, p = p->nxt) {
7440Sstevel@tonic-gate 		if (strcmp(p->name, name) == 0)
7450Sstevel@tonic-gate 			break;
7460Sstevel@tonic-gate 	}
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 	if (p != NULL) {
7490Sstevel@tonic-gate 		if (lp != NULL)
7500Sstevel@tonic-gate 			lp->nxt = p->nxt;
7510Sstevel@tonic-gate 		else
7520Sstevel@tonic-gate 			*list = p->nxt;
7530Sstevel@tonic-gate 	}
7540Sstevel@tonic-gate 	return (p);
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate /* see if all numbers */
758821Sdh145677 int
759821Sdh145677 numbers(char *yp)
7600Sstevel@tonic-gate {
7610Sstevel@tonic-gate 	if (yp == NULL)
7620Sstevel@tonic-gate 		return (0);
7630Sstevel@tonic-gate 	while ('0' <= *yp && *yp <= '9')
7640Sstevel@tonic-gate 		yp++;
7650Sstevel@tonic-gate 	if (*yp)
7660Sstevel@tonic-gate 		return (0);
7670Sstevel@tonic-gate 	return (1);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
770821Sdh145677 int
771821Sdh145677 execute(char *fsckdev, char *fstype, int Vflg, FILE *fd)
7720Sstevel@tonic-gate {
7730Sstevel@tonic-gate 	int	st;
7740Sstevel@tonic-gate 	pid_t	fk;
7750Sstevel@tonic-gate 	char	full_path[PATH_MAX];
7760Sstevel@tonic-gate 	char	*vfs_path = VFS_PATH;
7770Sstevel@tonic-gate 	int	status = 0;
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	nargv[nargc] = fsckdev;
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 	if (Vflg) {
7820Sstevel@tonic-gate 		prnt_cmd(stdout, fstype);
7830Sstevel@tonic-gate 		return (0);
7840Sstevel@tonic-gate 	}
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 	if (fd)
7870Sstevel@tonic-gate 		fcntl(fileno(fd), F_SETFD, 1);	/* close on exec */
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	if ((fk = fork()) == (pid_t)-1) {
7900Sstevel@tonic-gate 		fprintf(stderr,
7910Sstevel@tonic-gate 			gettext("%s: cannot fork.  Try again later\n"),
7920Sstevel@tonic-gate 			myname);
7930Sstevel@tonic-gate 		perror(myname);
7940Sstevel@tonic-gate 		exit(1);
7950Sstevel@tonic-gate 	}
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 	if (fk == 0) {
7980Sstevel@tonic-gate 		/* Try to exec the fstype dependent portion of the fsck. */
7990Sstevel@tonic-gate 		do_exec(fstype, nargv);
8000Sstevel@tonic-gate 	} else {
8010Sstevel@tonic-gate 		/* parent waits for child */
8020Sstevel@tonic-gate 		if (wait(&st) == (pid_t)-1) {
8030Sstevel@tonic-gate 			fprintf(stderr, gettext("%s: bad wait\n"), myname);
8040Sstevel@tonic-gate 			perror(myname);
8050Sstevel@tonic-gate 			exit(1);
8060Sstevel@tonic-gate 		}
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 		if ((st & 0xff) == 0x7f) {
8090Sstevel@tonic-gate 			fprintf(stderr,
8100Sstevel@tonic-gate 				gettext("%s: warning: the following command"
8110Sstevel@tonic-gate 				" (process %d) was stopped by signal %d\n"),
8120Sstevel@tonic-gate 				myname, fk, (st >> 8) & 0xff);
8130Sstevel@tonic-gate 			prnt_cmd(stderr, fstype);
8140Sstevel@tonic-gate 			status = ((st >> 8) & 0xff) | 0x80;
8150Sstevel@tonic-gate 		} else if (st & 0xff) {
8160Sstevel@tonic-gate 			if (st & 0x80)
8170Sstevel@tonic-gate 				fprintf(stderr,
8180Sstevel@tonic-gate 				gettext("%s: warning: the following command"
8190Sstevel@tonic-gate 				" (process %d) was terminated by signal %d"
8200Sstevel@tonic-gate 				" and dumped core\n"),
8210Sstevel@tonic-gate 				myname, fk, st & 0x7f);
8220Sstevel@tonic-gate 			else
8230Sstevel@tonic-gate 				fprintf(stderr,
8240Sstevel@tonic-gate 				gettext("%s: warning: the following command"
8250Sstevel@tonic-gate 				" (process %d) was terminated by signal %d\n"),
8260Sstevel@tonic-gate 				myname, fk, st & 0x7f);
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 			prnt_cmd(stderr, fstype);
8290Sstevel@tonic-gate 			status = ((st & 0xff) | 0x80);
8300Sstevel@tonic-gate 		} else if (st & 0xff00)
8310Sstevel@tonic-gate 			status = (st >> 8) & 0xff;
8320Sstevel@tonic-gate 	}
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	return (status);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate 
837821Sdh145677 static void
838821Sdh145677 do_exec(char *fstype, char *nargv[])
8390Sstevel@tonic-gate {
8400Sstevel@tonic-gate 	char	full_path[PATH_MAX];
8410Sstevel@tonic-gate 	char	*vfs_path = VFS_PATH;
8420Sstevel@tonic-gate 
843392Sswilcox 	if (strlen(fstype) > (size_t)FSTYPE_MAX) {
8440Sstevel@tonic-gate 		fprintf(stderr,
8450Sstevel@tonic-gate 			gettext("%s: Fstype %s exceeds %d characters\n"),
8460Sstevel@tonic-gate 			myname, fstype, FSTYPE_MAX);
8470Sstevel@tonic-gate 		exit(1);
8480Sstevel@tonic-gate 	}
8490Sstevel@tonic-gate 	/* build the full pathname of the fstype dependent command. */
8500Sstevel@tonic-gate 	sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname);
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate 	/* set the new argv[0] to the filename */
8530Sstevel@tonic-gate 	nargv[1] = myname;
8540Sstevel@tonic-gate 	/* Try to exec the fstype dependent portion of the fsck. */
8550Sstevel@tonic-gate 	execv(full_path, &nargv[1]);
8560Sstevel@tonic-gate 	if (errno == EACCES) {
8570Sstevel@tonic-gate 		fprintf(stderr,
8580Sstevel@tonic-gate 			gettext("%s: cannot execute %s - permission denied\n"),
8590Sstevel@tonic-gate 			myname, full_path);
8600Sstevel@tonic-gate 	}
8610Sstevel@tonic-gate 	if (errno == ENOEXEC) {
8620Sstevel@tonic-gate 		nargv[0] = "sh";
8630Sstevel@tonic-gate 		nargv[1] = full_path;
8640Sstevel@tonic-gate 		execv("/sbin/sh", &nargv[0]);
8650Sstevel@tonic-gate 	}
8660Sstevel@tonic-gate 	/* second path to try */
8670Sstevel@tonic-gate 	vfs_path = VFS_PATH2;
8680Sstevel@tonic-gate 	/* build the full pathname of the fstype dependent command. */
8690Sstevel@tonic-gate 	sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname);
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 	/* set the new argv[0] to the filename */
8720Sstevel@tonic-gate 	nargv[1] = myname;
8730Sstevel@tonic-gate 	/* Try to exec the second fstype dependent portion of the fsck. */
8740Sstevel@tonic-gate 	execv(full_path, &nargv[1]);
8750Sstevel@tonic-gate 	if (errno == EACCES) {
8760Sstevel@tonic-gate 		fprintf(stderr,
8770Sstevel@tonic-gate 			gettext("%s: cannot execute %s - permission denied\n"),
8780Sstevel@tonic-gate 			myname, full_path);
8790Sstevel@tonic-gate 		exit(1);
8800Sstevel@tonic-gate 	}
8810Sstevel@tonic-gate 	if (errno == ENOEXEC) {
8820Sstevel@tonic-gate 		nargv[0] = "sh";
8830Sstevel@tonic-gate 		nargv[1] = full_path;
8840Sstevel@tonic-gate 		execv("/sbin/sh", &nargv[0]);
8850Sstevel@tonic-gate 	}
8860Sstevel@tonic-gate 	fprintf(stderr,
8870Sstevel@tonic-gate 		gettext("%s: operation not applicable to FSType %s\n"),
8880Sstevel@tonic-gate 		myname, fstype);
8890Sstevel@tonic-gate 	exit(1);
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate 
892821Sdh145677 static void
893821Sdh145677 prnt_cmd(FILE *fd, char *fstype)
8940Sstevel@tonic-gate {
8950Sstevel@tonic-gate 	char	**argp;
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	fprintf(fd, "%s -F %s", myname, fstype);
8980Sstevel@tonic-gate 	for (argp = &nargv[2]; *argp; argp++)
8990Sstevel@tonic-gate 		fprintf(fd, " %s", *argp);
9000Sstevel@tonic-gate 	fprintf(fd, "\n");
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate 
903821Sdh145677 static void
904821Sdh145677 vfserror(int flag)
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate 	switch (flag) {
9070Sstevel@tonic-gate 	case VFS_TOOLONG:
9080Sstevel@tonic-gate 		fprintf(stderr,
9090Sstevel@tonic-gate 			gettext("%s: line in vfstab exceeds %d characters\n"),
9100Sstevel@tonic-gate 			myname, VFS_LINE_MAX-2);
9110Sstevel@tonic-gate 		break;
9120Sstevel@tonic-gate 	case VFS_TOOFEW:
9130Sstevel@tonic-gate 		fprintf(stderr,
9140Sstevel@tonic-gate 			gettext("%s: line in vfstab has too few entries\n"),
9150Sstevel@tonic-gate 			myname);
9160Sstevel@tonic-gate 		break;
9170Sstevel@tonic-gate 	case VFS_TOOMANY:
9180Sstevel@tonic-gate 		fprintf(stderr,
9190Sstevel@tonic-gate 			gettext("%s: line in vfstab has too many entries\n"),
9200Sstevel@tonic-gate 			myname);
9210Sstevel@tonic-gate 		break;
9220Sstevel@tonic-gate 	}
9230Sstevel@tonic-gate 	exit(1);
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate 
926821Sdh145677 static void
927821Sdh145677 usage(void)
9280Sstevel@tonic-gate {
9290Sstevel@tonic-gate 	fprintf(stderr,
9300Sstevel@tonic-gate 		gettext("Usage:\n%s [-F FSType] [-V] [-m] [special ...]\n"
9310Sstevel@tonic-gate 			"%s [-F FSType] [-V] [-y|Y|n|N]"
9320Sstevel@tonic-gate 			" [-o specific_options] [special ...]\n"),
9330Sstevel@tonic-gate 			myname, myname);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	exit(1);
9360Sstevel@tonic-gate }
937