Merge commit '7d815089a43a963b49eaddf97e514194ec29805b'
[unleashed.git] / usr / src / cmd / fs.d / ff.c
blobe11b072371f9fe81cf855848ae7c99dbd1b24b13
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <limits.h>
34 #include <string.h>
35 #include <sys/fstyp.h>
36 #include <errno.h>
37 #include <sys/vfstab.h>
38 #include <sys/wait.h>
39 #include <sys/types.h>
41 #define FSTYPE_MAX 8
42 #define FULLPATH_MAX 64
43 #define ARGV_MAX 1024
44 #define VFS_PATH "/usr/lib/fs"
46 extern char *default_fstype();
48 char *special = NULL; /* device special name */
49 char *fstype = NULL; /* fstype name is filled in here */
50 char *cbasename; /* name of command */
51 char *newargv[ARGV_MAX]; /* args for the fstype specific command */
52 char vfstab[] = VFSTAB;
53 char full_path[FULLPATH_MAX];
54 char *vfs_path = VFS_PATH;
55 int newargc = 2;
57 struct commands {
58 char *c_basename;
59 char *c_optstr;
60 char *c_usgstr;
61 } cmd_data[] = {
62 "ff", "F:o:p:a:m:c:n:i:?IlsuV",
63 "[-F FSType] [-V] [current_options] [-o specific_options] special ...",
64 "ncheck", "F:o:?i:asV",
65 "[-F FSType] [-V] [current_options] [-o specific_options] [special ...]",
66 NULL, "F:o:?V",
67 "[-F FSType] [-V] [current_options] [-o specific_options] special ..."
69 struct commands *c_ptr;
71 static void usage(char *cmd, char *usg);
72 static void exec_specific(void);
73 static void lookup(void);
75 int
76 main(int argc, char *argv[])
78 FILE *fp;
79 struct vfstab vfsbuf;
80 char *ptr;
81 int i;
82 int verbose = 0; /* set if -V is specified */
83 int F_flg = 0;
84 int usgflag = 0;
85 int fs_flag = 0;
86 int arg; /* argument from getopt() */
87 extern char *optarg; /* getopt specific */
88 extern int optind;
89 extern int opterr;
90 size_t strlen();
92 cbasename = ptr = argv[0];
93 while (*ptr) {
94 if (*ptr++ == '/')
95 cbasename = ptr;
98 * If there are no arguments and command is ncheck then the generic
99 * reads the VFSTAB and executes the specific module of
100 * each entry which has a numeric fsckpass field.
103 if (argc == 1) { /* no arguments or options */
104 if (strcmp(cbasename, "ncheck") == 0) {
105 /* open VFSTAB */
106 if ((fp = fopen(VFSTAB, "r")) == NULL) {
107 fprintf(stderr, "%s: cannot open vfstab\n",
108 cbasename);
109 exit(2);
111 while ((i = getvfsent(fp, &vfsbuf)) == 0) {
112 if (numbers(vfsbuf.vfs_fsckpass)) {
113 fstype = vfsbuf.vfs_fstype;
114 newargv[newargc] = vfsbuf.vfs_special;
115 exec_specific();
118 exit(0);
120 fprintf(stderr, "Usage:\n");
121 fprintf(stderr,
122 "%s [-F FSType] [-V] [current_options] [-o specific_options] special ...\n",
123 cbasename);
124 exit(2);
127 for (c_ptr = cmd_data; ((c_ptr->c_basename != NULL) &&
128 (strcmp(c_ptr->c_basename, cbasename) != 0)); c_ptr++)
130 while ((arg = getopt(argc, argv, c_ptr->c_optstr)) != -1) {
131 switch (arg) {
132 case 'V': /* echo complete command line */
133 verbose = 1;
134 break;
135 case 'F': /* FSType specified */
136 F_flg++;
137 fstype = optarg;
138 break;
139 case 'o': /* FSType specific arguments */
140 newargv[newargc++] = "-o";
141 newargv[newargc++] = optarg;
142 break;
143 case '?': /* print usage message */
144 newargv[newargc++] = "-?";
145 usgflag = 1;
146 break;
147 default:
148 newargv[newargc] = (char *)malloc(3);
149 sprintf(newargv[newargc++], "-%c", arg);
150 if (optarg)
151 newargv[newargc++] = optarg;
152 break;
154 optarg = NULL;
156 if (F_flg > 1) {
157 fprintf(stderr, "%s: more than one FSType specified\n",
158 cbasename);
159 usage(cbasename, c_ptr->c_usgstr);
161 if (F_flg && (strlen(fstype) > (size_t)FSTYPE_MAX)) {
162 fprintf(stderr, "%s: FSType %s exceeds %d characters\n",
163 cbasename, fstype, FSTYPE_MAX);
164 exit(2);
166 if (optind == argc) {
167 /* all commands except ncheck must exit now */
168 if (strcmp(cbasename, "ncheck") != 0) {
169 if ((F_flg) && (usgflag)) {
170 exec_specific();
171 exit(0);
173 usage(cbasename, c_ptr->c_usgstr);
175 if ((F_flg) && (usgflag)) {
176 exec_specific();
177 exit(0);
179 if (usgflag)
180 usage(cbasename, c_ptr->c_usgstr);
182 /* open VFSTAB */
183 if ((fp = fopen(VFSTAB, "r")) == NULL) {
184 fprintf(stderr, "%s: cannot open vfstab\n", cbasename);
185 exit(2);
187 while ((i = getvfsent(fp, &vfsbuf)) == 0) {
188 if (!numbers(vfsbuf.vfs_fsckpass))
189 continue;
190 if ((F_flg) && (strcmp(fstype, vfsbuf.vfs_fstype) != 0))
191 continue;
192 fs_flag++;
193 fstype = vfsbuf.vfs_fstype;
194 newargv[newargc] = vfsbuf.vfs_special;
195 if (verbose) {
196 printf("%s -F %s ", cbasename,
197 vfsbuf.vfs_fstype);
198 for (i = 2; newargv[i]; i++)
199 printf("%s\n", newargv[i]);
200 continue;
202 exec_specific();
205 * if (! fs_flag) {
206 * if (sysfs(GETFSIND, fstype) == (-1)) {
207 * fprintf(stderr,
208 * "%s: FSType %s not installed in the kernel\n",
209 * cbasename, fstype);
210 * exit(1);
215 exit(0);
218 /* All other arguments must be specials */
219 /* perform a lookup if fstype is not specified */
221 for (; optind < argc; optind++) {
222 newargv[newargc] = argv[optind];
223 special = newargv[newargc];
224 if ((F_flg) && (usgflag)) {
225 exec_specific();
226 exit(0);
228 if (usgflag)
229 usage(cbasename, c_ptr->c_usgstr);
230 if (fstype == NULL)
231 lookup();
232 if (verbose) {
233 printf("%s -F %s ", cbasename, fstype);
234 for (i = 2; newargv[i]; i++)
235 printf("%s ", newargv[i]);
236 printf("\n");
237 continue;
239 exec_specific();
240 if (!F_flg)
241 fstype = NULL;
243 return (0);
246 /* see if all numbers */
248 numbers(char *yp)
250 if (yp == NULL)
251 return (0);
252 while ('0' <= *yp && *yp <= '9')
253 yp++;
254 if (*yp)
255 return (0);
256 return (1);
259 static void
260 usage(char *cmd, char *usg)
262 fprintf(stderr, "Usage:\n");
263 fprintf(stderr, "%s %s\n", cmd, usg);
264 exit(2);
269 * This looks up the /etc/vfstab entry given the device 'special'.
270 * It is called when the fstype is not specified on the command line.
272 * The following global variables are used:
273 * special, fstype
276 static void
277 lookup(void)
279 FILE *fd;
280 int ret;
281 struct vfstab vget, vref;
283 if ((fd = fopen(vfstab, "r")) == NULL) {
284 fprintf(stderr, "%s: cannot open vfstab\n", cbasename);
285 exit(1);
287 vfsnull(&vref);
288 vref.vfs_special = special;
289 ret = getvfsany(fd, &vget, &vref);
290 if (ret == -1) {
291 rewind(fd);
292 vfsnull(&vref);
293 vref.vfs_fsckdev = special;
294 ret = getvfsany(fd, &vget, &vref);
296 fclose(fd);
298 switch (ret) {
299 case -1:
300 fstype = default_fstype(special);
301 break;
302 case 0:
303 fstype = vget.vfs_fstype;
304 break;
305 case VFS_TOOLONG:
306 fprintf(stderr, "%s: line in vfstab exceeds %d characters\n",
307 cbasename, VFS_LINE_MAX-2);
308 exit(1);
309 break;
310 case VFS_TOOFEW:
311 fprintf(stderr, "%s: line in vfstab has too few entries\n",
312 cbasename);
313 exit(1);
314 break;
315 case VFS_TOOMANY:
316 fprintf(stderr, "%s: line in vfstab has too many entries\n",
317 cbasename);
318 exit(1);
319 break;
323 static void
324 exec_specific(void)
326 int status, pid, ret;
328 sprintf(full_path, "%s/%s/%s", vfs_path, fstype, cbasename);
329 newargv[1] = &full_path[FULLPATH_MAX];
330 while (*newargv[1]-- != '/');
331 newargv[1] += 2;
332 switch (pid = fork()) {
333 case 0:
334 execv(full_path, &newargv[1]);
335 if (errno == ENOEXEC) {
336 newargv[0] = "sh";
337 newargv[1] = full_path;
338 execv("/sbin/sh", &newargv[0]);
340 if (errno != ENOENT) {
341 perror(cbasename);
342 fprintf(stderr, "%s: cannot execute %s\n", cbasename,
343 full_path);
344 exit(1);
346 if (sysfs(GETFSIND, fstype) == (-1)) {
347 fprintf(stderr,
348 "%s: FSType %s not installed in the kernel\n",
349 cbasename, fstype);
350 exit(1);
352 fprintf(stderr, "%s: operation not applicable for FSType %s\n",
353 cbasename, fstype);
354 exit(1);
355 case -1:
356 fprintf(stderr, "%s: cannot fork process\n", cbasename);
357 exit(2);
358 default:
360 * if cannot exec specific, or fstype is not installed, exit
361 * after first 'exec_specific' to avoid printing duplicate
362 * error messages
365 if (wait(&status) == pid) {
366 ret = WHIBYTE(status);
367 if (ret > 0) {
368 exit(ret);