xref: /onnv-gate/usr/src/cmd/fs.d/udfs/fsck/main.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*0Sstevel@tonic-gate 
9*0Sstevel@tonic-gate /*
10*0Sstevel@tonic-gate  * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11*0Sstevel@tonic-gate  * All rights reserved.
12*0Sstevel@tonic-gate  *
13*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
14*0Sstevel@tonic-gate  * provided that: (1) source distributions retain this entire copyright
15*0Sstevel@tonic-gate  * notice and comment, and (2) distributions including binaries display
16*0Sstevel@tonic-gate  * the following acknowledgement:  ``This product includes software
17*0Sstevel@tonic-gate  * developed by the University of California, Berkeley and its contributors''
18*0Sstevel@tonic-gate  * in the documentation or other materials provided with the distribution
19*0Sstevel@tonic-gate  * and in all advertising materials mentioning features or use of this
20*0Sstevel@tonic-gate  * software. Neither the name of the University nor the names of its
21*0Sstevel@tonic-gate  * contributors may be used to endorse or promote products derived
22*0Sstevel@tonic-gate  * from this software without specific prior written permission.
23*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24*0Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25*0Sstevel@tonic-gate  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26*0Sstevel@tonic-gate  */
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #include <stdio.h>
31*0Sstevel@tonic-gate #include <string.h>
32*0Sstevel@tonic-gate #include <ctype.h>	/* use isdigit macro rather than 4.1 libc routine */
33*0Sstevel@tonic-gate #include <unistd.h>
34*0Sstevel@tonic-gate #include <stdlib.h>
35*0Sstevel@tonic-gate #include <signal.h>
36*0Sstevel@tonic-gate #include <malloc.h>
37*0Sstevel@tonic-gate #include <ustat.h>
38*0Sstevel@tonic-gate #include <sys/param.h>
39*0Sstevel@tonic-gate #include <sys/types.h>
40*0Sstevel@tonic-gate #include <sys/sysmacros.h>
41*0Sstevel@tonic-gate #include <sys/mntent.h>
42*0Sstevel@tonic-gate #include <sys/vnode.h>
43*0Sstevel@tonic-gate #include <sys/stat.h>
44*0Sstevel@tonic-gate #include <sys/wait.h>
45*0Sstevel@tonic-gate #include <sys/mnttab.h>
46*0Sstevel@tonic-gate #include <sys/signal.h>
47*0Sstevel@tonic-gate #include <sys/vfstab.h>
48*0Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
49*0Sstevel@tonic-gate #include "fsck.h"
50*0Sstevel@tonic-gate #include <locale.h>
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate extern int32_t	writable(char *);
53*0Sstevel@tonic-gate extern void	pfatal(char *, ...);
54*0Sstevel@tonic-gate extern void	printfree();
55*0Sstevel@tonic-gate extern void	pwarn(char *, ...);
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate extern void	pass1();
58*0Sstevel@tonic-gate extern void	dofreemap();
59*0Sstevel@tonic-gate extern void	dolvint();
60*0Sstevel@tonic-gate extern char	*getfullblkname();
61*0Sstevel@tonic-gate extern char	*getfullrawname();
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate static int	mflag = 0;		/* sanity check only */
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate char	*mntopt();
66*0Sstevel@tonic-gate void	catch(), catchquit(), voidquit();
67*0Sstevel@tonic-gate int	returntosingle;
68*0Sstevel@tonic-gate static void	checkfilesys();
69*0Sstevel@tonic-gate static void	check_sanity();
70*0Sstevel@tonic-gate static void	usage();
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate static char *subopts [] = {
73*0Sstevel@tonic-gate #define	PREEN		0
74*0Sstevel@tonic-gate 	"p",
75*0Sstevel@tonic-gate #define	DEBUG		1
76*0Sstevel@tonic-gate 	"d",
77*0Sstevel@tonic-gate #define	READ_ONLY	2
78*0Sstevel@tonic-gate 	"r",
79*0Sstevel@tonic-gate #define	ONLY_WRITES	3
80*0Sstevel@tonic-gate 	"w",
81*0Sstevel@tonic-gate #define	FORCE		4	/* force checking, even if clean */
82*0Sstevel@tonic-gate 	"f",
83*0Sstevel@tonic-gate #define	STATS		5	/* print time and busy stats */
84*0Sstevel@tonic-gate 	"s",
85*0Sstevel@tonic-gate 	NULL
86*0Sstevel@tonic-gate };
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate uint32_t ecma_version = 2;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate void
91*0Sstevel@tonic-gate main(argc, argv)
92*0Sstevel@tonic-gate 	int	argc;
93*0Sstevel@tonic-gate 	char	*argv[];
94*0Sstevel@tonic-gate {
95*0Sstevel@tonic-gate 	int	c;
96*0Sstevel@tonic-gate 	char	*suboptions,	*value;
97*0Sstevel@tonic-gate 	int	suboption;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "mnNo:VyYz")) != EOF) {
102*0Sstevel@tonic-gate 		switch (c) {
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 		case 'm':
105*0Sstevel@tonic-gate 			mflag++;
106*0Sstevel@tonic-gate 			break;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 		case 'n':	/* default no answer flag */
109*0Sstevel@tonic-gate 		case 'N':
110*0Sstevel@tonic-gate 			nflag++;
111*0Sstevel@tonic-gate 			yflag = 0;
112*0Sstevel@tonic-gate 			break;
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 		case 'o':
115*0Sstevel@tonic-gate 			/*
116*0Sstevel@tonic-gate 			 * udfs specific options.
117*0Sstevel@tonic-gate 			 */
118*0Sstevel@tonic-gate 			suboptions = optarg;
119*0Sstevel@tonic-gate 			while (*suboptions != '\0') {
120*0Sstevel@tonic-gate 				suboption = getsubopt(&suboptions,
121*0Sstevel@tonic-gate 						subopts, &value);
122*0Sstevel@tonic-gate 				switch (suboption) {
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 				case PREEN:
125*0Sstevel@tonic-gate 					preen++;
126*0Sstevel@tonic-gate 					break;
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 				case DEBUG:
129*0Sstevel@tonic-gate 					debug++;
130*0Sstevel@tonic-gate 					break;
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 				case READ_ONLY:
133*0Sstevel@tonic-gate 					break;
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 				case ONLY_WRITES:
136*0Sstevel@tonic-gate 					/* check only writable filesystems */
137*0Sstevel@tonic-gate 					wflag++;
138*0Sstevel@tonic-gate 					break;
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 				case FORCE:
141*0Sstevel@tonic-gate 					fflag++;
142*0Sstevel@tonic-gate 					break;
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 				case STATS:
145*0Sstevel@tonic-gate 					sflag++;
146*0Sstevel@tonic-gate 					break;
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 				default:
149*0Sstevel@tonic-gate 					usage();
150*0Sstevel@tonic-gate 				}
151*0Sstevel@tonic-gate 			}
152*0Sstevel@tonic-gate 			break;
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 		case 'V':
155*0Sstevel@tonic-gate 			{
156*0Sstevel@tonic-gate 				int	opt_count;
157*0Sstevel@tonic-gate 				char	*opt_text;
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 				(void) fprintf(stdout, "fsck -F udfs ");
160*0Sstevel@tonic-gate 				for (opt_count = 1; opt_count < argc;
161*0Sstevel@tonic-gate 								opt_count++) {
162*0Sstevel@tonic-gate 					opt_text = argv[opt_count];
163*0Sstevel@tonic-gate 					if (opt_text)
164*0Sstevel@tonic-gate 						(void) fprintf(stdout, " %s ",
165*0Sstevel@tonic-gate 								opt_text);
166*0Sstevel@tonic-gate 				}
167*0Sstevel@tonic-gate 				(void) fprintf(stdout, "\n");
168*0Sstevel@tonic-gate 			}
169*0Sstevel@tonic-gate 			break;
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 		case 'y':	/* default yes answer flag */
172*0Sstevel@tonic-gate 		case 'Y':
173*0Sstevel@tonic-gate 			yflag++;
174*0Sstevel@tonic-gate 			nflag = 0;
175*0Sstevel@tonic-gate 			break;
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 		case '?':
178*0Sstevel@tonic-gate 			usage();
179*0Sstevel@tonic-gate 		}
180*0Sstevel@tonic-gate 	}
181*0Sstevel@tonic-gate 	argc -= optind;
182*0Sstevel@tonic-gate 	argv = &argv[optind];
183*0Sstevel@tonic-gate 	rflag++; /* check raw devices */
184*0Sstevel@tonic-gate 	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
185*0Sstevel@tonic-gate 		(void) signal(SIGINT, catch);
186*0Sstevel@tonic-gate 	}
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	if (preen) {
189*0Sstevel@tonic-gate 		(void) signal(SIGQUIT, catchquit);
190*0Sstevel@tonic-gate 	}
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	if (argc) {
193*0Sstevel@tonic-gate 		while (argc-- > 0) {
194*0Sstevel@tonic-gate 			if (wflag && !writable(*argv)) {
195*0Sstevel@tonic-gate 				(void) fprintf(stderr,
196*0Sstevel@tonic-gate 					gettext("not writeable '%s'\n"), *argv);
197*0Sstevel@tonic-gate 				argv++;
198*0Sstevel@tonic-gate 			} else
199*0Sstevel@tonic-gate 				checkfilesys(*argv++);
200*0Sstevel@tonic-gate 		}
201*0Sstevel@tonic-gate 		exit(exitstat);
202*0Sstevel@tonic-gate 	}
203*0Sstevel@tonic-gate }
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate static void
207*0Sstevel@tonic-gate checkfilesys(filesys)
208*0Sstevel@tonic-gate 	char *filesys;
209*0Sstevel@tonic-gate {
210*0Sstevel@tonic-gate 	char *devstr;
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	mountfd = -1;
213*0Sstevel@tonic-gate 	mountedfs = 0;
214*0Sstevel@tonic-gate 	iscorrupt = 1;
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	if ((devstr = setup(filesys)) == 0) {
217*0Sstevel@tonic-gate 		if (iscorrupt == 0)
218*0Sstevel@tonic-gate 			return;
219*0Sstevel@tonic-gate 		if (preen)
220*0Sstevel@tonic-gate 			pfatal(gettext("CAN'T CHECK FILE SYSTEM."));
221*0Sstevel@tonic-gate 		if ((exitstat == 0) && (mflag))
222*0Sstevel@tonic-gate 			exitstat = 32;
223*0Sstevel@tonic-gate 		exit(exitstat);
224*0Sstevel@tonic-gate 	}
225*0Sstevel@tonic-gate 	else
226*0Sstevel@tonic-gate 		devname = devstr;
227*0Sstevel@tonic-gate 	if (mflag)
228*0Sstevel@tonic-gate 		check_sanity(filesys);	/* this never returns */
229*0Sstevel@tonic-gate 	iscorrupt = 0;
230*0Sstevel@tonic-gate 	/*
231*0Sstevel@tonic-gate 	 * 1: scan inodes tallying blocks used
232*0Sstevel@tonic-gate 	 */
233*0Sstevel@tonic-gate 	if (preen == 0) {
234*0Sstevel@tonic-gate 		if (mountedfs)
235*0Sstevel@tonic-gate 			(void) printf(gettext("** Currently Mounted on %s\n"),
236*0Sstevel@tonic-gate 				mountpoint);
237*0Sstevel@tonic-gate 		if (mflag) {
238*0Sstevel@tonic-gate 			(void) printf(
239*0Sstevel@tonic-gate 				gettext("** Phase 1 - Sanity Check only\n"));
240*0Sstevel@tonic-gate 			return;
241*0Sstevel@tonic-gate 		} else
242*0Sstevel@tonic-gate 			(void) printf(
243*0Sstevel@tonic-gate 				gettext("** Phase 1 - Check Directories "
244*0Sstevel@tonic-gate 				"and Blocks\n"));
245*0Sstevel@tonic-gate 	}
246*0Sstevel@tonic-gate 	pass1();
247*0Sstevel@tonic-gate 	if (sflag) {
248*0Sstevel@tonic-gate 		if (preen)
249*0Sstevel@tonic-gate 			(void) printf("%s: ", devname);
250*0Sstevel@tonic-gate 		else
251*0Sstevel@tonic-gate 			(void) printf("** ");
252*0Sstevel@tonic-gate 	}
253*0Sstevel@tonic-gate 	if (debug)
254*0Sstevel@tonic-gate 		(void) printf("pass1 isdirty %d\n", isdirty);
255*0Sstevel@tonic-gate 	if (debug)
256*0Sstevel@tonic-gate 		printfree();
257*0Sstevel@tonic-gate 	dofreemap();
258*0Sstevel@tonic-gate 	dolvint();
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	/*
261*0Sstevel@tonic-gate 	 * print out summary statistics
262*0Sstevel@tonic-gate 	 */
263*0Sstevel@tonic-gate 	pwarn(gettext("%d files, %d dirs, %d used, %d free\n"), n_files, n_dirs,
264*0Sstevel@tonic-gate 		n_blks, part_len - n_blks);
265*0Sstevel@tonic-gate 	if (iscorrupt)
266*0Sstevel@tonic-gate 		exitstat = 36;
267*0Sstevel@tonic-gate 	if (!fsmodified)
268*0Sstevel@tonic-gate 		return;
269*0Sstevel@tonic-gate 	if (!preen)
270*0Sstevel@tonic-gate 		(void) printf(
271*0Sstevel@tonic-gate 			gettext("\n***** FILE SYSTEM WAS MODIFIED *****\n"));
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 	if (mountedfs) {
274*0Sstevel@tonic-gate 		exitstat = 40;
275*0Sstevel@tonic-gate 	}
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate /*
280*0Sstevel@tonic-gate  * exit 0 - file system is unmounted and okay
281*0Sstevel@tonic-gate  * exit 32 - file system is unmounted and needs checking
282*0Sstevel@tonic-gate  * exit 33 - file system is mounted
283*0Sstevel@tonic-gate  *	for root file system
284*0Sstevel@tonic-gate  * exit 34 - cannot stat device
285*0Sstevel@tonic-gate  */
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate static void
288*0Sstevel@tonic-gate check_sanity(filename)
289*0Sstevel@tonic-gate char	*filename;
290*0Sstevel@tonic-gate {
291*0Sstevel@tonic-gate 	struct stat stbd, stbr;
292*0Sstevel@tonic-gate 	struct ustat usb;
293*0Sstevel@tonic-gate 	char *devname;
294*0Sstevel@tonic-gate 	struct vfstab vfsbuf;
295*0Sstevel@tonic-gate 	FILE *vfstab;
296*0Sstevel@tonic-gate 	int is_root = 0;
297*0Sstevel@tonic-gate 	int is_usr = 0;
298*0Sstevel@tonic-gate 	int is_block = 0;
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 	if (stat(filename, &stbd) < 0) {
301*0Sstevel@tonic-gate 		(void) fprintf(stderr,
302*0Sstevel@tonic-gate 			gettext("udfs fsck: sanity check failed : cannot stat "
303*0Sstevel@tonic-gate 			"%s\n"), filename);
304*0Sstevel@tonic-gate 		exit(34);
305*0Sstevel@tonic-gate 	}
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 	if ((stbd.st_mode & S_IFMT) == S_IFBLK)
308*0Sstevel@tonic-gate 		is_block = 1;
309*0Sstevel@tonic-gate 	else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
310*0Sstevel@tonic-gate 		is_block = 0;
311*0Sstevel@tonic-gate 	else {
312*0Sstevel@tonic-gate 		(void) fprintf(stderr,
313*0Sstevel@tonic-gate 			gettext("udfs fsck: sanity check failed: %s not "
314*0Sstevel@tonic-gate 			"block or character device\n"), filename);
315*0Sstevel@tonic-gate 		exit(34);
316*0Sstevel@tonic-gate 	}
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 	/*
319*0Sstevel@tonic-gate 	 * Determine if this is the root file system via vfstab. Give up
320*0Sstevel@tonic-gate 	 * silently on failures. The whole point of this is not to care
321*0Sstevel@tonic-gate 	 * if the root file system is already mounted.
322*0Sstevel@tonic-gate 	 *
323*0Sstevel@tonic-gate 	 * XXX - similar for /usr. This should be fixed to simply return
324*0Sstevel@tonic-gate 	 * a new code indicating, mounted and needs to be checked.
325*0Sstevel@tonic-gate 	 */
326*0Sstevel@tonic-gate 	if ((vfstab = fopen(VFSTAB, "r")) != 0) {
327*0Sstevel@tonic-gate 		if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
328*0Sstevel@tonic-gate 			if (is_block)
329*0Sstevel@tonic-gate 				devname = vfsbuf.vfs_special;
330*0Sstevel@tonic-gate 			else
331*0Sstevel@tonic-gate 				devname = vfsbuf.vfs_fsckdev;
332*0Sstevel@tonic-gate 			if (stat(devname, &stbr) == 0)
333*0Sstevel@tonic-gate 				if (stbr.st_rdev == stbd.st_rdev)
334*0Sstevel@tonic-gate 					is_root = 1;
335*0Sstevel@tonic-gate 		}
336*0Sstevel@tonic-gate 		if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
337*0Sstevel@tonic-gate 			if (is_block)
338*0Sstevel@tonic-gate 				devname = vfsbuf.vfs_special;
339*0Sstevel@tonic-gate 			else
340*0Sstevel@tonic-gate 				devname = vfsbuf.vfs_fsckdev;
341*0Sstevel@tonic-gate 			if (stat(devname, &stbr) == 0)
342*0Sstevel@tonic-gate 				if (stbr.st_rdev == stbd.st_rdev)
343*0Sstevel@tonic-gate 					is_usr = 1;
344*0Sstevel@tonic-gate 		}
345*0Sstevel@tonic-gate 	}
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	/*
349*0Sstevel@tonic-gate 	 * XXX - only works if filename is a block device or if
350*0Sstevel@tonic-gate 	 * character and block device has the same dev_t value
351*0Sstevel@tonic-gate 	 */
352*0Sstevel@tonic-gate 	if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
353*0Sstevel@tonic-gate 		(void) fprintf(stderr,
354*0Sstevel@tonic-gate 			gettext("udfs fsck: sanity check: %s "
355*0Sstevel@tonic-gate 			"already mounted\n"), filename);
356*0Sstevel@tonic-gate 		exit(33);
357*0Sstevel@tonic-gate 	}
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 	if (lvintp->lvid_int_type == LVI_CLOSE) {
360*0Sstevel@tonic-gate 		(void) fprintf(stderr,
361*0Sstevel@tonic-gate 			gettext("udfs fsck: sanity check: %s okay\n"),
362*0Sstevel@tonic-gate 			filename);
363*0Sstevel@tonic-gate 	} else {
364*0Sstevel@tonic-gate 		(void) fprintf(stderr,
365*0Sstevel@tonic-gate 			gettext("udfs fsck: sanity check: %s needs checking\n"),
366*0Sstevel@tonic-gate 			filename);
367*0Sstevel@tonic-gate 		exit(32);
368*0Sstevel@tonic-gate 	}
369*0Sstevel@tonic-gate 	exit(0);
370*0Sstevel@tonic-gate }
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate char *
373*0Sstevel@tonic-gate unrawname(name)
374*0Sstevel@tonic-gate 	char *name;
375*0Sstevel@tonic-gate {
376*0Sstevel@tonic-gate 	char *dp;
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 	if ((dp = getfullblkname(name)) == NULL)
380*0Sstevel@tonic-gate 		return ("");
381*0Sstevel@tonic-gate 	return (dp);
382*0Sstevel@tonic-gate }
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate char *
385*0Sstevel@tonic-gate rawname(name)
386*0Sstevel@tonic-gate 	char *name;
387*0Sstevel@tonic-gate {
388*0Sstevel@tonic-gate 	char *dp;
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate 	if ((dp = getfullrawname(name)) == NULL)
391*0Sstevel@tonic-gate 		return ("");
392*0Sstevel@tonic-gate 	return (dp);
393*0Sstevel@tonic-gate }
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate char *
396*0Sstevel@tonic-gate hasvfsopt(vfs, opt)
397*0Sstevel@tonic-gate 	register struct vfstab *vfs;
398*0Sstevel@tonic-gate 	register char *opt;
399*0Sstevel@tonic-gate {
400*0Sstevel@tonic-gate 	char *f, *opts;
401*0Sstevel@tonic-gate 	static char *tmpopts;
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate 	if (vfs->vfs_mntopts == NULL)
404*0Sstevel@tonic-gate 		return (NULL);
405*0Sstevel@tonic-gate 	if (tmpopts == 0) {
406*0Sstevel@tonic-gate 		tmpopts = (char *)calloc(256, sizeof (char));
407*0Sstevel@tonic-gate 		if (tmpopts == 0)
408*0Sstevel@tonic-gate 			return (0);
409*0Sstevel@tonic-gate 	}
410*0Sstevel@tonic-gate 	(void) strncpy(tmpopts, vfs->vfs_mntopts, (sizeof (tmpopts) - 1));
411*0Sstevel@tonic-gate 	opts = tmpopts;
412*0Sstevel@tonic-gate 	f = mntopt(&opts);
413*0Sstevel@tonic-gate 	for (; *f; f = mntopt(&opts)) {
414*0Sstevel@tonic-gate 		if (strncmp(opt, f, strlen(opt)) == 0)
415*0Sstevel@tonic-gate 			return (f - tmpopts + vfs->vfs_mntopts);
416*0Sstevel@tonic-gate 	}
417*0Sstevel@tonic-gate 	return (NULL);
418*0Sstevel@tonic-gate }
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate static void
421*0Sstevel@tonic-gate usage()
422*0Sstevel@tonic-gate {
423*0Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("udfs usage: fsck [-F udfs] "
424*0Sstevel@tonic-gate 		"[generic options] [-o p,w,s] [special ....]\n"));
425*0Sstevel@tonic-gate 	exit(31+1);
426*0Sstevel@tonic-gate }
427