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>
24 #define VICE /* allow us to put our changes in at will */
27 #include <sys/param.h>
32 #endif /* AFS_SUN_ENV */
33 #include <sys/mount.h>
41 #include <sys/vnode.h>
42 #include <sys/mount.h>
43 #include <ufs/inode.h>
45 #else /* AFS_OSF_ENV */
46 #ifdef AFS_VFSINCL_ENV
48 #include <sys/vnode.h>
51 #include <sys/fs/ufs_inode.h>
52 #include <sys/fs/ufs_fs.h>
54 #include <sys/fs/ufs_fsdir.h>
56 #include <sys/fs/ufs_mount.h>
58 #include <ufs/inode.h>
61 #include <ufs/fsdir.h>
64 #else /* AFS_VFSINCL_ENV */
66 #include <sys/inode.h>
69 #define LONGFILENAMES 1
70 #include <sys/sysmacros.h>
80 #endif /* AFS_VFSINCL_ENV */
81 #endif /* AFS_OSF_ENV */
95 #include <sys/mnttab.h>
96 #include <sys/mntent.h>
97 #include <sys/vfstab.h>
98 #include <sys/ustat.h>
105 #include <sys/signal.h>
107 char *rawname(), *unrawname(), *blockcheck(), *malloc();
108 void catch(), catchquit(), voidquit();
115 char *name; /* device name */
116 char *fsname; /* mounted filesystem name */
117 struct part *next; /* forward link of partitions on disk */
118 } *badlist, **badnext = &badlist;
121 char *name; /* disk base name */
122 struct disk *next; /* forward link for list of disks */
123 struct part *part; /* head of list of partitions on disk */
124 int pid; /* If != 0, pid of proc working on */
127 int nrun, ndisks, maxrun, wflag = 0;
132 #if defined(AFS_HPUX100_ENV)
138 #define msgprintf vfscklogprintf
140 #define msgprintf printf
147 #include "AFS_component_version_number.c"
150 int ge_danger = 0; /* on when fsck is not able to fix the dirty file
151 * system within single run. Problems like dup table
152 * overflow, maxdup is exceeding MAXDUP.. etc. could
153 * potentailly prevent fsck from doing a complete
154 * repair. This is found in a GE hotsite. */
162 int pid, passno, sumstatus;
164 register struct disk *dk, *nextdisk;
165 register struct part *pt;
166 extern char *AFSVersion; /* generated version */
168 int other_than_ufs = 0;
179 #if defined(AFS_HPUX_ENV)
182 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
186 fsflag = oflag = mflag = exitstat = 0;
188 #if defined(AFS_HPUX100_ENV)
191 printf("----Open AFS (R) %s fsck----\n", AFSVersion); /* generated version */
192 if (access("/TRYFORCE", 0) == 0)
194 while (--argc > 0 && **++argv == '-') {
197 #if defined(AFS_HPUX_ENV)
198 #if defined(AFS_HPUX100_ENV)
199 case 'f': /* default yes to answer force to check */
202 #else /* AFS_HPUX100_ENV */
204 case 'F': /* default yes to answer force to check */
207 #endif /* AFS_HPUX_ENV */
208 #endif /* AFS_HPUX100_ENV */
217 #if defined(AFS_HPUX100_ENV)
223 (void)fprintf(stdout, "fsck -F hfs ");
224 for (opt_count = 1; opt_count < argc; opt_count++) {
225 opt_text = argv[opt_count];
227 (void)fprintf(stdout, " %s ", opt_text);
229 (void)fprintf(stdout, "\n");
243 (void)fprintf(stdout, "fsck -F ufs ");
244 for (opt_count = 1; opt_count < argc; opt_count++) {
245 opt_text = argv[opt_count];
247 (void)fprintf(stdout, " %s ", opt_text);
249 (void)fprintf(stdout, "\n");
256 while (*subopt != '\0') {
257 if (*subopt == 'p') {
260 } else if (*subopt == 'b') {
261 if (argv[0][1] != '\0') {
262 bflag = atoi(argv[0] + 1);
264 bflag = atoi(*++argv);
267 msgprintf("Alternate super block location: %d\n", bflag);
269 } else if (*subopt == 'd') {
272 } else if (*subopt == 'r') {
274 } else if (*subopt == 'w') {
277 } else if (*subopt == 'c') {
280 } else if (*subopt == 'f') {
284 errexit("-o %c option?\n", *subopt);
297 if (argv[0][1] != '\0') {
298 bflag = atoi(argv[0] + 1);
300 bflag = atoi(*++argv);
303 msgprintf("Alternate super block location: %d\n", bflag);
310 /* who knows? defined, but doesn't do much */
314 case 'w': /* check writable only */
321 if (!isdigit(argv[1][0]))
322 errexit("-l flag requires a number\n");
323 maxrun = atoi(*++argv);
326 #if !defined(AFS_HPUX100_ENV)
328 if (!isdigit(argv[1][0]))
329 errexit("-m flag requires a mode\n");
330 sscanf(*++argv, "%o", &lfmode);
332 errexit("bad mode to -m: %o\n", lfmode);
334 printf("** lost+found creation mode %o\n", lfmode);
336 #endif /* AFS_HPUX100_ENV */
337 #endif /* AFS_SUN5_ENV */
342 #endif /* AFS_OSF_ENV */
350 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
351 * it's general/useful flag to use.
364 errexit("%c option?\n", **argv);
368 * The following checks were only available on hpux but are useful to all systems.
371 errexit("Incompatible options: -n and -p\n");
373 errexit("Incompatible options: -n and -q\n");
376 rflag++; /* check raw devices */
378 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
379 (void)signal(SIGINT, catch);
381 (void)signal(SIGQUIT, catchquit);
386 if (wflag && !writable(*argv)) {
387 (void)fprintf(stderr, "not writeable '%s'\n", *argv);
391 checkfilesys(*argv++, NULL);
406 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
409 if ((fd = fopen(VFSTAB, "r")) == NULL) {
410 errexit("vfsck: cannot open vfstab\n");
412 while ((ret = getvfsent(fd, &vget)) == 0) {
413 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS)
414 && numbers(vget.vfs_fsckpass)) {
418 if (numbers(vget.vfs_fsckpass))
419 passno = atoi(vget.vfs_fsckpass);
424 if (preen == 0 || passno == 1) {
425 checkfilesys(vget.vfs_fsckdev, get.vfs_mountp);
426 } else if (passno > 1) {
427 addpart(vget.vfs_fsckdev, vget.vfs_special);
431 for (passno = 1; passno <= 2; passno++) {
433 errexit("Can't open checklist file: %s\n", FSTAB);
434 while ((fsp = getfsent()) != 0) {
435 if (strcmp(fsp->fs_type, FSTAB_RW)
436 && strcmp(fsp->fs_type, FSTAB_RO)
437 && strcmp(fsp->fs_type, FSTAB_RQ))
440 if (strcmp(fsp->fs_vfstype, "ufs") || fsp->fs_passno == 0) {
443 #endif /* AFS_OSF_ENV */
444 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
446 name = blockcheck(fsp->fs_spec);
448 checkfilesys(name, fsp->fs_file);
450 printf("pid %d exiting 8/1\n", getpid());
454 } else if (passno == 2 && fsp->fs_passno > 1) {
455 name = blockcheck(fsp->fs_spec);
457 pwarn("BAD DISK NAME %s\n", fsp->fs_spec);
459 printf("pid %d saw bad disk name 8/3\n", getpid());
462 addpart(name, fsp->fs_file);
465 #endif /* AFS_SUN5_ENV */
475 for (passno = 0; passno < maxrun; ++passno) {
477 nextdisk = nextdisk->next;
479 while ((pid = wait(&status)) != -1) {
480 for (dk = disks; dk; dk = dk->next)
484 printf("Unknown pid %d\n", pid);
487 rc = WEXITSTATUS(status);
488 if (WIFSIGNALED(status)) {
489 printf("%s (%s): EXITED WITH SIGNAL %d\n", dk->part->name,
490 dk->part->fsname, WTERMSIG(status));
496 badnext = &dk->part->next;
497 dk->part = dk->part->next;
500 dk->part = dk->part->next;
503 if (dk->part == NULL)
506 if (nextdisk == NULL) {
509 } else if (nrun < maxrun && nrun < ndisks) {
511 if ((nextdisk = nextdisk->next) == NULL)
513 if (nextdisk->part != NULL && nextdisk->pid == 0)
522 printf("pid %d exiting 8/2\n", getpid());
525 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
526 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
527 for (pt = badlist; pt; pt = pt->next)
528 printf("%s (%s)%s", pt->name, pt->fsname, pt->next ? ", " : "\n");
538 #endif /* !AFS_SUN5_ENV */
546 register struct disk *dk, **dkp;
550 for (p = name + strlen(name) - 1; p >= name; --p)
558 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
559 if (strncmp(dk->name, name, len) == 0 && dk->name[len] == 0)
562 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
563 errexit("out of memory");
565 if ((dk->name = malloc((unsigned int)len + 1)) == NULL)
566 errexit("out of memory");
567 strncpy(dk->name, name, len);
568 dk->name[len] = '\0';
576 addpart(name, fsname)
579 struct disk *dk = finddisk(name);
580 register struct part *pt, **ppt = &dk->part;
582 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
583 if (strcmp(pt->name, name) == 0) {
584 printf("%s in fstab more than once!\n", name);
587 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
588 errexit("out of memory");
590 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL)
591 errexit("out of memory");
592 strcpy(pt->name, name);
593 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL)
594 errexit("out of memory");
595 strcpy(pt->fsname, fsname);
600 register struct disk *dk;
610 (void)signal(SIGQUIT, voidquit);
611 checkfilesys(dk->part->name, dk->part->fsname);
616 checkfilesys(filesys, parname)
619 daddr_t n_ffree, n_bfree;
621 struct stat tstat; /* for ultrix 3 unmount */
628 #endif /* AFS_OSF_ENV */
638 ge_danger = 0; /* set to 1 by any table overflow or more
639 * dup/bad blocks than expected */
641 fixed = 1; /* set to 0 by any 'no' reply */
643 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
644 devname = devbuffer; /* remember generic ptr for later */
645 EnsureDevice(devname); /* canonicalize name */
649 ret_val = setup(devname);
657 pfatal("CAN'T CHECK FILE SYSTEM.");
659 if ((exitstat == 0) && (mflag))
665 } else if (ret_val == -1) { /* pclean && FS_CLEAN */
668 #if defined(AFS_OSF_ENV)
669 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
673 #if defined(AFS_HPUX100_ENV)
675 check_sanity(filesys);
680 check_sanity(filesys);
688 * 1: scan inodes tallying blocks used
691 #if defined(AFS_SUN5_ENV)
693 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
696 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
698 msgprintf("** Root file system\n");
701 printf("** Phase 1 - Sanity Check only\n");
705 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
710 * 1b: locate first references to duplicates, if any
714 pfatal("INTERNAL ERROR: dups with -p");
715 msgprintf("** Phase 1b - Rescan For More DUPS\n");
720 * 2: traverse directories from root to mark all connected directories
723 msgprintf("** Phase 2 - Check Pathnames\n");
727 * 3: scan inodes looking for disconnected directories
730 msgprintf("** Phase 3 - Check Connectivity\n");
734 * 4: scan inodes looking for disconnected files; check reference counts
737 msgprintf("** Phase 4 - Check Reference Counts\n");
741 * 5: check and repair resource counts in cylinder groups
744 msgprintf("** Phase 5 - Check Cyl groups\n");
747 #if defined(AFS_SUN_ENV)
753 * print out summary statistics
755 n_ffree = sblock.fs_cstotal.cs_nffree;
756 n_bfree = sblock.fs_cstotal.cs_nbfree;
758 #if defined(ACLS) && defined(AFS_HPUX_ENV)
759 pinfo("%d files, %d icont, %d used, %d free", n_files, n_cont, n_blks,
760 n_ffree + sblock.fs_frag * n_bfree);
762 pinfo("%d files, %d used, %d free", n_files, n_blks,
763 n_ffree + sblock.fs_frag * n_bfree);
766 msgprintf(", %d AFS files", nViceFiles);
767 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
768 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
770 #if defined(ACLS) && defined(AFS_HPUX_ENV)
771 pinfo("%d files, %d icont, %d used, %d free ", n_files, n_cont, n_blks,
772 n_ffree + sblock.fs_frag * n_bfree);
774 pinfo("%d files, %d used, %d free ", n_files, n_blks,
775 n_ffree + sblock.fs_frag * n_bfree);
777 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
778 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
780 if (debug && (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
781 msgprintf("%d files missing\n", n_files);
783 n_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
784 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
785 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
786 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
787 printf("%d blocks missing\n", n_blks);
788 if (duplist != NULL) {
789 msgprintf("The following duplicate blocks remain:");
790 for (dp = duplist; dp; dp = dp->next)
791 msgprintf(" %d,", dp->dup);
794 if (zlnhead != NULL) {
795 msgprintf("The following zero link count inodes remain:");
796 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
797 msgprintf(" %d,", zlnp->zlncnt);
802 /* if user's specification denotes that the file system block
803 * is going to be modified (nflag == 0) then fsck store the
804 * correct magic number in the super block if it is not already
807 if (!nflag && !(fswritefd < 0)) {
809 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
813 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
814 if (!preen && !qflag)
815 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
816 sblock.fs_clean = FS_CLEAN;
820 /* fix FS_CLEAN if changes made and no 'no' replies */
821 if (fsmodified && fixed)
822 sblock.fs_clean = FS_CLEAN;
824 * Fix fs_clean if there were no 'no' replies.
825 * This is done for both the s300 and s800. The s800 root will be
826 * guaranteed clean as of 7.0.
828 if (fixed && (sblock.fs_clean != FS_OK)) {
829 if (!preen && !qflag)
830 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
831 sblock.fs_clean = FS_CLEAN;
841 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
849 if (hotroot && sblock.fs_clean == FSACTIVE)
852 else if (!((sblock.fs_state + (afs_int32) sblock.fs_time == FSOKAY) &&
854 else if (!((fs_get_state(&sblock) + (afs_int32) sblock.fs_time == FSOKAY)
857 (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
858 if (yflag || !iscorrupt) {
859 printf("%s FILE SYSTEM STATE SET TO OKAY\n", devname);
862 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n", devname);
867 (void)time(&sblock.fs_time);
869 if (hotroot && rebflg)
870 sblock.fs_clean = FSACTIVE;
872 sblock.fs_clean = FSSTABLE;
874 sblock.fs_state = FSOKAY - (afs_int32) sblock.fs_time;
876 fs_set_state(&sblock, FSOKAY - (afs_int32) sblock.fs_time);
883 if (!nflag && !bflag && !hotroot) {
885 sblock.fs_clean = FS_CLEAN;
886 (void)time(&sblock.fs_time);
888 flush(fswritefd, &sblk);
891 #else /* AFS_OSF_ENV */
893 (void)time(&sblock.fs_time);
901 free((char *)lncntp);
903 blockmap = statemap = NULL;
911 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
914 msgprintf("\n***** REBOOT UNIX *****\n");
917 if (mountedfs || hotroot) {
935 (void)close(fsreadfd);
936 (void)close(fswritefd);
937 if (nViceFiles || tryForce) {
938 /* Modified file system with vice files: force full salvage */
939 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
940 struct ufs_args ufsargs;
942 char pname[100], fname[100], *special;
943 int fd, code, failed = 0;
946 ("%s: AFS file system partition was modified; forcing full salvage\n",
948 devname = unrawname(devname);
949 special = (char *)strrchr(devname, '/');
952 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
953 * /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
954 strcat(pname, special);
956 /* if system mounted / as read-only, we'll try to fix now */
957 if (access("/", W_OK) < 0 && errno == EROFS) {
958 code = system("mount -o remount /");
960 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
967 /* if system mounted / as read-only, we'll try to fix now */
968 if (access("/", W_OK) < 0 && errno == EROFS) {
969 printf("Can't RW acceess /; %d\n", errno);
970 code = system("/sbin/mount -u /");
972 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
980 if (mkdir(pname, 0777) < 0) {
981 if (errno != EEXIST) {
982 perror("fsck mkdir");
986 if (failed && parname) {
987 strcpy(pname, parname);
989 #if !defined(AFS_HPUX_ENV)
991 ufsargs.flags = UFSMNT_NOINTR;
993 ufsargs.fspec = devname;
997 (devname, pname, MS_DATA, "ufs", (char *)&ufsargs,
998 sizeof(ufsargs)) < 0) {
1000 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1003 if (mount(devname, pname, 0) < 0) {
1006 ("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n",
1007 devname, pname, errno);
1009 strcpy(fname, pname);
1010 strcat(fname, "/FORCESALVAGE");
1011 fd = open(fname, O_CREAT, 0);
1013 errexit("Couldn't create %s to force full salvage!\n", fname);
1018 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1021 #if defined(AFS_OSF_ENV)
1022 umount(pname, MNT_NOFORCE);
1023 #else /* AFS_OSF_ENV */
1031 fsync(fileno(logfile)); /* Since update isn't running */
1043 struct stat stslash, stblock, stchar;
1048 if (stat("/", &stslash) < 0) {
1050 printf("Can't stat root\n");
1054 if (stat(name, &stblock) < 0) {
1056 printf("Can't stat %s\n", name);
1059 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1060 if (stslash.st_dev == stblock.st_rdev) {
1062 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1064 #endif /* AFS_OSF_ENV */
1066 raw = rawname(name);
1070 printf("Cannot find character device for %s\n", name);
1073 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1074 name = unrawname(name);
1078 printf("Can't make sense out of name %s\n", name);
1083 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1087 * exit 0 - file system is unmounted and okay
1088 * exit 32 - file system is unmounted and needs checking
1089 * exit 33 - file system is mounted for root file system
1090 * exit 34 - cannot stat device
1092 check_sanity(filename)
1095 struct stat stbd, stbr;
1098 struct vfstab vfsbuf;
1104 if (stat(filename, &stbd) < 0) {
1105 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n",
1110 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1112 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1116 "ufs fsck: sanity check failed: %s not block or character device\n",
1121 * Determine if this is the root file system via vfstab. Give up
1122 * silently on failures. The whole point of this is not to care
1123 * if the root file system is already mounted.
1125 * XXX - similar for /usr. This should be fixed to simply return
1126 * a new code indicating, mounted and needs to be checked.
1128 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1129 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1131 devname = vfsbuf.vfs_special;
1133 devname = vfsbuf.vfs_fsckdev;
1134 if (stat(devname, &stbr) == 0)
1135 if (stbr.st_rdev == stbd.st_rdev)
1138 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1140 devname = vfsbuf.vfs_special;
1142 devname = vfsbuf.vfs_fsckdev;
1143 if (stat(devname, &stbr) == 0)
1144 if (stbr.st_rdev == stbd.st_rdev)
1149 /* XXX - only works if filename is a block device or if
1150 * character and block device has the same dev_t value */
1151 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1152 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n",
1157 * We mount the ufs root file system read-only first. After fsck
1158 * runs, we remount the root as read-write. Therefore, we no longer
1159 * check for different values for fs_state between the root file
1160 * system and the rest of file systems.
1162 if (!((sblock.fs_state + (time_t) sblock.fs_time == FSOKAY)
1163 && (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
1164 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n",
1168 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1173 #if defined(AFS_HPUX100_ENV)
1174 check_sanity(filename)
1177 struct stat stbd, stbr;
1186 if (stat(filename, &stbd) < 0) {
1187 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n",
1192 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1194 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1198 "hfs fsck: sanity check failed: %s not block or character device\n",
1203 * Determine if this is the root file system via vfstab. Give up
1204 * silently on failures. The whole point of this is not to care
1205 * if the root file system is already mounted.
1207 * XXX - similar for /usr. This should be fixed to simply return
1208 * a new code indicating, mounted and needs to be checked.
1210 if ((vfstab = setmntent(FSTAB, "r")) != 0) {
1211 while (mnt = getmntent(vfstab)) {
1212 if (!strcmp(mnt->mnt_dir, "/"))
1213 if (stat(mnt->mnt_fsname, &stbr) == 0)
1214 if (stbr.st_rdev == stbd.st_rdev)
1217 if (!strcmp(mnt->mnt_dir, "/usr"))
1218 if (stat(mnt->mnt_fsname, &stbr) == 0)
1219 if (stbr.st_rdev == stbd.st_rdev)
1225 /* XXX - only works if filename is a block device or if
1226 * character and block device has the same dev_t value */
1227 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1228 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n",
1233 * We mount the ufs root file system read-only first. After fsck
1234 * runs, we remount the root as read-write. Therefore, we no longer
1235 * check for different values for fs_state between the root file
1236 * system and the rest of file systems.
1238 if (!((sblock.fs_clean == FS_CLEAN || sblock.fs_clean == FS_OK))) {
1239 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n",
1243 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1247 /* see if all numbers */
1253 while ('0' <= *yp && *yp <= '9')
1261 /* Convert a raw device name into a block device name.
1262 * If the block device is not found, return the raw device name.
1263 * For HP and SUN, the returned value is not changed. For other
1264 * platforms it is changed (I see no rhyme or reason -jpm).
1270 static char bldev[256];
1271 struct stat statbuf;
1274 code = stat(rawdev, &statbuf);
1275 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1276 return (rawdev); /* Not a char device */
1278 for (i = strlen(rawdev) - 2; i >= 0; i--) {
1279 if ((rawdev[i] == '/') && (rawdev[i + 1] == 'r')) {
1280 strcpy(bldev, rawdev);
1282 strcat(bldev, &rawdev[i + 2]);
1284 code = stat(bldev, &statbuf); /* test for block device */
1285 if (!code && S_ISBLK(statbuf.st_mode)) {
1286 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1289 strcpy(rawdev, bldev); /* Replace */
1298 /* Convert a block device name into a raw device name.
1299 * If the block device is not found, return null
1305 static char rawdev[256];
1306 struct stat statbuf;
1309 for (i = strlen(bldev) - 1; i >= 0; i--) {
1310 if (bldev[i] == '/') {
1311 strcpy(rawdev, bldev);
1312 rawdev[i + 1] = 'r';
1314 strcat(rawdev, &bldev[i + 1]);
1316 code = stat(rawdev, &statbuf);
1317 if (!code && S_ISCHR(statbuf.st_mode))