2 * Copyright (c) 1980, 1986 The Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 #include <afsconfig.h>
19 #include <afs/param.h>
22 /* We need the old directory type headers (included below), so don't include
23 * the normal dirent.h, or it will conflict. */
25 # include <sys/inode.h>
26 # define LONGFILENAMES 1
27 # include <sys/sysmacros.h>
30 # ifdef HAVE_USR_OLD_USR_INCLUDE_NDIR_H
31 # include </usr/old/usr/include/ndir.h>
41 #ifdef HAVE_SYS_FILE_H
45 #define VICE /* allow us to put our changes in at will */
49 #endif /* AFS_SUN_ENV */
50 #include <sys/mount.h>
56 #include <sys/vnode.h>
57 #include <sys/mount.h>
58 #include <ufs/inode.h>
60 #else /* AFS_OSF_ENV */
61 #ifdef AFS_VFSINCL_ENV
63 #include <sys/vnode.h>
65 #include <sys/fs/ufs_inode.h>
66 #include <sys/fs/ufs_fs.h>
68 #include <sys/fs/ufs_fsdir.h>
70 #include <sys/fs/ufs_mount.h>
72 #include <ufs/inode.h>
75 #include <ufs/fsdir.h>
78 #else /* AFS_VFSINCL_ENV */
80 #include <sys/inode.h>
87 #endif /* AFS_VFSINCL_ENV */
88 #endif /* AFS_OSF_ENV */
95 #include <sys/mnttab.h>
96 #include <sys/mntent.h>
97 #include <sys/vfstab.h>
98 #include <sys/ustat.h>
104 #include <sys/signal.h>
106 char *rawname(), *unrawname(), *blockcheck();
107 void catch(), catchquit(), voidquit();
114 char *name; /* device name */
115 char *fsname; /* mounted filesystem name */
116 struct part *next; /* forward link of partitions on disk */
117 } *badlist, **badnext = &badlist;
120 char *name; /* disk base name */
121 struct disk *next; /* forward link for list of disks */
122 struct part *part; /* head of list of partitions on disk */
123 int pid; /* If != 0, pid of proc working on */
126 int nrun, ndisks, maxrun, wflag = 0;
131 #if defined(AFS_HPUX100_ENV)
137 #define msgprintf vfscklogprintf
139 #define msgprintf printf
146 #include "AFS_component_version_number.c"
149 int ge_danger = 0; /* on when fsck is not able to fix the dirty file
150 * system within single run. Problems like dup table
151 * overflow, maxdup is exceeding MAXDUP.. etc. could
152 * potentailly prevent fsck from doing a complete
153 * repair. This is found in a GE hotsite. */
161 int pid, passno, sumstatus;
163 struct disk *dk, *nextdisk;
165 extern char *AFSVersion; /* generated version */
167 int other_than_ufs = 0;
178 #if defined(AFS_HPUX_ENV)
181 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
185 fsflag = oflag = mflag = exitstat = 0;
187 #if defined(AFS_HPUX100_ENV)
190 printf("----Open AFS (R) %s fsck----\n", AFSVersion); /* generated version */
191 if (access("/TRYFORCE", 0) == 0)
193 while (--argc > 0 && **++argv == '-') {
196 #if defined(AFS_HPUX_ENV)
197 #if defined(AFS_HPUX100_ENV)
198 case 'f': /* default yes to answer force to check */
201 #else /* AFS_HPUX100_ENV */
203 case 'F': /* default yes to answer force to check */
206 #endif /* AFS_HPUX_ENV */
207 #endif /* AFS_HPUX100_ENV */
216 #if defined(AFS_HPUX100_ENV)
222 (void)fprintf(stdout, "fsck -F hfs ");
223 for (opt_count = 1; opt_count < argc; opt_count++) {
224 opt_text = argv[opt_count];
226 (void)fprintf(stdout, " %s ", opt_text);
228 (void)fprintf(stdout, "\n");
242 (void)fprintf(stdout, "fsck -F ufs ");
243 for (opt_count = 1; opt_count < argc; opt_count++) {
244 opt_text = argv[opt_count];
246 (void)fprintf(stdout, " %s ", opt_text);
248 (void)fprintf(stdout, "\n");
255 while (*subopt != '\0') {
256 if (*subopt == 'p') {
259 } else if (*subopt == 'b') {
260 if (argv[0][1] != '\0') {
261 bflag = atoi(argv[0] + 1);
263 bflag = atoi(*++argv);
266 msgprintf("Alternate super block location: %d\n", bflag);
268 } else if (*subopt == 'd') {
271 } else if (*subopt == 'r') {
273 } else if (*subopt == 'w') {
276 } else if (*subopt == 'c') {
279 } else if (*subopt == 'f') {
283 errexit("-o %c option?\n", *subopt);
296 if (argv[0][1] != '\0') {
297 bflag = atoi(argv[0] + 1);
299 bflag = atoi(*++argv);
302 msgprintf("Alternate super block location: %d\n", bflag);
309 /* who knows? defined, but doesn't do much */
313 case 'w': /* check writable only */
320 if (!isdigit(argv[1][0]))
321 errexit("-l flag requires a number\n");
322 maxrun = atoi(*++argv);
325 #if !defined(AFS_HPUX100_ENV)
327 if (!isdigit(argv[1][0]))
328 errexit("-m flag requires a mode\n");
329 sscanf(*++argv, "%o", &lfmode);
331 errexit("bad mode to -m: %o\n", lfmode);
333 printf("** lost+found creation mode %o\n", lfmode);
335 #endif /* AFS_HPUX100_ENV */
336 #endif /* AFS_SUN5_ENV */
341 #endif /* AFS_OSF_ENV */
349 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
350 * it's general/useful flag to use.
363 errexit("%c option?\n", **argv);
367 * The following checks were only available on hpux but are useful to all systems.
370 errexit("Incompatible options: -n and -p\n");
372 errexit("Incompatible options: -n and -q\n");
375 rflag++; /* check raw devices */
377 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
378 (void)signal(SIGINT, catch);
380 (void)signal(SIGQUIT, catchquit);
385 if (wflag && !writable(*argv)) {
386 (void)fprintf(stderr, "not writable '%s'\n", *argv);
390 checkfilesys(*argv++, NULL);
405 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
408 if ((fd = fopen(VFSTAB, "r")) == NULL) {
409 errexit("vfsck: cannot open vfstab\n");
411 while ((ret = getvfsent(fd, &vget)) == 0) {
412 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS)
413 && numbers(vget.vfs_fsckpass)) {
417 if (numbers(vget.vfs_fsckpass))
418 passno = atoi(vget.vfs_fsckpass);
423 if (preen == 0 || passno == 1) {
424 checkfilesys(vget.vfs_fsckdev, get.vfs_mountp);
425 } else if (passno > 1) {
426 addpart(vget.vfs_fsckdev, vget.vfs_special);
430 for (passno = 1; passno <= 2; passno++) {
432 errexit("Can't open checklist file: %s\n", FSTAB);
433 while ((fsp = getfsent()) != 0) {
434 if (strcmp(fsp->fs_type, FSTAB_RW)
435 && strcmp(fsp->fs_type, FSTAB_RO)
436 && strcmp(fsp->fs_type, FSTAB_RQ))
439 if (strcmp(fsp->fs_vfstype, "ufs") || fsp->fs_passno == 0) {
442 #endif /* AFS_OSF_ENV */
443 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
445 name = blockcheck(fsp->fs_spec);
447 checkfilesys(name, fsp->fs_file);
449 printf("pid %d exiting 8/1\n", getpid());
453 } else if (passno == 2 && fsp->fs_passno > 1) {
454 name = blockcheck(fsp->fs_spec);
456 pwarn("BAD DISK NAME %s\n", fsp->fs_spec);
458 printf("pid %d saw bad disk name 8/3\n", getpid());
461 addpart(name, fsp->fs_file);
464 #endif /* AFS_SUN5_ENV */
474 for (passno = 0; passno < maxrun; ++passno) {
476 nextdisk = nextdisk->next;
478 while ((pid = wait(&status)) != -1) {
479 for (dk = disks; dk; dk = dk->next)
483 printf("Unknown pid %d\n", pid);
486 rc = WEXITSTATUS(status);
487 if (WIFSIGNALED(status)) {
488 printf("%s (%s): EXITED WITH SIGNAL %d\n", dk->part->name,
489 dk->part->fsname, WTERMSIG(status));
495 badnext = &dk->part->next;
496 dk->part = dk->part->next;
499 dk->part = dk->part->next;
502 if (dk->part == NULL)
505 if (nextdisk == NULL) {
508 } else if (nrun < maxrun && nrun < ndisks) {
510 if ((nextdisk = nextdisk->next) == NULL)
512 if (nextdisk->part != NULL && nextdisk->pid == 0)
521 printf("pid %d exiting 8/2\n", getpid());
524 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
525 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
526 for (pt = badlist; pt; pt = pt->next)
527 printf("%s (%s)%s", pt->name, pt->fsname, pt->next ? ", " : "\n");
537 #endif /* !AFS_SUN5_ENV */
545 struct disk *dk, **dkp;
549 for (p = name + strlen(name) - 1; p >= name; --p)
557 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
558 if (strncmp(dk->name, name, len) == 0 && dk->name[len] == 0)
561 if ((*dkp = malloc(sizeof(struct disk))) == NULL)
562 errexit("out of memory");
564 if ((dk->name = strdup(name)) == NULL)
565 errexit("out of memory");
573 addpart(name, fsname)
576 struct disk *dk = finddisk(name);
577 struct part *pt, **ppt = &dk->part;
579 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
580 if (strcmp(pt->name, name) == 0) {
581 printf("%s in fstab more than once!\n", name);
584 if ((*ppt = malloc(sizeof(struct part))) == NULL)
585 errexit("out of memory");
587 if ((pt->name = strdup(name)) == NULL)
588 errexit("out of memory");
589 if ((pt->fsname = strdup(fsname)) == NULL)
590 errexit("out of memory");
605 (void)signal(SIGQUIT, voidquit);
606 checkfilesys(dk->part->name, dk->part->fsname);
611 checkfilesys(filesys, parname)
614 daddr_t n_ffree, n_bfree;
616 struct stat tstat; /* for ultrix 3 unmount */
623 #endif /* AFS_OSF_ENV */
633 ge_danger = 0; /* set to 1 by any table overflow or more
634 * dup/bad blocks than expected */
636 fixed = 1; /* set to 0 by any 'no' reply */
638 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
639 devname = devbuffer; /* remember generic ptr for later */
640 EnsureDevice(devname); /* canonicalize name */
644 ret_val = setup(devname);
652 pfatal("CAN'T CHECK FILE SYSTEM.");
654 if ((exitstat == 0) && (mflag))
660 } else if (ret_val == -1) { /* pclean && FS_CLEAN */
663 #if defined(AFS_OSF_ENV)
664 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
668 #if defined(AFS_HPUX100_ENV)
670 check_sanity(filesys);
675 check_sanity(filesys);
683 * 1: scan inodes tallying blocks used
686 #if defined(AFS_SUN5_ENV)
688 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
691 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
693 msgprintf("** Root file system\n");
696 printf("** Phase 1 - Sanity Check only\n");
700 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
705 * 1b: locate first references to duplicates, if any
709 pfatal("INTERNAL ERROR: dups with -p");
710 msgprintf("** Phase 1b - Rescan For More DUPS\n");
715 * 2: traverse directories from root to mark all connected directories
718 msgprintf("** Phase 2 - Check Pathnames\n");
722 * 3: scan inodes looking for disconnected directories
725 msgprintf("** Phase 3 - Check Connectivity\n");
729 * 4: scan inodes looking for disconnected files; check reference counts
732 msgprintf("** Phase 4 - Check Reference Counts\n");
736 * 5: check and repair resource counts in cylinder groups
739 msgprintf("** Phase 5 - Check Cyl groups\n");
742 #if defined(AFS_SUN_ENV)
748 * print out summary statistics
750 n_ffree = sblock.fs_cstotal.cs_nffree;
751 n_bfree = sblock.fs_cstotal.cs_nbfree;
753 #if defined(ACLS) && defined(AFS_HPUX_ENV)
754 pinfo("%d files, %d icont, %d used, %d free", n_files, n_cont, n_blks,
755 n_ffree + sblock.fs_frag * n_bfree);
757 pinfo("%d files, %d used, %d free", n_files, n_blks,
758 n_ffree + sblock.fs_frag * n_bfree);
761 msgprintf(", %d AFS files", nViceFiles);
762 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
763 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
765 #if defined(ACLS) && defined(AFS_HPUX_ENV)
766 pinfo("%d files, %d icont, %d used, %d free ", n_files, n_cont, n_blks,
767 n_ffree + sblock.fs_frag * n_bfree);
769 pinfo("%d files, %d used, %d free ", n_files, n_blks,
770 n_ffree + sblock.fs_frag * n_bfree);
772 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
773 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
775 if (debug && (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
776 msgprintf("%d files missing\n", n_files);
778 n_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
779 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
780 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
781 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
782 printf("%d blocks missing\n", n_blks);
783 if (duplist != NULL) {
784 msgprintf("The following duplicate blocks remain:");
785 for (dp = duplist; dp; dp = dp->next)
786 msgprintf(" %d,", dp->dup);
789 if (zlnhead != NULL) {
790 msgprintf("The following zero link count inodes remain:");
791 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
792 msgprintf(" %d,", zlnp->zlncnt);
797 /* if user's specification denotes that the file system block
798 * is going to be modified (nflag == 0) then fsck store the
799 * correct magic number in the super block if it is not already
802 if (!nflag && !(fswritefd < 0)) {
804 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
808 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
809 if (!preen && !qflag)
810 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
811 sblock.fs_clean = FS_CLEAN;
815 /* fix FS_CLEAN if changes made and no 'no' replies */
816 if (fsmodified && fixed)
817 sblock.fs_clean = FS_CLEAN;
819 * Fix fs_clean if there were no 'no' replies.
820 * This is done for both the s300 and s800. The s800 root will be
821 * guaranteed clean as of 7.0.
823 if (fixed && (sblock.fs_clean != FS_OK)) {
824 if (!preen && !qflag)
825 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
826 sblock.fs_clean = FS_CLEAN;
836 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
844 if (hotroot && sblock.fs_clean == FSACTIVE)
847 else if (!((sblock.fs_state + (afs_int32) sblock.fs_time == FSOKAY) &&
849 else if (!((fs_get_state(&sblock) + (afs_int32) sblock.fs_time == FSOKAY)
852 (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
853 if (yflag || !iscorrupt) {
854 printf("%s FILE SYSTEM STATE SET TO OKAY\n", devname);
857 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n", devname);
862 (void)time(&sblock.fs_time);
864 if (hotroot && rebflg)
865 sblock.fs_clean = FSACTIVE;
867 sblock.fs_clean = FSSTABLE;
869 sblock.fs_state = FSOKAY - (afs_int32) sblock.fs_time;
871 fs_set_state(&sblock, FSOKAY - (afs_int32) sblock.fs_time);
878 if (!nflag && !bflag && !hotroot) {
880 sblock.fs_clean = FS_CLEAN;
881 (void)time(&sblock.fs_time);
883 flush(fswritefd, &sblk);
886 #else /* AFS_OSF_ENV */
888 (void)time(&sblock.fs_time);
898 blockmap = statemap = NULL;
906 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
909 msgprintf("\n***** REBOOT UNIX *****\n");
912 if (mountedfs || hotroot) {
930 (void)close(fsreadfd);
931 (void)close(fswritefd);
932 if (nViceFiles || tryForce) {
933 /* Modified file system with vice files: force full salvage */
934 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
935 struct ufs_args ufsargs;
937 char pname[100], fname[100], *special;
938 int fd, code, failed = 0;
941 ("%s: AFS file system partition was modified; forcing full salvage\n",
943 devname = unrawname(devname);
944 special = (char *)strrchr(devname, '/');
947 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
948 * /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
949 strcat(pname, special);
951 /* if system mounted / as read-only, we'll try to fix now */
952 if (access("/", W_OK) < 0 && errno == EROFS) {
953 code = system("mount -o remount /");
955 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
962 /* if system mounted / as read-only, we'll try to fix now */
963 if (access("/", W_OK) < 0 && errno == EROFS) {
964 printf("Can't RW acceess /; %d\n", errno);
965 code = system("/sbin/mount -u /");
967 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
975 if (mkdir(pname, 0777) < 0) {
976 if (errno != EEXIST) {
977 perror("fsck mkdir");
981 if (failed && parname) {
982 strcpy(pname, parname);
984 #if !defined(AFS_HPUX_ENV)
986 ufsargs.flags = UFSMNT_NOINTR;
988 ufsargs.fspec = devname;
992 (devname, pname, MS_DATA, "ufs", (char *)&ufsargs,
993 sizeof(ufsargs)) < 0) {
995 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
998 if (mount(devname, pname, 0) < 0) {
1001 ("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n",
1002 devname, pname, errno);
1004 strcpy(fname, pname);
1005 strcat(fname, "/FORCESALVAGE");
1006 fd = open(fname, O_CREAT, 0);
1008 errexit("Couldn't create %s to force full salvage!\n", fname);
1013 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1016 #if defined(AFS_OSF_ENV)
1017 umount(pname, MNT_NOFORCE);
1018 #else /* AFS_OSF_ENV */
1026 fsync(fileno(logfile)); /* Since update isn't running */
1038 struct stat stslash, stblock, stchar;
1043 if (stat("/", &stslash) < 0) {
1045 printf("Can't stat root\n");
1049 if (stat(name, &stblock) < 0) {
1051 printf("Can't stat %s\n", name);
1054 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1055 if (stslash.st_dev == stblock.st_rdev) {
1057 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1059 #endif /* AFS_OSF_ENV */
1061 raw = rawname(name);
1065 printf("Cannot find character device for %s\n", name);
1068 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1069 name = unrawname(name);
1073 printf("Can't make sense out of name %s\n", name);
1078 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1082 * exit 0 - file system is unmounted and okay
1083 * exit 32 - file system is unmounted and needs checking
1084 * exit 33 - file system is mounted for root file system
1085 * exit 34 - cannot stat device
1087 check_sanity(filename)
1090 struct stat stbd, stbr;
1093 struct vfstab vfsbuf;
1099 if (stat(filename, &stbd) < 0) {
1100 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n",
1105 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1107 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1111 "ufs fsck: sanity check failed: %s not block or character device\n",
1116 * Determine if this is the root file system via vfstab. Give up
1117 * silently on failures. The whole point of this is not to care
1118 * if the root file system is already mounted.
1120 * XXX - similar for /usr. This should be fixed to simply return
1121 * a new code indicating, mounted and needs to be checked.
1123 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1124 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1126 devname = vfsbuf.vfs_special;
1128 devname = vfsbuf.vfs_fsckdev;
1129 if (stat(devname, &stbr) == 0)
1130 if (stbr.st_rdev == stbd.st_rdev)
1133 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1135 devname = vfsbuf.vfs_special;
1137 devname = vfsbuf.vfs_fsckdev;
1138 if (stat(devname, &stbr) == 0)
1139 if (stbr.st_rdev == stbd.st_rdev)
1144 /* XXX - only works if filename is a block device or if
1145 * character and block device has the same dev_t value */
1146 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1147 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n",
1152 * We mount the ufs root file system read-only first. After fsck
1153 * runs, we remount the root as read-write. Therefore, we no longer
1154 * check for different values for fs_state between the root file
1155 * system and the rest of file systems.
1157 if (!((sblock.fs_state + (time_t) sblock.fs_time == FSOKAY)
1158 && (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
1159 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n",
1163 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1168 #if defined(AFS_HPUX100_ENV)
1169 check_sanity(filename)
1172 struct stat stbd, stbr;
1181 if (stat(filename, &stbd) < 0) {
1182 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n",
1187 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1189 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1193 "hfs fsck: sanity check failed: %s not block or character device\n",
1198 * Determine if this is the root file system via vfstab. Give up
1199 * silently on failures. The whole point of this is not to care
1200 * if the root file system is already mounted.
1202 * XXX - similar for /usr. This should be fixed to simply return
1203 * a new code indicating, mounted and needs to be checked.
1205 if ((vfstab = setmntent(FSTAB, "r")) != 0) {
1206 while (mnt = getmntent(vfstab)) {
1207 if (!strcmp(mnt->mnt_dir, "/"))
1208 if (stat(mnt->mnt_fsname, &stbr) == 0)
1209 if (stbr.st_rdev == stbd.st_rdev)
1212 if (!strcmp(mnt->mnt_dir, "/usr"))
1213 if (stat(mnt->mnt_fsname, &stbr) == 0)
1214 if (stbr.st_rdev == stbd.st_rdev)
1220 /* XXX - only works if filename is a block device or if
1221 * character and block device has the same dev_t value */
1222 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1223 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n",
1228 * We mount the ufs root file system read-only first. After fsck
1229 * runs, we remount the root as read-write. Therefore, we no longer
1230 * check for different values for fs_state between the root file
1231 * system and the rest of file systems.
1233 if (!((sblock.fs_clean == FS_CLEAN || sblock.fs_clean == FS_OK))) {
1234 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n",
1238 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1242 /* see if all numbers */
1248 while ('0' <= *yp && *yp <= '9')
1256 /* Convert a raw device name into a block device name.
1257 * If the block device is not found, return the raw device name.
1258 * For HP and SUN, the returned value is not changed. For other
1259 * platforms it is changed (I see no rhyme or reason -jpm).
1265 static char bldev[256];
1266 struct stat statbuf;
1269 code = stat(rawdev, &statbuf);
1270 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1271 return (rawdev); /* Not a char device */
1273 for (i = strlen(rawdev) - 2; i >= 0; i--) {
1274 if ((rawdev[i] == '/') && (rawdev[i + 1] == 'r')) {
1275 strcpy(bldev, rawdev);
1277 strcat(bldev, &rawdev[i + 2]);
1279 code = stat(bldev, &statbuf); /* test for block device */
1280 if (!code && S_ISBLK(statbuf.st_mode)) {
1281 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1284 strcpy(rawdev, bldev); /* Replace */
1293 /* Convert a block device name into a raw device name.
1294 * If the block device is not found, return null
1300 static char rawdev[256];
1301 struct stat statbuf;
1304 for (i = strlen(bldev) - 1; i >= 0; i--) {
1305 if (bldev[i] == '/') {
1306 strcpy(rawdev, bldev);
1307 rawdev[i + 1] = 'r';
1309 strcat(rawdev, &bldev[i + 1]);
1311 code = stat(rawdev, &statbuf);
1312 if (!code && S_ISCHR(statbuf.st_mode))