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.
20 "@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
21 All rights reserved.\n";
25 static char sccsid[] = "@(#)main.c 5.17 (Berkeley) 2/1/90";
28 #include <afs/param.h>
29 #define VICE /* allow us to put our changes in at will */
32 #include <sys/param.h>
37 #endif /* AFS_SUN_ENV */
38 #include <sys/mount.h>
46 #include <sys/vnode.h>
47 #include <sys/mount.h>
48 #include <ufs/inode.h>
50 #else /* AFS_OSF_ENV */
51 #ifdef AFS_VFSINCL_ENV
53 #include <sys/vnode.h>
56 #include <sys/fs/ufs_inode.h>
57 #include <sys/fs/ufs_fs.h>
59 #include <sys/fs/ufs_fsdir.h>
61 #include <sys/fs/ufs_mount.h>
63 #include <ufs/inode.h>
66 #include <ufs/fsdir.h>
69 #else /* AFS_VFSINCL_ENV */
71 #include <sys/inode.h>
74 #define LONGFILENAMES 1
75 #include <sys/sysmacros.h>
85 #endif /* AFS_VFSINCL_ENV */
86 #endif /* AFS_OSF_ENV */
89 #include <sys/fs_types.h>
104 #include <sys/mnttab.h>
105 #include <sys/mntent.h>
106 #include <sys/vfstab.h>
107 #include <sys/ustat.h>
114 #include <sys/signal.h>
116 char *rawname(), *unrawname(), *blockcheck(), *malloc();
117 void catch(), catchquit(), voidquit();
124 char *name; /* device name */
125 char *fsname; /* mounted filesystem name */
126 struct part *next; /* forward link of partitions on disk */
127 } *badlist, **badnext = &badlist;
130 char *name; /* disk base name */
131 struct disk *next; /* forward link for list of disks */
132 struct part *part; /* head of list of partitions on disk */
133 int pid; /* If != 0, pid of proc working on */
136 int nrun, ndisks, maxrun, wflag=0;
141 #if defined(AFS_HPUX100_ENV)
147 #define msgprintf vfscklogprintf
149 #define msgprintf printf
156 #include "AFS_component_version_number.c"
159 int ge_danger = 0; /* on when fsck is not able to fix the dirty file
160 system within single run. Problems like dup table
161 overflow, maxdup is exceeding MAXDUP.. etc. could
162 potentailly prevent fsck from doing a complete
163 repair. This is found in a GE hotsite. */
171 int pid, passno, sumstatus;
173 register struct disk *dk, *nextdisk;
174 register struct part *pt;
175 extern char* AFSVersion; /* generated version */
177 int other_than_ufs=0;
188 #if defined(AFS_HPUX_ENV)
191 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
195 fsflag = oflag = mflag = exitstat = 0;
197 #if defined(AFS_HPUX100_ENV)
200 printf("----Open AFS (R) %s fsck----\n", AFSVersion); /* generated version */
201 if (access("/TRYFORCE", 0) == 0)
203 while (--argc > 0 && **++argv == '-') {
206 #if defined(AFS_HPUX_ENV)
207 #if defined(AFS_HPUX100_ENV)
208 case 'f': /* default yes to answer force to check */
211 #else /* AFS_HPUX100_ENV */
213 case 'F': /* default yes to answer force to check */
216 #endif /* AFS_HPUX_ENV */
217 #endif /* AFS_HPUX100_ENV */
223 #if defined(AFS_DEC_ENV)
224 /* On the late versions of Ultrix they changed the defn of '-p' a bit. Particularly,
225 * -p is used to check a file system that was not unmounted cleanly, and they added,
226 * -P to check a file system regardless of how it was unmounted; this, unfortunately,
227 * is identical to '-p' on the rest of the systems but we have to maintain vendor's
228 * semantics so we leave it the way Dec likes it.
232 /* P is for Ultrix compatibility */
239 #if defined(AFS_HPUX100_ENV)
245 (void) fprintf (stdout, "fsck -F hfs ");
246 for (opt_count = 1; opt_count < argc ; opt_count++) {
247 opt_text = argv[opt_count];
249 (void) fprintf (stdout, " %s ", opt_text);
251 (void) fprintf (stdout, "\n");
265 (void) fprintf (stdout, "fsck -F ufs ");
266 for (opt_count = 1; opt_count < argc ; opt_count++) {
267 opt_text = argv[opt_count];
269 (void) fprintf (stdout, " %s ", opt_text);
271 (void) fprintf (stdout, "\n");
278 while (*subopt != '\0') {
279 if (*subopt == 'p') {
282 } else if (*subopt == 'b') {
283 if (argv[0][1] != '\0') {
284 bflag = atoi(argv[0]+1);
286 bflag = atoi(*++argv);
289 msgprintf("Alternate super block location: %d\n", bflag);
291 } else if (*subopt == 'd') {
294 } else if (*subopt == 'r') {
296 } else if (*subopt == 'w') {
299 } else if (*subopt == 'c') {
302 } else if (*subopt == 'f') {
306 errexit("-o %c option?\n", *subopt);
319 if (argv[0][1] != '\0') {
320 bflag = atoi(argv[0]+1);
322 bflag = atoi(*++argv);
325 msgprintf("Alternate super block location: %d\n", bflag);
332 /* who knows? defined, but doesn't do much */
336 case 'w': /* check writable only */
343 if (!isdigit(argv[1][0]))
344 errexit("-l flag requires a number\n");
345 maxrun = atoi(*++argv);
348 #if !defined(AFS_HPUX100_ENV)
350 if (!isdigit(argv[1][0]))
351 errexit("-m flag requires a mode\n");
352 sscanf(*++argv, "%o", &lfmode);
354 errexit("bad mode to -m: %o\n", lfmode);
356 printf("** lost+found creation mode %o\n", lfmode);
358 #endif /* AFS_HPUX100_ENV */
359 #endif /* AFS_SUN5_ENV */
364 #endif /* AFS_OSF_ENV */
372 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
373 * it's general/useful flag to use.
386 errexit("%c option?\n", **argv);
390 * The following checks were only available on hpux but are useful to all systems.
393 errexit("Incompatible options: -n and -p\n");
395 errexit("Incompatible options: -n and -q\n");
398 rflag++; /* check raw devices */
400 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
401 (void)signal(SIGINT, catch);
403 (void)signal(SIGQUIT, catchquit);
408 if (wflag && !writable(*argv)) {
409 (void) fprintf (stderr, "not writeable '%s'\n", *argv);
413 checkfilesys(*argv++, (char *)0);
428 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
431 if ((fd = fopen(VFSTAB, "r")) == NULL) {
432 errexit("vfsck: cannot open vfstab\n");
434 while ((ret = getvfsent(fd, &vget)) == 0) {
435 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) && numbers(vget.vfs_fsckpass)) {
439 if (numbers(vget.vfs_fsckpass))
440 passno = atoi(vget.vfs_fsckpass);
445 if (preen == 0 || passno == 1) {
446 checkfilesys(vget.vfs_fsckdev, get.vfs_mountp);
447 } else if (passno > 1) {
448 addpart(vget.vfs_fsckdev, vget.vfs_special);
452 for (passno = 1; passno <= 2; passno++) {
454 errexit("Can't open checklist file: %s\n", FSTAB);
455 while ((fsp = getfsent()) != 0) {
456 if (strcmp(fsp->fs_type, FSTAB_RW) &&
457 strcmp(fsp->fs_type, FSTAB_RO) &&
458 strcmp(fsp->fs_type, FSTAB_RQ))
461 /* Only check local (i.e. ufs) file systems */
462 if (strcmp(fsp->fs_name, "4.2") && strcmp(fsp->fs_name, "ufs"))
466 if (strcmp(fsp->fs_vfstype, "ufs") ||
467 fsp->fs_passno == 0) {
470 #endif /* AFS_OSF_ENV */
471 if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
473 name = blockcheck(fsp->fs_spec);
475 checkfilesys(name, fsp->fs_file);
477 printf("pid %d exiting 8/1\n", getpid());
481 } else if (passno == 2 && fsp->fs_passno > 1) {
482 name = blockcheck(fsp->fs_spec);
484 pwarn("BAD DISK NAME %s\n",
487 printf("pid %d saw bad disk name 8/3\n", getpid());
490 addpart(name, fsp->fs_file);
503 for (passno = 0; passno < maxrun; ++passno) {
505 nextdisk = nextdisk->next;
507 while ((pid = wait(&status)) != -1) {
508 for (dk = disks; dk; dk = dk->next)
512 printf("Unknown pid %d\n", pid);
515 rc = WEXITSTATUS(status);
516 if (WIFSIGNALED(status)) {
517 printf("%s (%s): EXITED WITH SIGNAL %d\n",
518 dk->part->name, dk->part->fsname,
525 badnext = &dk->part->next;
526 dk->part = dk->part->next;
529 dk->part = dk->part->next;
532 if (dk->part == NULL)
535 if (nextdisk == NULL) {
538 } else if (nrun < maxrun && nrun < ndisks) {
540 if ((nextdisk = nextdisk->next) == NULL)
542 if (nextdisk->part != NULL &&
552 printf("pid %d exiting 8/2\n", getpid());
555 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
556 badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
557 for (pt = badlist; pt; pt = pt->next)
558 printf("%s (%s)%s", pt->name, pt->fsname,
559 pt->next ? ", " : "\n");
569 #endif /* !AFS_SUN5_ENV */
577 register struct disk *dk, **dkp;
581 for (p = name + strlen(name) - 1; p >= name; --p)
589 for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
590 if (strncmp(dk->name, name, len) == 0 &&
594 if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
595 errexit("out of memory");
597 if ((dk->name = malloc((unsigned int)len + 1)) == NULL)
598 errexit("out of memory");
599 strncpy(dk->name, name, len);
600 dk->name[len] = '\0';
608 addpart(name, fsname)
611 struct disk *dk = finddisk(name);
612 register struct part *pt, **ppt = &dk->part;
614 for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
615 if (strcmp(pt->name, name) == 0) {
616 printf("%s in fstab more than once!\n", name);
619 if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
620 errexit("out of memory");
622 if ((pt->name = malloc((unsigned int)strlen(name) + 1)) == NULL)
623 errexit("out of memory");
624 strcpy(pt->name, name);
625 if ((pt->fsname = malloc((unsigned int)strlen(fsname) + 1)) == NULL)
626 errexit("out of memory");
627 strcpy(pt->fsname, fsname);
632 register struct disk *dk;
642 (void)signal(SIGQUIT, voidquit);
643 checkfilesys(dk->part->name, dk->part->fsname);
648 checkfilesys(filesys, parname)
651 daddr_t n_ffree, n_bfree;
653 struct stat tstat; /* for ultrix 3 unmount */
658 int retries = 3; /* # of retries fora clean fsck pass */
659 int fsdirty = 0; /* file system was or is dirty */
660 int rootdirty = 0; /* Root was or is dirty */
665 #endif /* AFS_OSF_ENV */
675 ge_danger = 0; /* set to 1 by any table overflow or more
676 dup/bad blocks than expected */
678 fixed = 1; /* set to 0 by any 'no' reply */
680 strcpy(devbuffer, filesys); /* copy the file system name to the device buffer */
681 devname = devbuffer; /* remember generic ptr for later */
682 EnsureDevice(devname); /* canonicalize name */
686 for (; retries > 0; retries--) { /* 003 - Loop for NUMRETRIES or until clean */
689 ret_val = setup(devname);
697 pfatal("CAN'T CHECK FILE SYSTEM.");
699 if ((exitstat == 0) && (mflag))
705 } else if (ret_val == -1 ) { /* pclean && FS_CLEAN */
708 #if defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV)
709 } else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
713 #if defined(AFS_HPUX100_ENV)
715 check_sanity(filesys);
720 check_sanity(filesys);
728 * 1: scan inodes tallying blocks used
731 #if defined(AFS_SUN5_ENV)
733 msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
736 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
738 msgprintf("** Root file system\n");
741 printf("** Phase 1 - Sanity Check only\n");
745 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
750 * 1b: locate first references to duplicates, if any
754 pfatal("INTERNAL ERROR: dups with -p");
755 msgprintf("** Phase 1b - Rescan For More DUPS\n");
760 * 2: traverse directories from root to mark all connected directories
763 msgprintf("** Phase 2 - Check Pathnames\n");
767 * 3: scan inodes looking for disconnected directories
770 msgprintf("** Phase 3 - Check Connectivity\n");
774 * 4: scan inodes looking for disconnected files; check reference counts
777 msgprintf("** Phase 4 - Check Reference Counts\n");
781 * 5: check and repair resource counts in cylinder groups
784 msgprintf("** Phase 5 - Check Cyl groups\n");
788 if (fsmodified || (sblk.b_dirty) || (cgblk.b_dirty)) {
794 * 003 - Number of retry attempts have been
795 * exhausted. Mark super block as dirty.
797 (void)time(&sblock.fs_time);
802 * 003 - If checking root file system, and it was
803 * modified during any pass, don't assume it is ok. Must reboot.
809 if ((!hotroot) && (!bflag) && (!nflag) && (!iscorrupt)) {
811 sblock.fs_clean = FS_CLEAN;
812 (void)time(&sblock.fs_time);
813 (void)time(&sblock.fs_lastfsck);
814 if ((sblock.fs_deftimer) && (sblock.fs_deftimer > 0) && (sblock.fs_deftimer < 255))
815 sblock.fs_cleantimer = sblock.fs_deftimer;
817 sblock.fs_cleantimer = sblock.fs_deftimer = FSCLEAN_TIMEOUTFACTOR;
821 * 006 - If an alternate super block was used,
822 * we want to re fsck the partition after
823 * updating the primary super block.
829 /* Unless no updates are to be done, write out maps. */
835 daddr_t nn_files = n_files;
836 daddr_t nn_blks = n_blks;
838 n_ffree = sblock.fs_cstotal.cs_nffree;
839 n_bfree = sblock.fs_cstotal.cs_nbfree;
840 if (nn_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)
841 printf("%d files missing\n", nn_files);
842 nn_blks += sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
843 nn_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
844 nn_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
845 if (nn_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
846 printf("%d blocks missing\n", nn_blks);
848 if (duplist != NULL) {
849 if (debug) printf("The following duplicate blocks remain:");
850 for (dp = duplist; dp; dp = dp->next) {
852 printf(" %d,", dp->dup);
858 if (zlnhead != NULL) {
860 printf("The following zero link count inodes remain:");
861 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) {
863 printf(" %d,", zlnp->zlncnt);
869 zlnhead = (struct zlncnt *)0;
870 duplist = (struct dups *)0;
874 free((char *)lncntp);
875 /* Print out retry message, and fsck file system again. */
878 printf("%s: FILE SYSTEM MODIFIED, VERIFYING\n",filesys);
880 printf("**** FILE SYSTEM MODIFIED, VERIFYING\n");
884 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
890 * print out summary statistics
892 n_ffree = sblock.fs_cstotal.cs_nffree;
893 n_bfree = sblock.fs_cstotal.cs_nbfree;
895 #if defined(ACLS) && defined(AFS_HPUX_ENV)
896 pinfo("%d files, %d icont, %d used, %d free",
897 n_files, n_cont, n_blks, n_ffree + sblock.fs_frag * n_bfree);
899 pinfo("%d files, %d used, %d free",
900 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
903 msgprintf(", %d AFS files", nViceFiles);
904 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n",
905 n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
907 #if defined(ACLS) && defined(AFS_HPUX_ENV)
908 pinfo("%d files, %d icont, %d used, %d free ",
909 n_files, n_cont, n_blks, n_ffree + sblock.fs_frag * n_bfree);
911 pinfo("%d files, %d used, %d free ",
912 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
914 n printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
915 n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
918 if ((!fsdirty) && (!rootdirty))
921 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
923 printf("\n***** HALT PROCESSOR WITHOUT SYNCING DISK *****\n");
931 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
932 msgprintf("%d files missing\n", n_files);
934 n_blks += sblock.fs_ncg *
935 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
936 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
937 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
938 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree))
939 printf("%d blocks missing\n", n_blks);
940 if (duplist != NULL) {
941 msgprintf("The following duplicate blocks remain:");
942 for (dp = duplist; dp; dp = dp->next)
943 msgprintf(" %d,", dp->dup);
946 if (zlnhead != NULL) {
947 msgprintf("The following zero link count inodes remain:");
948 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
949 msgprintf(" %d,", zlnp->zlncnt);
955 /* if user's specification denotes that the file system block
956 * is going to be modified (nflag == 0) then fsck store the
957 * correct magic number in the super block if it is not already
960 if (!nflag && !(fswritefd < 0)) {
962 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
966 if (fixed && (sblock.fs_clean != FS_CLEAN)) {
967 if (!preen && !qflag)
968 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
969 sblock.fs_clean = FS_CLEAN;
973 /* fix FS_CLEAN if changes made and no 'no' replies */
974 if (fsmodified && fixed)
975 sblock.fs_clean = FS_CLEAN;
977 * Fix fs_clean if there were no 'no' replies.
978 * This is done for both the s300 and s800. The s800 root will be
979 * guaranteed clean as of 7.0.
981 if (fixed && (sblock.fs_clean != FS_OK)) {
982 if (!preen && !qflag)
983 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
984 sblock.fs_clean = FS_CLEAN;
991 zlnhead = (struct zlncnt *)0;
992 duplist = (struct dups *)0;
994 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
1002 if (hotroot && sblock.fs_clean == FSACTIVE)
1005 else if (!((sblock.fs_state + (afs_int32)sblock.fs_time == FSOKAY) &&
1007 else if (!((fs_get_state(&sblock) + (afs_int32)sblock.fs_time == FSOKAY) &&
1009 (sblock.fs_clean ==FSCLEAN || sblock.fs_clean ==FSSTABLE))) {
1010 if (yflag || !iscorrupt) {
1011 printf("%s FILE SYSTEM STATE SET TO OKAY\n",
1015 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n",
1021 (void)time(&sblock.fs_time);
1023 if (hotroot && rebflg)
1024 sblock.fs_clean = FSACTIVE;
1026 sblock.fs_clean = FSSTABLE;
1028 sblock.fs_state = FSOKAY - (afs_int32)sblock.fs_time;
1030 fs_set_state(&sblock, FSOKAY - (afs_int32)sblock.fs_time);
1037 if (!nflag && !bflag && !hotroot) {
1039 sblock.fs_clean = FS_CLEAN;
1040 (void)time(&sblock.fs_time);
1042 flush(fswritefd, &sblk);
1045 #else /* AFS_OSF_ENV */
1047 (void)time(&sblock.fs_time);
1056 free((char *)lncntp);
1058 blockmap = statemap = NULL;
1066 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
1069 msgprintf("\n***** REBOOT UNIX *****\n");
1072 if (mountedfs || hotroot) {
1087 (void)close(fsreadfd);
1088 (void)close(fswritefd);
1089 if (nViceFiles || tryForce) {
1090 /* Modified file system with vice files: force full salvage */
1091 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
1092 #if !defined(AFS_DEC_ENV)
1093 struct ufs_args ufsargs;
1096 char pname[100], fname[100], *special;
1097 int fd, code, failed=0;
1099 msgprintf("%s: AFS file system partition was modified; forcing full salvage\n", devname);
1100 devname = unrawname(devname);
1101 special = (char *) rindex(devname, '/');
1102 if (!special++) special = devname;
1103 strcpy(pname, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
1104 /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
1105 strcat(pname, special);
1107 /* if system mounted / as read-only, we'll try to fix now */
1108 if (access("/", W_OK) < 0 && errno == EROFS) {
1109 code = system("mount -o remount /");
1111 printf("Couldn't remount / R/W; continuing anyway (%d).\n", errno);
1117 /* if system mounted / as read-only, we'll try to fix now */
1118 if (access("/", W_OK) < 0 && errno == EROFS) {
1119 printf("Can't RW acceess /; %d\n", errno);
1120 code = system("/sbin/mount -u /");
1122 printf("Couldn't remount / R/W; continuing anyway (%d).\n", errno);
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;
1146 if (mount(devname, pname, MS_DATA, "ufs", (char *)&ufsargs, sizeof(ufsargs)) < 0) {
1148 if (mount("4.2", pname, M_NEWTYPE, &ufsargs) < 0) {
1151 if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1155 if (mount(devname, pname, 0, GT_ULTRIX, (char *) 0)) {
1157 if (mount(devname, pname, 0) < 0) {
1160 printf("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n", devname, pname, errno);
1162 strcpy(fname, pname);
1163 strcat(fname, "/FORCESALVAGE");
1164 fd = open(fname, O_CREAT, 0);
1166 errexit("Couldn't create %s to force full salvage!\n", fname);
1167 #if defined(AFS_DEC_ENV)
1174 #if /*defined(AFS_VFS_ENV) &&*/ !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1177 #if defined(AFS_DEC_ENV)
1178 umount(tstat.st_dev);
1180 #if defined(AFS_OSF_ENV)
1181 umount(pname, MNT_NOFORCE);
1182 #else /* AFS_OSF_ENV */
1191 fsync(fileno(logfile)); /* Since update isn't running */
1203 struct stat stslash, stblock, stchar;
1208 if (stat("/", &stslash) < 0) {
1210 printf("Can't stat root\n");
1214 if (stat(name, &stblock) < 0) {
1216 printf("Can't stat %s\n", name);
1219 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1220 if (stslash.st_dev == stblock.st_rdev) {
1222 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1224 #endif /* AFS_OSF_ENV */
1226 raw = rawname(name);
1230 printf("Cannot find character device for %s\n", name);
1233 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1234 name = unrawname(name);
1238 printf("Can't make sense out of name %s\n", name);
1243 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1247 * exit 0 - file system is unmounted and okay
1248 * exit 32 - file system is unmounted and needs checking
1249 * exit 33 - file system is mounted for root file system
1250 * exit 34 - cannot stat device
1252 check_sanity(filename)
1255 struct stat stbd, stbr;
1258 struct vfstab vfsbuf;
1264 if (stat(filename, &stbd) < 0) {
1265 fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n", filename);
1269 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1271 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1274 fprintf(stderr, "ufs fsck: sanity check failed: %s not block or character device\n", filename);
1278 * Determine if this is the root file system via vfstab. Give up
1279 * silently on failures. The whole point of this is not to care
1280 * if the root file system is already mounted.
1282 * XXX - similar for /usr. This should be fixed to simply return
1283 * a new code indicating, mounted and needs to be checked.
1285 if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1286 if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1288 devname = vfsbuf.vfs_special;
1290 devname = vfsbuf.vfs_fsckdev;
1291 if (stat(devname, &stbr) == 0)
1292 if (stbr.st_rdev == stbd.st_rdev)
1295 if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1297 devname = vfsbuf.vfs_special;
1299 devname = vfsbuf.vfs_fsckdev;
1300 if (stat(devname, &stbr) == 0)
1301 if (stbr.st_rdev == stbd.st_rdev)
1306 /* XXX - only works if filename is a block device or if
1307 character and block device has the same dev_t value */
1308 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1309 fprintf(stderr, "ufs fsck: sanity check: %s already mounted\n", filename);
1313 * We mount the ufs root file system read-only first. After fsck
1314 * runs, we remount the root as read-write. Therefore, we no longer
1315 * check for different values for fs_state between the root file
1316 * system and the rest of file systems.
1318 if (!((sblock.fs_state + (time_t)sblock.fs_time == FSOKAY) &&
1319 (sblock.fs_clean ==FSCLEAN || sblock.fs_clean ==FSSTABLE))) {
1320 fprintf(stderr, "ufs fsck: sanity check: %s needs checking\n", filename);
1323 fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1328 #if defined(AFS_HPUX100_ENV)
1329 check_sanity(filename)
1332 struct stat stbd, stbr;
1341 if (stat(filename, &stbd) < 0) {
1342 fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n", filename);
1346 if ((stbd.st_mode & S_IFMT) == S_IFBLK)
1348 else if ((stbd.st_mode & S_IFMT) == S_IFCHR)
1351 fprintf(stderr, "hfs fsck: sanity check failed: %s not block or character device\n", filename);
1355 * Determine if this is the root file system via vfstab. Give up
1356 * silently on failures. The whole point of this is not to care
1357 * if the root file system is already mounted.
1359 * XXX - similar for /usr. This should be fixed to simply return
1360 * a new code indicating, mounted and needs to be checked.
1362 if ((vfstab = setmntent(FSTAB, "r")) != 0)
1364 while ( mnt = getmntent(vfstab))
1366 if ( !strcmp(mnt->mnt_dir,"/") )
1367 if (stat(mnt->mnt_fsname, &stbr) == 0)
1368 if (stbr.st_rdev == stbd.st_rdev)
1371 if ( !strcmp(mnt->mnt_dir,"/usr") )
1372 if (stat(mnt->mnt_fsname, &stbr) == 0)
1373 if (stbr.st_rdev == stbd.st_rdev)
1379 /* XXX - only works if filename is a block device or if
1380 character and block device has the same dev_t value */
1381 if (is_root == 0 && is_usr == 0 && ustat(stbd.st_rdev, &usb) == 0) {
1382 fprintf(stderr, "hfs fsck: sanity check: %s already mounted\n", filename);
1386 * We mount the ufs root file system read-only first. After fsck
1387 * runs, we remount the root as read-write. Therefore, we no longer
1388 * check for different values for fs_state between the root file
1389 * system and the rest of file systems.
1391 if (! ((sblock.fs_clean ==FS_CLEAN || sblock.fs_clean ==FS_OK))) {
1392 fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n", filename);
1395 fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1399 /* see if all numbers */
1405 while ('0' <= *yp && *yp <= '9')
1413 /* Convert a raw device name into a block device name.
1414 * If the block device is not found, return the raw device name.
1415 * For HP and SUN, the returned value is not changed. For other
1416 * platforms it is changed (I see no rhyme or reason -jpm).
1422 static char bldev[256];
1423 struct stat statbuf;
1426 code = stat(rawdev, &statbuf);
1427 if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1428 return(rawdev); /* Not a char device */
1430 for (i=strlen(rawdev)-2; i>=0; i--) {
1431 if ((rawdev[i] == '/') && (rawdev[i+1] == 'r')) {
1432 strcpy(bldev, rawdev);
1434 strcat(bldev, &rawdev[i+2]);
1436 code = stat(bldev, &statbuf); /* test for block device */
1437 if (!code && S_ISBLK(statbuf.st_mode)) {
1438 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1441 strcpy(rawdev, bldev); /* Replace */
1450 /* Convert a block device name into a raw device name.
1451 * If the block device is not found, return null
1457 static char rawdev[256];
1458 struct stat statbuf;
1461 for (i=strlen(bldev)-1; i>=0; i--) {
1462 if (bldev[i] == '/') {
1463 strcpy(rawdev, bldev);
1466 strcat(rawdev, &bldev[i+1]);
1468 code = stat(rawdev, &statbuf);
1469 if (!code && S_ISCHR(statbuf.st_mode))