xref: /onnv-gate/usr/src/cmd/fs.d/ff.c (revision 821:ef17b74dd690)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
230Sstevel@tonic-gate /*	  All Rights Reserved  	*/
240Sstevel@tonic-gate 
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
27*821Sdh145677  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
280Sstevel@tonic-gate  * Use is subject to license terms.
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include	<stdio.h>
340Sstevel@tonic-gate #include 	<limits.h>
350Sstevel@tonic-gate #include	<string.h>
360Sstevel@tonic-gate #include	<sys/fstyp.h>
370Sstevel@tonic-gate #include	<errno.h>
380Sstevel@tonic-gate #include	<sys/vfstab.h>
390Sstevel@tonic-gate #include	<sys/wait.h>
400Sstevel@tonic-gate #include	<sys/types.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #define	FSTYPE_MAX	8
430Sstevel@tonic-gate #define	FULLPATH_MAX	64
440Sstevel@tonic-gate #define	ARGV_MAX	1024
450Sstevel@tonic-gate #define	VFS_PATH	"/usr/lib/fs"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate extern char	*default_fstype();
480Sstevel@tonic-gate 
490Sstevel@tonic-gate char	*special = NULL;  /*  device special name  */
500Sstevel@tonic-gate char	*fstype = NULL;	  /*  fstype name is filled in here  */
510Sstevel@tonic-gate char	*cbasename;	  /* name of command */
520Sstevel@tonic-gate char	*newargv[ARGV_MAX]; 	/* args for the fstype specific command  */
530Sstevel@tonic-gate char	vfstab[] = VFSTAB;
540Sstevel@tonic-gate 	char	full_path[FULLPATH_MAX];
550Sstevel@tonic-gate 	char	*vfs_path = VFS_PATH;
560Sstevel@tonic-gate int	newargc = 2;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate struct commands {
590Sstevel@tonic-gate 	char *c_basename;
600Sstevel@tonic-gate 	char *c_optstr;
610Sstevel@tonic-gate 	char *c_usgstr;
620Sstevel@tonic-gate } cmd_data[] = {
630Sstevel@tonic-gate 	"ff", "F:o:p:a:m:c:n:i:?IlsuV",
640Sstevel@tonic-gate 	"[-F FSType] [-V] [current_options] [-o specific_options] special ...",
650Sstevel@tonic-gate 	"ncheck", "F:o:?i:asV",
660Sstevel@tonic-gate "[-F FSType] [-V] [current_options] [-o specific_options] [special ...]",
670Sstevel@tonic-gate 	NULL, "F:o:?V",
680Sstevel@tonic-gate 	"[-F FSType] [-V] [current_options] [-o specific_options] special ..."
690Sstevel@tonic-gate 	};
700Sstevel@tonic-gate struct 	commands *c_ptr;
710Sstevel@tonic-gate 
72*821Sdh145677 static void usage(char *cmd, char *usg);
73*821Sdh145677 static void exec_specific(void);
74*821Sdh145677 static void lookup(void);
75*821Sdh145677 
76*821Sdh145677 int
77*821Sdh145677 main(int argc, char *argv[])
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	FILE *fp;
800Sstevel@tonic-gate 	struct vfstab	vfsbuf;
81*821Sdh145677 	char *ptr;
820Sstevel@tonic-gate 	int	i;
830Sstevel@tonic-gate 	int	verbose = 0;		/* set if -V is specified */
840Sstevel@tonic-gate 	int	F_flg = 0;
850Sstevel@tonic-gate 	int	usgflag = 0;
860Sstevel@tonic-gate 	int	fs_flag = 0;
870Sstevel@tonic-gate 	int	arg;			/* argument from getopt() */
880Sstevel@tonic-gate 	extern	char *optarg;		/* getopt specific */
890Sstevel@tonic-gate 	extern	int optind;
900Sstevel@tonic-gate 	extern	int opterr;
910Sstevel@tonic-gate 	size_t	strlen();
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	cbasename = ptr = argv[0];
940Sstevel@tonic-gate 	while (*ptr) {
950Sstevel@tonic-gate 		if (*ptr++ == '/')
960Sstevel@tonic-gate 			cbasename = ptr;
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 	/*
990Sstevel@tonic-gate 	 * If there are no arguments and command is ncheck then the generic
1000Sstevel@tonic-gate 	 * reads the VFSTAB and executes the specific module of
1010Sstevel@tonic-gate 	 * each entry which has a numeric fsckpass field.
1020Sstevel@tonic-gate 	 */
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	if (argc == 1) {		/* no arguments or options */
1050Sstevel@tonic-gate 		if (strcmp(cbasename, "ncheck") == 0) {
1060Sstevel@tonic-gate 			/* open VFSTAB */
1070Sstevel@tonic-gate 			if ((fp = fopen(VFSTAB, "r")) == NULL) {
1080Sstevel@tonic-gate 				fprintf(stderr, "%s: cannot open vfstab\n",
1090Sstevel@tonic-gate 				    cbasename);
1100Sstevel@tonic-gate 				exit(2);
1110Sstevel@tonic-gate 			}
1120Sstevel@tonic-gate 			while ((i = getvfsent(fp, &vfsbuf)) == 0) {
1130Sstevel@tonic-gate 				if (numbers(vfsbuf.vfs_fsckpass)) {
1140Sstevel@tonic-gate 					fstype = vfsbuf.vfs_fstype;
1150Sstevel@tonic-gate 					newargv[newargc]  = vfsbuf.vfs_special;
1160Sstevel@tonic-gate 					exec_specific();
1170Sstevel@tonic-gate 				}
1180Sstevel@tonic-gate 			}
1190Sstevel@tonic-gate 			exit(0);
1200Sstevel@tonic-gate 		}
1210Sstevel@tonic-gate 		fprintf(stderr, "Usage:\n");
1220Sstevel@tonic-gate 		fprintf(stderr,
1230Sstevel@tonic-gate "%s [-F FSType] [-V] [current_options] [-o specific_options] special ...\n",
1240Sstevel@tonic-gate 		    cbasename);
1250Sstevel@tonic-gate 		exit(2);
1260Sstevel@tonic-gate 	}
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	for (c_ptr = cmd_data; ((c_ptr->c_basename != NULL) &&
1290Sstevel@tonic-gate 	    (strcmp(c_ptr->c_basename, cbasename) != 0));  c_ptr++)
1300Sstevel@tonic-gate 		;
1310Sstevel@tonic-gate 	while ((arg = getopt(argc, argv, c_ptr->c_optstr)) != -1) {
1320Sstevel@tonic-gate 			switch (arg) {
1330Sstevel@tonic-gate 			case 'V':	/* echo complete command line */
1340Sstevel@tonic-gate 				verbose = 1;
1350Sstevel@tonic-gate 				break;
1360Sstevel@tonic-gate 			case 'F':	/* FSType specified */
1370Sstevel@tonic-gate 				F_flg++;
1380Sstevel@tonic-gate 				fstype = optarg;
1390Sstevel@tonic-gate 				break;
1400Sstevel@tonic-gate 			case 'o':	/* FSType specific arguments */
1410Sstevel@tonic-gate 				newargv[newargc++] = "-o";
1420Sstevel@tonic-gate 				newargv[newargc++] = optarg;
1430Sstevel@tonic-gate 				break;
1440Sstevel@tonic-gate 			case '?':	/* print usage message */
1450Sstevel@tonic-gate 				newargv[newargc++] = "-?";
1460Sstevel@tonic-gate 				usgflag = 1;
1470Sstevel@tonic-gate 				break;
1480Sstevel@tonic-gate 			default:
1490Sstevel@tonic-gate 				newargv[newargc] = (char *)malloc(3);
1500Sstevel@tonic-gate 				sprintf(newargv[newargc++], "-%c", arg);
1510Sstevel@tonic-gate 				if (optarg)
1520Sstevel@tonic-gate 					newargv[newargc++] = optarg;
1530Sstevel@tonic-gate 				break;
1540Sstevel@tonic-gate 			}
1550Sstevel@tonic-gate 			optarg = NULL;
1560Sstevel@tonic-gate 	}
1570Sstevel@tonic-gate 	if (F_flg > 1) {
1580Sstevel@tonic-gate 		fprintf(stderr, "%s: more than one FSType specified\n",
1590Sstevel@tonic-gate 			cbasename);
1600Sstevel@tonic-gate 		usage(cbasename, c_ptr->c_usgstr);
1610Sstevel@tonic-gate 	}
1620Sstevel@tonic-gate 	if (F_flg && (strlen(fstype) > (size_t)FSTYPE_MAX)) {
1630Sstevel@tonic-gate 		fprintf(stderr, "%s: FSType %s exceeds %d characters\n",
1640Sstevel@tonic-gate 			cbasename, fstype, FSTYPE_MAX);
1650Sstevel@tonic-gate 		exit(2);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 	if (optind == argc) {
1680Sstevel@tonic-gate 		/* all commands except ncheck must exit now */
1690Sstevel@tonic-gate 		if (strcmp(cbasename, "ncheck") != 0) {
1700Sstevel@tonic-gate 			if ((F_flg) && (usgflag)) {
1710Sstevel@tonic-gate 				exec_specific();
1720Sstevel@tonic-gate 				exit(0);
1730Sstevel@tonic-gate 			}
1740Sstevel@tonic-gate 			usage(cbasename, c_ptr->c_usgstr);
1750Sstevel@tonic-gate 		}
1760Sstevel@tonic-gate 		if ((F_flg) && (usgflag)) {
1770Sstevel@tonic-gate 			exec_specific();
1780Sstevel@tonic-gate 			exit(0);
1790Sstevel@tonic-gate 		}
1800Sstevel@tonic-gate 		if (usgflag)
1810Sstevel@tonic-gate 			usage(cbasename, c_ptr->c_usgstr);
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 		/* open VFSTAB */
1840Sstevel@tonic-gate 		if ((fp = fopen(VFSTAB, "r")) == NULL) {
1850Sstevel@tonic-gate 			fprintf(stderr, "%s: cannot open vfstab\n", cbasename);
1860Sstevel@tonic-gate 			exit(2);
1870Sstevel@tonic-gate 		}
1880Sstevel@tonic-gate 		while ((i = getvfsent(fp, &vfsbuf)) == 0) {
1890Sstevel@tonic-gate 			if (!numbers(vfsbuf.vfs_fsckpass))
1900Sstevel@tonic-gate 				continue;
1910Sstevel@tonic-gate 			if ((F_flg) && (strcmp(fstype, vfsbuf.vfs_fstype) != 0))
1920Sstevel@tonic-gate 				continue;
1930Sstevel@tonic-gate 			fs_flag++;
1940Sstevel@tonic-gate 			fstype = vfsbuf.vfs_fstype;
1950Sstevel@tonic-gate 			newargv[newargc] = vfsbuf.vfs_special;
1960Sstevel@tonic-gate 			if (verbose) {
1970Sstevel@tonic-gate 				printf("%s -F %s ", cbasename,
1980Sstevel@tonic-gate 				    vfsbuf.vfs_fstype);
1990Sstevel@tonic-gate 				for (i = 2; newargv[i]; i++)
2000Sstevel@tonic-gate 					printf("%s\n", newargv[i]);
2010Sstevel@tonic-gate 				continue;
2020Sstevel@tonic-gate 			}
2030Sstevel@tonic-gate 			exec_specific();
2040Sstevel@tonic-gate 		}
2050Sstevel@tonic-gate 		/*
2060Sstevel@tonic-gate 		 * if (! fs_flag) {
2070Sstevel@tonic-gate 		 *	if (sysfs(GETFSIND, fstype) == (-1)) {
2080Sstevel@tonic-gate 		 *		fprintf(stderr,
2090Sstevel@tonic-gate 		 *		"%s: FSType %s not installed in the kernel\n",
2100Sstevel@tonic-gate 		 *			cbasename, fstype);
2110Sstevel@tonic-gate 		 *		exit(1);
2120Sstevel@tonic-gate 		 *	}
2130Sstevel@tonic-gate 		 * }
2140Sstevel@tonic-gate 		 */
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 		exit(0);
2170Sstevel@tonic-gate 	}
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	/* All other arguments must be specials */
2200Sstevel@tonic-gate 	/*  perform a lookup if fstype is not specified  */
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	for (; optind < argc; optind++)  {
2230Sstevel@tonic-gate 		newargv[newargc] = argv[optind];
2240Sstevel@tonic-gate 		special = newargv[newargc];
2250Sstevel@tonic-gate 		if ((F_flg) && (usgflag)) {
2260Sstevel@tonic-gate 			exec_specific();
2270Sstevel@tonic-gate 			exit(0);
2280Sstevel@tonic-gate 		}
2290Sstevel@tonic-gate 		if (usgflag)
2300Sstevel@tonic-gate 			usage(cbasename, c_ptr->c_usgstr);
2310Sstevel@tonic-gate 		if (fstype == NULL)
2320Sstevel@tonic-gate 			lookup();
2330Sstevel@tonic-gate 		if (verbose) {
2340Sstevel@tonic-gate 			printf("%s -F %s ", cbasename, fstype);
2350Sstevel@tonic-gate 			for (i = 2; newargv[i]; i++)
2360Sstevel@tonic-gate 				printf("%s ", newargv[i]);
2370Sstevel@tonic-gate 			printf("\n");
2380Sstevel@tonic-gate 			continue;
2390Sstevel@tonic-gate 		}
2400Sstevel@tonic-gate 		exec_specific();
2410Sstevel@tonic-gate 		if (!F_flg)
2420Sstevel@tonic-gate 			fstype = NULL;
2430Sstevel@tonic-gate 	}
244*821Sdh145677 	return (0);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate /* see if all numbers */
248*821Sdh145677 int
249*821Sdh145677 numbers(char *yp)
2500Sstevel@tonic-gate {
2510Sstevel@tonic-gate 	if (yp == NULL)
2520Sstevel@tonic-gate 		return (0);
2530Sstevel@tonic-gate 	while ('0' <= *yp && *yp <= '9')
2540Sstevel@tonic-gate 		yp++;
2550Sstevel@tonic-gate 	if (*yp)
2560Sstevel@tonic-gate 		return (0);
2570Sstevel@tonic-gate 	return (1);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
260*821Sdh145677 static void
261*821Sdh145677 usage(char *cmd, char *usg)
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate 	fprintf(stderr, "Usage:\n");
2640Sstevel@tonic-gate 	fprintf(stderr, "%s %s\n", cmd, usg);
2650Sstevel@tonic-gate 	exit(2);
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate /*
2700Sstevel@tonic-gate  *  This looks up the /etc/vfstab entry given the device 'special'.
2710Sstevel@tonic-gate  *  It is called when the fstype is not specified on the command line.
2720Sstevel@tonic-gate  *
2730Sstevel@tonic-gate  *  The following global variables are used:
2740Sstevel@tonic-gate  *	special, fstype
2750Sstevel@tonic-gate  */
2760Sstevel@tonic-gate 
277*821Sdh145677 static void
278*821Sdh145677 lookup(void)
2790Sstevel@tonic-gate {
2800Sstevel@tonic-gate 	FILE	*fd;
2810Sstevel@tonic-gate 	int	ret;
2820Sstevel@tonic-gate 	struct vfstab	vget, vref;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	if ((fd = fopen(vfstab, "r")) == NULL) {
2850Sstevel@tonic-gate 		fprintf(stderr, "%s: cannot open vfstab\n", cbasename);
2860Sstevel@tonic-gate 		exit(1);
2870Sstevel@tonic-gate 	}
2880Sstevel@tonic-gate 	vfsnull(&vref);
2890Sstevel@tonic-gate 	vref.vfs_special = special;
2900Sstevel@tonic-gate 	ret = getvfsany(fd, &vget, &vref);
2910Sstevel@tonic-gate 	if (ret == -1) {
2920Sstevel@tonic-gate 		rewind(fd);
2930Sstevel@tonic-gate 		vfsnull(&vref);
2940Sstevel@tonic-gate 		vref.vfs_fsckdev = special;
2950Sstevel@tonic-gate 		ret = getvfsany(fd, &vget, &vref);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 	fclose(fd);
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	switch (ret) {
3000Sstevel@tonic-gate 	case -1:
3010Sstevel@tonic-gate 		fstype = default_fstype(special);
3020Sstevel@tonic-gate 		break;
3030Sstevel@tonic-gate 	case 0:
3040Sstevel@tonic-gate 		fstype = vget.vfs_fstype;
3050Sstevel@tonic-gate 		break;
3060Sstevel@tonic-gate 	case VFS_TOOLONG:
3070Sstevel@tonic-gate 		fprintf(stderr, "%s: line in vfstab exceeds %d characters\n",
3080Sstevel@tonic-gate 			cbasename, VFS_LINE_MAX-2);
3090Sstevel@tonic-gate 		exit(1);
3100Sstevel@tonic-gate 		break;
3110Sstevel@tonic-gate 	case VFS_TOOFEW:
3120Sstevel@tonic-gate 		fprintf(stderr, "%s: line in vfstab has too few entries\n",
3130Sstevel@tonic-gate 			cbasename);
3140Sstevel@tonic-gate 		exit(1);
3150Sstevel@tonic-gate 		break;
3160Sstevel@tonic-gate 	case VFS_TOOMANY:
3170Sstevel@tonic-gate 		fprintf(stderr, "%s: line in vfstab has too many entries\n",
3180Sstevel@tonic-gate 			cbasename);
3190Sstevel@tonic-gate 		exit(1);
3200Sstevel@tonic-gate 		break;
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate }
323*821Sdh145677 
324*821Sdh145677 static void
325*821Sdh145677 exec_specific(void)
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate int status, pid, ret;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	sprintf(full_path, "%s/%s/%s", vfs_path, fstype, cbasename);
3300Sstevel@tonic-gate 	newargv[1] = &full_path[FULLPATH_MAX];
3310Sstevel@tonic-gate 	while (*newargv[1]-- != '/');
3320Sstevel@tonic-gate 	newargv[1] += 2;
3330Sstevel@tonic-gate 	switch (pid = fork()) {
3340Sstevel@tonic-gate 	case 0:
3350Sstevel@tonic-gate 		execv(full_path, &newargv[1]);
3360Sstevel@tonic-gate 		if (errno == ENOEXEC) {
3370Sstevel@tonic-gate 			newargv[0] = "sh";
3380Sstevel@tonic-gate 			newargv[1] = full_path;
3390Sstevel@tonic-gate 			execv("/sbin/sh", &newargv[0]);
3400Sstevel@tonic-gate 		}
3410Sstevel@tonic-gate 		if (errno != ENOENT) {
3420Sstevel@tonic-gate 			perror(cbasename);
3430Sstevel@tonic-gate 			fprintf(stderr, "%s: cannot execute %s\n", cbasename,
3440Sstevel@tonic-gate 			    full_path);
3450Sstevel@tonic-gate 			exit(1);
3460Sstevel@tonic-gate 		}
3470Sstevel@tonic-gate 		if (sysfs(GETFSIND, fstype) == (-1)) {
3480Sstevel@tonic-gate 			fprintf(stderr,
3490Sstevel@tonic-gate 				"%s: FSType %s not installed in the kernel\n",
3500Sstevel@tonic-gate 				cbasename, fstype);
3510Sstevel@tonic-gate 			exit(1);
3520Sstevel@tonic-gate 		}
3530Sstevel@tonic-gate 		fprintf(stderr, "%s: operation not applicable for FSType %s\n",
3540Sstevel@tonic-gate 		    cbasename, fstype);
3550Sstevel@tonic-gate 		exit(1);
3560Sstevel@tonic-gate 	case -1:
3570Sstevel@tonic-gate 		fprintf(stderr, "%s: cannot fork process\n", cbasename);
3580Sstevel@tonic-gate 		exit(2);
3590Sstevel@tonic-gate 	default:
3600Sstevel@tonic-gate 		/*
3610Sstevel@tonic-gate 		 * if cannot exec specific, or fstype is not installed, exit
3620Sstevel@tonic-gate 		 * after first 'exec_specific' to avoid printing duplicate
3630Sstevel@tonic-gate 		 * error messages
3640Sstevel@tonic-gate 		 */
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 		if (wait(&status) == pid) {
3670Sstevel@tonic-gate 			ret = WHIBYTE(status);
3680Sstevel@tonic-gate 			if (ret > 0) {
3690Sstevel@tonic-gate 				exit(ret);
3700Sstevel@tonic-gate 			}
3710Sstevel@tonic-gate 		}
3720Sstevel@tonic-gate 	}
3730Sstevel@tonic-gate }
374