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>
25 #ifdef HAVE_SYS_FILE_H
29 #define VICE /* allow us to put our changes in at will */
33 #endif /* AFS_SUN_ENV */
34 #include <sys/mount.h>
40 #include <sys/vnode.h>
41 #include <sys/mount.h>
42 #include <ufs/inode.h>
44 #else /* AFS_OSF_ENV */
45 #ifdef AFS_VFSINCL_ENV
47 #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>
66 #define LONGFILENAMES 1
67 #include <sys/sysmacros.h>
70 #ifdef HAVE_USR_OLD_USR_INCLUDE_NDIR_H
71 #include </usr/old/usr/include/ndir.h>
81 #endif /* AFS_VFSINCL_ENV */
82 #endif /* AFS_OSF_ENV */
89 #include <sys/mnttab.h>
90 #include <sys/mntent.h>
91 #include <sys/vfstab.h>
92 #include <sys/ustat.h>
98 #include <sys/signal.h>
100 char *rawname(), *unrawname(), *blockcheck(), *malloc();
101 void catch(), catchquit(), voidquit();
108 char *name; /* device name */
109 char *fsname; /* mounted filesystem name */
110 struct part *next; /* forward link of partitions on disk */
111 } *badlist, **badnext = &badlist;
114 char *name; /* disk base name */
115 struct disk *next; /* forward link for list of disks */
116 struct part *part; /* head of list of partitions on disk */
117 int pid; /* If != 0, pid of proc working on */
120 int nrun, ndisks, maxrun, wflag = 0;
125 #if defined(AFS_HPUX100_ENV)
131 #define msgprintf vfscklogprintf
133 #define msgprintf printf
140 #include "AFS_component_version_number.c"
143 int ge_danger = 0; /* on when fsck is not able to fix the dirty file
144 * system within single run. Problems like dup table
145 * overflow, maxdup is exceeding MAXDUP.. etc. could
146 * potentailly prevent fsck from doing a complete
147 * repair. This is found in a GE hotsite. */
155 int pid, passno, sumstatus;
157 struct disk *dk, *nextdisk;
159 extern char *AFSVersion; /* generated version */
161 int other_than_ufs = 0;
172 #if defined(AFS_HPUX_ENV)
175 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
179 fsflag = oflag = mflag = exitstat = 0;
181 #if defined(AFS_HPUX100_ENV)
184 printf("----Open AFS (R) %s fsck----\n", AFSVersion); /* generated version */
185 if (access("/TRYFORCE", 0) == 0)
187 while (--argc > 0 && **++argv == '-') {
190 #if defined(AFS_HPUX_ENV)
191 #if defined(AFS_HPUX100_ENV)
192 case 'f': /* default yes to answer force to check */
195 #else /* AFS_HPUX100_ENV */
197 case 'F': /* default yes to answer force to check */
200 #endif /* AFS_HPUX_ENV */
201 #endif /* AFS_HPUX100_ENV */
210 #if defined(AFS_HPUX100_ENV)
216 (void)fprintf(stdout, "fsck -F hfs ");
217 for (opt_count = 1; opt_count < argc; opt_count++) {
218 opt_text = argv[opt_count];
220 (void)fprintf(stdout, " %s ", opt_text);
222 (void)fprintf(stdout, "\n");
236 (void)fprintf(stdout, "fsck -F ufs ");
237 for (opt_count = 1; opt_count < argc; opt_count++) {
238 opt_text = argv[opt_count];
240 (void)fprintf(stdout, " %s ", opt_text);
242 (void)fprintf(stdout, "\n");
249 while (*subopt != '\0') {
250 if (*subopt == 'p') {
253 } else if (*subopt == 'b') {
254 if (argv[0][1] != '\0') {
255 bflag = atoi(argv[0] + 1);
257 bflag = atoi(*++argv);
260 msgprintf("Alternate super block location: %d\n", bflag);
262 } else if (*subopt == 'd') {
265 } else if (*subopt == 'r') {
267 } else if (*subopt == 'w') {
270 } else if (*subopt == 'c') {
273 } else if (*subopt == 'f') {
277 errexit("-o %c option?\n", *subopt);
290 if (argv[0][1] != '\0') {
291 bflag = atoi(argv[0] + 1);
293 bflag = atoi(*++argv);
296 msgprintf("Alternate super block location: %d\n", bflag);
303 /* who knows? defined, but doesn't do much */
307 case 'w': /* check writable only */
314 if (!isdigit(argv[1][0]))
315 errexit("-l flag requires a number\n");
316 maxrun = atoi(*++argv);
319 #if !defined(AFS_HPUX100_ENV)
321 if (!isdigit(argv[1][0]))
322 errexit("-m flag requires a mode\n");
323 sscanf(*++argv, "%o", &lfmode);
325 errexit("bad mode to -m: %o\n", lfmode);
327 printf("** lost+found creation mode %o\n", lfmode);
329 #endif /* AFS_HPUX100_ENV */
330 #endif /* AFS_SUN5_ENV */
335 #endif /* AFS_OSF_ENV */
343 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
344 * it's general/useful flag to use.
357 errexit("%c option?\n", **argv);
361 * The following checks were only available on hpux but are useful to all systems.
364 errexit("Incompatible options: -n and -p\n");
366 errexit("Incompatible options: -n and -q\n");
369 rflag++; /* check raw devices */
371 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
372 (void)signal(SIGINT, catch);
374 (void)signal(SIGQUIT, catchquit);
379 if (wflag && !writable(*argv)) {
380 (void)fprintf(stderr, "not writeable '%s'\n", *argv);
384 checkfilesys(*argv++, NULL);
399 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
402 if ((fd = fopen(VFSTAB, "r")) == NULL) {
403 errexit("vfsck: cannot open vfstab\n");
405 while ((ret = getvfsent(fd, &vget)) == 0) {
406 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS)
407 && numbers(vget.vfs_fsckpass)) {
411 if (numbers(vget.vfs_fsckpass))
412 passno = atoi(vget.vfs_fsckpass);
417 if (preen == 0 || passno == 1) {
418 checkfilesys(vget.vfs_fsckdev, get.vfs_mountp);
419 } else if (passno > 1) {
420 addpart(vget.vfs_fsckdev, vget.vfs_special);
424 for (passno = 1; passno <= 2; passno++) {
426 errexit("Can't open checklist file: %s\n", FSTAB);
427 while ((fsp = getfsent()) != 0) {
428 if (strcmp(fsp->fs_type, FSTAB_RW)
429 && strcmp(fsp->fs_type, FSTAB_RO)
430 && strcmp(fsp->fs_type, FSTAB_RQ))
433 if (strcmp(fsp->fs_vfstype, "ufs") || fsp->fs_passno == 0) {
436 #endif /* AFS_OSF_ENV */
437 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
439 name = blockcheck(fsp->fs_spec);
441 checkfilesys(name, fsp->fs_file);
443 printf("pid %d exiting 8/1\n", getpid());
447 } else if (passno == 2 && fsp->fs_passno > 1) {
448 name = blockcheck(fsp->fs_spec);
450 pwarn("BAD DISK NAME %s\n", fsp->fs_spec);
452 printf("pid %d saw bad disk name 8/3\n", getpid());
455 addpart(name, fsp->fs_file);
458 #endif /* AFS_SUN5_ENV */
468 for (passno = 0; passno < maxrun; ++passno) {
470 nextdisk = nextdisk->next;
472 while ((pid = wait(&status)) != -1) {
473 for (dk = disks; dk; dk = dk->next)
477 printf("Unknown pid %d\n", pid);
480 rc = WEXITSTATUS(status);
481 if (WIFSIGNALED(status)) {
482 printf("%s (%s): EXITED WITH SIGNAL %d\n", dk->part->name,
483 dk->part->fsname, WTERMSIG(status));
489 badnext = &dk->part->next;
490 dk->part = dk->part->next;
493 dk->part = dk->part->next;
496 if (dk->part == NULL)
499 if (nextdisk == NULL) {
502 } else if (nrun < maxrun && nrun < ndisks) {
504 if ((nextdisk = nextdisk->next) == NULL)
506 if (nextdisk->part != NULL && nextdisk->pid == 0)
515 printf("pid %d exiting 8/2\n", getpid());
518 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
519 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
520 for (pt = badlist; pt; pt = pt->next)
521 printf("%s (%s)%s", pt->name, pt->fsname, pt->next ? ", " : "\n");
531 #endif /* !AFS_SUN5_ENV */
539 struct disk *dk, **dkp;
543 for (p = name + strlen(name) - 1; p >= name; --p)
551 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
552 if (strncmp(dk->name, name, len) == 0 && dk->name[len] == 0)
555 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
556 errexit("out of memory");
558 if ((dk->name = malloc((unsigned int)len + 1)) == NULL)
559 errexit("out of memory");
560 strncpy(dk->name, name, len);
561 dk->name[len] = '\0';
569 addpart(name, fsname)
572 struct disk *dk = finddisk(name);
573 struct part *pt, **ppt = &dk->part;
575 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
576 if (strcmp(pt->name, name) == 0) {
577 printf("%s in fstab more than once!\n", name);
580 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
581 errexit("out of memory");
583 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL)
584 errexit("out of memory");
585 strcpy(pt->name, name);
586 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL)
587 errexit("out of memory");
588 strcpy(pt->fsname, fsname);
603 (void)signal(SIGQUIT, voidquit);
604 checkfilesys(dk->part->name, dk->part->fsname);
609 checkfilesys(filesys, parname)
612 daddr_t n_ffree, n_bfree;
614 struct stat tstat; /* for ultrix 3 unmount */
621 #endif /* AFS_OSF_ENV */
631 ge_danger = 0; /* set to 1 by any table overflow or more
632 * dup/bad blocks than expected */
634 fixed = 1; /* set to 0 by any 'no' reply */
636 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
637 devname = devbuffer; /* remember generic ptr for later */
638 EnsureDevice(devname); /* canonicalize name */
642 ret_val = setup(devname);
650 pfatal("CAN'T CHECK FILE SYSTEM.");
652 if ((exitstat == 0) && (mflag))
658 } else if (ret_val == -1) { /* pclean && FS_CLEAN */
661 #if defined(AFS_OSF_ENV)
662 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
666 #if defined(AFS_HPUX100_ENV)
668 check_sanity(filesys);
673 check_sanity(filesys);
681 * 1: scan inodes tallying blocks used
684 #if defined(AFS_SUN5_ENV)
686 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
689 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
691 msgprintf("** Root file system\n");
694 printf("** Phase 1 - Sanity Check only\n");
698 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
703 * 1b: locate first references to duplicates, if any
707 pfatal("INTERNAL ERROR: dups with -p");
708 msgprintf("** Phase 1b - Rescan For More DUPS\n");
713 * 2: traverse directories from root to mark all connected directories
716 msgprintf("** Phase 2 - Check Pathnames\n");
720 * 3: scan inodes looking for disconnected directories
723 msgprintf("** Phase 3 - Check Connectivity\n");
727 * 4: scan inodes looking for disconnected files; check reference counts
730 msgprintf("** Phase 4 - Check Reference Counts\n");
734 * 5: check and repair resource counts in cylinder groups
737 msgprintf("** Phase 5 - Check Cyl groups\n");
740 #if defined(AFS_SUN_ENV)
746 * print out summary statistics
748 n_ffree = sblock.fs_cstotal.cs_nffree;
749 n_bfree = sblock.fs_cstotal.cs_nbfree;
751 #if defined(ACLS) && defined(AFS_HPUX_ENV)
752 pinfo("%d files, %d icont, %d used, %d free", n_files, n_cont, n_blks,
753 n_ffree + sblock.fs_frag * n_bfree);
755 pinfo("%d files, %d used, %d free", n_files, n_blks,
756 n_ffree + sblock.fs_frag * n_bfree);
759 msgprintf(", %d AFS files", nViceFiles);
760 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
761 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
763 #if defined(ACLS) && defined(AFS_HPUX_ENV)
764 pinfo("%d files, %d icont, %d used, %d free ", n_files, n_cont, n_blks,
765 n_ffree + sblock.fs_frag * n_bfree);
767 pinfo("%d files, %d used, %d free ", n_files, n_blks,
768 n_ffree + sblock.fs_frag * n_bfree);
770 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
771 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
773 if (debug && (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
774 msgprintf("%d files missing\n", n_files);
776 n_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
777 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
778 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
779 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
780 printf("%d blocks missing\n", n_blks);
781 if (duplist != NULL) {
782 msgprintf("The following duplicate blocks remain:");
783 for (dp = duplist; dp; dp = dp->next)
784 msgprintf(" %d,", dp->dup);
787 if (zlnhead != NULL) {
788 msgprintf("The following zero link count inodes remain:");
789 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
790 msgprintf(" %d,", zlnp->zlncnt);
795 /* if user's specification denotes that the file system block
796 * is going to be modified (nflag == 0) then fsck store the
797 * correct magic number in the super block if it is not already
800 if (!nflag && !(fswritefd < 0)) {
802 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
806 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
807 if (!preen && !qflag)
808 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
809 sblock.fs_clean = FS_CLEAN;
813 /* fix FS_CLEAN if changes made and no 'no' replies */
814 if (fsmodified && fixed)
815 sblock.fs_clean = FS_CLEAN;
817 * Fix fs_clean if there were no 'no' replies.
818 * This is done for both the s300 and s800. The s800 root will be
819 * guaranteed clean as of 7.0.
821 if (fixed && (sblock.fs_clean != FS_OK)) {
822 if (!preen && !qflag)
823 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
824 sblock.fs_clean = FS_CLEAN;
834 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
842 if (hotroot && sblock.fs_clean == FSACTIVE)
845 else if (!((sblock.fs_state + (afs_int32) sblock.fs_time == FSOKAY) &&
847 else if (!((fs_get_state(&sblock) + (afs_int32) sblock.fs_time == FSOKAY)
850 (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
851 if (yflag || !iscorrupt) {
852 printf("%s FILE SYSTEM STATE SET TO OKAY\n", devname);
855 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n", devname);
860 (void)time(&sblock.fs_time);
862 if (hotroot && rebflg)
863 sblock.fs_clean = FSACTIVE;
865 sblock.fs_clean = FSSTABLE;
867 sblock.fs_state = FSOKAY - (afs_int32) sblock.fs_time;
869 fs_set_state(&sblock, FSOKAY - (afs_int32) sblock.fs_time);
876 if (!nflag && !bflag && !hotroot) {
878 sblock.fs_clean = FS_CLEAN;
879 (void)time(&sblock.fs_time);
881 flush(fswritefd, &sblk);
884 #else /* AFS_OSF_ENV */
886 (void)time(&sblock.fs_time);
894 free((char *)lncntp);
896 blockmap = statemap = NULL;
904 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
907 msgprintf("\n***** REBOOT UNIX *****\n");
910 if (mountedfs || hotroot) {
928 (void)close(fsreadfd);
929 (void)close(fswritefd);
930 if (nViceFiles || tryForce) {
931 /* Modified file system with vice files: force full salvage */
932 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
933 struct ufs_args ufsargs;
935 char pname[100], fname[100], *special;
936 int fd, code, failed = 0;
939 ("%s: AFS file system partition was modified; forcing full salvage\n",
941 devname = unrawname(devname);
942 special = (char *)strrchr(devname, '/');
945 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
946 * /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
947 strcat(pname, special);
949 /* if system mounted / as read-only, we'll try to fix now */
950 if (access("/", W_OK) < 0 && errno == EROFS) {
951 code = system("mount -o remount /");
953 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
960 /* if system mounted / as read-only, we'll try to fix now */
961 if (access("/", W_OK) < 0 && errno == EROFS) {
962 printf("Can't RW acceess /; %d\n", errno);
963 code = system("/sbin/mount -u /");
965 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
973 if (mkdir(pname, 0777) < 0) {
974 if (errno != EEXIST) {
975 perror("fsck mkdir");
979 if (failed && parname) {
980 strcpy(pname, parname);
982 #if !defined(AFS_HPUX_ENV)
984 ufsargs.flags = UFSMNT_NOINTR;
986 ufsargs.fspec = devname;
990 (devname, pname, MS_DATA, "ufs", (char *)&ufsargs,
991 sizeof(ufsargs)) < 0) {
993 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
996 if (mount(devname, pname, 0) < 0) {
999 ("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n",
1000 devname, pname, errno);
1002 strcpy(fname, pname);
1003 strcat(fname, "/FORCESALVAGE");
1004 fd = open(fname, O_CREAT, 0);
1006 errexit("Couldn't create %s to force full salvage!\n", fname);
1011 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1014 #if defined(AFS_OSF_ENV)
1015 umount(pname, MNT_NOFORCE);
1016 #else /* AFS_OSF_ENV */
1024 fsync(fileno(logfile)); /* Since update isn't running */
1036 struct stat stslash, stblock, stchar;
1041 if (stat("/", &stslash) < 0) {
1043 printf("Can't stat root\n");
1047 if (stat(name, &stblock) < 0) {
1049 printf("Can't stat %s\n", name);
1052 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1053 if (stslash.st_dev == stblock.st_rdev) {
1055 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1057 #endif /* AFS_OSF_ENV */
1059 raw = rawname(name);
1063 printf("Cannot find character device for %s\n", name);
1066 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1067 name = unrawname(name);
1071 printf("Can't make sense out of name %s\n", name);
1076 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1080 * exit 0 - file system is unmounted and okay
1081 * exit 32 - file system is unmounted and needs checking
1082 * exit 33 - file system is mounted for root file system
1083 * exit 34 - cannot stat device
1085 check_sanity(filename)
1088 struct stat stbd, stbr;
1091 struct vfstab vfsbuf;
1097 if (stat(filename, &stbd) < 0) {
1098 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n",
1103 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1105 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1109 "ufs fsck: sanity check failed: %s not block or character device\n",
1114 * Determine if this is the root file system via vfstab. Give up
1115 * silently on failures. The whole point of this is not to care
1116 * if the root file system is already mounted.
1118 * XXX - similar for /usr. This should be fixed to simply return
1119 * a new code indicating, mounted and needs to be checked.
1121 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1122 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1124 devname = vfsbuf.vfs_special;
1126 devname = vfsbuf.vfs_fsckdev;
1127 if (stat(devname, &stbr) == 0)
1128 if (stbr.st_rdev == stbd.st_rdev)
1131 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 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)
1142 /* XXX - only works if filename is a block device or if
1143 * character and block device has the same dev_t value */
1144 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1145 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n",
1150 * We mount the ufs root file system read-only first. After fsck
1151 * runs, we remount the root as read-write. Therefore, we no longer
1152 * check for different values for fs_state between the root file
1153 * system and the rest of file systems.
1155 if (!((sblock.fs_state + (time_t) sblock.fs_time == FSOKAY)
1156 && (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
1157 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n",
1161 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1166 #if defined(AFS_HPUX100_ENV)
1167 check_sanity(filename)
1170 struct stat stbd, stbr;
1179 if (stat(filename, &stbd) < 0) {
1180 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n",
1185 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1187 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1191 "hfs fsck: sanity check failed: %s not block or character device\n",
1196 * Determine if this is the root file system via vfstab. Give up
1197 * silently on failures. The whole point of this is not to care
1198 * if the root file system is already mounted.
1200 * XXX - similar for /usr. This should be fixed to simply return
1201 * a new code indicating, mounted and needs to be checked.
1203 if ((vfstab = setmntent(FSTAB, "r")) != 0) {
1204 while (mnt = getmntent(vfstab)) {
1205 if (!strcmp(mnt->mnt_dir, "/"))
1206 if (stat(mnt->mnt_fsname, &stbr) == 0)
1207 if (stbr.st_rdev == stbd.st_rdev)
1210 if (!strcmp(mnt->mnt_dir, "/usr"))
1211 if (stat(mnt->mnt_fsname, &stbr) == 0)
1212 if (stbr.st_rdev == stbd.st_rdev)
1218 /* XXX - only works if filename is a block device or if
1219 * character and block device has the same dev_t value */
1220 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1221 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n",
1226 * We mount the ufs root file system read-only first. After fsck
1227 * runs, we remount the root as read-write. Therefore, we no longer
1228 * check for different values for fs_state between the root file
1229 * system and the rest of file systems.
1231 if (!((sblock.fs_clean == FS_CLEAN || sblock.fs_clean == FS_OK))) {
1232 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n",
1236 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1240 /* see if all numbers */
1246 while ('0' <= *yp && *yp <= '9')
1254 /* Convert a raw device name into a block device name.
1255 * If the block device is not found, return the raw device name.
1256 * For HP and SUN, the returned value is not changed. For other
1257 * platforms it is changed (I see no rhyme or reason -jpm).
1263 static char bldev[256];
1264 struct stat statbuf;
1267 code = stat(rawdev, &statbuf);
1268 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1269 return (rawdev); /* Not a char device */
1271 for (i = strlen(rawdev) - 2; i >= 0; i--) {
1272 if ((rawdev[i] == '/') && (rawdev[i + 1] == 'r')) {
1273 strcpy(bldev, rawdev);
1275 strcat(bldev, &rawdev[i + 2]);
1277 code = stat(bldev, &statbuf); /* test for block device */
1278 if (!code && S_ISBLK(statbuf.st_mode)) {
1279 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1282 strcpy(rawdev, bldev); /* Replace */
1291 /* Convert a block device name into a raw device name.
1292 * If the block device is not found, return null
1298 static char rawdev[256];
1299 struct stat statbuf;
1302 for (i = strlen(bldev) - 1; i >= 0; i--) {
1303 if (bldev[i] == '/') {
1304 strcpy(rawdev, bldev);
1305 rawdev[i + 1] = 'r';
1307 strcat(rawdev, &bldev[i + 1]);
1309 code = stat(rawdev, &statbuf);
1310 if (!code && S_ISCHR(statbuf.st_mode))