xref: /titanic_51/usr/src/cmd/fs.d/ff.c (revision bd335c6465ddbafe543900df4b03247bfa288eff)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright 1996-2003 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include	<stdio.h>
34 #include 	<limits.h>
35 #include	<string.h>
36 #include	<sys/fstyp.h>
37 #include	<errno.h>
38 #include	<sys/vfstab.h>
39 #include	<sys/wait.h>
40 #include	<sys/types.h>
41 
42 #define	FSTYPE_MAX	8
43 #define	FULLPATH_MAX	64
44 #define	ARGV_MAX	1024
45 #define	VFS_PATH	"/usr/lib/fs"
46 
47 extern char	*default_fstype();
48 
49 char	*special = NULL;  /*  device special name  */
50 char	*fstype = NULL;	  /*  fstype name is filled in here  */
51 char	*cbasename;	  /* name of command */
52 char	*newargv[ARGV_MAX]; 	/* args for the fstype specific command  */
53 char	vfstab[] = VFSTAB;
54 	char	full_path[FULLPATH_MAX];
55 	char	*vfs_path = VFS_PATH;
56 int	newargc = 2;
57 
58 struct commands {
59 	char *c_basename;
60 	char *c_optstr;
61 	char *c_usgstr;
62 } cmd_data[] = {
63 	"ff", "F:o:p:a:m:c:n:i:?IlsuV",
64 	"[-F FSType] [-V] [current_options] [-o specific_options] special ...",
65 	"ncheck", "F:o:?i:asV",
66 "[-F FSType] [-V] [current_options] [-o specific_options] [special ...]",
67 	NULL, "F:o:?V",
68 	"[-F FSType] [-V] [current_options] [-o specific_options] special ..."
69 	};
70 struct 	commands *c_ptr;
71 
72 main(argc, argv)
73 int	argc;
74 char	*argv[];
75 {
76 	FILE *fp;
77 	struct vfstab	vfsbuf;
78 	register char *ptr;
79 	int	i;
80 	int	verbose = 0;		/* set if -V is specified */
81 	int	F_flg = 0;
82 	int	usgflag = 0;
83 	int	fs_flag = 0;
84 	int	arg;			/* argument from getopt() */
85 	extern	char *optarg;		/* getopt specific */
86 	extern	int optind;
87 	extern	int opterr;
88 	size_t	strlen();
89 
90 	cbasename = ptr = argv[0];
91 	while (*ptr) {
92 		if (*ptr++ == '/')
93 			cbasename = ptr;
94 	}
95 	/*
96 	 * If there are no arguments and command is ncheck then the generic
97 	 * reads the VFSTAB and executes the specific module of
98 	 * each entry which has a numeric fsckpass field.
99 	 */
100 
101 	if (argc == 1) {		/* no arguments or options */
102 		if (strcmp(cbasename, "ncheck") == 0) {
103 			/* open VFSTAB */
104 			if ((fp = fopen(VFSTAB, "r")) == NULL) {
105 				fprintf(stderr, "%s: cannot open vfstab\n",
106 				    cbasename);
107 				exit(2);
108 			}
109 			while ((i = getvfsent(fp, &vfsbuf)) == 0) {
110 				if (numbers(vfsbuf.vfs_fsckpass)) {
111 					fstype = vfsbuf.vfs_fstype;
112 					newargv[newargc]  = vfsbuf.vfs_special;
113 					exec_specific();
114 				}
115 			}
116 			exit(0);
117 		}
118 		fprintf(stderr, "Usage:\n");
119 		fprintf(stderr,
120 "%s [-F FSType] [-V] [current_options] [-o specific_options] special ...\n",
121 		    cbasename);
122 		exit(2);
123 	}
124 
125 	for (c_ptr = cmd_data; ((c_ptr->c_basename != NULL) &&
126 	    (strcmp(c_ptr->c_basename, cbasename) != 0));  c_ptr++)
127 		;
128 	while ((arg = getopt(argc, argv, c_ptr->c_optstr)) != -1) {
129 			switch (arg) {
130 			case 'V':	/* echo complete command line */
131 				verbose = 1;
132 				break;
133 			case 'F':	/* FSType specified */
134 				F_flg++;
135 				fstype = optarg;
136 				break;
137 			case 'o':	/* FSType specific arguments */
138 				newargv[newargc++] = "-o";
139 				newargv[newargc++] = optarg;
140 				break;
141 			case '?':	/* print usage message */
142 				newargv[newargc++] = "-?";
143 				usgflag = 1;
144 				break;
145 			default:
146 				newargv[newargc] = (char *)malloc(3);
147 				sprintf(newargv[newargc++], "-%c", arg);
148 				if (optarg)
149 					newargv[newargc++] = optarg;
150 				break;
151 			}
152 			optarg = NULL;
153 	}
154 	if (F_flg > 1) {
155 		fprintf(stderr, "%s: more than one FSType specified\n",
156 			cbasename);
157 		usage(cbasename, c_ptr->c_usgstr);
158 	}
159 	if (F_flg && (strlen(fstype) > (size_t)FSTYPE_MAX)) {
160 		fprintf(stderr, "%s: FSType %s exceeds %d characters\n",
161 			cbasename, fstype, FSTYPE_MAX);
162 		exit(2);
163 	}
164 	if (optind == argc) {
165 		/* all commands except ncheck must exit now */
166 		if (strcmp(cbasename, "ncheck") != 0) {
167 			if ((F_flg) && (usgflag)) {
168 				exec_specific();
169 				exit(0);
170 			}
171 			usage(cbasename, c_ptr->c_usgstr);
172 		}
173 		if ((F_flg) && (usgflag)) {
174 			exec_specific();
175 			exit(0);
176 		}
177 		if (usgflag)
178 			usage(cbasename, c_ptr->c_usgstr);
179 
180 		/* open VFSTAB */
181 		if ((fp = fopen(VFSTAB, "r")) == NULL) {
182 			fprintf(stderr, "%s: cannot open vfstab\n", cbasename);
183 			exit(2);
184 		}
185 		while ((i = getvfsent(fp, &vfsbuf)) == 0) {
186 			if (!numbers(vfsbuf.vfs_fsckpass))
187 				continue;
188 			if ((F_flg) && (strcmp(fstype, vfsbuf.vfs_fstype) != 0))
189 				continue;
190 			fs_flag++;
191 			fstype = vfsbuf.vfs_fstype;
192 			newargv[newargc] = vfsbuf.vfs_special;
193 			if (verbose) {
194 				printf("%s -F %s ", cbasename,
195 				    vfsbuf.vfs_fstype);
196 				for (i = 2; newargv[i]; i++)
197 					printf("%s\n", newargv[i]);
198 				continue;
199 			}
200 			exec_specific();
201 		}
202 		/*
203 		 * if (! fs_flag) {
204 		 *	if (sysfs(GETFSIND, fstype) == (-1)) {
205 		 *		fprintf(stderr,
206 		 *		"%s: FSType %s not installed in the kernel\n",
207 		 *			cbasename, fstype);
208 		 *		exit(1);
209 		 *	}
210 		 * }
211 		 */
212 
213 		exit(0);
214 	}
215 
216 	/* All other arguments must be specials */
217 	/*  perform a lookup if fstype is not specified  */
218 
219 	for (; optind < argc; optind++)  {
220 		newargv[newargc] = argv[optind];
221 		special = newargv[newargc];
222 		if ((F_flg) && (usgflag)) {
223 			exec_specific();
224 			exit(0);
225 		}
226 		if (usgflag)
227 			usage(cbasename, c_ptr->c_usgstr);
228 		if (fstype == NULL)
229 			lookup();
230 		if (verbose) {
231 			printf("%s -F %s ", cbasename, fstype);
232 			for (i = 2; newargv[i]; i++)
233 				printf("%s ", newargv[i]);
234 			printf("\n");
235 			continue;
236 		}
237 		exec_specific();
238 		if (!F_flg)
239 			fstype = NULL;
240 	}
241 	exit(0);
242 }
243 
244 /* see if all numbers */
245 numbers(yp)
246 	char	*yp;
247 {
248 	if (yp == NULL)
249 		return (0);
250 	while ('0' <= *yp && *yp <= '9')
251 		yp++;
252 	if (*yp)
253 		return (0);
254 	return (1);
255 }
256 
257 
258 usage(cmd, usg)
259 char *cmd, *usg;
260 {
261 	fprintf(stderr, "Usage:\n");
262 	fprintf(stderr, "%s %s\n", cmd, usg);
263 	exit(2);
264 }
265 
266 
267 /*
268  *  This looks up the /etc/vfstab entry given the device 'special'.
269  *  It is called when the fstype is not specified on the command line.
270  *
271  *  The following global variables are used:
272  *	special, fstype
273  */
274 
275 lookup()
276 {
277 	FILE	*fd;
278 	int	ret;
279 	struct vfstab	vget, vref;
280 
281 	if ((fd = fopen(vfstab, "r")) == NULL) {
282 		fprintf(stderr, "%s: cannot open vfstab\n", cbasename);
283 		exit(1);
284 	}
285 	vfsnull(&vref);
286 	vref.vfs_special = special;
287 	ret = getvfsany(fd, &vget, &vref);
288 	if (ret == -1) {
289 		rewind(fd);
290 		vfsnull(&vref);
291 		vref.vfs_fsckdev = special;
292 		ret = getvfsany(fd, &vget, &vref);
293 	}
294 	fclose(fd);
295 
296 	switch (ret) {
297 	case -1:
298 		fstype = default_fstype(special);
299 		break;
300 	case 0:
301 		fstype = vget.vfs_fstype;
302 		break;
303 	case VFS_TOOLONG:
304 		fprintf(stderr, "%s: line in vfstab exceeds %d characters\n",
305 			cbasename, VFS_LINE_MAX-2);
306 		exit(1);
307 		break;
308 	case VFS_TOOFEW:
309 		fprintf(stderr, "%s: line in vfstab has too few entries\n",
310 			cbasename);
311 		exit(1);
312 		break;
313 	case VFS_TOOMANY:
314 		fprintf(stderr, "%s: line in vfstab has too many entries\n",
315 			cbasename);
316 		exit(1);
317 		break;
318 	}
319 }
320 exec_specific()
321 {
322 int status, pid, ret;
323 
324 	sprintf(full_path, "%s/%s/%s", vfs_path, fstype, cbasename);
325 	newargv[1] = &full_path[FULLPATH_MAX];
326 	while (*newargv[1]-- != '/');
327 	newargv[1] += 2;
328 	switch (pid = fork()) {
329 	case 0:
330 		execv(full_path, &newargv[1]);
331 		if (errno == ENOEXEC) {
332 			newargv[0] = "sh";
333 			newargv[1] = full_path;
334 			execv("/sbin/sh", &newargv[0]);
335 		}
336 		if (errno != ENOENT) {
337 			perror(cbasename);
338 			fprintf(stderr, "%s: cannot execute %s\n", cbasename,
339 			    full_path);
340 			exit(1);
341 		}
342 		if (sysfs(GETFSIND, fstype) == (-1)) {
343 			fprintf(stderr,
344 				"%s: FSType %s not installed in the kernel\n",
345 				cbasename, fstype);
346 			exit(1);
347 		}
348 		fprintf(stderr, "%s: operation not applicable for FSType %s\n",
349 		    cbasename, fstype);
350 		exit(1);
351 	case -1:
352 		fprintf(stderr, "%s: cannot fork process\n", cbasename);
353 		exit(2);
354 	default:
355 		/*
356 		 * if cannot exec specific, or fstype is not installed, exit
357 		 * after first 'exec_specific' to avoid printing duplicate
358 		 * error messages
359 		 */
360 
361 		if (wait(&status) == pid) {
362 			ret = WHIBYTE(status);
363 			if (ret > 0) {
364 				exit(ret);
365 			}
366 		}
367 	}
368 }
369