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 */
84 #include <sys/fs_types.h>
99 #include <sys/mnttab.h>
100 #include <sys/mntent.h>
101 #include <sys/vfstab.h>
102 #include <sys/ustat.h>
109 #include <sys/signal.h>
111 char *rawname(), *unrawname(), *blockcheck(), *malloc();
112 void catch(), catchquit(), voidquit();
119 char *name; /* device name */
120 char *fsname; /* mounted filesystem name */
121 struct part *next; /* forward link of partitions on disk */
122 } *badlist, **badnext = &badlist;
125 char *name; /* disk base name */
126 struct disk *next; /* forward link for list of disks */
127 struct part *part; /* head of list of partitions on disk */
128 int pid; /* If != 0, pid of proc working on */
131 int nrun, ndisks, maxrun, wflag = 0;
136 #if defined(AFS_HPUX100_ENV)
142 #define msgprintf vfscklogprintf
144 #define msgprintf printf
151 #include "AFS_component_version_number.c"
154 int ge_danger = 0; /* on when fsck is not able to fix the dirty file
155 * system within single run. Problems like dup table
156 * overflow, maxdup is exceeding MAXDUP.. etc. could
157 * potentailly prevent fsck from doing a complete
158 * repair. This is found in a GE hotsite. */
166 int pid, passno, sumstatus;
168 register struct disk *dk, *nextdisk;
169 register struct part *pt;
170 extern char *AFSVersion; /* generated version */
172 int other_than_ufs = 0;
183 #if defined(AFS_HPUX_ENV)
186 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
190 fsflag = oflag = mflag = exitstat = 0;
192 #if defined(AFS_HPUX100_ENV)
195 printf("----Open AFS (R) %s fsck----\n", AFSVersion); /* generated version */
196 if (access("/TRYFORCE", 0) == 0)
198 while (--argc > 0 && **++argv == '-') {
201 #if defined(AFS_HPUX_ENV)
202 #if defined(AFS_HPUX100_ENV)
203 case 'f': /* default yes to answer force to check */
206 #else /* AFS_HPUX100_ENV */
208 case 'F': /* default yes to answer force to check */
211 #endif /* AFS_HPUX_ENV */
212 #endif /* AFS_HPUX100_ENV */
218 #if defined(AFS_DEC_ENV)
219 /* On the late versions of Ultrix they changed the defn of '-p' a bit. Particularly,
220 * -p is used to check a file system that was not unmounted cleanly, and they added,
221 * -P to check a file system regardless of how it was unmounted; this, unfortunately,
222 * is identical to '-p' on the rest of the systems but we have to maintain vendor's
223 * semantics so we leave it the way Dec likes it.
227 /* P is for Ultrix compatibility */
234 #if defined(AFS_HPUX100_ENV)
240 (void)fprintf(stdout, "fsck -F hfs ");
241 for (opt_count = 1; opt_count < argc; opt_count++) {
242 opt_text = argv[opt_count];
244 (void)fprintf(stdout, " %s ", opt_text);
246 (void)fprintf(stdout, "\n");
260 (void)fprintf(stdout, "fsck -F ufs ");
261 for (opt_count = 1; opt_count < argc; opt_count++) {
262 opt_text = argv[opt_count];
264 (void)fprintf(stdout, " %s ", opt_text);
266 (void)fprintf(stdout, "\n");
273 while (*subopt != '\0') {
274 if (*subopt == 'p') {
277 } else if (*subopt == 'b') {
278 if (argv[0][1] != '\0') {
279 bflag = atoi(argv[0] + 1);
281 bflag = atoi(*++argv);
284 msgprintf("Alternate super block location: %d\n", bflag);
286 } else if (*subopt == 'd') {
289 } else if (*subopt == 'r') {
291 } else if (*subopt == 'w') {
294 } else if (*subopt == 'c') {
297 } else if (*subopt == 'f') {
301 errexit("-o %c option?\n", *subopt);
314 if (argv[0][1] != '\0') {
315 bflag = atoi(argv[0] + 1);
317 bflag = atoi(*++argv);
320 msgprintf("Alternate super block location: %d\n", bflag);
327 /* who knows? defined, but doesn't do much */
331 case 'w': /* check writable only */
338 if (!isdigit(argv[1][0]))
339 errexit("-l flag requires a number\n");
340 maxrun = atoi(*++argv);
343 #if !defined(AFS_HPUX100_ENV)
345 if (!isdigit(argv[1][0]))
346 errexit("-m flag requires a mode\n");
347 sscanf(*++argv, "%o", &lfmode);
349 errexit("bad mode to -m: %o\n", lfmode);
351 printf("** lost+found creation mode %o\n", lfmode);
353 #endif /* AFS_HPUX100_ENV */
354 #endif /* AFS_SUN5_ENV */
359 #endif /* AFS_OSF_ENV */
367 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
368 * it's general/useful flag to use.
381 errexit("%c option?\n", **argv);
385 * The following checks were only available on hpux but are useful to all systems.
388 errexit("Incompatible options: -n and -p\n");
390 errexit("Incompatible options: -n and -q\n");
393 rflag++; /* check raw devices */
395 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
396 (void)signal(SIGINT, catch);
398 (void)signal(SIGQUIT, catchquit);
403 if (wflag && !writable(*argv)) {
404 (void)fprintf(stderr, "not writeable '%s'\n", *argv);
408 checkfilesys(*argv++, NULL);
423 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
426 if ((fd = fopen(VFSTAB, "r")) == NULL) {
427 errexit("vfsck: cannot open vfstab\n");
429 while ((ret = getvfsent(fd, &vget)) == 0) {
430 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS)
431 && numbers(vget.vfs_fsckpass)) {
435 if (numbers(vget.vfs_fsckpass))
436 passno = atoi(vget.vfs_fsckpass);
441 if (preen == 0 || passno == 1) {
442 checkfilesys(vget.vfs_fsckdev, get.vfs_mountp);
443 } else if (passno > 1) {
444 addpart(vget.vfs_fsckdev, vget.vfs_special);
448 for (passno = 1; passno <= 2; passno++) {
450 errexit("Can't open checklist file: %s\n", FSTAB);
451 while ((fsp = getfsent()) != 0) {
452 if (strcmp(fsp->fs_type, FSTAB_RW)
453 && strcmp(fsp->fs_type, FSTAB_RO)
454 && strcmp(fsp->fs_type, FSTAB_RQ))
457 /* Only check local (i.e. ufs) file systems */
458 if (strcmp(fsp->fs_name, "4.2") && strcmp(fsp->fs_name, "ufs"))
462 if (strcmp(fsp->fs_vfstype, "ufs") || fsp->fs_passno == 0) {
465 #endif /* AFS_OSF_ENV */
466 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
468 name = blockcheck(fsp->fs_spec);
470 checkfilesys(name, fsp->fs_file);
472 printf("pid %d exiting 8/1\n", getpid());
476 } else if (passno == 2 && fsp->fs_passno > 1) {
477 name = blockcheck(fsp->fs_spec);
479 pwarn("BAD DISK NAME %s\n", fsp->fs_spec);
481 printf("pid %d saw bad disk name 8/3\n", getpid());
484 addpart(name, fsp->fs_file);
487 #endif /* AFS_SUN5_ENV */
497 for (passno = 0; passno < maxrun; ++passno) {
499 nextdisk = nextdisk->next;
501 while ((pid = wait(&status)) != -1) {
502 for (dk = disks; dk; dk = dk->next)
506 printf("Unknown pid %d\n", pid);
509 rc = WEXITSTATUS(status);
510 if (WIFSIGNALED(status)) {
511 printf("%s (%s): EXITED WITH SIGNAL %d\n", dk->part->name,
512 dk->part->fsname, WTERMSIG(status));
518 badnext = &dk->part->next;
519 dk->part = dk->part->next;
522 dk->part = dk->part->next;
525 if (dk->part == NULL)
528 if (nextdisk == NULL) {
531 } else if (nrun < maxrun && nrun < ndisks) {
533 if ((nextdisk = nextdisk->next) == NULL)
535 if (nextdisk->part != NULL && nextdisk->pid == 0)
544 printf("pid %d exiting 8/2\n", getpid());
547 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
548 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
549 for (pt = badlist; pt; pt = pt->next)
550 printf("%s (%s)%s", pt->name, pt->fsname, pt->next ? ", " : "\n");
560 #endif /* !AFS_SUN5_ENV */
568 register struct disk *dk, **dkp;
572 for (p = name + strlen(name) - 1; p >= name; --p)
580 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
581 if (strncmp(dk->name, name, len) == 0 && dk->name[len] == 0)
584 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
585 errexit("out of memory");
587 if ((dk->name = malloc((unsigned int)len + 1)) == NULL)
588 errexit("out of memory");
589 strncpy(dk->name, name, len);
590 dk->name[len] = '\0';
598 addpart(name, fsname)
601 struct disk *dk = finddisk(name);
602 register struct part *pt, **ppt = &dk->part;
604 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
605 if (strcmp(pt->name, name) == 0) {
606 printf("%s in fstab more than once!\n", name);
609 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
610 errexit("out of memory");
612 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL)
613 errexit("out of memory");
614 strcpy(pt->name, name);
615 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL)
616 errexit("out of memory");
617 strcpy(pt->fsname, fsname);
622 register struct disk *dk;
632 (void)signal(SIGQUIT, voidquit);
633 checkfilesys(dk->part->name, dk->part->fsname);
638 checkfilesys(filesys, parname)
641 daddr_t n_ffree, n_bfree;
643 struct stat tstat; /* for ultrix 3 unmount */
648 int retries = 3; /* # of retries fora clean fsck pass */
649 int fsdirty = 0; /* file system was or is dirty */
650 int rootdirty = 0; /* Root was or is dirty */
655 #endif /* AFS_OSF_ENV */
665 ge_danger = 0; /* set to 1 by any table overflow or more
666 * dup/bad blocks than expected */
668 fixed = 1; /* set to 0 by any 'no' reply */
670 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
671 devname = devbuffer; /* remember generic ptr for later */
672 EnsureDevice(devname); /* canonicalize name */
676 for (; retries > 0; retries--) { /* 003 - Loop for NUMRETRIES or until clean */
679 ret_val = setup(devname);
687 pfatal("CAN'T CHECK FILE SYSTEM.");
689 if ((exitstat == 0) && (mflag))
695 } else if (ret_val == -1) { /* pclean && FS_CLEAN */
698 #if defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV)
699 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
703 #if defined(AFS_HPUX100_ENV)
705 check_sanity(filesys);
710 check_sanity(filesys);
718 * 1: scan inodes tallying blocks used
721 #if defined(AFS_SUN5_ENV)
723 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
726 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
728 msgprintf("** Root file system\n");
731 printf("** Phase 1 - Sanity Check only\n");
735 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
740 * 1b: locate first references to duplicates, if any
744 pfatal("INTERNAL ERROR: dups with -p");
745 msgprintf("** Phase 1b - Rescan For More DUPS\n");
750 * 2: traverse directories from root to mark all connected directories
753 msgprintf("** Phase 2 - Check Pathnames\n");
757 * 3: scan inodes looking for disconnected directories
760 msgprintf("** Phase 3 - Check Connectivity\n");
764 * 4: scan inodes looking for disconnected files; check reference counts
767 msgprintf("** Phase 4 - Check Reference Counts\n");
771 * 5: check and repair resource counts in cylinder groups
774 msgprintf("** Phase 5 - Check Cyl groups\n");
778 if (fsmodified || (sblk.b_dirty) || (cgblk.b_dirty)) {
784 * 003 - Number of retry attempts have been
785 * exhausted. Mark super block as dirty.
787 (void)time(&sblock.fs_time);
792 * 003 - If checking root file system, and it was
793 * modified during any pass, don't assume it is ok. Must reboot.
799 if ((!hotroot) && (!bflag) && (!nflag) && (!iscorrupt)) {
801 sblock.fs_clean = FS_CLEAN;
802 (void)time(&sblock.fs_time);
803 (void)time(&sblock.fs_lastfsck);
804 if ((sblock.fs_deftimer) && (sblock.fs_deftimer > 0)
805 && (sblock.fs_deftimer < 255))
806 sblock.fs_cleantimer = sblock.fs_deftimer;
808 sblock.fs_cleantimer = sblock.fs_deftimer =
809 FSCLEAN_TIMEOUTFACTOR;
813 * 006 - If an alternate super block was used,
814 * we want to re fsck the partition after
815 * updating the primary super block.
821 /* Unless no updates are to be done, write out maps. */
827 daddr_t nn_files = n_files;
828 daddr_t nn_blks = n_blks;
830 n_ffree = sblock.fs_cstotal.cs_nffree;
831 n_bfree = sblock.fs_cstotal.cs_nbfree;
832 if (nn_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)
833 printf("%d files missing\n", nn_files);
835 sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
836 nn_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
837 nn_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
838 if (nn_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
839 printf("%d blocks missing\n", nn_blks);
841 if (duplist != NULL) {
843 printf("The following duplicate blocks remain:");
844 for (dp = duplist; dp; dp = dp->next) {
846 printf(" %d,", dp->dup);
852 if (zlnhead != NULL) {
854 printf("The following zero link count inodes remain:");
855 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) {
857 printf(" %d,", zlnp->zlncnt);
868 free((char *)lncntp);
869 /* Print out retry message, and fsck file system again. */
872 printf("%s: FILE SYSTEM MODIFIED, VERIFYING\n", filesys);
874 printf("**** FILE SYSTEM MODIFIED, VERIFYING\n");
878 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
884 * print out summary statistics
886 n_ffree = sblock.fs_cstotal.cs_nffree;
887 n_bfree = sblock.fs_cstotal.cs_nbfree;
889 #if defined(ACLS) && defined(AFS_HPUX_ENV)
890 pinfo("%d files, %d icont, %d used, %d free", n_files, n_cont, n_blks,
891 n_ffree + sblock.fs_frag * n_bfree);
893 pinfo("%d files, %d used, %d free", n_files, n_blks,
894 n_ffree + sblock.fs_frag * n_bfree);
897 msgprintf(", %d AFS files", nViceFiles);
898 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
899 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
901 #if defined(ACLS) && defined(AFS_HPUX_ENV)
902 pinfo("%d files, %d icont, %d used, %d free ", n_files, n_cont, n_blks,
903 n_ffree + sblock.fs_frag * n_bfree);
905 pinfo("%d files, %d used, %d free ", n_files, n_blks,
906 n_ffree + sblock.fs_frag * n_bfree);
908 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree,
909 n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
912 if ((!fsdirty) && (!rootdirty))
915 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
917 printf("\n***** HALT PROCESSOR WITHOUT SYNCING DISK *****\n");
924 if (debug && (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
925 msgprintf("%d files missing\n", n_files);
927 n_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
928 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
929 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
930 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
931 printf("%d blocks missing\n", n_blks);
932 if (duplist != NULL) {
933 msgprintf("The following duplicate blocks remain:");
934 for (dp = duplist; dp; dp = dp->next)
935 msgprintf(" %d,", dp->dup);
938 if (zlnhead != NULL) {
939 msgprintf("The following zero link count inodes remain:");
940 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
941 msgprintf(" %d,", zlnp->zlncnt);
947 /* if user's specification denotes that the file system block
948 * is going to be modified (nflag == 0) then fsck store the
949 * correct magic number in the super block if it is not already
952 if (!nflag && !(fswritefd < 0)) {
954 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
958 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
959 if (!preen && !qflag)
960 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
961 sblock.fs_clean = FS_CLEAN;
965 /* fix FS_CLEAN if changes made and no 'no' replies */
966 if (fsmodified && fixed)
967 sblock.fs_clean = FS_CLEAN;
969 * Fix fs_clean if there were no 'no' replies.
970 * This is done for both the s300 and s800. The s800 root will be
971 * guaranteed clean as of 7.0.
973 if (fixed && (sblock.fs_clean != FS_OK)) {
974 if (!preen && !qflag)
975 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
976 sblock.fs_clean = FS_CLEAN;
986 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
994 if (hotroot && sblock.fs_clean == FSACTIVE)
997 else if (!((sblock.fs_state + (afs_int32) sblock.fs_time == FSOKAY) &&
999 else if (!((fs_get_state(&sblock) + (afs_int32) sblock.fs_time == FSOKAY)
1002 (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
1003 if (yflag || !iscorrupt) {
1004 printf("%s FILE SYSTEM STATE SET TO OKAY\n", devname);
1007 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n", devname);
1012 (void)time(&sblock.fs_time);
1014 if (hotroot && rebflg)
1015 sblock.fs_clean = FSACTIVE;
1017 sblock.fs_clean = FSSTABLE;
1019 sblock.fs_state = FSOKAY - (afs_int32) sblock.fs_time;
1021 fs_set_state(&sblock, FSOKAY - (afs_int32) sblock.fs_time);
1028 if (!nflag && !bflag && !hotroot) {
1030 sblock.fs_clean = FS_CLEAN;
1031 (void)time(&sblock.fs_time);
1033 flush(fswritefd, &sblk);
1036 #else /* AFS_OSF_ENV */
1038 (void)time(&sblock.fs_time);
1047 free((char *)lncntp);
1049 blockmap = statemap = NULL;
1057 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
1060 msgprintf("\n***** REBOOT UNIX *****\n");
1063 if (mountedfs || hotroot) {
1082 (void)close(fsreadfd);
1083 (void)close(fswritefd);
1084 if (nViceFiles || tryForce) {
1085 /* Modified file system with vice files: force full salvage */
1086 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
1087 #if !defined(AFS_DEC_ENV)
1088 struct ufs_args ufsargs;
1091 char pname[100], fname[100], *special;
1092 int fd, code, failed = 0;
1095 ("%s: AFS file system partition was modified; forcing full salvage\n",
1097 devname = unrawname(devname);
1098 special = (char *)strrchr(devname, '/');
1101 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
1102 * /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
1103 strcat(pname, special);
1105 /* if system mounted / as read-only, we'll try to fix now */
1106 if (access("/", W_OK) < 0 && errno == EROFS) {
1107 code = system("mount -o remount /");
1109 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
1116 /* if system mounted / as read-only, we'll try to fix now */
1117 if (access("/", W_OK) < 0 && errno == EROFS) {
1118 printf("Can't RW acceess /; %d\n", errno);
1119 code = system("/sbin/mount -u /");
1121 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
1129 if (mkdir(pname, 0777) < 0) {
1130 if (errno != EEXIST) {
1131 perror("fsck mkdir");
1135 if (failed && parname) {
1136 strcpy(pname, parname);
1138 #if !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV)
1140 ufsargs.flags = UFSMNT_NOINTR;
1142 ufsargs.fspec = devname;
1147 (devname, pname, MS_DATA, "ufs", (char *)&ufsargs,
1148 sizeof(ufsargs)) < 0) {
1150 if (mount("4.2", pname, M_NEWTYPE, &ufsargs) < 0) {
1153 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1157 if (mount(devname, pname, 0, GT_ULTRIX, NULL)) {
1159 if (mount(devname, pname, 0) < 0) {
1163 ("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n",
1164 devname, pname, errno);
1166 strcpy(fname, pname);
1167 strcat(fname, "/FORCESALVAGE");
1168 fd = open(fname, O_CREAT, 0);
1170 errexit("Couldn't create %s to force full salvage!\n", fname);
1171 #if defined(AFS_DEC_ENV)
1178 #if /*defined(AFS_VFS_ENV) &&*/ !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1181 #if defined(AFS_DEC_ENV)
1182 umount(tstat.st_dev);
1184 #if defined(AFS_OSF_ENV)
1185 umount(pname, MNT_NOFORCE);
1186 #else /* AFS_OSF_ENV */
1195 fsync(fileno(logfile)); /* Since update isn't running */
1207 struct stat stslash, stblock, stchar;
1212 if (stat("/", &stslash) < 0) {
1214 printf("Can't stat root\n");
1218 if (stat(name, &stblock) < 0) {
1220 printf("Can't stat %s\n", name);
1223 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1224 if (stslash.st_dev == stblock.st_rdev) {
1226 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1228 #endif /* AFS_OSF_ENV */
1230 raw = rawname(name);
1234 printf("Cannot find character device for %s\n", name);
1237 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1238 name = unrawname(name);
1242 printf("Can't make sense out of name %s\n", name);
1247 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1251 * exit 0 - file system is unmounted and okay
1252 * exit 32 - file system is unmounted and needs checking
1253 * exit 33 - file system is mounted for root file system
1254 * exit 34 - cannot stat device
1256 check_sanity(filename)
1259 struct stat stbd, stbr;
1262 struct vfstab vfsbuf;
1268 if (stat(filename, &stbd) < 0) {
1269 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n",
1274 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1276 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1280 "ufs fsck: sanity check failed: %s not block or character device\n",
1285 * Determine if this is the root file system via vfstab. Give up
1286 * silently on failures. The whole point of this is not to care
1287 * if the root file system is already mounted.
1289 * XXX - similar for /usr. This should be fixed to simply return
1290 * a new code indicating, mounted and needs to be checked.
1292 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1293 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1295 devname = vfsbuf.vfs_special;
1297 devname = vfsbuf.vfs_fsckdev;
1298 if (stat(devname, &stbr) == 0)
1299 if (stbr.st_rdev == stbd.st_rdev)
1302 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1304 devname = vfsbuf.vfs_special;
1306 devname = vfsbuf.vfs_fsckdev;
1307 if (stat(devname, &stbr) == 0)
1308 if (stbr.st_rdev == stbd.st_rdev)
1313 /* XXX - only works if filename is a block device or if
1314 * character and block device has the same dev_t value */
1315 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1316 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n",
1321 * We mount the ufs root file system read-only first. After fsck
1322 * runs, we remount the root as read-write. Therefore, we no longer
1323 * check for different values for fs_state between the root file
1324 * system and the rest of file systems.
1326 if (!((sblock.fs_state + (time_t) sblock.fs_time == FSOKAY)
1327 && (sblock.fs_clean == FSCLEAN || sblock.fs_clean == FSSTABLE))) {
1328 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n",
1332 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1337 #if defined(AFS_HPUX100_ENV)
1338 check_sanity(filename)
1341 struct stat stbd, stbr;
1350 if (stat(filename, &stbd) < 0) {
1351 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n",
1356 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1358 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1362 "hfs fsck: sanity check failed: %s not block or character device\n",
1367 * Determine if this is the root file system via vfstab. Give up
1368 * silently on failures. The whole point of this is not to care
1369 * if the root file system is already mounted.
1371 * XXX - similar for /usr. This should be fixed to simply return
1372 * a new code indicating, mounted and needs to be checked.
1374 if ((vfstab = setmntent(FSTAB, "r")) != 0) {
1375 while (mnt = getmntent(vfstab)) {
1376 if (!strcmp(mnt->mnt_dir, "/"))
1377 if (stat(mnt->mnt_fsname, &stbr) == 0)
1378 if (stbr.st_rdev == stbd.st_rdev)
1381 if (!strcmp(mnt->mnt_dir, "/usr"))
1382 if (stat(mnt->mnt_fsname, &stbr) == 0)
1383 if (stbr.st_rdev == stbd.st_rdev)
1389 /* XXX - only works if filename is a block device or if
1390 * character and block device has the same dev_t value */
1391 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1392 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n",
1397 * We mount the ufs root file system read-only first. After fsck
1398 * runs, we remount the root as read-write. Therefore, we no longer
1399 * check for different values for fs_state between the root file
1400 * system and the rest of file systems.
1402 if (!((sblock.fs_clean == FS_CLEAN || sblock.fs_clean == FS_OK))) {
1403 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n",
1407 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1411 /* see if all numbers */
1417 while ('0' <= *yp && *yp <= '9')
1425 /* Convert a raw device name into a block device name.
1426 * If the block device is not found, return the raw device name.
1427 * For HP and SUN, the returned value is not changed. For other
1428 * platforms it is changed (I see no rhyme or reason -jpm).
1434 static char bldev[256];
1435 struct stat statbuf;
1438 code = stat(rawdev, &statbuf);
1439 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1440 return (rawdev); /* Not a char device */
1442 for (i = strlen(rawdev) - 2; i >= 0; i--) {
1443 if ((rawdev[i] == '/') && (rawdev[i + 1] == 'r')) {
1444 strcpy(bldev, rawdev);
1446 strcat(bldev, &rawdev[i + 2]);
1448 code = stat(bldev, &statbuf); /* test for block device */
1449 if (!code && S_ISBLK(statbuf.st_mode)) {
1450 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1453 strcpy(rawdev, bldev); /* Replace */
1462 /* Convert a block device name into a raw device name.
1463 * If the block device is not found, return null
1469 static char rawdev[256];
1470 struct stat statbuf;
1473 for (i = strlen(bldev) - 1; i >= 0; i--) {
1474 if (bldev[i] == '/') {
1475 strcpy(rawdev, bldev);
1476 rawdev[i + 1] = 'r';
1478 strcat(rawdev, &bldev[i + 1]);
1480 code = stat(rawdev, &statbuf);
1481 if (!code && S_ISCHR(statbuf.st_mode))