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>
22 /* We need the old directory type headers (included below), so don't include
23 * the normal dirent.h, or it will conflict. */
25 # include <sys/inode.h>
26 # define LONGFILENAMES 1
27 # include <sys/sysmacros.h>
30 # ifdef HAVE_USR_OLD_USR_INCLUDE_NDIR_H
31 # include </usr/old/usr/include/ndir.h>
41 #ifdef HAVE_SYS_FILE_H
45 #define VICE /* allow us to put our changes in at will */
49 #endif /* AFS_SUN_ENV */
50 #include <sys/mount.h>
56 #include <sys/vnode.h>
57 #include <sys/mount.h>
58 #include <ufs/inode.h>
60 #else /* AFS_OSF_ENV */
61 #ifdef AFS_VFSINCL_ENV
63 #include <sys/vnode.h>
65 #include <sys/fs/ufs_inode.h>
66 #include <sys/fs/ufs_fs.h>
68 #include <sys/fs/ufs_fsdir.h>
70 #include <sys/fs/ufs_mount.h>
72 #include <ufs/inode.h>
75 #include <ufs/fsdir.h>
78 #else /* AFS_VFSINCL_ENV */
80 #include <sys/inode.h>
87 #endif /* AFS_VFSINCL_ENV */
88 #endif /* AFS_OSF_ENV */
95 #include <sys/mnttab.h>
96 #include <sys/mntent.h>
97 #include <sys/vfstab.h>
98 #include <sys/ustat.h>
104 #include <sys/signal.h>
106 char *rawname(), *unrawname(), *blockcheck();
107 void catch(), catchquit(), voidquit();
114 char *name
; /* device name */
115 char *fsname
; /* mounted filesystem name */
116 struct part
*next
; /* forward link of partitions on disk */
117 } *badlist
, **badnext
= &badlist
;
120 char *name
; /* disk base name */
121 struct disk
*next
; /* forward link for list of disks */
122 struct part
*part
; /* head of list of partitions on disk */
123 int pid
; /* If != 0, pid of proc working on */
126 int nrun
, ndisks
, maxrun
, wflag
= 0;
131 #if defined(AFS_HPUX100_ENV)
137 #define msgprintf vfscklogprintf
139 #define msgprintf printf
146 #include "AFS_component_version_number.c"
149 int ge_danger
= 0; /* on when fsck is not able to fix the dirty file
150 * system within single run. Problems like dup table
151 * overflow, maxdup is exceeding MAXDUP.. etc. could
152 * potentailly prevent fsck from doing a complete
153 * repair. This is found in a GE hotsite. */
161 int pid
, passno
, sumstatus
;
163 struct disk
*dk
, *nextdisk
;
165 extern char *AFSVersion
; /* generated version */
167 int other_than_ufs
= 0;
178 #if defined(AFS_HPUX_ENV)
181 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
185 fsflag
= oflag
= mflag
= exitstat
= 0;
187 #if defined(AFS_HPUX100_ENV)
190 printf("----Open AFS (R) %s fsck----\n", AFSVersion
); /* generated version */
191 if (access("/TRYFORCE", 0) == 0)
193 while (--argc
> 0 && **++argv
== '-') {
196 #if defined(AFS_HPUX_ENV)
197 #if defined(AFS_HPUX100_ENV)
198 case 'f': /* default yes to answer force to check */
201 #else /* AFS_HPUX100_ENV */
203 case 'F': /* default yes to answer force to check */
206 #endif /* AFS_HPUX_ENV */
207 #endif /* AFS_HPUX100_ENV */
216 #if defined(AFS_HPUX100_ENV)
222 (void)fprintf(stdout
, "fsck -F hfs ");
223 for (opt_count
= 1; opt_count
< argc
; opt_count
++) {
224 opt_text
= argv
[opt_count
];
226 (void)fprintf(stdout
, " %s ", opt_text
);
228 (void)fprintf(stdout
, "\n");
242 (void)fprintf(stdout
, "fsck -F ufs ");
243 for (opt_count
= 1; opt_count
< argc
; opt_count
++) {
244 opt_text
= argv
[opt_count
];
246 (void)fprintf(stdout
, " %s ", opt_text
);
248 (void)fprintf(stdout
, "\n");
255 while (*subopt
!= '\0') {
256 if (*subopt
== 'p') {
259 } else if (*subopt
== 'b') {
260 if (argv
[0][1] != '\0') {
261 bflag
= atoi(argv
[0] + 1);
263 bflag
= atoi(*++argv
);
266 msgprintf("Alternate super block location: %d\n", bflag
);
268 } else if (*subopt
== 'd') {
271 } else if (*subopt
== 'r') {
273 } else if (*subopt
== 'w') {
276 } else if (*subopt
== 'c') {
279 } else if (*subopt
== 'f') {
283 errexit("-o %c option?\n", *subopt
);
296 if (argv
[0][1] != '\0') {
297 bflag
= atoi(argv
[0] + 1);
299 bflag
= atoi(*++argv
);
302 msgprintf("Alternate super block location: %d\n", bflag
);
309 /* who knows? defined, but doesn't do much */
313 case 'w': /* check writable only */
320 if (!isdigit(argv
[1][0]))
321 errexit("-l flag requires a number\n");
322 maxrun
= atoi(*++argv
);
325 #if !defined(AFS_HPUX100_ENV)
327 if (!isdigit(argv
[1][0]))
328 errexit("-m flag requires a mode\n");
329 sscanf(*++argv
, "%o", &lfmode
);
331 errexit("bad mode to -m: %o\n", lfmode
);
333 printf("** lost+found creation mode %o\n", lfmode
);
335 #endif /* AFS_HPUX100_ENV */
336 #endif /* AFS_SUN5_ENV */
341 #endif /* AFS_OSF_ENV */
349 * NOTE: -q flag is used only by HPux fsck versions but we add it for all systems since
350 * it's general/useful flag to use.
363 errexit("%c option?\n", **argv
);
367 * The following checks were only available on hpux but are useful to all systems.
370 errexit("Incompatible options: -n and -p\n");
372 errexit("Incompatible options: -n and -q\n");
375 rflag
++; /* check raw devices */
377 if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
378 (void)signal(SIGINT
, catch);
380 (void)signal(SIGQUIT
, catchquit
);
385 if (wflag
&& !writable(*argv
)) {
386 (void)fprintf(stderr
, "not writable '%s'\n", *argv
);
390 checkfilesys(*argv
++, NULL
);
405 if (fstype
== NULL
|| strcmp(fstype
, MNTTYPE_UFS
) == 0) {
408 if ((fd
= fopen(VFSTAB
, "r")) == NULL
) {
409 errexit("vfsck: cannot open vfstab\n");
411 while ((ret
= getvfsent(fd
, &vget
)) == 0) {
412 if (strcmp(vget
.vfs_fstype
, MNTTYPE_UFS
)
413 && numbers(vget
.vfs_fsckpass
)) {
417 if (numbers(vget
.vfs_fsckpass
))
418 passno
= atoi(vget
.vfs_fsckpass
);
423 if (preen
== 0 || passno
== 1) {
424 checkfilesys(vget
.vfs_fsckdev
, get
.vfs_mountp
);
425 } else if (passno
> 1) {
426 addpart(vget
.vfs_fsckdev
, vget
.vfs_special
);
430 for (passno
= 1; passno
<= 2; passno
++) {
432 errexit("Can't open checklist file: %s\n", FSTAB
);
433 while ((fsp
= getfsent()) != 0) {
434 if (strcmp(fsp
->fs_type
, FSTAB_RW
)
435 && strcmp(fsp
->fs_type
, FSTAB_RO
)
436 && strcmp(fsp
->fs_type
, FSTAB_RQ
))
439 if (strcmp(fsp
->fs_vfstype
, "ufs") || fsp
->fs_passno
== 0) {
442 #endif /* AFS_OSF_ENV */
443 if (preen
== 0 || passno
== 1 && fsp
->fs_passno
== 1) {
445 name
= blockcheck(fsp
->fs_spec
);
447 checkfilesys(name
, fsp
->fs_file
);
449 printf("pid %d exiting 8/1\n", getpid());
453 } else if (passno
== 2 && fsp
->fs_passno
> 1) {
454 name
= blockcheck(fsp
->fs_spec
);
456 pwarn("BAD DISK NAME %s\n", fsp
->fs_spec
);
458 printf("pid %d saw bad disk name 8/3\n", getpid());
461 addpart(name
, fsp
->fs_file
);
464 #endif /* AFS_SUN5_ENV */
474 for (passno
= 0; passno
< maxrun
; ++passno
) {
476 nextdisk
= nextdisk
->next
;
478 while ((pid
= wait(&status
)) != -1) {
479 for (dk
= disks
; dk
; dk
= dk
->next
)
483 printf("Unknown pid %d\n", pid
);
486 rc
= WEXITSTATUS(status
);
487 if (WIFSIGNALED(status
)) {
488 printf("%s (%s): EXITED WITH SIGNAL %d\n", dk
->part
->name
,
489 dk
->part
->fsname
, WTERMSIG(status
));
495 badnext
= &dk
->part
->next
;
496 dk
->part
= dk
->part
->next
;
499 dk
->part
= dk
->part
->next
;
502 if (dk
->part
== NULL
)
505 if (nextdisk
== NULL
) {
508 } else if (nrun
< maxrun
&& nrun
< ndisks
) {
510 if ((nextdisk
= nextdisk
->next
) == NULL
)
512 if (nextdisk
->part
!= NULL
&& nextdisk
->pid
== 0)
521 printf("pid %d exiting 8/2\n", getpid());
524 printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
525 badlist
->next
? "S" : "", "UNEXPECTED INCONSISTENCY:");
526 for (pt
= badlist
; pt
; pt
= pt
->next
)
527 printf("%s (%s)%s", pt
->name
, pt
->fsname
, pt
->next
? ", " : "\n");
537 #endif /* !AFS_SUN5_ENV */
545 struct disk
*dk
, **dkp
;
549 for (p
= name
+ strlen(name
) - 1; p
>= name
; --p
)
557 for (dk
= disks
, dkp
= &disks
; dk
; dkp
= &dk
->next
, dk
= dk
->next
) {
558 if (strncmp(dk
->name
, name
, len
) == 0 && dk
->name
[len
] == 0)
561 if ((*dkp
= malloc(sizeof(struct disk
))) == NULL
)
562 errexit("out of memory");
564 if ((dk
->name
= strdup(name
)) == NULL
)
565 errexit("out of memory");
573 addpart(name
, fsname
)
576 struct disk
*dk
= finddisk(name
);
577 struct part
*pt
, **ppt
= &dk
->part
;
579 for (pt
= dk
->part
; pt
; ppt
= &pt
->next
, pt
= pt
->next
)
580 if (strcmp(pt
->name
, name
) == 0) {
581 printf("%s in fstab more than once!\n", name
);
584 if ((*ppt
= malloc(sizeof(struct part
))) == NULL
)
585 errexit("out of memory");
587 if ((pt
->name
= strdup(name
)) == NULL
)
588 errexit("out of memory");
589 if ((pt
->fsname
= strdup(fsname
)) == NULL
)
590 errexit("out of memory");
605 (void)signal(SIGQUIT
, voidquit
);
606 checkfilesys(dk
->part
->name
, dk
->part
->fsname
);
611 checkfilesys(filesys
, parname
)
614 daddr_t n_ffree
, n_bfree
;
616 struct stat tstat
; /* for ultrix 3 unmount */
623 #endif /* AFS_OSF_ENV */
633 ge_danger
= 0; /* set to 1 by any table overflow or more
634 * dup/bad blocks than expected */
636 fixed
= 1; /* set to 0 by any 'no' reply */
638 strcpy(devbuffer
, filesys
); /* copy the file system name to the device buffer */
639 devname
= devbuffer
; /* remember generic ptr for later */
640 EnsureDevice(devname
); /* canonicalize name */
644 ret_val
= setup(devname
);
652 pfatal("CAN'T CHECK FILE SYSTEM.");
654 if ((exitstat
== 0) && (mflag
))
660 } else if (ret_val
== -1) { /* pclean && FS_CLEAN */
663 #if defined(AFS_OSF_ENV)
664 } else if (ret_val
== FS_CLEAN
) { /* pclean && FS_CLEAN */
668 #if defined(AFS_HPUX100_ENV)
670 check_sanity(filesys
);
675 check_sanity(filesys
);
683 * 1: scan inodes tallying blocks used
686 #if defined(AFS_SUN5_ENV)
688 msgprintf("** Currently Mounted on %s\n", sblock
.fs_fsmnt
);
691 msgprintf("** Last Mounted on %s\n", sblock
.fs_fsmnt
);
693 msgprintf("** Root file system\n");
696 printf("** Phase 1 - Sanity Check only\n");
700 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
705 * 1b: locate first references to duplicates, if any
709 pfatal("INTERNAL ERROR: dups with -p");
710 msgprintf("** Phase 1b - Rescan For More DUPS\n");
715 * 2: traverse directories from root to mark all connected directories
718 msgprintf("** Phase 2 - Check Pathnames\n");
722 * 3: scan inodes looking for disconnected directories
725 msgprintf("** Phase 3 - Check Connectivity\n");
729 * 4: scan inodes looking for disconnected files; check reference counts
732 msgprintf("** Phase 4 - Check Reference Counts\n");
736 * 5: check and repair resource counts in cylinder groups
739 msgprintf("** Phase 5 - Check Cyl groups\n");
742 #if defined(AFS_SUN_ENV)
748 * print out summary statistics
750 n_ffree
= sblock
.fs_cstotal
.cs_nffree
;
751 n_bfree
= sblock
.fs_cstotal
.cs_nbfree
;
753 #if defined(ACLS) && defined(AFS_HPUX_ENV)
754 pinfo("%d files, %d icont, %d used, %d free", n_files
, n_cont
, n_blks
,
755 n_ffree
+ sblock
.fs_frag
* n_bfree
);
757 pinfo("%d files, %d used, %d free", n_files
, n_blks
,
758 n_ffree
+ sblock
.fs_frag
* n_bfree
);
761 msgprintf(", %d AFS files", nViceFiles
);
762 msgprintf(" (%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree
,
763 n_bfree
, (float)(n_ffree
* 100) / sblock
.fs_dsize
);
765 #if defined(ACLS) && defined(AFS_HPUX_ENV)
766 pinfo("%d files, %d icont, %d used, %d free ", n_files
, n_cont
, n_blks
,
767 n_ffree
+ sblock
.fs_frag
* n_bfree
);
769 pinfo("%d files, %d used, %d free ", n_files
, n_blks
,
770 n_ffree
+ sblock
.fs_frag
* n_bfree
);
772 n
printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", n_ffree
,
773 n_bfree
, (float)(n_ffree
* 100) / sblock
.fs_dsize
);
775 if (debug
&& (n_files
-= maxino
- ROOTINO
- sblock
.fs_cstotal
.cs_nifree
))
776 msgprintf("%d files missing\n", n_files
);
778 n_blks
+= sblock
.fs_ncg
* (cgdmin(&sblock
, 0) - cgsblock(&sblock
, 0));
779 n_blks
+= cgsblock(&sblock
, 0) - cgbase(&sblock
, 0);
780 n_blks
+= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
781 if (n_blks
-= maxfsblock
- (n_ffree
+ sblock
.fs_frag
* n_bfree
))
782 printf("%d blocks missing\n", n_blks
);
783 if (duplist
!= NULL
) {
784 msgprintf("The following duplicate blocks remain:");
785 for (dp
= duplist
; dp
; dp
= dp
->next
)
786 msgprintf(" %d,", dp
->dup
);
789 if (zlnhead
!= NULL
) {
790 msgprintf("The following zero link count inodes remain:");
791 for (zlnp
= zlnhead
; zlnp
; zlnp
= zlnp
->next
)
792 msgprintf(" %d,", zlnp
->zlncnt
);
797 /* if user's specification denotes that the file system block
798 * is going to be modified (nflag == 0) then fsck store the
799 * correct magic number in the super block if it is not already
802 if (!nflag
&& !(fswritefd
< 0)) {
804 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
808 if (fixed
&& (sblock
.fs_clean
!= FS_CLEAN
)) {
809 if (!preen
&& !qflag
)
810 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
811 sblock
.fs_clean
= FS_CLEAN
;
815 /* fix FS_CLEAN if changes made and no 'no' replies */
816 if (fsmodified
&& fixed
)
817 sblock
.fs_clean
= FS_CLEAN
;
819 * Fix fs_clean if there were no 'no' replies.
820 * This is done for both the s300 and s800. The s800 root will be
821 * guaranteed clean as of 7.0.
823 if (fixed
&& (sblock
.fs_clean
!= FS_OK
)) {
824 if (!preen
&& !qflag
)
825 printf("***** MARKING FILE SYSTEM CLEAN *****\n");
826 sblock
.fs_clean
= FS_CLEAN
;
836 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV) /* WAS AFS_SUN5_ENV */
844 if (hotroot
&& sblock
.fs_clean
== FSACTIVE
)
847 else if (!((sblock
.fs_state
+ (afs_int32
) sblock
.fs_time
== FSOKAY
) &&
849 else if (!((fs_get_state(&sblock
) + (afs_int32
) sblock
.fs_time
== FSOKAY
)
852 (sblock
.fs_clean
== FSCLEAN
|| sblock
.fs_clean
== FSSTABLE
))) {
853 if (yflag
|| !iscorrupt
) {
854 printf("%s FILE SYSTEM STATE SET TO OKAY\n", devname
);
857 printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n", devname
);
862 (void)time(&sblock
.fs_time
);
864 if (hotroot
&& rebflg
)
865 sblock
.fs_clean
= FSACTIVE
;
867 sblock
.fs_clean
= FSSTABLE
;
869 sblock
.fs_state
= FSOKAY
- (afs_int32
) sblock
.fs_time
;
871 fs_set_state(&sblock
, FSOKAY
- (afs_int32
) sblock
.fs_time
);
878 if (!nflag
&& !bflag
&& !hotroot
) {
880 sblock
.fs_clean
= FS_CLEAN
;
881 (void)time(&sblock
.fs_time
);
883 flush(fswritefd
, &sblk
);
886 #else /* AFS_OSF_ENV */
888 (void)time(&sblock
.fs_time
);
898 blockmap
= statemap
= NULL
;
906 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
909 msgprintf("\n***** REBOOT UNIX *****\n");
912 if (mountedfs
|| hotroot
) {
930 (void)close(fsreadfd
);
931 (void)close(fswritefd
);
932 if (nViceFiles
|| tryForce
) {
933 /* Modified file system with vice files: force full salvage */
934 /* Salvager recognizes the file FORCESALVAGE in the root of each partition */
935 struct ufs_args ufsargs
;
937 char pname
[100], fname
[100], *special
;
938 int fd
, code
, failed
= 0;
941 ("%s: AFS file system partition was modified; forcing full salvage\n",
943 devname
= unrawname(devname
);
944 special
= (char *)strrchr(devname
, '/');
947 strcpy(pname
, "/etc/vfsck."); /* Using /etc, rather than /tmp, since
948 * /tmp is a link to /usr/tmp on some systems, and isn't mounted now */
949 strcat(pname
, special
);
951 /* if system mounted / as read-only, we'll try to fix now */
952 if (access("/", W_OK
) < 0 && errno
== EROFS
) {
953 code
= system("mount -o remount /");
955 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
962 /* if system mounted / as read-only, we'll try to fix now */
963 if (access("/", W_OK
) < 0 && errno
== EROFS
) {
964 printf("Can't RW acceess /; %d\n", errno
);
965 code
= system("/sbin/mount -u /");
967 printf("Couldn't remount / R/W; continuing anyway (%d).\n",
975 if (mkdir(pname
, 0777) < 0) {
976 if (errno
!= EEXIST
) {
977 perror("fsck mkdir");
981 if (failed
&& parname
) {
982 strcpy(pname
, parname
);
984 #if !defined(AFS_HPUX_ENV)
986 ufsargs
.flags
= UFSMNT_NOINTR
;
988 ufsargs
.fspec
= devname
;
992 (devname
, pname
, MS_DATA
, "ufs", (char *)&ufsargs
,
993 sizeof(ufsargs
)) < 0) {
995 if (mount(MOUNT_UFS
, pname
, 0, &ufsargs
) < 0) {
998 if (mount(devname
, pname
, 0) < 0) {
1001 ("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n",
1002 devname
, pname
, errno
);
1004 strcpy(fname
, pname
);
1005 strcat(fname
, "/FORCESALVAGE");
1006 fd
= open(fname
, O_CREAT
, 0);
1008 errexit("Couldn't create %s to force full salvage!\n", fname
);
1013 #if !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1016 #if defined(AFS_OSF_ENV)
1017 umount(pname
, MNT_NOFORCE
);
1018 #else /* AFS_OSF_ENV */
1026 fsync(fileno(logfile
)); /* Since update isn't running */
1038 struct stat stslash
, stblock
, stchar
;
1043 if (stat("/", &stslash
) < 0) {
1045 printf("Can't stat root\n");
1049 if (stat(name
, &stblock
) < 0) {
1051 printf("Can't stat %s\n", name
);
1054 if ((stblock
.st_mode
& S_IFMT
) == S_IFBLK
) {
1055 if (stslash
.st_dev
== stblock
.st_rdev
) {
1057 #if !defined(AFS_OSF_ENV) /* OSF/1 always uses the raw device, even for / */
1059 #endif /* AFS_OSF_ENV */
1061 raw
= rawname(name
);
1065 printf("Cannot find character device for %s\n", name
);
1068 } else if ((stblock
.st_mode
& S_IFMT
) == S_IFCHR
&& !retried
) {
1069 name
= unrawname(name
);
1073 printf("Can't make sense out of name %s\n", name
);
1078 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1082 * exit 0 - file system is unmounted and okay
1083 * exit 32 - file system is unmounted and needs checking
1084 * exit 33 - file system is mounted for root file system
1085 * exit 34 - cannot stat device
1087 check_sanity(filename
)
1090 struct stat stbd
, stbr
;
1093 struct vfstab vfsbuf
;
1099 if (stat(filename
, &stbd
) < 0) {
1100 fprintf(stderr
, "ufs fsck: sanity check failed : cannot stat %s\n",
1105 if ((stbd
.st_mode
& S_IFMT
) == S_IFBLK
)
1107 else if ((stbd
.st_mode
& S_IFMT
) == S_IFCHR
)
1111 "ufs fsck: sanity check failed: %s not block or character device\n",
1116 * Determine if this is the root file system via vfstab. Give up
1117 * silently on failures. The whole point of this is not to care
1118 * if the root file system is already mounted.
1120 * XXX - similar for /usr. This should be fixed to simply return
1121 * a new code indicating, mounted and needs to be checked.
1123 if ((vfstab
= fopen(VFSTAB
, "r")) != 0) {
1124 if (getvfsfile(vfstab
, &vfsbuf
, "/") == 0) {
1126 devname
= vfsbuf
.vfs_special
;
1128 devname
= vfsbuf
.vfs_fsckdev
;
1129 if (stat(devname
, &stbr
) == 0)
1130 if (stbr
.st_rdev
== stbd
.st_rdev
)
1133 if (getvfsfile(vfstab
, &vfsbuf
, "/usr") == 0) {
1135 devname
= vfsbuf
.vfs_special
;
1137 devname
= vfsbuf
.vfs_fsckdev
;
1138 if (stat(devname
, &stbr
) == 0)
1139 if (stbr
.st_rdev
== stbd
.st_rdev
)
1144 /* XXX - only works if filename is a block device or if
1145 * character and block device has the same dev_t value */
1146 if (is_root
== 0 && is_usr
== 0 && ustat(stbd
.st_rdev
, &usb
) == 0) {
1147 fprintf(stderr
, "ufs fsck: sanity check: %s already mounted\n",
1152 * We mount the ufs root file system read-only first. After fsck
1153 * runs, we remount the root as read-write. Therefore, we no longer
1154 * check for different values for fs_state between the root file
1155 * system and the rest of file systems.
1157 if (!((sblock
.fs_state
+ (time_t) sblock
.fs_time
== FSOKAY
)
1158 && (sblock
.fs_clean
== FSCLEAN
|| sblock
.fs_clean
== FSSTABLE
))) {
1159 fprintf(stderr
, "ufs fsck: sanity check: %s needs checking\n",
1163 fprintf(stderr
, "ufs fsck: sanity check: %s okay\n", filename
);
1168 #if defined(AFS_HPUX100_ENV)
1169 check_sanity(filename
)
1172 struct stat stbd
, stbr
;
1181 if (stat(filename
, &stbd
) < 0) {
1182 fprintf(stderr
, "hfs fsck: sanity check failed : cannot stat %s\n",
1187 if ((stbd
.st_mode
& S_IFMT
) == S_IFBLK
)
1189 else if ((stbd
.st_mode
& S_IFMT
) == S_IFCHR
)
1193 "hfs fsck: sanity check failed: %s not block or character device\n",
1198 * Determine if this is the root file system via vfstab. Give up
1199 * silently on failures. The whole point of this is not to care
1200 * if the root file system is already mounted.
1202 * XXX - similar for /usr. This should be fixed to simply return
1203 * a new code indicating, mounted and needs to be checked.
1205 if ((vfstab
= setmntent(FSTAB
, "r")) != 0) {
1206 while (mnt
= getmntent(vfstab
)) {
1207 if (!strcmp(mnt
->mnt_dir
, "/"))
1208 if (stat(mnt
->mnt_fsname
, &stbr
) == 0)
1209 if (stbr
.st_rdev
== stbd
.st_rdev
)
1212 if (!strcmp(mnt
->mnt_dir
, "/usr"))
1213 if (stat(mnt
->mnt_fsname
, &stbr
) == 0)
1214 if (stbr
.st_rdev
== stbd
.st_rdev
)
1220 /* XXX - only works if filename is a block device or if
1221 * character and block device has the same dev_t value */
1222 if (is_root
== 0 && is_usr
== 0 && ustat(stbd
.st_rdev
, &usb
) == 0) {
1223 fprintf(stderr
, "hfs fsck: sanity check: %s already mounted\n",
1228 * We mount the ufs root file system read-only first. After fsck
1229 * runs, we remount the root as read-write. Therefore, we no longer
1230 * check for different values for fs_state between the root file
1231 * system and the rest of file systems.
1233 if (!((sblock
.fs_clean
== FS_CLEAN
|| sblock
.fs_clean
== FS_OK
))) {
1234 fprintf(stderr
, "hfs fsck: sanity check: %s needs checking\n",
1238 fprintf(stderr
, "hfs fsck: sanity check: %s okay\n", filename
);
1242 /* see if all numbers */
1248 while ('0' <= *yp
&& *yp
<= '9')
1256 /* Convert a raw device name into a block device name.
1257 * If the block device is not found, return the raw device name.
1258 * For HP and SUN, the returned value is not changed. For other
1259 * platforms it is changed (I see no rhyme or reason -jpm).
1265 static char bldev
[256];
1266 struct stat statbuf
;
1269 code
= stat(rawdev
, &statbuf
);
1270 if ((code
< 0) || !S_ISCHR(statbuf
.st_mode
))
1271 return (rawdev
); /* Not a char device */
1273 for (i
= strlen(rawdev
) - 2; i
>= 0; i
--) {
1274 if ((rawdev
[i
] == '/') && (rawdev
[i
+ 1] == 'r')) {
1275 strcpy(bldev
, rawdev
);
1277 strcat(bldev
, &rawdev
[i
+ 2]);
1279 code
= stat(bldev
, &statbuf
); /* test for block device */
1280 if (!code
&& S_ISBLK(statbuf
.st_mode
)) {
1281 #if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1284 strcpy(rawdev
, bldev
); /* Replace */
1293 /* Convert a block device name into a raw device name.
1294 * If the block device is not found, return null
1300 static char rawdev
[256];
1301 struct stat statbuf
;
1304 for (i
= strlen(bldev
) - 1; i
>= 0; i
--) {
1305 if (bldev
[i
] == '/') {
1306 strcpy(rawdev
, bldev
);
1307 rawdev
[i
+ 1] = 'r';
1309 strcat(rawdev
, &bldev
[i
+ 1]);
1311 code
= stat(rawdev
, &statbuf
);
1312 if (!code
&& S_ISCHR(statbuf
.st_mode
))