Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / vfsck / main.c
1 /*
2  * Copyright (c) 1980, 1986 The Regents of the University of California.
3  * All rights reserved.
4  *
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.
16  */
17
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23
24 #ifndef lint
25 static char sccsid[] = "@(#)main.c      5.17 (Berkeley) 2/1/90";
26 #endif /* not lint */
27
28 #include <afs/param.h>
29 #define VICE    /* allow us to put our changes in at will */
30 #include <stdio.h>
31
32 #include <sys/param.h>
33 #include <sys/time.h>
34
35 #ifdef AFS_SUN_ENV
36 #define KERNEL
37 #endif /* AFS_SUN_ENV */
38 #include <sys/mount.h>
39 #ifdef AFS_SUN_ENV
40 #undef KERNEL
41 #endif
42
43 #include <sys/file.h>
44
45 #ifdef  AFS_OSF_ENV
46 #include <sys/vnode.h>
47 #include <sys/mount.h>
48 #include <ufs/inode.h>
49 #include <ufs/fs.h>
50 #else   /* AFS_OSF_ENV */
51 #ifdef AFS_VFSINCL_ENV
52 #define VFS
53 #include <sys/vnode.h>
54 #ifdef    AFS_SUN5_ENV
55 #include <unistd.h>
56 #include <sys/fs/ufs_inode.h>
57 #include <sys/fs/ufs_fs.h>
58 #define _KERNEL
59 #include <sys/fs/ufs_fsdir.h>
60 #undef _KERNEL
61 #include <sys/fs/ufs_mount.h>
62 #else
63 #include <ufs/inode.h>
64 #include <ufs/fs.h>
65 #define KERNEL
66 #include <ufs/fsdir.h>
67 #undef KERNEL
68 #endif
69 #else /* AFS_VFSINCL_ENV */
70
71 #include <sys/inode.h>
72 #ifdef  AFS_HPUX_ENV
73 #include <ctype.h>
74 #define LONGFILENAMES   1
75 #include <sys/sysmacros.h>
76 #include <sys/ino.h>
77 #define DIRSIZ_MACRO
78 #include <ndir.h>
79 #else
80 #define KERNEL
81 #include <sys/dir.h>
82 #undef KERNEL
83 #endif
84 #include <sys/fs.h>
85 #endif /* AFS_VFSINCL_ENV */
86 #endif  /* AFS_OSF_ENV */
87
88 #ifdef AFS_DEC_ENV
89 #include <sys/fs_types.h>
90 #endif
91
92 #include <sys/stat.h>
93 #include <sys/wait.h>
94 #ifdef  AFS_SUN5_ENV
95 #include <string.h>
96 #else
97 #include <strings.h>
98 #endif
99 #include <ctype.h>
100 #ifdef  XAFS_SUN_ENV
101 #include <mntent.h>
102 #else
103 #ifdef  AFS_SUN5_ENV
104 #include <sys/mnttab.h>
105 #include <sys/mntent.h>
106 #include <sys/vfstab.h>
107 #include <sys/ustat.h>
108 #else
109 #include <fstab.h>
110 #endif
111 #endif  
112 #include "fsck.h"
113 #include <errno.h>
114 #include <sys/signal.h>
115
116 char    *rawname(), *unrawname(), *blockcheck(), *malloc();
117 void    catch(), catchquit(), voidquit();
118 static  int tryForce;
119 int     returntosingle;
120
121 extern int errno;
122
123 struct part {
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;
128
129 struct disk {
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 */
134 } *disks;
135
136 int     nrun, ndisks, maxrun, wflag=0;
137 #ifdef  AFS_HPUX_ENV
138 int fixed;
139 #endif
140
141 #if     defined(AFS_HPUX100_ENV)
142 #include <ustat.h>
143 #include <mntent.h>
144 #endif 
145
146 #ifdef VICE
147 #define msgprintf   vfscklogprintf
148 #else /* VICE */
149 #define msgprintf   printf
150 #endif /* VICE */
151
152 #ifdef  AFS_SUN5_ENV
153 int     mnt_passno = 0;
154 #endif
155
156 #include "AFS_component_version_number.c"
157
158 #ifdef  AFS_HPUX_ENV
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. */
164 #endif
165
166 main(argc, argv)
167         int     argc;
168         char    *argv[];
169 {
170         struct fstab *fsp;
171         int pid, passno, sumstatus;
172         char *name;
173         register struct disk *dk, *nextdisk;
174         register struct part *pt;
175         extern   char*  AFSVersion;  /* generated version */
176 #ifdef  AFS_SUN5_ENV
177         int other_than_ufs=0;
178         char *subopt;
179         struct vfstab vt;
180         FILE *vfile;
181         int ret;
182         struct vfstab vget;
183         FILE *fd;
184 #endif
185
186         sync();
187         tryForce = 0;
188 #if     defined(AFS_HPUX_ENV) 
189         pclean = 0;
190 #endif
191 #if     defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
192         fflag = 0;
193 #endif
194 #ifdef  AFS_SUN5_ENV
195         fsflag = oflag = mflag = exitstat = 0;
196 #endif
197 #if     defined(AFS_HPUX100_ENV)
198         mflag = 0;
199 #endif
200         printf("----Transarc AFS (R) %s fsck----\n", AFSVersion); /* generated version */
201         if (access("/TRYFORCE", 0) == 0)
202             tryForce = 1;
203         while (--argc > 0 && **++argv == '-') {
204                 switch (*++*argv) {
205
206 #if     defined(AFS_HPUX_ENV) 
207 #if     defined(AFS_HPUX100_ENV)
208                 case 'f':       /* default yes to answer force to check */
209                     fflag++;
210                     break;
211 #else  /* AFS_HPUX100_ENV */
212 #ifdef  AFS_HPUX_ENV
213                 case 'F':       /* default yes to answer force to check */
214                     fflag++;
215                     break;
216 #endif /* AFS_HPUX_ENV */
217 #endif /* AFS_HPUX100_ENV */
218                 case 'P':
219                         pclean++;
220                         preen++;
221                         break;              
222 #endif
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.
229                      */
230                 case 'p':
231                     only_when_needed++;
232                 /* P is for Ultrix compatibility */
233                 case 'P':
234 #else
235                 case 'p':
236 #endif
237                         preen++;
238                         break;
239 #if     defined(AFS_HPUX100_ENV)
240                 case 'V':
241                     {
242                     int opt_count;
243                     char        *opt_text;
244
245                     (void) fprintf (stdout, "fsck -F hfs ");
246                     for (opt_count = 1; opt_count < argc ; opt_count++) {
247                         opt_text = argv[opt_count];
248                         if (opt_text)
249                             (void) fprintf (stdout, " %s ", opt_text);
250                     }
251                     (void) fprintf (stdout, "\n");
252                     exit(0);
253                     }
254                     break;
255                 case 'm':
256                     mflag++;
257                     break;
258 #endif
259 #ifdef  AFS_SUN5_ENV
260                 case 'V':
261                     {
262                     int opt_count;
263                     char        *opt_text;
264
265                     (void) fprintf (stdout, "fsck -F ufs ");
266                     for (opt_count = 1; opt_count < argc ; opt_count++) {
267                         opt_text = argv[opt_count];
268                         if (opt_text)
269                             (void) fprintf (stdout, " %s ", opt_text);
270                     }
271                     (void) fprintf (stdout, "\n");
272                     }
273                     break;
274
275                 case 'o':
276                     subopt = *++argv;
277                     argc--;
278                     while (*subopt != '\0') {
279                         if (*subopt == 'p') {
280                             preen++;
281                             break;
282                         } else if (*subopt == 'b') {
283                             if (argv[0][1] != '\0') {
284                                 bflag = atoi(argv[0]+1);
285                             } else {
286                                 bflag = atoi(*++argv);
287                                 argc--;
288                             }
289                             msgprintf("Alternate super block location: %d\n", bflag);
290                             break;                          
291                         } else if (*subopt == 'd') {
292                             debug++;
293                             break;
294                         } else if (*subopt == 'r') {
295                             break;
296                         } else if (*subopt == 'w') {
297                             wflag++;
298                             break;
299                         } else if (*subopt == 'c') {
300                             cvtflag++;
301                             break;
302                         } else if (*subopt == 'f') {
303                             fflag++;
304                             break;                          
305                         } else {
306                             errexit("-o %c option?\n", *subopt);
307                         }
308                         subopt++;
309                         ++argv;
310                         argc--;
311                     }
312                     oflag++;
313                     break;
314                 case 'm':
315                     mflag++;
316                     break;
317 #else
318                 case 'b':
319                         if (argv[0][1] != '\0') {
320                                 bflag = atoi(argv[0]+1);
321                         } else {
322                                 bflag = atoi(*++argv);
323                                 argc--;
324                         }
325                         msgprintf("Alternate super block location: %d\n", bflag);
326                         break;
327
328                 case 'c':
329                         cvtflag++;
330                         break;
331
332                         /* who knows?  defined, but doesn't do much */
333                 case 'r':
334                         break;
335
336                 case 'w':       /* check writable only */
337                         wflag++;
338                         break;
339                 case 'd':
340                         debug++;
341                         break;
342                 case 'l':
343                         if (!isdigit(argv[1][0]))
344                                 errexit("-l flag requires a number\n");
345                         maxrun = atoi(*++argv);
346                         argc--;
347                         break;
348 #if     !defined(AFS_HPUX100_ENV)
349                 case 'm':
350                         if (!isdigit(argv[1][0]))
351                                 errexit("-m flag requires a mode\n");
352                         sscanf(*++argv, "%o", &lfmode);
353                         if (lfmode &~ 07777)
354                                 errexit("bad mode to -m: %o\n", lfmode);
355                         argc--;
356                         printf("** lost+found creation mode %o\n", lfmode);
357                         break;
358 #endif /* AFS_HPUX100_ENV */
359 #endif  /* AFS_SUN5_ENV */
360 #ifdef  AFS_OSF_ENV
361                 case 'o':
362                         fflag++;
363                         break;
364 #endif  /* AFS_OSF_ENV */
365                 case 'n':
366                 case 'N':
367                         nflag++;
368                         yflag = 0;
369                         break;
370
371                 /*
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.
374                  */
375                 case 'q':
376                         qflag++;
377                         break;
378
379                 case 'y':
380                 case 'Y':
381                         yflag++;
382                         nflag = 0;
383                         break;
384
385                 default:
386                         errexit("%c option?\n", **argv);
387                 }
388         }
389         /*
390          * The following checks were only available on hpux but are useful to all systems.
391          */
392         if (nflag && preen)
393                 errexit("Incompatible options: -n and -p\n");
394         if (nflag && qflag)
395                 errexit("Incompatible options: -n and -q\n");
396
397 #ifdef  AFS_SUN5_ENV
398         rflag++;        /* check raw devices */
399 #endif
400         if (signal(SIGINT, SIG_IGN) != SIG_IGN)
401                 (void)signal(SIGINT, catch);
402         if (preen)
403                 (void)signal(SIGQUIT, catchquit);
404         if (argc) {
405                 while (argc-- > 0) {
406                         hotroot = 0;
407 #ifdef  AFS_SUN5_ENV
408                         if (wflag && !writable(*argv)) {
409                                 (void) fprintf (stderr, "not writeable '%s'\n", *argv);
410                                 argv++;
411                         } else
412 #endif
413                         checkfilesys(*argv++, (char *)0);
414                 }
415 #ifdef  AFS_HPUX_ENV
416                 if (ge_danger)
417                         exit(-1);
418 #endif
419 #ifdef  AFS_SUN5_ENV
420                 exit(exitstat);
421 #else
422                 exit(0);
423 #endif
424         }
425 #ifndef AFS_SUN5_ENV
426         sumstatus = 0;
427 #ifdef  AFS_SUN5_ENV
428         if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
429             int status;
430
431             if ((fd = fopen(VFSTAB, "r")) == NULL) {
432                 errexit("vfsck: cannot open vfstab\n");
433             }
434             while ((ret = getvfsent(fd, &vget)) == 0) {
435                 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) &&  numbers(vget.vfs_fsckpass)) {
436                     other_than_ufs++;
437                     continue;
438                 }
439                 if (numbers(vget.vfs_fsckpass))
440                     passno = atoi(vget.vfs_fsckpass);
441                 else
442                     continue;
443                 if (passno < 1)
444                     continue;
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);
449                 }
450             }
451 #else
452         for (passno = 1; passno <= 2; passno++) {
453             if (setfsent() == 0)
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))
459                     continue;
460 #ifdef  AFS_DEC_ENV
461                         /* Only check local (i.e. ufs) file systems */
462                         if (strcmp(fsp->fs_name, "4.2") && strcmp(fsp->fs_name, "ufs"))
463                           continue;
464 #endif
465 #ifdef  AFS_OSF_ENV
466                 if (strcmp(fsp->fs_vfstype, "ufs") ||
467                     fsp->fs_passno == 0) {
468                     continue;
469                 }
470 #endif  /* AFS_OSF_ENV */
471                         if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
472                             if (passno == 1) {
473                                 name = blockcheck(fsp->fs_spec);
474                                 if (name != NULL) {
475                                         checkfilesys(name, fsp->fs_file);
476                                 } else if (preen) {
477                                     printf("pid %d exiting 8/1\n", getpid());
478                                     exit(8);
479                                 }
480                             }
481                         } else if (passno == 2 && fsp->fs_passno > 1) {
482                                 name = blockcheck(fsp->fs_spec);
483                                 if (name == NULL) {
484                                         pwarn("BAD DISK NAME %s\n",
485                                                 fsp->fs_spec);
486                                         sumstatus |= 8;
487                                         printf("pid %d saw bad disk name 8/3\n", getpid());
488                                         continue;
489                                 }
490                                 addpart(name, fsp->fs_file);
491                         }
492                 }
493 #endif  AFS_SUN5_ENV
494         }
495         if (preen) {
496                 int status, rc;
497
498                 if (maxrun == 0)
499                         maxrun = ndisks;
500                 if (maxrun > ndisks)
501                         maxrun = ndisks;
502                 nextdisk = disks;
503                 for (passno = 0; passno < maxrun; ++passno) {
504                         startdisk(nextdisk);
505                         nextdisk = nextdisk->next;
506                 }
507                 while ((pid = wait(&status)) != -1) {
508                         for (dk = disks; dk; dk = dk->next)
509                                 if (dk->pid == pid)
510                                         break;
511                         if (dk == 0) {
512                                 printf("Unknown pid %d\n", pid);
513                                 continue;
514                         }
515                         rc = WEXITSTATUS(status);
516                         if (WIFSIGNALED(status)) {
517                                 printf("%s (%s): EXITED WITH SIGNAL %d\n",
518                                         dk->part->name, dk->part->fsname,
519                                         WTERMSIG(status));
520                                 rc = 8;
521                         }
522                         if (rc != 0) {
523                                 sumstatus |= rc;
524                                 *badnext = dk->part;
525                                 badnext = &dk->part->next;
526                                 dk->part = dk->part->next;
527                                 *badnext = NULL;
528                         } else
529                                 dk->part = dk->part->next;
530                         dk->pid = 0;
531                         nrun--;
532                         if (dk->part == NULL)
533                                 ndisks--;
534
535                         if (nextdisk == NULL) {
536                                 if (dk->part)
537                                         startdisk(dk);
538                         } else if (nrun < maxrun && nrun < ndisks) {
539                                 for ( ;; ) {
540                                         if ((nextdisk = nextdisk->next) == NULL)
541                                                 nextdisk = disks;
542                                         if (nextdisk->part != NULL &&
543                                             nextdisk->pid == 0)
544                                                 break;
545                                 }
546                                 startdisk(nextdisk);
547                         }
548                 }
549         }
550         if (sumstatus) {
551                 if (badlist == 0) {
552                     printf("pid %d exiting 8/2\n", getpid());
553                     exit(8);
554                 }
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");
560                 exit(8);
561         }
562 #ifdef  AFS_SUN5_ENV
563         fclose(fd);
564 #else
565         (void)endfsent();
566 #endif
567         if (returntosingle)
568                 exit(2);
569 #endif  /* !AFS_SUN5_ENV */
570         exit(0);
571 }
572
573 struct disk *
574 finddisk(name)
575         char *name;
576 {
577         register struct disk *dk, **dkp;
578         register char *p;
579         int len;
580
581         for (p = name + strlen(name) - 1; p >= name; --p)
582                 if (isdigit(*p)) {
583                         len = p - name + 1;
584                         break;
585                 }
586         if (p < name)
587                 len = strlen(name);
588
589         for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
590                 if (strncmp(dk->name, name, len) == 0 &&
591                     dk->name[len] == 0)
592                         return (dk);
593         }
594         if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
595                 errexit("out of memory");
596         dk = *dkp;
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';
601         dk->part = NULL;
602         dk->next = NULL;
603         dk->pid = 0;
604         ndisks++;
605         return (dk);
606 }
607
608 addpart(name, fsname)
609         char *name, *fsname;
610 {
611         struct disk *dk = finddisk(name);
612         register struct part *pt, **ppt = &dk->part;
613
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);
617                         return;
618                 }
619         if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
620                 errexit("out of memory");
621         pt = *ppt;
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);
628         pt->next = NULL;
629 }
630
631 startdisk(dk)
632         register struct disk *dk;
633 {
634
635         nrun++;
636         dk->pid = fork();
637         if (dk->pid < 0) {
638                 perror("fork");
639                 exit(8);
640         }
641         if (dk->pid == 0) {
642                 (void)signal(SIGQUIT, voidquit);
643                 checkfilesys(dk->part->name, dk->part->fsname);
644                 exit(0);
645         }
646 }
647
648 checkfilesys(filesys, parname)
649         char *filesys;
650 {
651         daddr_t n_ffree, n_bfree;
652         struct dups *dp;
653         struct stat tstat;      /* for ultrix 3 unmount */
654         struct zlncnt *zlnp;
655         char devbuffer[128];
656         int ret_val;
657 #ifdef  AFS_DEC_ENV
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 */
661 #endif
662
663 #ifdef  AFS_OSF_ENV
664         int temp;
665 #endif  /* AFS_OSF_ENV */
666
667 #ifdef  AFS_SUN_ENV
668         iscorrupt = 1;
669 #endif
670 #ifdef  AFS_SUN5_ENV
671         mountedfs = 0;
672         isconvert = 0;
673 #endif
674 #ifdef  AFS_HPUX_ENV
675         ge_danger = 0;          /* set to 1 by any table overflow or more 
676                                    dup/bad blocks than expected */
677
678         fixed = 1;                      /* set to 0 by any 'no' reply */
679 #endif
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 */
683         if (debug && preen)
684                 pinfo("starting\n");
685 #ifdef  AFS_DEC_ENV
686         for (; retries > 0; retries--) {        /* 003 - Loop for NUMRETRIES or until clean */
687 #endif
688
689         ret_val = setup(devname);
690
691         if (ret_val == 0) {
692 #ifdef  AFS_SUN_ENV
693                 if (iscorrupt == 0)
694                         return;     
695 #endif
696                 if (preen)
697                         pfatal("CAN'T CHECK FILE SYSTEM.");
698 #ifdef  AFS_SUN5_ENV
699                 if ((exitstat == 0) && (mflag))
700                         exitstat = 32;
701                 exit(exitstat);
702 #endif
703                 return (0);
704 #ifdef  AFS_HPUX_ENV
705         }  else if (ret_val == -1 ) {   /* pclean && FS_CLEAN */
706                 return(1);
707 #endif
708 #if     defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV)
709         }  else if (ret_val == FS_CLEAN) { /* pclean && FS_CLEAN */
710             return(1);
711 #endif
712         }       
713 #if     defined(AFS_HPUX100_ENV)
714         if (mflag)
715             check_sanity(filesys);
716 #endif
717
718 #ifdef  AFS_SUN5_ENV
719         if (mflag)
720             check_sanity(filesys);
721         if (debug)
722             printclean();
723 #endif
724 #ifdef  AFS_SUN_ENV
725         iscorrupt = 0;
726 #endif
727         /*
728          * 1: scan inodes tallying blocks used
729          */
730         if (preen == 0) {
731 #if     defined(AFS_SUN5_ENV)
732                 if (mountedfs)
733                         msgprintf("** Currently Mounted on %s\n", sblock.fs_fsmnt);
734                 else
735 #endif
736                 msgprintf("** Last Mounted on %s\n", sblock.fs_fsmnt);
737                 if (hotroot)
738                         msgprintf("** Root file system\n");
739 #ifdef  AFS_SUN5_ENV
740                 if (mflag) {
741                         printf("** Phase 1 - Sanity Check only\n");
742                         return;
743                 } else
744 #endif
745                 msgprintf("** Phase 1 - Check Blocks and Sizes\n");
746         }
747         pass1();
748
749         /*
750          * 1b: locate first references to duplicates, if any
751          */
752         if (duplist) {
753                 if (preen)
754                         pfatal("INTERNAL ERROR: dups with -p");
755                 msgprintf("** Phase 1b - Rescan For More DUPS\n");
756                 pass1b();
757         }
758
759         /*
760          * 2: traverse directories from root to mark all connected directories
761          */
762         if (preen == 0)
763                 msgprintf("** Phase 2 - Check Pathnames\n");
764         pass2();
765
766         /*
767          * 3: scan inodes looking for disconnected directories
768          */
769         if (preen == 0)
770                 msgprintf("** Phase 3 - Check Connectivity\n");
771         pass3();
772
773         /*
774          * 4: scan inodes looking for disconnected files; check reference counts
775          */
776         if (preen == 0)
777                 msgprintf("** Phase 4 - Check Reference Counts\n");
778         pass4();
779
780         /*
781          * 5: check and repair resource counts in cylinder groups
782          */
783         if (preen == 0)
784                 msgprintf("** Phase 5 - Check Cyl groups\n");
785         pass5();
786
787 #ifdef  AFS_DEC_ENV
788         if (fsmodified || (sblk.b_dirty) || (cgblk.b_dirty)) {
789             fsdirty = 1;
790             if (hotroot)
791                 rootdirty = 1;
792             if (retries <= 1) {
793                 /*
794                  * 003 - Number of retry attempts have been
795                  * exhausted. Mark super block as dirty.
796                  */
797                 (void)time(&sblock.fs_time);
798                 sbdirty();
799             }
800         } else {
801             /*
802              * 003 - If checking root file system, and it was
803              * modified during any pass, don't assume it is ok. Must reboot.
804              */
805             if (rootdirty) {
806                 sbdirty();
807                 retries = 0;
808             } else {
809                 if ((!hotroot) && (!bflag) && (!nflag) && (!iscorrupt)) {
810                     sblock.fs_fmod = 0;
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;
816                     else
817                         sblock.fs_cleantimer =  sblock.fs_deftimer = FSCLEAN_TIMEOUTFACTOR;
818                     sbdirty();
819                 }
820                 /*
821                  * 006 - If an alternate super block was used,
822                  * we want to re fsck the partition after 
823                  * updating the primary super block.
824                  */
825                 if (!bflag)
826                     retries = 0;
827             }
828         }
829         /* Unless no updates are to be done, write out maps. */
830         if (nflag)
831             retries = 0;
832         else
833             ckfini();
834         if (debug) {
835             daddr_t nn_files = n_files;
836             daddr_t nn_blks = n_blks;
837
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);
847         }
848         if (duplist != NULL) {
849             if (debug) printf("The following duplicate blocks remain:");
850             for (dp = duplist; dp; dp = dp->next) {
851                 if (debug)
852                     printf(" %d,", dp->dup);
853                 free(dp);
854             }
855             if (debug)
856                 printf("\n");
857         }
858         if (zlnhead != NULL) {
859             if (debug)
860                 printf("The following zero link count inodes remain:");
861             for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) {
862                 if (debug)
863                     printf(" %d,", zlnp->zlncnt);
864                 free(zlnp);
865             }
866             if (debug)
867                 printf("\n");
868         }
869         zlnhead = (struct zlncnt *)0;
870         duplist = (struct dups *)0;
871
872         free(blockmap);
873         free(statemap);
874         free((char *)lncntp);
875         /* Print out retry message, and fsck file system again. */
876         if (retries > 1)
877             if (preen)          
878                 printf("%s: FILE SYSTEM MODIFIED, VERIFYING\n",filesys);
879             else
880                 printf("**** FILE SYSTEM MODIFIED, VERIFYING\n");
881         } /* for retries */
882 #endif
883
884 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
885         updateclean();
886         if (debug)
887                 printclean();
888 #endif
889         /*
890          * print out summary statistics
891          */
892         n_ffree = sblock.fs_cstotal.cs_nffree;
893         n_bfree = sblock.fs_cstotal.cs_nbfree;
894 #ifdef VICE
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);
898 #else
899         pinfo("%d files, %d used, %d free",
900             n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
901 #endif
902         if (nViceFiles)
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);
906 #else /* VICE */
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);
910 #else
911         pinfo("%d files, %d used, %d free ",
912             n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
913 #endif
914 n       printf("(%d frags, %d blocks, %.1f%% fragmentation)\n",
915             n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
916 #endif /* VICE */
917 #ifdef  AFS_DEC_ENV
918         if ((!fsdirty) && (!rootdirty))
919                 return;
920         if (!preen) {
921                 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
922                 if (hotroot)
923                         printf("\n***** HALT PROCESSOR WITHOUT SYNCING DISK *****\n");
924         }
925         if (hotroot) {
926                 sync();
927                 exit(4);
928         }
929 #else
930         if (debug &&
931             (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
932                 msgprintf("%d files missing\n", n_files);
933         if (debug) {
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);
944                         msgprintf("\n");
945                 }
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);
950                         msgprintf("\n");
951                 }
952         }
953 #endif
954 #ifdef  AFS_HPUX_ENV
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
958          * there
959          */
960         if (!nflag && !(fswritefd < 0)) {
961             if (ge_danger) {
962                 printf("***** FILE SYSTEM IS NOT CLEAN, FSCK AGAIN *****\n");
963                 fsmodified++;
964             } else {
965                 if (!hotroot) {
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;
970                         fsmodified++;
971                     }
972                 } else {
973                     /* fix FS_CLEAN if changes made and no 'no' replies */
974                     if (fsmodified && fixed)
975                         sblock.fs_clean = FS_CLEAN;
976                     /*
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.
980                      */
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;
985                         fsmodified++;
986                     }
987                 }
988             }
989         }
990 #endif
991         zlnhead = (struct zlncnt *)0;
992         duplist = (struct dups *)0;
993
994 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)          /* WAS AFS_SUN5_ENV */
995 #ifdef  notdef
996         inocleanup();
997 #endif
998         if (fsmodified)
999                 fixstate = 1;
1000         else
1001                 fixstate = 0;
1002         if (hotroot && sblock.fs_clean == FSACTIVE)
1003                 rebflg = 1;
1004 #ifdef  AFS_SUN5_ENV
1005         else if (!((sblock.fs_state + (afs_int32)sblock.fs_time == FSOKAY) &&
1006 #else
1007         else if (!((fs_get_state(&sblock) + (afs_int32)sblock.fs_time == FSOKAY) &&
1008 #endif
1009                 (sblock.fs_clean ==FSCLEAN || sblock.fs_clean ==FSSTABLE))) {
1010                 if (yflag || !iscorrupt) {
1011                         printf("%s FILE SYSTEM STATE SET TO OKAY\n",
1012                                 devname);
1013                         fixstate = 1;
1014                 } else {
1015                         printf("%s FILE SYSTEM STATE NOT SET TO OKAY\n",
1016                                 devname);
1017                         fixstate = 0;
1018                 }
1019         }
1020         if (fixstate) {
1021                 (void)time(&sblock.fs_time);
1022                 if (!iscorrupt) {
1023                         if (hotroot && rebflg)
1024                                 sblock.fs_clean = FSACTIVE;
1025                         else
1026                                 sblock.fs_clean = FSSTABLE;
1027 #ifdef  AFS_SUN5_ENV
1028                         sblock.fs_state = FSOKAY - (afs_int32)sblock.fs_time;
1029 #else
1030                         fs_set_state(&sblock, FSOKAY - (afs_int32)sblock.fs_time);
1031 #endif
1032                 }
1033                 sbdirty();
1034         }
1035 #else
1036 #ifdef  AFS_OSF_ENV
1037         if (!nflag && !bflag && !hotroot) {
1038             temp = fsmodified;
1039             sblock.fs_clean = FS_CLEAN;
1040             (void)time(&sblock.fs_time);
1041             sbdirty();
1042             flush(fswritefd, &sblk);
1043             fsmodified = temp;
1044         }
1045 #else   /* AFS_OSF_ENV */
1046         if (fsmodified) {
1047                 (void)time(&sblock.fs_time);
1048                 sbdirty();
1049         }
1050 #endif
1051 #endif
1052 #ifndef AFS_DEC_ENV
1053         ckfini();
1054         free(blockmap);
1055         free(statemap);
1056         free((char *)lncntp);
1057         lncntp = NULL;
1058         blockmap = statemap = NULL;
1059 #ifdef  AFS_SUN5_ENV
1060         if (iscorrupt)
1061             exitstat = 36;      
1062 #endif
1063         if (!fsmodified)
1064                 return;
1065         if (!preen) {
1066                 msgprintf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
1067
1068                 if (hotroot)
1069                         msgprintf("\n***** REBOOT UNIX *****\n");
1070         }
1071 #ifdef  AFS_SUN5_ENV
1072         if (mountedfs || hotroot) {
1073             exitstat = 40;
1074         }
1075 #endif
1076         if (hotroot) {
1077                 sync();
1078 #ifdef  AFS_HPUX_ENV
1079                 if (ge_danger)
1080                         exit(-1);
1081                 else
1082 #endif
1083                 exit(4);
1084         }
1085 #endif
1086 #ifdef VICE
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;
1094 #endif 
1095
1096             char pname[100], fname[100], *special;
1097             int fd, code, failed=0;
1098
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);
1106 #ifdef AFS_SUN_ENV
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 /");
1110                 if (code) {
1111                     printf("Couldn't remount / R/W; continuing anyway (%d).\n", errno);
1112                     failed = 1;
1113                 }
1114             }
1115 #endif
1116 #ifdef  AFS_OSF_ENV
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 /");
1121                 if (code) {
1122                     printf("Couldn't remount / R/W; continuing anyway (%d).\n", errno);
1123                     failed = 1;
1124                 }
1125             }
1126 #endif
1127             rmdir(pname);
1128             unlink(pname);
1129             if (mkdir(pname, 0777) < 0) {
1130                 if (errno != EEXIST) {
1131                     perror("fsck mkdir");
1132                     failed = 1;
1133                 }
1134             }
1135             if (failed && parname) {
1136                 strcpy(pname, parname);
1137             }
1138 #if !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV)
1139 #ifdef  AFS_SUN5_ENV
1140             ufsargs.flags = UFSMNT_NOINTR;
1141 #else
1142             ufsargs.fspec = devname;
1143 #endif
1144 #ifdef AFS_SUN_ENV
1145 #ifdef  AFS_SUN5_ENV
1146             if (mount(devname, pname, MS_DATA, "ufs", (char *)&ufsargs, sizeof(ufsargs)) < 0) {
1147 #else
1148             if (mount("4.2", pname, M_NEWTYPE, &ufsargs) < 0) {
1149 #endif
1150 #else
1151             if (mount(MOUNT_UFS, pname, 0, &ufsargs) < 0) {
1152 #endif
1153 #else 
1154 #ifdef AFS_DEC_ENV
1155             if (mount(devname, pname, 0, GT_ULTRIX, (char *) 0)) {
1156 #else 
1157             if (mount(devname, pname, 0) < 0) {
1158 #endif
1159 #endif          
1160                 printf("Couldn't mount %s on %s to force FULL SALVAGE; continuing anyway (%d)!\n", devname, pname, errno);
1161             } else {
1162                 strcpy(fname, pname);
1163                 strcat(fname, "/FORCESALVAGE");
1164                 fd = open(fname, O_CREAT, 0);
1165                 if (fd == -1) {
1166                     errexit("Couldn't create %s to force full salvage!\n", fname);
1167 #if defined(AFS_DEC_ENV)
1168                     stat(".", &tstat);
1169 #endif
1170                 } else {
1171                     fstat(fd, &tstat);
1172                     close(fd);
1173                 }
1174 #if /*defined(AFS_VFS_ENV) &&*/ !defined(AFS_DEC_ENV) && !defined(AFS_HPUX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_OSF_ENV)
1175                 unmount(pname);
1176 #else
1177 #if defined(AFS_DEC_ENV)
1178                 umount(tstat.st_dev);
1179 #else
1180 #if     defined(AFS_OSF_ENV)
1181                 umount(pname, MNT_NOFORCE);
1182 #else   /* AFS_OSF_ENV */
1183                 umount(devname);
1184 #endif
1185 #endif
1186 #endif
1187             }
1188             rmdir(pname);
1189         }
1190         if (logfile) {
1191             fsync(fileno(logfile)); /* Since update isn't running */
1192             fclose(logfile);
1193             logfile = 0;
1194         }
1195 #endif /* VICE */
1196
1197 }
1198
1199 char *
1200 blockcheck(name)
1201         char *name;
1202 {
1203         struct stat stslash, stblock, stchar;
1204         char *raw;
1205         int retried = 0;
1206
1207         hotroot = 0;
1208         if (stat("/", &stslash) < 0) {
1209                 perror("/");
1210                 printf("Can't stat root\n");
1211                 return (0);
1212         }
1213 retry:
1214         if (stat(name, &stblock) < 0) {
1215                 perror(name);
1216                 printf("Can't stat %s\n", name);
1217                 return (0);
1218         }
1219         if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
1220                 if (stslash.st_dev == stblock.st_rdev) {
1221                         hotroot++;
1222 #if     !defined(AFS_OSF_ENV)           /*  OSF/1 always uses the raw device, even for / */
1223                         return (name);
1224 #endif  /* AFS_OSF_ENV */
1225                 }
1226                 raw = rawname(name);
1227                 if (raw) {
1228                    return (raw);
1229                 } else {
1230                    printf("Cannot find character device for %s\n", name);
1231                    return (name);
1232                 }
1233         } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
1234                 name = unrawname(name);
1235                 retried++;
1236                 goto retry;
1237         }
1238         printf("Can't make sense out of name %s\n", name);
1239         return (0);
1240 }
1241
1242
1243 #if     defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
1244
1245 #ifdef  AFS_SUN5_ENV
1246 /*
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
1251  */
1252 check_sanity(filename)
1253 char    *filename;
1254 {
1255     struct stat stbd, stbr;
1256     struct ustat usb;
1257     char *devname;
1258     struct vfstab vfsbuf;
1259     FILE *vfstab;
1260     int is_root = 0;
1261     int is_usr = 0;
1262     int is_block = 0;
1263
1264     if (stat(filename, &stbd) < 0) {
1265         fprintf(stderr, "ufs fsck: sanity check failed : cannot stat %s\n", filename);
1266         exit(34);
1267     }
1268
1269     if ((stbd.st_mode & S_IFMT) == S_IFBLK) 
1270         is_block = 1;
1271     else if ((stbd.st_mode & S_IFMT) == S_IFCHR) 
1272         is_block = 0;
1273     else {
1274         fprintf(stderr, "ufs fsck: sanity check failed: %s not block or character device\n", filename);
1275         exit(34);
1276     }
1277     /*
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.
1281      *
1282      * XXX - similar for /usr. This should be fixed to simply return
1283      * a new code indicating, mounted and needs to be checked.
1284      */
1285     if ((vfstab = fopen(VFSTAB, "r")) != 0) {
1286         if (getvfsfile(vfstab, &vfsbuf, "/") == 0) {
1287             if (is_block)
1288                 devname = vfsbuf.vfs_special;
1289             else
1290                 devname = vfsbuf.vfs_fsckdev;
1291             if (stat(devname, &stbr) == 0)
1292                 if (stbr.st_rdev == stbd.st_rdev)
1293                     is_root = 1;
1294         }
1295         if (getvfsfile(vfstab, &vfsbuf, "/usr") == 0) {
1296             if (is_block)
1297                 devname = vfsbuf.vfs_special;
1298             else
1299                 devname = vfsbuf.vfs_fsckdev;
1300             if (stat(devname, &stbr) == 0)
1301                 if (stbr.st_rdev == stbd.st_rdev)
1302                     is_usr = 1;
1303         }
1304     }
1305
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);
1310         exit(33);
1311     }
1312     /*
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.
1317      */
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);
1321         exit(32);
1322     }
1323     fprintf(stderr, "ufs fsck: sanity check: %s okay\n", filename);
1324     exit(0);
1325 }
1326 #endif
1327
1328 #if     defined(AFS_HPUX100_ENV)
1329 check_sanity(filename)
1330 char    *filename;
1331 {
1332     struct stat stbd, stbr;
1333     struct ustat usb;
1334     char *devname;
1335     FILE *vfstab;
1336     struct mntent *mnt;
1337     int is_root = 0;
1338     int is_usr = 0;
1339     int is_block = 0;
1340
1341     if (stat(filename, &stbd) < 0) {
1342         fprintf(stderr, "hfs fsck: sanity check failed : cannot stat %s\n", filename);
1343         exit(34);
1344     }
1345
1346     if ((stbd.st_mode & S_IFMT) == S_IFBLK) 
1347         is_block = 1;
1348     else if ((stbd.st_mode & S_IFMT) == S_IFCHR) 
1349         is_block = 0;
1350     else {
1351         fprintf(stderr, "hfs fsck: sanity check failed: %s not block or character device\n", filename);
1352         exit(34);
1353     }
1354     /*
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.
1358      *
1359      * XXX - similar for /usr. This should be fixed to simply return
1360      * a new code indicating, mounted and needs to be checked.
1361      */
1362     if ((vfstab = setmntent(FSTAB, "r")) != 0) 
1363     {
1364         while ( mnt = getmntent(vfstab))
1365         {
1366           if ( !strcmp(mnt->mnt_dir,"/") )      
1367             if (stat(mnt->mnt_fsname, &stbr) == 0)
1368                 if (stbr.st_rdev == stbd.st_rdev)
1369                     is_root = 1;
1370
1371           if ( !strcmp(mnt->mnt_dir,"/usr") )
1372             if (stat(mnt->mnt_fsname, &stbr) == 0)
1373                 if (stbr.st_rdev == stbd.st_rdev)
1374                     is_usr = 1;
1375         }
1376         endmntent(vfstab);
1377     }
1378
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);
1383         exit(33);
1384     }
1385     /*
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.
1390      */
1391     if (! ((sblock.fs_clean ==FS_CLEAN || sblock.fs_clean ==FS_OK))) {
1392         fprintf(stderr, "hfs fsck: sanity check: %s needs checking\n", filename);
1393         exit(32);
1394     }
1395     fprintf(stderr, "hfs fsck: sanity check: %s okay\n", filename);
1396     exit(0);
1397 }
1398 #endif
1399 /* see if all numbers */
1400 numbers(yp)
1401         char    *yp;
1402 {
1403         if (yp == NULL)
1404                 return (0);
1405         while ('0' <= *yp && *yp <= '9')
1406                 yp++;
1407         if (*yp)
1408                 return (0);
1409         return (1);
1410 }
1411 #endif
1412
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).
1417  */
1418 char *
1419 unrawname(rawdev)
1420   char *rawdev;
1421 {
1422   static char bldev[256];
1423   struct stat statbuf;
1424   int code, i;
1425
1426   code = stat(rawdev, &statbuf);
1427   if ((code < 0) || !S_ISCHR(statbuf.st_mode))
1428      return(rawdev);                           /* Not a char device */
1429
1430   for (i=strlen(rawdev)-2; i>=0; i--) {
1431      if ((rawdev[i] == '/') && (rawdev[i+1] == 'r')) {
1432         strcpy(bldev, rawdev);
1433         bldev[i+1] = 0;
1434         strcat(bldev, &rawdev[i+2]);
1435
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)
1439            return(bldev);
1440 #else
1441            strcpy(rawdev, bldev);              /* Replace */
1442            return(rawdev);
1443 #endif
1444         }
1445      }
1446   }
1447   return(rawdev);
1448 }
1449
1450 /* Convert a block device name into a raw device name. 
1451  * If the block device is not found, return null
1452  */
1453 char *
1454 rawname(bldev)
1455   char *bldev;
1456 {
1457   static char rawdev[256];
1458   struct stat statbuf;
1459   int code, i;
1460
1461   for (i=strlen(bldev)-1; i>=0; i--) {
1462      if (bldev[i] == '/') {
1463         strcpy(rawdev, bldev);
1464         rawdev[i+1] = 'r';
1465         rawdev[i+2] = 0;
1466         strcat(rawdev, &bldev[i+1]);
1467
1468         code = stat(rawdev, &statbuf);
1469         if (!code && S_ISCHR(statbuf.st_mode))
1470            return(rawdev);
1471      }
1472   }
1473   return (char *)0;
1474 }