2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11 * All rights reserved.
13 * Redistribution and use in source and binary forms are permitted
14 * provided that: (1) source distributions retain this entire copyright
15 * notice and comment, and (2) distributions including binaries display
16 * the following acknowledgement: ``This product includes software
17 * developed by the University of California, Berkeley and its contributors''
18 * in the documentation or other materials provided with the distribution
19 * and in all advertising materials mentioning features or use of this
20 * software. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <ctype.h> /* use isdigit macro rather than 4.1 libc routine */
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/sysmacros.h>
41 #include <sys/mntent.h>
42 #include <sys/vnode.h>
45 #include <sys/mnttab.h>
46 #include <sys/signal.h>
47 #include <sys/vfstab.h>
48 #include <sys/fs/udf_volume.h>
52 extern int32_t writable(char *);
53 extern void pfatal(char *, ...);
54 extern void printfree();
55 extern void pwarn(char *, ...);
58 extern void dofreemap();
59 extern void dolvint();
60 extern char *getfullblkname();
61 extern char *getfullrawname();
63 static int mflag
= 0; /* sanity check only */
66 void catch(), catchquit(), voidquit();
68 static void checkfilesys();
69 static void check_sanity();
72 static char *subopts
[] = {
81 #define FORCE 4 /* force checking, even if clean */
83 #define STATS 5 /* print time and busy stats */
88 uint32_t ecma_version
= 2;
91 main(int argc
, char *argv
[])
94 char *suboptions
, *value
;
97 (void) setlocale(LC_ALL
, "");
99 while ((c
= getopt(argc
, argv
, "mnNo:VyYz")) != EOF
) {
106 case 'n': /* default no answer flag */
114 * udfs specific options.
117 while (*suboptions
!= '\0') {
118 suboption
= getsubopt(&suboptions
,
134 /* check only writable filesystems */
157 (void) fprintf(stdout
, "fsck -F udfs ");
158 for (opt_count
= 1; opt_count
< argc
;
160 opt_text
= argv
[opt_count
];
162 (void) fprintf(stdout
, " %s ",
165 (void) fprintf(stdout
, "\n");
169 case 'y': /* default yes answer flag */
180 argv
= &argv
[optind
];
181 rflag
++; /* check raw devices */
182 if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
) {
183 (void) signal(SIGINT
, catch);
187 (void) signal(SIGQUIT
, catchquit
);
192 if (wflag
&& !writable(*argv
)) {
193 (void) fprintf(stderr
,
194 gettext("not writeable '%s'\n"), *argv
);
197 checkfilesys(*argv
++);
206 checkfilesys(char *filesys
)
214 if ((devstr
= setup(filesys
)) == 0) {
218 pfatal(gettext("CAN'T CHECK FILE SYSTEM."));
219 if ((exitstat
== 0) && (mflag
))
226 check_sanity(filesys
); /* this never returns */
229 * 1: scan inodes tallying blocks used
233 (void) printf(gettext("** Currently Mounted on %s\n"),
237 gettext("** Phase 1 - Sanity Check only\n"));
241 gettext("** Phase 1 - Check Directories "
247 (void) printf("%s: ", devname
);
249 (void) printf("** ");
252 (void) printf("pass1 isdirty %d\n", isdirty
);
259 * print out summary statistics
261 pwarn(gettext("%d files, %d dirs, %d used, %d free\n"), n_files
, n_dirs
,
262 n_blks
, part_len
- n_blks
);
269 gettext("\n***** FILE SYSTEM WAS MODIFIED *****\n"));
278 * exit 0 - file system is unmounted and okay
279 * exit 32 - file system is unmounted and needs checking
280 * exit 33 - file system is mounted
281 * for root file system
282 * exit 34 - cannot stat device
286 check_sanity(char *filename
)
288 struct stat stbd
, stbr
;
291 struct vfstab vfsbuf
;
297 if (stat(filename
, &stbd
) < 0) {
298 (void) fprintf(stderr
,
299 gettext("udfs fsck: sanity check failed : cannot stat "
304 if ((stbd
.st_mode
& S_IFMT
) == S_IFBLK
)
306 else if ((stbd
.st_mode
& S_IFMT
) == S_IFCHR
)
309 (void) fprintf(stderr
,
310 gettext("udfs fsck: sanity check failed: %s not "
311 "block or character device\n"), filename
);
316 * Determine if this is the root file system via vfstab. Give up
317 * silently on failures. The whole point of this is not to care
318 * if the root file system is already mounted.
320 * XXX - similar for /usr. This should be fixed to simply return
321 * a new code indicating, mounted and needs to be checked.
323 if ((vfstab
= fopen(VFSTAB
, "r")) != 0) {
324 if (getvfsfile(vfstab
, &vfsbuf
, "/") == 0) {
326 devname
= vfsbuf
.vfs_special
;
328 devname
= vfsbuf
.vfs_fsckdev
;
329 if (stat(devname
, &stbr
) == 0)
330 if (stbr
.st_rdev
== stbd
.st_rdev
)
333 if (getvfsfile(vfstab
, &vfsbuf
, "/usr") == 0) {
335 devname
= vfsbuf
.vfs_special
;
337 devname
= vfsbuf
.vfs_fsckdev
;
338 if (stat(devname
, &stbr
) == 0)
339 if (stbr
.st_rdev
== stbd
.st_rdev
)
346 * XXX - only works if filename is a block device or if
347 * character and block device has the same dev_t value
349 if (is_root
== 0 && is_usr
== 0 && ustat(stbd
.st_rdev
, &usb
) == 0) {
350 (void) fprintf(stderr
,
351 gettext("udfs fsck: sanity check: %s "
352 "already mounted\n"), filename
);
356 if (lvintp
->lvid_int_type
== LVI_CLOSE
) {
357 (void) fprintf(stderr
,
358 gettext("udfs fsck: sanity check: %s okay\n"),
361 (void) fprintf(stderr
,
362 gettext("udfs fsck: sanity check: %s needs checking\n"),
370 unrawname(char *name
)
375 if ((dp
= getfullblkname(name
)) == NULL
)
385 if ((dp
= getfullrawname(name
)) == NULL
)
391 hasvfsopt(struct vfstab
*vfs
, char *opt
)
394 static char *tmpopts
;
396 if (vfs
->vfs_mntopts
== NULL
)
399 tmpopts
= (char *)calloc(256, sizeof (char));
403 (void) strncpy(tmpopts
, vfs
->vfs_mntopts
, (sizeof (tmpopts
) - 1));
406 for (; *f
; f
= mntopt(&opts
)) {
407 if (strncmp(opt
, f
, strlen(opt
)) == 0)
408 return (f
- tmpopts
+ vfs
->vfs_mntopts
);
416 (void) fprintf(stderr
, gettext("udfs usage: fsck [-F udfs] "
417 "[generic options] [-o p,w,s] [special ....]\n"));