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>
23 #define VICE /* allow us to put our changes in at will */
26 #include <sys/param.h>
31 #endif /* AFS_SUN_ENV */
32 #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>
50 #include <sys/fs/ufs_inode.h>
51 #include <sys/fs/ufs_fs.h>
53 #include <sys/fs/ufs_fsdir.h>
55 #include <sys/fs/ufs_mount.h>
57 #include <ufs/inode.h>
60 #include <ufs/fsdir.h>
63 #else /* AFS_VFSINCL_ENV */
65 #include <sys/inode.h>
68 #define LONGFILENAMES 1
69 #include <sys/sysmacros.h>
79 #endif /* AFS_VFSINCL_ENV */
80 #endif /* AFS_OSF_ENV */
83 #include <sys/fs_types.h>
98 #include <sys/mnttab.h>
99 #include <sys/mntent.h>
100 #include <sys/vfstab.h>
101 #include <sys/ustat.h>
108 #include <sys/signal.h>
110 char *rawname(), *unrawname(), *blockcheck(), *malloc();
111 void catch(), catchquit(), voidquit();
118 char *name; /* device name */
119 char *fsname; /* mounted filesystem name */
120 struct part *next; /* forward link of partitions on disk */
121 } *badlist, **badnext = &badlist;
124 char *name; /* disk base name */
125 struct disk *next; /* forward link for list of disks */
126 struct part *part; /* head of list of partitions on disk */
127 int pid; /* If != 0, pid of proc working on */
130 int nrun, ndisks, maxrun, wflag=0;
135 #if defined(AFS_HPUX100_ENV)
141 #define msgprintf vfscklogprintf
143 #define msgprintf printf
150 #include "AFS_component_version_number.c"
153 int ge_danger = 0; /* on when fsck is not able to fix the dirty file
154 system within single run. Problems like dup table
155 overflow, maxdup is exceeding MAXDUP.. etc. could
156 potentailly prevent fsck from doing a complete
157 repair. This is found in a GE hotsite. */
165 int pid, passno, sumstatus;
167 register struct disk *dk, *nextdisk;
168 register struct part *pt;
169 extern char* AFSVersion; /* generated version */
171 int other_than_ufs=0;
182 #if defined(AFS_HPUX_ENV)
185 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
189 fsflag = oflag = mflag = exitstat = 0;
191 #if defined(AFS_HPUX100_ENV)
194 printf("----Open AFS (R) %s fsck----\n", AFSVersion); /* generated version */
195 if (access("/TRYFORCE", 0) == 0)
197 while (--argc > 0 && **++argv == '-') {
200 #if defined(AFS_HPUX_ENV)
201 #if defined(AFS_HPUX100_ENV)
202 case 'f': /* default yes to answer force to check */
205 #else /* AFS_HPUX100_ENV */
207 case 'F': /* default yes to answer force to check */
210 #endif /* AFS_HPUX_ENV */
211 #endif /* AFS_HPUX100_ENV */
217 #if defined(AFS_DEC_ENV)
218 /* On the late versions of Ultrix they changed the defn of '-p' a bit. Particularly,
219 * -p is used to check a file system that was not unmounted cleanly, and they added,
220 * -P to check a file system regardless of how it was unmounted; this, unfortunately,
221 * is identical to '-p' on the rest of the systems but we have to maintain vendor's
222 * semantics so we leave it the way Dec likes it.
226 /* P is for Ultrix compatibility */
233 #if defined(AFS_HPUX100_ENV)
239 (void) fprintf (stdout, "fsck -F hfs ");
240 for (opt_count = 1; opt_count < argc ; opt_count++) {
241 opt_text = argv[opt_count];
243 (void) fprintf (stdout, " %s ", opt_text);
245 (void) fprintf (stdout, "\n");
259 (void) fprintf (stdout, "fsck -F ufs ");
260 for (opt_count = 1; opt_count < argc ; opt_count++) {
261 opt_text = argv[opt_count];
263 (void) fprintf (stdout, " %s ", opt_text);
265 (void) fprintf (stdout, "\n");
272 while (*subopt != '\0') {
273 if (*subopt == 'p') {
276 } else if (*subopt == 'b') {
277 if (argv[0][1] != '\0') {
278 bflag = atoi(argv[0]+1);
280 bflag = atoi(*++argv);
283 msgprintf("Alternate super block location: %d\n", bflag);
285 } else if (*subopt == 'd') {
288 } else if (*subopt == 'r') {
290 } else if (*subopt == 'w') {
293 } else if (*subopt == 'c') {
296 } else if (*subopt == 'f') {
300 errexit("-o %c option?\n", *subopt);
313 if (argv[0][1] != '\0') {
314 bflag = atoi(argv[0]+1);
316 bflag = atoi(*++argv);
319 msgprintf("Alternate super block location: %d\n", bflag);
326 /* who knows? defined, but doesn't do much */
330 case 'w': /* check writable only */
337 if (!isdigit(argv[1][0]))
338 errexit("-l flag requires a number\n");
339 maxrun = atoi(*++argv);
342 #if !defined(AFS_HPUX100_ENV)
344 if (!isdigit(argv[1][0]))
345 errexit("-m flag requires a mode\n");
346 sscanf(*++argv, "%o", &lfmode);
348 errexit("bad mode to -m: %o\n", lfmode);
350 printf("** lost+found creation mode %o\n", lfmode);
352 #endif /* AFS_HPUX100_ENV */
353 #endif /* AFS_SUN5_ENV */
358 #endif /* AFS_OSF_ENV */
366 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
367 * it's general/useful flag to use.
380 errexit("%c option?\n", **argv);
384 * The following checks were only available on hpux but are useful to all systems.
387 errexit("Incompatible options: -n and -p\n");
389 errexit("Incompatible options: -n and -q\n");
392 rflag++; /* check raw devices */
394 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
395 (void)signal(SIGINT, catch);
397 (void)signal(SIGQUIT, catchquit);
402 if (wflag && !writable(*argv)) {
403 (void) fprintf (stderr, "not writeable '%s'\n", *argv);
407 checkfilesys(*argv++, (char *)0);
422 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
425 if ((fd = fopen(VFSTAB, "r")) == NULL) {
426 errexit("vfsck: cannot open vfstab\n");
428 while ((ret = getvfsent(fd, &vget)) == 0) {
429 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) && numbers(vget.vfs_fsckpass)) {
433 if (numbers(vget.vfs_fsckpass))
434 passno = atoi(vget.vfs_fsckpass);
439 if (preen == 0 || passno == 1) {
440 checkfilesys(vget.vfs_fsckdev, get.vfs_mountp);
441 } else if (passno > 1) {
442 addpart(vget.vfs_fsckdev, vget.vfs_special);
446 for (passno = 1; passno <= 2; passno++) {
448 errexit("Can't open checklist file: %s\n", FSTAB);
449 while ((fsp = getfsent()) != 0) {
450 if (strcmp(fsp->fs_type, FSTAB_RW) &&
451 strcmp(fsp->fs_type, FSTAB_RO) &&
452 strcmp(fsp->fs_type, FSTAB_RQ))
455 /* Only check local (i.e. ufs) file systems */
456 if (strcmp(fsp->fs_name, "4.2") && strcmp(fsp->fs_name, "ufs"))
460 if (strcmp(fsp->fs_vfstype, "ufs") ||
461 fsp->fs_passno == 0) {
464 #endif /* AFS_OSF_ENV */
465 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
467 name = blockcheck(fsp->fs_spec);
469 checkfilesys(name, fsp->fs_file);
471 printf("pid %d exiting 8/1\n", getpid());
475 } else if (passno == 2 && fsp->fs_passno > 1) {
476 name = blockcheck(fsp->fs_spec);
478 pwarn("BAD DISK NAME %s\n",
481 printf("pid %d saw bad disk name 8/3\n", getpid());
484 addpart(name, fsp->fs_file);
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",
512 dk->part->name, dk->part->fsname,
519 badnext = &dk->part->next;
520 dk->part = dk->part->next;
523 dk->part = dk->part->next;
526 if (dk->part == NULL)
529 if (nextdisk == NULL) {
532 } else if (nrun < maxrun && nrun < ndisks) {
534 if ((nextdisk = nextdisk->next) == NULL)
536 if (nextdisk->part != NULL &&
546 printf("pid %d exiting 8/2\n", getpid());
549 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
550 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
551 for (pt = badlist; pt; pt = pt->next)
552 printf("%s (%s)%s", pt->name, pt->fsname,
553 pt->next ? ", " : "\n");
563 #endif /* !AFS_SUN5_ENV */
571 register struct disk *dk, **dkp;
575 for (p = name + strlen(name) - 1; p >= name; --p)
583 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
584 if (strncmp(dk->name, name, len) == 0 &&
588 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
589 errexit("out of memory");
591 if ((dk->name = malloc((unsigned int)len + 1)) == NULL)
592 errexit("out of memory");
593 strncpy(dk->name, name, len);
594 dk->name[len] = '\0';
602 addpart(name, fsname)
605 struct disk *dk = finddisk(name);
606 register struct part *pt, **ppt = &dk->part;
608 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
609 if (strcmp(pt->name, name) == 0) {
610 printf("%s in fstab more than once!\n", name);
613 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
614 errexit("out of memory");
616 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL)
617 errexit("out of memory");
618 strcpy(pt->name, name);
619 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL)
620 errexit("out of memory");
621 strcpy(pt->fsname, fsname);
626 register struct disk *dk;
636 (void)signal(SIGQUIT, voidquit);
637 checkfilesys(dk->part->name, dk->part->fsname);
642 checkfilesys(filesys, parname)
645 daddr_t n_ffree, n_bfree;
647 struct stat tstat; /* for ultrix 3 unmount */
652 int retries = 3; /* # of retries fora clean fsck pass */
653 int fsdirty = 0; /* file system was or is dirty */
654 int rootdirty = 0; /* Root was or is dirty */
659 #endif /* AFS_OSF_ENV */
669 ge_danger = 0; /* set to 1 by any table overflow or more
670 dup/bad blocks than expected */
672 fixed = 1; /* set to 0 by any 'no' reply */
674 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
675 devname = devbuffer; /* remember generic ptr for later */
676 EnsureDevice(devname); /* canonicalize name */
680 for (; retries > 0; retries--) { /* 003 - Loop for NUMRETRIES or until clean */
683 ret_val = setup(devname);
691 pfatal("CAN'T CHECK FILE SYSTEM.");
693 if ((exitstat == 0) && (mflag))
699 } else if (ret_val == -1 ) { /* pclean && FS_CLEAN */
702 #if defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV)
703 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
707 #if defined(AFS_HPUX100_ENV)
709 check_sanity(filesys);
714 check_sanity(filesys);
722 * 1: scan inodes tallying blocks used
725 #if defined(AFS_SUN5_ENV)
727 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
730 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
732 msgprintf("** Root file system\n");
735 printf("** Phase 1 - Sanity Check only\n");
739 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
744 * 1b: locate first references to duplicates, if any
748 pfatal("INTERNAL ERROR: dups with -p");
749 msgprintf("** Phase 1b - Rescan For More DUPS\n");
754 * 2: traverse directories from root to mark all connected directories
757 msgprintf("** Phase 2 - Check Pathnames\n");
761 * 3: scan inodes looking for disconnected directories
764 msgprintf("** Phase 3 - Check Connectivity\n");
768 * 4: scan inodes looking for disconnected files; check reference counts
771 msgprintf("** Phase 4 - Check Reference Counts\n");
775 * 5: check and repair resource counts in cylinder groups
778 msgprintf("** Phase 5 - Check Cyl groups\n");
782 if (fsmodified || (sblk.b_dirty) || (cgblk.b_dirty)) {
788 * 003 - Number of retry attempts have been
789 * exhausted. Mark super block as dirty.
791 (void)time(&sblock.fs_time);
796 * 003 - If checking root file system, and it was
797 * modified during any pass, don't assume it is ok. Must reboot.
803 if ((!hotroot) && (!bflag) && (!nflag) && (!iscorrupt)) {
805 sblock.fs_clean = FS_CLEAN;
806 (void)time(&sblock.fs_time);
807 (void)time(&sblock.fs_lastfsck);
808 if ((sblock.fs_deftimer) && (sblock.fs_deftimer > 0) && (sblock.fs_deftimer < 255))
809 sblock.fs_cleantimer = sblock.fs_deftimer;
811 sblock.fs_cleantimer = sblock.fs_deftimer = FSCLEAN_TIMEOUTFACTOR;
815 * 006 - If an alternate super block was used,
816 * we want to re fsck the partition after
817 * updating the primary super block.
823 /* Unless no updates are to be done, write out maps. */
829 daddr_t nn_files = n_files;
830 daddr_t nn_blks = n_blks;
832 n_ffree = sblock.fs_cstotal.cs_nffree;
833 n_bfree = sblock.fs_cstotal.cs_nbfree;
834 if (nn_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)
835 printf("%d files missing\n", nn_files);
836 nn_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
837 nn_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
838 nn_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
839 if (nn_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
840 printf("%d blocks missing\n", nn_blks);
842 if (duplist != NULL) {
843 if (debug) 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);
863 zlnhead = (struct zlncnt *)0;
864 duplist = (struct dups *)0;
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",
891 n_files, n_cont, n_blks, n_ffree + sblock.fs_frag * n_bfree);
893 pinfo("%d files, %d used, %d free",
894 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
897 msgprintf(", %d AFS files", nViceFiles);
898 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n",
899 n_ffree, 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 ",
903 n_files, n_cont, n_blks, n_ffree + sblock.fs_frag * n_bfree);
905 pinfo("%d files, %d used, %d free ",
906 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
908 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
909 n_ffree, 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");
925 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
926 msgprintf("%d files missing\n", n_files);
928 n_blks += sblock.fs_ncg *
929 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
930 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
931 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
932 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
933 printf("%d blocks missing\n", n_blks);
934 if (duplist != NULL) {
935 msgprintf("The following duplicate blocks remain:");
936 for (dp = duplist; dp; dp = dp->next)
937 msgprintf(" %d,", dp->dup);
940 if (zlnhead != NULL) {
941 msgprintf("The following zero link count inodes remain:");
942 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
943 msgprintf(" %d,", zlnp->zlncnt);
949 /* if user's specification denotes that the file system block
950 * is going to be modified (nflag == 0) then fsck store the
951 * correct magic number in the super block if it is not already
954 if (!nflag && !(fswritefd < 0)) {
956 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
960 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
961 if (!preen && !qflag)
962 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
963 sblock.fs_clean = FS_CLEAN;
967 /* fix FS_CLEAN if changes made and no 'no' replies */
968 if (fsmodified && fixed)
969 sblock.fs_clean = FS_CLEAN;
971 * Fix fs_clean if there were no 'no' replies.
972 * This is done for both the s300 and s800. The s800 root will be
973 * guaranteed clean as of 7.0.
975 if (fixed && (sblock.fs_clean != FS_OK)) {
976 if (!preen && !qflag)
977 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
978 sblock.fs_clean = FS_CLEAN;
985 zlnhead = (struct zlncnt *)0;
986 duplist = (struct dups *)0;
988 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
996 if (hotroot && sblock.fs_clean == FSACTIVE)
999 else if (!((sblock.fs_state + (afs_int32)sblock.fs_time == FSOKAY) &&
1001 else if (!((fs_get_state(&sblock) + (afs_int32)sblock.fs_time == FSOKAY) &&
1003 (sblock.fs_clean ==FSCLEAN || sblock.fs_clean ==FSSTABLE))) {
1004 if (yflag || !iscorrupt) {
1005 printf("%s FILE SYSTEM STATE SET TO OKAY\n",
1009 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n",
1015 (void)time(&sblock.fs_time);
1017 if (hotroot && rebflg)
1018 sblock.fs_clean = FSACTIVE;
1020 sblock.fs_clean = FSSTABLE;
1022 sblock.fs_state = FSOKAY - (afs_int32)sblock.fs_time;
1024 fs_set_state(&sblock, FSOKAY - (afs_int32)sblock.fs_time);
1031 if (!nflag && !bflag && !hotroot) {
1033 sblock.fs_clean = FS_CLEAN;
1034 (void)time(&sblock.fs_time);
1036 flush(fswritefd, &sblk);
1039 #else /* AFS_OSF_ENV */
1041 (void)time(&sblock.fs_time);
1050 free((char *)lncntp);
1052 blockmap = statemap = NULL;
1060 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
1063 msgprintf("\n***** REBOOT UNIX *****\n");
1066 if (mountedfs || hotroot) {
1085 (void)close(fsreadfd);
1086 (void)close(fswritefd);
1087 if (nViceFiles || tryForce) {
1088 /* Modified file system with vice files: force full salvage */
1089 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
1090 #if !defined(AFS_DEC_ENV)
1091 struct ufs_args ufsargs;
1094 char pname[100], fname[100], *special;
1095 int fd, code, failed=0;
1097 msgprintf("%s: AFS file system partition was modified; forcing full salvage\n", devname);
1098 devname = unrawname(devname);
1099 special = (char *) strrchr(devname, '/');
1100 if (!special++) special = 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", errno);
1115 /* if system mounted / as read-only, we'll try to fix now */
1116 if (access("/", W_OK) < 0 && errno == EROFS) {
1117 printf("Can't RW acceess /; %d\n", errno);
1118 code = system("/sbin/mount -u /");
1120 printf("Couldn't remount / R/W; continuing anyway (%d).\n", errno);
1127 if (mkdir(pname, 0777) < 0) {
1128 if (errno != EEXIST) {
1129 perror("fsck mkdir");
1133 if (failed && parname) {
1134 strcpy(pname, parname);
1136 #if !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV)
1138 ufsargs.flags = UFSMNT_NOINTR;
1140 ufsargs.fspec = devname;
1144 if (mount(devname, pname, MS_DATA, "ufs", (char *)&ufsargs, sizeof(ufsargs)) < 0) {
1146 if (mount("4.2", pname, M_NEWTYPE, &ufsargs) < 0) {
1149 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1153 if (mount(devname, pname, 0, GT_ULTRIX, (char *) 0)) {
1155 if (mount(devname, pname, 0) < 0) {
1158 printf("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n", devname, pname, errno);
1160 strcpy(fname, pname);
1161 strcat(fname, "/FORCESALVAGE");
1162 fd = open(fname, O_CREAT, 0);
1164 errexit("Couldn't create %s to force full salvage!\n", fname);
1165 #if defined(AFS_DEC_ENV)
1172 #if /*defined(AFS_VFS_ENV) &&*/ !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1175 #if defined(AFS_DEC_ENV)
1176 umount(tstat.st_dev);
1178 #if defined(AFS_OSF_ENV)
1179 umount(pname, MNT_NOFORCE);
1180 #else /* AFS_OSF_ENV */
1189 fsync(fileno(logfile)); /* Since update isn't running */
1201 struct stat stslash, stblock, stchar;
1206 if (stat("/", &stslash) < 0) {
1208 printf("Can't stat root\n");
1212 if (stat(name, &stblock) < 0) {
1214 printf("Can't stat %s\n", name);
1217 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1218 if (stslash.st_dev == stblock.st_rdev) {
1220 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1222 #endif /* AFS_OSF_ENV */
1224 raw = rawname(name);
1228 printf("Cannot find character device for %s\n", name);
1231 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1232 name = unrawname(name);
1236 printf("Can't make sense out of name %s\n", name);
1241 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1245 * exit 0 - file system is unmounted and okay
1246 * exit 32 - file system is unmounted and needs checking
1247 * exit 33 - file system is mounted for root file system
1248 * exit 34 - cannot stat device
1250 check_sanity(filename)
1253 struct stat stbd, stbr;
1256 struct vfstab vfsbuf;
1262 if (stat(filename, &stbd) < 0) {
1263 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n", filename);
1267 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1269 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1272 fprintf(stderr, "ufs fsck: sanity check failed: %s not block or character device\n", filename);
1276 * Determine if this is the root file system via vfstab. Give up
1277 * silently on failures. The whole point of this is not to care
1278 * if the root file system is already mounted.
1280 * XXX - similar for /usr. This should be fixed to simply return
1281 * a new code indicating, mounted and needs to be checked.
1283 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1284 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1286 devname = vfsbuf.vfs_special;
1288 devname = vfsbuf.vfs_fsckdev;
1289 if (stat(devname, &stbr) == 0)
1290 if (stbr.st_rdev == stbd.st_rdev)
1293 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 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)
1304 /* XXX - only works if filename is a block device or if
1305 character and block device has the same dev_t value */
1306 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1307 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n", filename);
1311 * We mount the ufs root file system read-only first. After fsck
1312 * runs, we remount the root as read-write. Therefore, we no longer
1313 * check for different values for fs_state between the root file
1314 * system and the rest of file systems.
1316 if (!((sblock.fs_state + (time_t)sblock.fs_time == FSOKAY) &&
1317 (sblock.fs_clean ==FSCLEAN || sblock.fs_clean ==FSSTABLE))) {
1318 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n", filename);
1321 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1326 #if defined(AFS_HPUX100_ENV)
1327 check_sanity(filename)
1330 struct stat stbd, stbr;
1339 if (stat(filename, &stbd) < 0) {
1340 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n", filename);
1344 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1346 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1349 fprintf(stderr, "hfs fsck: sanity check failed: %s not block or character device\n", filename);
1353 * Determine if this is the root file system via vfstab. Give up
1354 * silently on failures. The whole point of this is not to care
1355 * if the root file system is already mounted.
1357 * XXX - similar for /usr. This should be fixed to simply return
1358 * a new code indicating, mounted and needs to be checked.
1360 if ((vfstab = setmntent(FSTAB, "r")) != 0)
1362 while ( mnt = getmntent(vfstab))
1364 if ( !strcmp(mnt->mnt_dir,"/") )
1365 if (stat(mnt->mnt_fsname, &stbr) == 0)
1366 if (stbr.st_rdev == stbd.st_rdev)
1369 if ( !strcmp(mnt->mnt_dir,"/usr") )
1370 if (stat(mnt->mnt_fsname, &stbr) == 0)
1371 if (stbr.st_rdev == stbd.st_rdev)
1377 /* XXX - only works if filename is a block device or if
1378 character and block device has the same dev_t value */
1379 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1380 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n", filename);
1384 * We mount the ufs root file system read-only first. After fsck
1385 * runs, we remount the root as read-write. Therefore, we no longer
1386 * check for different values for fs_state between the root file
1387 * system and the rest of file systems.
1389 if (! ((sblock.fs_clean ==FS_CLEAN || sblock.fs_clean ==FS_OK))) {
1390 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n", filename);
1393 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1397 /* see if all numbers */
1403 while ('0' <= *yp && *yp <= '9')
1411 /* Convert a raw device name into a block device name.
1412 * If the block device is not found, return the raw device name.
1413 * For HP and SUN, the returned value is not changed. For other
1414 * platforms it is changed (I see no rhyme or reason -jpm).
1420 static char bldev[256];
1421 struct stat statbuf;
1424 code = stat(rawdev, &statbuf);
1425 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1426 return(rawdev); /* Not a char device */
1428 for (i=strlen(rawdev)-2; i>=0; i--) {
1429 if ((rawdev[i] == '/') && (rawdev[i+1] == 'r')) {
1430 strcpy(bldev, rawdev);
1432 strcat(bldev, &rawdev[i+2]);
1434 code = stat(bldev, &statbuf); /* test for block device */
1435 if (!code && S_ISBLK(statbuf.st_mode)) {
1436 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1439 strcpy(rawdev, bldev); /* Replace */
1448 /* Convert a block device name into a raw device name.
1449 * If the block device is not found, return null
1455 static char rawdev[256];
1456 struct stat statbuf;
1459 for (i=strlen(bldev)-1; i>=0; i--) {
1460 if (bldev[i] == '/') {
1461 strcpy(rawdev, bldev);
1464 strcat(rawdev, &bldev[i+1]);
1466 code = stat(rawdev, &statbuf);
1467 if (!code && S_ISCHR(statbuf.st_mode))