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 writeable '%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 = (struct disk *)malloc(sizeof(struct disk))) == NULL)
562 errexit("out of memory");
564 if ((dk->name = malloc((unsigned int)len + 1)) == NULL)
565 errexit("out of memory");
566 strncpy(dk->name, name, len);
567 dk->name[len] = '\0';
575 addpart(name, fsname)
578 struct disk *dk = finddisk(name);
579 struct part *pt, **ppt = &dk->part;
581 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
582 if (strcmp(pt->name, name) == 0) {
583 printf("%s in fstab more than once!\n", name);
586 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
587 errexit("out of memory");
589 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL)
590 errexit("out of memory");
591 strcpy(pt->name, name);
592 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL)
593 errexit("out of memory");
594 strcpy(pt->fsname, fsname);
609 (void)signal(SIGQUIT, voidquit);
610 checkfilesys(dk->part->name, dk->part->fsname);
615 checkfilesys(filesys, parname)
618 daddr_t n_ffree, n_bfree;
620 struct stat tstat; /* for ultrix 3 unmount */
627 #endif /* AFS_OSF_ENV */
637 ge_danger = 0; /* set to 1 by any table overflow or more
638 * dup/bad blocks than expected */
640 fixed = 1; /* set to 0 by any 'no' reply */
642 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
643 devname = devbuffer; /* remember generic ptr for later */
644 EnsureDevice(devname); /* canonicalize name */
648 ret_val = setup(devname);
656 pfatal("CAN'T CHECK FILE SYSTEM.");
658 if ((exitstat == 0) && (mflag))
664 } else if (ret_val == -1) { /* pclean && FS_CLEAN */
667 #if defined(AFS_OSF_ENV)
668 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
672 #if defined(AFS_HPUX100_ENV)
674 check_sanity(filesys);
679 check_sanity(filesys);
687 * 1: scan inodes tallying blocks used
690 #if defined(AFS_SUN5_ENV)
692 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
695 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
697 msgprintf("** Root file system\n");
700 printf("** Phase 1 - Sanity Check only\n");
704 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
709 * 1b: locate first references to duplicates, if any
713 pfatal("INTERNAL ERROR: dups with -p");
714 msgprintf("** Phase 1b - Rescan For More DUPS\n");
719 * 2: traverse directories from root to mark all connected directories
722 msgprintf("** Phase 2 - Check Pathnames\n");
726 * 3: scan inodes looking for disconnected directories
729 msgprintf("** Phase 3 - Check Connectivity\n");
733 * 4: scan inodes looking for disconnected files; check reference counts
736 msgprintf("** Phase 4 - Check Reference Counts\n");
740 * 5: check and repair resource counts in cylinder groups
743 msgprintf("** Phase 5 - Check Cyl groups\n");
746 #if defined(AFS_SUN_ENV)
752 * print out summary statistics
754 n_ffree = sblock.fs_cstotal.cs_nffree;
755 n_bfree = sblock.fs_cstotal.cs_nbfree;
757 #if defined(ACLS) && defined(AFS_HPUX_ENV)
758 pinfo("%d files, %d icont, %d used, %d free", n_files, n_cont, n_blks,
759 n_ffree + sblock.fs_frag * n_bfree);
761 pinfo("%d files, %d used, %d free", n_files, n_blks,
762 n_ffree + sblock.fs_frag * n_bfree);
765 msgprintf(", %d AFS files", nViceFiles);
766 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
767 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
769 #if defined(ACLS) && defined(AFS_HPUX_ENV)
770 pinfo("%d files, %d icont, %d used, %d free ", n_files, n_cont, n_blks,
771 n_ffree + sblock.fs_frag * n_bfree);
773 pinfo("%d files, %d used, %d free ", n_files, n_blks,
774 n_ffree + sblock.fs_frag * n_bfree);
776 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
777 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
779 if (debug && (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
780 msgprintf("%d files missing\n", n_files);
782 n_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
783 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
784 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
785 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
786 printf("%d blocks missing\n", n_blks);
787 if (duplist != NULL) {
788 msgprintf("The following duplicate blocks remain:");
789 for (dp = duplist; dp; dp = dp->next)
790 msgprintf(" %d,", dp->dup);
793 if (zlnhead != NULL) {
794 msgprintf("The following zero link count inodes remain:");
795 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
796 msgprintf(" %d,", zlnp->zlncnt);
801 /* if user's specification denotes that the file system block
802 * is going to be modified (nflag == 0) then fsck store the
803 * correct magic number in the super block if it is not already
806 if (!nflag && !(fswritefd < 0)) {
808 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
812 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
813 if (!preen && !qflag)
814 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
815 sblock.fs_clean = FS_CLEAN;
819 /* fix FS_CLEAN if changes made and no 'no' replies */
820 if (fsmodified && fixed)
821 sblock.fs_clean = FS_CLEAN;
823 * Fix fs_clean if there were no 'no' replies.
824 * This is done for both the s300 and s800. The s800 root will be
825 * guaranteed clean as of 7.0.
827 if (fixed && (sblock.fs_clean != FS_OK)) {
828 if (!preen && !qflag)
829 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
830 sblock.fs_clean = FS_CLEAN;
840 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
848 if (hotroot && sblock.fs_clean == FSACTIVE)
851 else if (!((sblock.fs_state + (afs_int32) sblock.fs_time == FSOKAY) &&
853 else if (!((fs_get_state(&sblock) + (afs_int32) sblock.fs_time == FSOKAY)
856 (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
857 if (yflag || !iscorrupt) {
858 printf("%s FILE SYSTEM STATE SET TO OKAY\n", devname);
861 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n", devname);
866 (void)time(&sblock.fs_time);
868 if (hotroot && rebflg)
869 sblock.fs_clean = FSACTIVE;
871 sblock.fs_clean = FSSTABLE;
873 sblock.fs_state = FSOKAY - (afs_int32) sblock.fs_time;
875 fs_set_state(&sblock, FSOKAY - (afs_int32) sblock.fs_time);
882 if (!nflag && !bflag && !hotroot) {
884 sblock.fs_clean = FS_CLEAN;
885 (void)time(&sblock.fs_time);
887 flush(fswritefd, &sblk);
890 #else /* AFS_OSF_ENV */
892 (void)time(&sblock.fs_time);
900 free((char *)lncntp);
902 blockmap = statemap = NULL;
910 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
913 msgprintf("\n***** REBOOT UNIX *****\n");
916 if (mountedfs || hotroot) {
934 (void)close(fsreadfd);
935 (void)close(fswritefd);
936 if (nViceFiles || tryForce) {
937 /* Modified file system with vice files: force full salvage */
938 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
939 struct ufs_args ufsargs;
941 char pname[100], fname[100], *special;
942 int fd, code, failed = 0;
945 ("%s: AFS file system partition was modified; forcing full salvage\n",
947 devname = unrawname(devname);
948 special = (char *)strrchr(devname, '/');
951 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
952 * /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
953 strcat(pname, special);
955 /* if system mounted / as read-only, we'll try to fix now */
956 if (access("/", W_OK) < 0 && errno == EROFS) {
957 code = system("mount -o remount /");
959 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
966 /* if system mounted / as read-only, we'll try to fix now */
967 if (access("/", W_OK) < 0 && errno == EROFS) {
968 printf("Can't RW acceess /; %d\n", errno);
969 code = system("/sbin/mount -u /");
971 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
979 if (mkdir(pname, 0777) < 0) {
980 if (errno != EEXIST) {
981 perror("fsck mkdir");
985 if (failed && parname) {
986 strcpy(pname, parname);
988 #if !defined(AFS_HPUX_ENV)
990 ufsargs.flags = UFSMNT_NOINTR;
992 ufsargs.fspec = devname;
996 (devname, pname, MS_DATA, "ufs", (char *)&ufsargs,
997 sizeof(ufsargs)) < 0) {
999 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1002 if (mount(devname, pname, 0) < 0) {
1005 ("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n",
1006 devname, pname, errno);
1008 strcpy(fname, pname);
1009 strcat(fname, "/FORCESALVAGE");
1010 fd = open(fname, O_CREAT, 0);
1012 errexit("Couldn't create %s to force full salvage!\n", fname);
1017 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1020 #if defined(AFS_OSF_ENV)
1021 umount(pname, MNT_NOFORCE);
1022 #else /* AFS_OSF_ENV */
1030 fsync(fileno(logfile)); /* Since update isn't running */
1042 struct stat stslash, stblock, stchar;
1047 if (stat("/", &stslash) < 0) {
1049 printf("Can't stat root\n");
1053 if (stat(name, &stblock) < 0) {
1055 printf("Can't stat %s\n", name);
1058 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1059 if (stslash.st_dev == stblock.st_rdev) {
1061 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1063 #endif /* AFS_OSF_ENV */
1065 raw = rawname(name);
1069 printf("Cannot find character device for %s\n", name);
1072 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1073 name = unrawname(name);
1077 printf("Can't make sense out of name %s\n", name);
1082 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1086 * exit 0 - file system is unmounted and okay
1087 * exit 32 - file system is unmounted and needs checking
1088 * exit 33 - file system is mounted for root file system
1089 * exit 34 - cannot stat device
1091 check_sanity(filename)
1094 struct stat stbd, stbr;
1097 struct vfstab vfsbuf;
1103 if (stat(filename, &stbd) < 0) {
1104 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n",
1109 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1111 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1115 "ufs fsck: sanity check failed: %s not block or character device\n",
1120 * Determine if this is the root file system via vfstab. Give up
1121 * silently on failures. The whole point of this is not to care
1122 * if the root file system is already mounted.
1124 * XXX - similar for /usr. This should be fixed to simply return
1125 * a new code indicating, mounted and needs to be checked.
1127 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1128 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1130 devname = vfsbuf.vfs_special;
1132 devname = vfsbuf.vfs_fsckdev;
1133 if (stat(devname, &stbr) == 0)
1134 if (stbr.st_rdev == stbd.st_rdev)
1137 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1139 devname = vfsbuf.vfs_special;
1141 devname = vfsbuf.vfs_fsckdev;
1142 if (stat(devname, &stbr) == 0)
1143 if (stbr.st_rdev == stbd.st_rdev)
1148 /* XXX - only works if filename is a block device or if
1149 * character and block device has the same dev_t value */
1150 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1151 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n",
1156 * We mount the ufs root file system read-only first. After fsck
1157 * runs, we remount the root as read-write. Therefore, we no longer
1158 * check for different values for fs_state between the root file
1159 * system and the rest of file systems.
1161 if (!((sblock.fs_state + (time_t) sblock.fs_time == FSOKAY)
1162 && (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
1163 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n",
1167 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1172 #if defined(AFS_HPUX100_ENV)
1173 check_sanity(filename)
1176 struct stat stbd, stbr;
1185 if (stat(filename, &stbd) < 0) {
1186 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n",
1191 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1193 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1197 "hfs fsck: sanity check failed: %s not block or character device\n",
1202 * Determine if this is the root file system via vfstab. Give up
1203 * silently on failures. The whole point of this is not to care
1204 * if the root file system is already mounted.
1206 * XXX - similar for /usr. This should be fixed to simply return
1207 * a new code indicating, mounted and needs to be checked.
1209 if ((vfstab = setmntent(FSTAB, "r")) != 0) {
1210 while (mnt = getmntent(vfstab)) {
1211 if (!strcmp(mnt->mnt_dir, "/"))
1212 if (stat(mnt->mnt_fsname, &stbr) == 0)
1213 if (stbr.st_rdev == stbd.st_rdev)
1216 if (!strcmp(mnt->mnt_dir, "/usr"))
1217 if (stat(mnt->mnt_fsname, &stbr) == 0)
1218 if (stbr.st_rdev == stbd.st_rdev)
1224 /* XXX - only works if filename is a block device or if
1225 * character and block device has the same dev_t value */
1226 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1227 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n",
1232 * We mount the ufs root file system read-only first. After fsck
1233 * runs, we remount the root as read-write. Therefore, we no longer
1234 * check for different values for fs_state between the root file
1235 * system and the rest of file systems.
1237 if (!((sblock.fs_clean == FS_CLEAN || sblock.fs_clean == FS_OK))) {
1238 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n",
1242 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1246 /* see if all numbers */
1252 while ('0' <= *yp && *yp <= '9')
1260 /* Convert a raw device name into a block device name.
1261 * If the block device is not found, return the raw device name.
1262 * For HP and SUN, the returned value is not changed. For other
1263 * platforms it is changed (I see no rhyme or reason -jpm).
1269 static char bldev[256];
1270 struct stat statbuf;
1273 code = stat(rawdev, &statbuf);
1274 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1275 return (rawdev); /* Not a char device */
1277 for (i = strlen(rawdev) - 2; i >= 0; i--) {
1278 if ((rawdev[i] == '/') && (rawdev[i + 1] == 'r')) {
1279 strcpy(bldev, rawdev);
1281 strcat(bldev, &rawdev[i + 2]);
1283 code = stat(bldev, &statbuf); /* test for block device */
1284 if (!code && S_ISBLK(statbuf.st_mode)) {
1285 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1288 strcpy(rawdev, bldev); /* Replace */
1297 /* Convert a block device name into a raw device name.
1298 * If the block device is not found, return null
1304 static char rawdev[256];
1305 struct stat statbuf;
1308 for (i = strlen(bldev) - 1; i >= 0; i--) {
1309 if (bldev[i] == '/') {
1310 strcpy(rawdev, bldev);
1311 rawdev[i + 1] = 'r';
1313 strcat(rawdev, &bldev[i + 1]);
1315 code = stat(rawdev, &statbuf);
1316 if (!code && S_ISCHR(statbuf.st_mode))