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 #define VICE /* allow us to put our changes in at will */
25 #include <sys/param.h>
30 #endif /* AFS_SUN_ENV */
31 #include <sys/mount.h>
39 #include <sys/vnode.h>
40 #include <sys/mount.h>
41 #include <ufs/inode.h>
43 #else /* AFS_OSF_ENV */
44 #ifdef AFS_VFSINCL_ENV
46 #include <sys/vnode.h>
49 #include <sys/fs/ufs_inode.h>
50 #include <sys/fs/ufs_fs.h>
52 #include <sys/fs/ufs_fsdir.h>
54 #include <sys/fs/ufs_mount.h>
56 #include <ufs/inode.h>
59 #include <ufs/fsdir.h>
62 #else /* AFS_VFSINCL_ENV */
64 #include <sys/inode.h>
67 #define LONGFILENAMES 1
68 #include <sys/sysmacros.h>
71 #ifdef HAVE_USR_OLD_USR_INCLUDE_NDIR_H
72 #include </usr/old/usr/include/ndir.h>
82 #endif /* AFS_VFSINCL_ENV */
83 #endif /* AFS_OSF_ENV */
97 #include <sys/mnttab.h>
98 #include <sys/mntent.h>
99 #include <sys/vfstab.h>
100 #include <sys/ustat.h>
107 #include <sys/signal.h>
109 char *rawname(), *unrawname(), *blockcheck(), *malloc();
110 void catch(), catchquit(), voidquit();
117 char *name; /* device name */
118 char *fsname; /* mounted filesystem name */
119 struct part *next; /* forward link of partitions on disk */
120 } *badlist, **badnext = &badlist;
123 char *name; /* disk base name */
124 struct disk *next; /* forward link for list of disks */
125 struct part *part; /* head of list of partitions on disk */
126 int pid; /* If != 0, pid of proc working on */
129 int nrun, ndisks, maxrun, wflag = 0;
134 #if defined(AFS_HPUX100_ENV)
140 #define msgprintf vfscklogprintf
142 #define msgprintf printf
149 #include "AFS_component_version_number.c"
152 int ge_danger = 0; /* on when fsck is not able to fix the dirty file
153 * system within single run. Problems like dup table
154 * overflow, maxdup is exceeding MAXDUP.. etc. could
155 * potentailly prevent fsck from doing a complete
156 * repair. This is found in a GE hotsite. */
164 int pid, passno, sumstatus;
166 struct disk *dk, *nextdisk;
168 extern char *AFSVersion; /* generated version */
170 int other_than_ufs = 0;
181 #if defined(AFS_HPUX_ENV)
184 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
188 fsflag = oflag = mflag = exitstat = 0;
190 #if defined(AFS_HPUX100_ENV)
193 printf("----Open AFS (R) %s fsck----\n", AFSVersion); /* generated version */
194 if (access("/TRYFORCE", 0) == 0)
196 while (--argc > 0 && **++argv == '-') {
199 #if defined(AFS_HPUX_ENV)
200 #if defined(AFS_HPUX100_ENV)
201 case 'f': /* default yes to answer force to check */
204 #else /* AFS_HPUX100_ENV */
206 case 'F': /* default yes to answer force to check */
209 #endif /* AFS_HPUX_ENV */
210 #endif /* AFS_HPUX100_ENV */
219 #if defined(AFS_HPUX100_ENV)
225 (void)fprintf(stdout, "fsck -F hfs ");
226 for (opt_count = 1; opt_count < argc; opt_count++) {
227 opt_text = argv[opt_count];
229 (void)fprintf(stdout, " %s ", opt_text);
231 (void)fprintf(stdout, "\n");
245 (void)fprintf(stdout, "fsck -F ufs ");
246 for (opt_count = 1; opt_count < argc; opt_count++) {
247 opt_text = argv[opt_count];
249 (void)fprintf(stdout, " %s ", opt_text);
251 (void)fprintf(stdout, "\n");
258 while (*subopt != '\0') {
259 if (*subopt == 'p') {
262 } else if (*subopt == 'b') {
263 if (argv[0][1] != '\0') {
264 bflag = atoi(argv[0] + 1);
266 bflag = atoi(*++argv);
269 msgprintf("Alternate super block location: %d\n", bflag);
271 } else if (*subopt == 'd') {
274 } else if (*subopt == 'r') {
276 } else if (*subopt == 'w') {
279 } else if (*subopt == 'c') {
282 } else if (*subopt == 'f') {
286 errexit("-o %c option?\n", *subopt);
299 if (argv[0][1] != '\0') {
300 bflag = atoi(argv[0] + 1);
302 bflag = atoi(*++argv);
305 msgprintf("Alternate super block location: %d\n", bflag);
312 /* who knows? defined, but doesn't do much */
316 case 'w': /* check writable only */
323 if (!isdigit(argv[1][0]))
324 errexit("-l flag requires a number\n");
325 maxrun = atoi(*++argv);
328 #if !defined(AFS_HPUX100_ENV)
330 if (!isdigit(argv[1][0]))
331 errexit("-m flag requires a mode\n");
332 sscanf(*++argv, "%o", &lfmode);
334 errexit("bad mode to -m: %o\n", lfmode);
336 printf("** lost+found creation mode %o\n", lfmode);
338 #endif /* AFS_HPUX100_ENV */
339 #endif /* AFS_SUN5_ENV */
344 #endif /* AFS_OSF_ENV */
352 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
353 * it's general/useful flag to use.
366 errexit("%c option?\n", **argv);
370 * The following checks were only available on hpux but are useful to all systems.
373 errexit("Incompatible options: -n and -p\n");
375 errexit("Incompatible options: -n and -q\n");
378 rflag++; /* check raw devices */
380 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
381 (void)signal(SIGINT, catch);
383 (void)signal(SIGQUIT, catchquit);
388 if (wflag && !writable(*argv)) {
389 (void)fprintf(stderr, "not writeable '%s'\n", *argv);
393 checkfilesys(*argv++, NULL);
408 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
411 if ((fd = fopen(VFSTAB, "r")) == NULL) {
412 errexit("vfsck: cannot open vfstab\n");
414 while ((ret = getvfsent(fd, &vget)) == 0) {
415 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS)
416 && numbers(vget.vfs_fsckpass)) {
420 if (numbers(vget.vfs_fsckpass))
421 passno = atoi(vget.vfs_fsckpass);
426 if (preen == 0 || passno == 1) {
427 checkfilesys(vget.vfs_fsckdev, get.vfs_mountp);
428 } else if (passno > 1) {
429 addpart(vget.vfs_fsckdev, vget.vfs_special);
433 for (passno = 1; passno <= 2; passno++) {
435 errexit("Can't open checklist file: %s\n", FSTAB);
436 while ((fsp = getfsent()) != 0) {
437 if (strcmp(fsp->fs_type, FSTAB_RW)
438 && strcmp(fsp->fs_type, FSTAB_RO)
439 && strcmp(fsp->fs_type, FSTAB_RQ))
442 if (strcmp(fsp->fs_vfstype, "ufs") || fsp->fs_passno == 0) {
445 #endif /* AFS_OSF_ENV */
446 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
448 name = blockcheck(fsp->fs_spec);
450 checkfilesys(name, fsp->fs_file);
452 printf("pid %d exiting 8/1\n", getpid());
456 } else if (passno == 2 && fsp->fs_passno > 1) {
457 name = blockcheck(fsp->fs_spec);
459 pwarn("BAD DISK NAME %s\n", fsp->fs_spec);
461 printf("pid %d saw bad disk name 8/3\n", getpid());
464 addpart(name, fsp->fs_file);
467 #endif /* AFS_SUN5_ENV */
477 for (passno = 0; passno < maxrun; ++passno) {
479 nextdisk = nextdisk->next;
481 while ((pid = wait(&status)) != -1) {
482 for (dk = disks; dk; dk = dk->next)
486 printf("Unknown pid %d\n", pid);
489 rc = WEXITSTATUS(status);
490 if (WIFSIGNALED(status)) {
491 printf("%s (%s): EXITED WITH SIGNAL %d\n", dk->part->name,
492 dk->part->fsname, WTERMSIG(status));
498 badnext = &dk->part->next;
499 dk->part = dk->part->next;
502 dk->part = dk->part->next;
505 if (dk->part == NULL)
508 if (nextdisk == NULL) {
511 } else if (nrun < maxrun && nrun < ndisks) {
513 if ((nextdisk = nextdisk->next) == NULL)
515 if (nextdisk->part != NULL && nextdisk->pid == 0)
524 printf("pid %d exiting 8/2\n", getpid());
527 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
528 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
529 for (pt = badlist; pt; pt = pt->next)
530 printf("%s (%s)%s", pt->name, pt->fsname, pt->next ? ", " : "\n");
540 #endif /* !AFS_SUN5_ENV */
548 struct disk *dk, **dkp;
552 for (p = name + strlen(name) - 1; p >= name; --p)
560 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
561 if (strncmp(dk->name, name, len) == 0 && dk->name[len] == 0)
564 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
565 errexit("out of memory");
567 if ((dk->name = malloc((unsigned int)len + 1)) == NULL)
568 errexit("out of memory");
569 strncpy(dk->name, name, len);
570 dk->name[len] = '\0';
578 addpart(name, fsname)
581 struct disk *dk = finddisk(name);
582 struct part *pt, **ppt = &dk->part;
584 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
585 if (strcmp(pt->name, name) == 0) {
586 printf("%s in fstab more than once!\n", name);
589 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
590 errexit("out of memory");
592 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL)
593 errexit("out of memory");
594 strcpy(pt->name, name);
595 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL)
596 errexit("out of memory");
597 strcpy(pt->fsname, fsname);
612 (void)signal(SIGQUIT, voidquit);
613 checkfilesys(dk->part->name, dk->part->fsname);
618 checkfilesys(filesys, parname)
621 daddr_t n_ffree, n_bfree;
623 struct stat tstat; /* for ultrix 3 unmount */
630 #endif /* AFS_OSF_ENV */
640 ge_danger = 0; /* set to 1 by any table overflow or more
641 * dup/bad blocks than expected */
643 fixed = 1; /* set to 0 by any 'no' reply */
645 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
646 devname = devbuffer; /* remember generic ptr for later */
647 EnsureDevice(devname); /* canonicalize name */
651 ret_val = setup(devname);
659 pfatal("CAN'T CHECK FILE SYSTEM.");
661 if ((exitstat == 0) && (mflag))
667 } else if (ret_val == -1) { /* pclean && FS_CLEAN */
670 #if defined(AFS_OSF_ENV)
671 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
675 #if defined(AFS_HPUX100_ENV)
677 check_sanity(filesys);
682 check_sanity(filesys);
690 * 1: scan inodes tallying blocks used
693 #if defined(AFS_SUN5_ENV)
695 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
698 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
700 msgprintf("** Root file system\n");
703 printf("** Phase 1 - Sanity Check only\n");
707 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
712 * 1b: locate first references to duplicates, if any
716 pfatal("INTERNAL ERROR: dups with -p");
717 msgprintf("** Phase 1b - Rescan For More DUPS\n");
722 * 2: traverse directories from root to mark all connected directories
725 msgprintf("** Phase 2 - Check Pathnames\n");
729 * 3: scan inodes looking for disconnected directories
732 msgprintf("** Phase 3 - Check Connectivity\n");
736 * 4: scan inodes looking for disconnected files; check reference counts
739 msgprintf("** Phase 4 - Check Reference Counts\n");
743 * 5: check and repair resource counts in cylinder groups
746 msgprintf("** Phase 5 - Check Cyl groups\n");
749 #if defined(AFS_SUN_ENV)
755 * print out summary statistics
757 n_ffree = sblock.fs_cstotal.cs_nffree;
758 n_bfree = sblock.fs_cstotal.cs_nbfree;
760 #if defined(ACLS) && defined(AFS_HPUX_ENV)
761 pinfo("%d files, %d icont, %d used, %d free", n_files, n_cont, n_blks,
762 n_ffree + sblock.fs_frag * n_bfree);
764 pinfo("%d files, %d used, %d free", n_files, n_blks,
765 n_ffree + sblock.fs_frag * n_bfree);
768 msgprintf(", %d AFS files", nViceFiles);
769 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
770 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
772 #if defined(ACLS) && defined(AFS_HPUX_ENV)
773 pinfo("%d files, %d icont, %d used, %d free ", n_files, n_cont, n_blks,
774 n_ffree + sblock.fs_frag * n_bfree);
776 pinfo("%d files, %d used, %d free ", n_files, n_blks,
777 n_ffree + sblock.fs_frag * n_bfree);
779 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
780 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
782 if (debug && (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
783 msgprintf("%d files missing\n", n_files);
785 n_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
786 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
787 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
788 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
789 printf("%d blocks missing\n", n_blks);
790 if (duplist != NULL) {
791 msgprintf("The following duplicate blocks remain:");
792 for (dp = duplist; dp; dp = dp->next)
793 msgprintf(" %d,", dp->dup);
796 if (zlnhead != NULL) {
797 msgprintf("The following zero link count inodes remain:");
798 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
799 msgprintf(" %d,", zlnp->zlncnt);
804 /* if user's specification denotes that the file system block
805 * is going to be modified (nflag == 0) then fsck store the
806 * correct magic number in the super block if it is not already
809 if (!nflag && !(fswritefd < 0)) {
811 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
815 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
816 if (!preen && !qflag)
817 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
818 sblock.fs_clean = FS_CLEAN;
822 /* fix FS_CLEAN if changes made and no 'no' replies */
823 if (fsmodified && fixed)
824 sblock.fs_clean = FS_CLEAN;
826 * Fix fs_clean if there were no 'no' replies.
827 * This is done for both the s300 and s800. The s800 root will be
828 * guaranteed clean as of 7.0.
830 if (fixed && (sblock.fs_clean != FS_OK)) {
831 if (!preen && !qflag)
832 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
833 sblock.fs_clean = FS_CLEAN;
843 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
851 if (hotroot && sblock.fs_clean == FSACTIVE)
854 else if (!((sblock.fs_state + (afs_int32) sblock.fs_time == FSOKAY) &&
856 else if (!((fs_get_state(&sblock) + (afs_int32) sblock.fs_time == FSOKAY)
859 (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
860 if (yflag || !iscorrupt) {
861 printf("%s FILE SYSTEM STATE SET TO OKAY\n", devname);
864 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n", devname);
869 (void)time(&sblock.fs_time);
871 if (hotroot && rebflg)
872 sblock.fs_clean = FSACTIVE;
874 sblock.fs_clean = FSSTABLE;
876 sblock.fs_state = FSOKAY - (afs_int32) sblock.fs_time;
878 fs_set_state(&sblock, FSOKAY - (afs_int32) sblock.fs_time);
885 if (!nflag && !bflag && !hotroot) {
887 sblock.fs_clean = FS_CLEAN;
888 (void)time(&sblock.fs_time);
890 flush(fswritefd, &sblk);
893 #else /* AFS_OSF_ENV */
895 (void)time(&sblock.fs_time);
903 free((char *)lncntp);
905 blockmap = statemap = NULL;
913 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
916 msgprintf("\n***** REBOOT UNIX *****\n");
919 if (mountedfs || hotroot) {
937 (void)close(fsreadfd);
938 (void)close(fswritefd);
939 if (nViceFiles || tryForce) {
940 /* Modified file system with vice files: force full salvage */
941 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
942 struct ufs_args ufsargs;
944 char pname[100], fname[100], *special;
945 int fd, code, failed = 0;
948 ("%s: AFS file system partition was modified; forcing full salvage\n",
950 devname = unrawname(devname);
951 special = (char *)strrchr(devname, '/');
954 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
955 * /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
956 strcat(pname, special);
958 /* if system mounted / as read-only, we'll try to fix now */
959 if (access("/", W_OK) < 0 && errno == EROFS) {
960 code = system("mount -o remount /");
962 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
969 /* if system mounted / as read-only, we'll try to fix now */
970 if (access("/", W_OK) < 0 && errno == EROFS) {
971 printf("Can't RW acceess /; %d\n", errno);
972 code = system("/sbin/mount -u /");
974 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
982 if (mkdir(pname, 0777) < 0) {
983 if (errno != EEXIST) {
984 perror("fsck mkdir");
988 if (failed && parname) {
989 strcpy(pname, parname);
991 #if !defined(AFS_HPUX_ENV)
993 ufsargs.flags = UFSMNT_NOINTR;
995 ufsargs.fspec = devname;
999 (devname, pname, MS_DATA, "ufs", (char *)&ufsargs,
1000 sizeof(ufsargs)) < 0) {
1002 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1005 if (mount(devname, pname, 0) < 0) {
1008 ("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n",
1009 devname, pname, errno);
1011 strcpy(fname, pname);
1012 strcat(fname, "/FORCESALVAGE");
1013 fd = open(fname, O_CREAT, 0);
1015 errexit("Couldn't create %s to force full salvage!\n", fname);
1020 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1023 #if defined(AFS_OSF_ENV)
1024 umount(pname, MNT_NOFORCE);
1025 #else /* AFS_OSF_ENV */
1033 fsync(fileno(logfile)); /* Since update isn't running */
1045 struct stat stslash, stblock, stchar;
1050 if (stat("/", &stslash) < 0) {
1052 printf("Can't stat root\n");
1056 if (stat(name, &stblock) < 0) {
1058 printf("Can't stat %s\n", name);
1061 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1062 if (stslash.st_dev == stblock.st_rdev) {
1064 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1066 #endif /* AFS_OSF_ENV */
1068 raw = rawname(name);
1072 printf("Cannot find character device for %s\n", name);
1075 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1076 name = unrawname(name);
1080 printf("Can't make sense out of name %s\n", name);
1085 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1089 * exit 0 - file system is unmounted and okay
1090 * exit 32 - file system is unmounted and needs checking
1091 * exit 33 - file system is mounted for root file system
1092 * exit 34 - cannot stat device
1094 check_sanity(filename)
1097 struct stat stbd, stbr;
1100 struct vfstab vfsbuf;
1106 if (stat(filename, &stbd) < 0) {
1107 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n",
1112 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1114 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1118 "ufs fsck: sanity check failed: %s not block or character device\n",
1123 * Determine if this is the root file system via vfstab. Give up
1124 * silently on failures. The whole point of this is not to care
1125 * if the root file system is already mounted.
1127 * XXX - similar for /usr. This should be fixed to simply return
1128 * a new code indicating, mounted and needs to be checked.
1130 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1131 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1133 devname = vfsbuf.vfs_special;
1135 devname = vfsbuf.vfs_fsckdev;
1136 if (stat(devname, &stbr) == 0)
1137 if (stbr.st_rdev == stbd.st_rdev)
1140 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1142 devname = vfsbuf.vfs_special;
1144 devname = vfsbuf.vfs_fsckdev;
1145 if (stat(devname, &stbr) == 0)
1146 if (stbr.st_rdev == stbd.st_rdev)
1151 /* XXX - only works if filename is a block device or if
1152 * character and block device has the same dev_t value */
1153 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1154 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n",
1159 * We mount the ufs root file system read-only first. After fsck
1160 * runs, we remount the root as read-write. Therefore, we no longer
1161 * check for different values for fs_state between the root file
1162 * system and the rest of file systems.
1164 if (!((sblock.fs_state + (time_t) sblock.fs_time == FSOKAY)
1165 && (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
1166 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n",
1170 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1175 #if defined(AFS_HPUX100_ENV)
1176 check_sanity(filename)
1179 struct stat stbd, stbr;
1188 if (stat(filename, &stbd) < 0) {
1189 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n",
1194 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1196 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1200 "hfs fsck: sanity check failed: %s not block or character device\n",
1205 * Determine if this is the root file system via vfstab. Give up
1206 * silently on failures. The whole point of this is not to care
1207 * if the root file system is already mounted.
1209 * XXX - similar for /usr. This should be fixed to simply return
1210 * a new code indicating, mounted and needs to be checked.
1212 if ((vfstab = setmntent(FSTAB, "r")) != 0) {
1213 while (mnt = getmntent(vfstab)) {
1214 if (!strcmp(mnt->mnt_dir, "/"))
1215 if (stat(mnt->mnt_fsname, &stbr) == 0)
1216 if (stbr.st_rdev == stbd.st_rdev)
1219 if (!strcmp(mnt->mnt_dir, "/usr"))
1220 if (stat(mnt->mnt_fsname, &stbr) == 0)
1221 if (stbr.st_rdev == stbd.st_rdev)
1227 /* XXX - only works if filename is a block device or if
1228 * character and block device has the same dev_t value */
1229 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1230 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n",
1235 * We mount the ufs root file system read-only first. After fsck
1236 * runs, we remount the root as read-write. Therefore, we no longer
1237 * check for different values for fs_state between the root file
1238 * system and the rest of file systems.
1240 if (!((sblock.fs_clean == FS_CLEAN || sblock.fs_clean == FS_OK))) {
1241 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n",
1245 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1249 /* see if all numbers */
1255 while ('0' <= *yp && *yp <= '9')
1263 /* Convert a raw device name into a block device name.
1264 * If the block device is not found, return the raw device name.
1265 * For HP and SUN, the returned value is not changed. For other
1266 * platforms it is changed (I see no rhyme or reason -jpm).
1272 static char bldev[256];
1273 struct stat statbuf;
1276 code = stat(rawdev, &statbuf);
1277 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1278 return (rawdev); /* Not a char device */
1280 for (i = strlen(rawdev) - 2; i >= 0; i--) {
1281 if ((rawdev[i] == '/') && (rawdev[i + 1] == 'r')) {
1282 strcpy(bldev, rawdev);
1284 strcat(bldev, &rawdev[i + 2]);
1286 code = stat(bldev, &statbuf); /* test for block device */
1287 if (!code && S_ISBLK(statbuf.st_mode)) {
1288 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1291 strcpy(rawdev, bldev); /* Replace */
1300 /* Convert a block device name into a raw device name.
1301 * If the block device is not found, return null
1307 static char rawdev[256];
1308 struct stat statbuf;
1311 for (i = strlen(bldev) - 1; i >= 0; i--) {
1312 if (bldev[i] == '/') {
1313 strcpy(rawdev, bldev);
1314 rawdev[i + 1] = 'r';
1316 strcat(rawdev, &bldev[i + 1]);
1318 code = stat(rawdev, &statbuf);
1319 if (!code && S_ISCHR(statbuf.st_mode))