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 <afs/param.h>
19 #include <afsconfig.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) {
1081 (void)close(fsreadfd);
1082 (void)close(fswritefd);
1083 if (nViceFiles || tryForce) {
1084 /* Modified file system with vice files: force full salvage */
1085 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
1086 #if !defined(AFS_DEC_ENV)
1087 struct ufs_args ufsargs;
1090 char pname[100], fname[100], *special;
1091 int fd, code, failed=0;
1093 msgprintf("%s: AFS file system partition was modified; forcing full salvage\n", devname);
1094 devname = unrawname(devname);
1095 special = (char *) rindex(devname, '/');
1096 if (!special++) special = devname;
1097 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
1098 /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
1099 strcat(pname, special);
1101 /* if system mounted / as read-only, we'll try to fix now */
1102 if (access("/", W_OK) < 0 && errno == EROFS) {
1103 code = system("mount -o remount /");
1105 printf("Couldn't remount / R/W; continuing anyway (%d).\n", errno);
1111 /* if system mounted / as read-only, we'll try to fix now */
1112 if (access("/", W_OK) < 0 && errno == EROFS) {
1113 printf("Can't RW acceess /; %d\n", errno);
1114 code = system("/sbin/mount -u /");
1116 printf("Couldn't remount / R/W; continuing anyway (%d).\n", errno);
1123 if (mkdir(pname, 0777) < 0) {
1124 if (errno != EEXIST) {
1125 perror("fsck mkdir");
1129 if (failed && parname) {
1130 strcpy(pname, parname);
1132 #if !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV)
1134 ufsargs.flags = UFSMNT_NOINTR;
1136 ufsargs.fspec = devname;
1140 if (mount(devname, pname, MS_DATA, "ufs", (char *)&ufsargs, sizeof(ufsargs)) < 0) {
1142 if (mount("4.2", pname, M_NEWTYPE, &ufsargs) < 0) {
1145 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1149 if (mount(devname, pname, 0, GT_ULTRIX, (char *) 0)) {
1151 if (mount(devname, pname, 0) < 0) {
1154 printf("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n", devname, pname, errno);
1156 strcpy(fname, pname);
1157 strcat(fname, "/FORCESALVAGE");
1158 fd = open(fname, O_CREAT, 0);
1160 errexit("Couldn't create %s to force full salvage!\n", fname);
1161 #if defined(AFS_DEC_ENV)
1168 #if /*defined(AFS_VFS_ENV) &&*/ !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1171 #if defined(AFS_DEC_ENV)
1172 umount(tstat.st_dev);
1174 #if defined(AFS_OSF_ENV)
1175 umount(pname, MNT_NOFORCE);
1176 #else /* AFS_OSF_ENV */
1185 fsync(fileno(logfile)); /* Since update isn't running */
1197 struct stat stslash, stblock, stchar;
1202 if (stat("/", &stslash) < 0) {
1204 printf("Can't stat root\n");
1208 if (stat(name, &stblock) < 0) {
1210 printf("Can't stat %s\n", name);
1213 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1214 if (stslash.st_dev == stblock.st_rdev) {
1216 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1218 #endif /* AFS_OSF_ENV */
1220 raw = rawname(name);
1224 printf("Cannot find character device for %s\n", name);
1227 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1228 name = unrawname(name);
1232 printf("Can't make sense out of name %s\n", name);
1237 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1241 * exit 0 - file system is unmounted and okay
1242 * exit 32 - file system is unmounted and needs checking
1243 * exit 33 - file system is mounted for root file system
1244 * exit 34 - cannot stat device
1246 check_sanity(filename)
1249 struct stat stbd, stbr;
1252 struct vfstab vfsbuf;
1258 if (stat(filename, &stbd) < 0) {
1259 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n", filename);
1263 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1265 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1268 fprintf(stderr, "ufs fsck: sanity check failed: %s not block or character device\n", filename);
1272 * Determine if this is the root file system via vfstab. Give up
1273 * silently on failures. The whole point of this is not to care
1274 * if the root file system is already mounted.
1276 * XXX - similar for /usr. This should be fixed to simply return
1277 * a new code indicating, mounted and needs to be checked.
1279 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1280 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1282 devname = vfsbuf.vfs_special;
1284 devname = vfsbuf.vfs_fsckdev;
1285 if (stat(devname, &stbr) == 0)
1286 if (stbr.st_rdev == stbd.st_rdev)
1289 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1291 devname = vfsbuf.vfs_special;
1293 devname = vfsbuf.vfs_fsckdev;
1294 if (stat(devname, &stbr) == 0)
1295 if (stbr.st_rdev == stbd.st_rdev)
1300 /* XXX - only works if filename is a block device or if
1301 character and block device has the same dev_t value */
1302 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1303 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n", filename);
1307 * We mount the ufs root file system read-only first. After fsck
1308 * runs, we remount the root as read-write. Therefore, we no longer
1309 * check for different values for fs_state between the root file
1310 * system and the rest of file systems.
1312 if (!((sblock.fs_state + (time_t)sblock.fs_time == FSOKAY) &&
1313 (sblock.fs_clean ==FSCLEAN || sblock.fs_clean ==FSSTABLE))) {
1314 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n", filename);
1317 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1322 #if defined(AFS_HPUX100_ENV)
1323 check_sanity(filename)
1326 struct stat stbd, stbr;
1335 if (stat(filename, &stbd) < 0) {
1336 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n", filename);
1340 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1342 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1345 fprintf(stderr, "hfs fsck: sanity check failed: %s not block or character device\n", filename);
1349 * Determine if this is the root file system via vfstab. Give up
1350 * silently on failures. The whole point of this is not to care
1351 * if the root file system is already mounted.
1353 * XXX - similar for /usr. This should be fixed to simply return
1354 * a new code indicating, mounted and needs to be checked.
1356 if ((vfstab = setmntent(FSTAB, "r")) != 0)
1358 while ( mnt = getmntent(vfstab))
1360 if ( !strcmp(mnt->mnt_dir,"/") )
1361 if (stat(mnt->mnt_fsname, &stbr) == 0)
1362 if (stbr.st_rdev == stbd.st_rdev)
1365 if ( !strcmp(mnt->mnt_dir,"/usr") )
1366 if (stat(mnt->mnt_fsname, &stbr) == 0)
1367 if (stbr.st_rdev == stbd.st_rdev)
1373 /* XXX - only works if filename is a block device or if
1374 character and block device has the same dev_t value */
1375 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1376 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n", filename);
1380 * We mount the ufs root file system read-only first. After fsck
1381 * runs, we remount the root as read-write. Therefore, we no longer
1382 * check for different values for fs_state between the root file
1383 * system and the rest of file systems.
1385 if (! ((sblock.fs_clean ==FS_CLEAN || sblock.fs_clean ==FS_OK))) {
1386 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n", filename);
1389 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1393 /* see if all numbers */
1399 while ('0' <= *yp && *yp <= '9')
1407 /* Convert a raw device name into a block device name.
1408 * If the block device is not found, return the raw device name.
1409 * For HP and SUN, the returned value is not changed. For other
1410 * platforms it is changed (I see no rhyme or reason -jpm).
1416 static char bldev[256];
1417 struct stat statbuf;
1420 code = stat(rawdev, &statbuf);
1421 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1422 return(rawdev); /* Not a char device */
1424 for (i=strlen(rawdev)-2; i>=0; i--) {
1425 if ((rawdev[i] == '/') && (rawdev[i+1] == 'r')) {
1426 strcpy(bldev, rawdev);
1428 strcat(bldev, &rawdev[i+2]);
1430 code = stat(bldev, &statbuf); /* test for block device */
1431 if (!code && S_ISBLK(statbuf.st_mode)) {
1432 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1435 strcpy(rawdev, bldev); /* Replace */
1444 /* Convert a block device name into a raw device name.
1445 * If the block device is not found, return null
1451 static char rawdev[256];
1452 struct stat statbuf;
1455 for (i=strlen(bldev)-1; i>=0; i--) {
1456 if (bldev[i] == '/') {
1457 strcpy(rawdev, bldev);
1460 strcat(rawdev, &bldev[i+1]);
1462 code = stat(rawdev, &statbuf);
1463 if (!code && S_ISCHR(statbuf.st_mode))