Remove DUX/OSF code
[openafs.git] / src / vfsck / setup.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 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 #include <roken.h>
22
23 #include <ctype.h>
24
25 #define VICE
26
27 #if     defined(AFS_SUN_ENV)
28 #define AFS_NEWCG_ENV
29 #else
30 #undef AFS_NEWCG_ENV
31 #endif
32
33 #ifdef VICE
34 #define msgprintf vfscklogprintf
35 extern vfscklogprintf();
36 #endif
37
38 #define DKTYPENAMES
39
40 #ifdef AFS_VFSINCL_ENV
41 #include <sys/vnode.h>
42 #ifdef    AFS_SUN5_ENV
43 #include <sys/fs/ufs_inode.h>
44 #include <sys/fs/ufs_fs.h>
45 #define _KERNEL
46 #include <sys/fs/ufs_fsdir.h>
47 #undef _KERNEL
48 #include <sys/fs/ufs_mount.h>
49 #else
50 #include <ufs/inode.h>
51 #include <ufs/fs.h>
52 #endif
53 #else /* AFS_VFSINCL_ENV */
54 #include <sys/inode.h>
55 #ifdef  AFS_HPUX_ENV
56 #define LONGFILENAMES   1
57 #include <sys/sysmacros.h>
58 #include <sys/ino.h>
59 #endif
60 #include <sys/fs.h>
61 #endif /* AFS_VFSINCL_ENV */
62
63 #include <sys/file.h>
64 #ifdef  AFS_SUN5_ENV
65 #include <sys/mntent.h>
66 #include <sys/vfstab.h>
67 #endif
68
69 #include <afs/osi_inode.h>
70 #include "fsck.h"
71
72 struct bufarea asblk;
73 struct bufarea *pbp;
74
75 #define altsblock (*asblk.b_un.b_fs)
76 #define POWEROF2(num)   (((num) & ((num) - 1)) == 0)
77
78 /*
79  * The size of a cylinder group is calculated by CGSIZE. The maximum size
80  * is limited by the fact that cylinder groups are at most one block.
81  * Its size is derived from the size of the maps maintained in the
82  * cylinder group and the (struct cg) size.
83  */
84 #define CGSIZE(fs) \
85     /* base cg */       (sizeof(struct cg) + \
86     /* blktot size */   (fs)->fs_cpg * sizeof(afs_int32) + \
87     /* blks size */     (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
88     /* inode map */     howmany((fs)->fs_ipg, NBBY) + \
89     /* block map */     howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
90
91 struct disklabel *getdisklabel();
92
93 setup(dev)
94      char *dev;
95 {
96     dev_t rootdev;
97     long cg, size, asked, i, j;
98     long bmapsize;
99     struct disklabel *lp;
100     struct stat statb;
101     struct fs proto;
102 #if     defined(AFS_SUN5_ENV)
103     static char sname[MAXPATHLEN];
104 #endif
105
106     /* reset static variables that may have been damaged by parent fork */
107     mlk_pbp = 0;
108     pbp = 0;
109     mlk_startinum = 0;
110 #if defined(ACLS) && defined(AFS_HPUX_ENV)
111     n_cont = 0;
112 #endif
113     havesb = 0;
114     if (stat("/", &statb) < 0)
115         errexit("Can't stat root\n");
116     rootdev = statb.st_dev;
117 #if     defined(AFS_SUN5_ENV)
118     strncpy(sname, dev, sizeof(sname));
119   restat:
120     if (stat(sname, &statb) < 0) {
121         perror(sname);
122         msgprintf("Can't stat %s\n", sname);
123 #else
124     if (stat(dev, &statb) < 0) {
125         perror(dev);
126         printf("Can't stat %s\n", dev);
127 #endif
128         return (0);
129     }
130 #ifdef  AFS_SUN5_ENV
131     if ((statb.st_mode & S_IFMT) == S_IFDIR) {
132         FILE *fp;
133         struct vfstab vtab;
134
135         if ((fp = fopen(VFSTAB, "r")) == NULL) {
136             pfatal("Can't open %s file\n", VFSTAB);
137             exit(1);
138         }
139         while (!getvfsent(fp, &vtab)) {
140             if (vtab.vfs_mountp && !strcmp(vtab.vfs_mountp, sname)) {
141                 strcpy(sname, vtab.vfs_special);
142                 if (rflag) {
143                     char *s = vtab.vfs_fsckdev;
144                     strcpy(sname, s);
145                 }
146                 goto restat;
147             }
148         }
149         fclose(fp);
150     }
151 #endif
152     if ((statb.st_mode & S_IFMT) != S_IFBLK
153         && (statb.st_mode & S_IFMT) != S_IFCHR) {
154         pfatal("device is not a block or character device");
155         if (reply("file is not a block or character device; OK") == 0)
156             return (0);
157     }
158 #ifdef  AFS_SUN5_ENV
159     if (mounted(sname))
160         if (rflag)
161             mountedfs++;
162         else {
163             printf("%s is mounted, fsck on BLOCK device ignored\n", sname);
164             exit(33);
165         }
166     if (rflag) {
167         char bname[MAXPATHLEN], *tname;
168
169         strcpy(bname, sname);
170         tname = unrawname(bname);
171         if (stat(tname, &statb) < 0) {
172             pfatal("Can't stat %s\n", tname);
173             return (0);
174         }
175         dev = sname;
176     }
177 #endif
178     hotroot = is_hotroot(dev);
179
180     /*
181      * The following code is added to improve usability of fsck.
182      * we need to give user a warning if the device being checked is
183      * a hotroot, a mounted file system, or a swap device.
184      * The rules are:
185      *      1) if nflag is set, it's pretty safe to fsck the target dev
186      *      2) if the target device is a swap, exit
187      *      3) if hotroot is set, and "-F" is not specified prompt the
188      *              user and wait for reply
189      *      4) if the target is a mounted file system, and "-F" is not
190      *              specified, prompt the user and wait for reply
191      *      5) if the "-m" is specifed, do no prompting since only a sanity
192      *              check is being done. important during booting
193      *
194      * Caveat: There is no way to tell the current run level, so we cannot
195      * tell whether or not we are in single user mode.
196      */
197     if (!nflag) {
198         int mounted, swap;
199         struct stat st_mounted;
200
201         mounted = swap = 0;
202         if (!hotroot) {
203             mounted = is_mounted(dev, &st_mounted);
204 #ifdef  AFS_HPUX_ENV
205             swap = is_swap(st_mounted.st_rdev);
206 #endif
207         }
208         if (!fflag
209 #ifdef  AFS_HPUX_ENV
210             && !mflag
211 #endif
212             ) {
213             if (hotroot) {
214                 msgprintf("fsck: %s: root file system", dev);
215                 if (preen)
216                     msgprintf(" (CONTINUING)\n");
217                 else {
218                     if (!freply("continue (y/n)"))
219                         return (0);
220                 }
221             } else if (mounted) {
222                 msgprintf("fsck: %s: mounted file system", dev);
223                 if (preen)
224                     msgprintf(" (CONTINUING)\n");
225                 else {
226                     if (!freply("continue (y/n)"))
227                         return (0);
228                 }
229             } else if (swap) {
230                 msgprintf("fsck: %s: swap device\n", dev);
231                 if (preen)
232                     msgprintf(" (CONTINUING)\n");
233                 else {
234                     if (!freply("continue (y/n)"))
235                         return (0);
236                 }
237             }
238         }
239     }
240     if (rootdev == statb.st_rdev)
241         hotroot++;
242     if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
243         perror(dev);
244         msgprintf("Can't open %s\n", dev);
245         return (0);
246     }
247     if (preen == 0)
248         msgprintf("** %s", dev);
249     if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) {
250         fswritefd = -1;
251         msgprintf(" (NO WRITE)");
252 #ifdef  notdef
253         if (preen) {
254             pfatal("NO WRITE ACCESS");
255         }
256 #endif
257     }
258     if (preen == 0)
259         msgprintf("\n");
260 #if     defined(AFS_HPUX101_ENV)
261     setup_all_block_seek();
262 #endif
263 #ifdef  AFS_SUN5_ENV
264     if (!preen && debug)
265         printf(" pid %d\n", getpid());
266     if (debug && (hotroot || mountedfs)) {
267         printf("** %s", sname);
268         if (hotroot) {
269             printf(" is root fs");
270             if (mountedfs)
271                 printf(" and");
272         }
273         if (mountedfs)
274             printf(" is mounted");
275         printf(".\n");
276     }
277 #endif
278     fsmodified = 0;
279     lfdir = 0;
280     initbarea(&sblk);
281     initbarea(&asblk);
282 #ifdef __alpha
283     sblk.b_un.b_buf = malloc(SBSIZE + ALPHA_EXT);
284     asblk.b_un.b_buf = malloc(SBSIZE + ALPHA_EXT);
285 #else /* __alpha */
286     sblk.b_un.b_buf = malloc(SBSIZE);
287     asblk.b_un.b_buf = malloc(SBSIZE);
288 #endif
289     if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
290         errexit("cannot allocate space for superblock\n");
291     dev_bsize = secsize = DEV_BSIZE;
292
293     /*
294      * Read in the superblock, looking for alternates if necessary
295      */
296     if (readsb(1) == 0) {
297         if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0)
298             return (0);
299         if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
300             return (0);
301         for (cg = 0; cg < proto.fs_ncg; cg++) {
302             bflag = fsbtodb(&proto, cgsblock(&proto, cg));
303             if (readsb(0) != 0)
304                 break;
305         }
306         if (cg >= proto.fs_ncg) {
307             msgprintf("%s %s\n%s %s\n%s %s\n",
308                       "SEARCH FOR ALTERNATE SUPER-BLOCK",
309                       "FAILED. YOU MUST USE THE",
310                       "-b OPTION TO FSCK TO SPECIFY THE",
311                       "LOCATION OF AN ALTERNATE",
312                       "SUPER-BLOCK TO SUPPLY NEEDED",
313                       "INFORMATION; SEE fsck(8).");
314             return (0);
315         }
316         pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
317     }
318     maxfsblock = sblock.fs_size;
319     maxino = sblock.fs_ncg * sblock.fs_ipg;
320     /*
321      * Check and potentially fix certain fields in the super block.
322      */
323     if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) {
324         pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK");
325         if (reply("SET TO DEFAULT") == 1) {
326             sblock.fs_optim = FS_OPTTIME;
327             sbdirty();
328         }
329     }
330     if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) {
331         pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", sblock.fs_minfree);
332         if (reply("SET TO DEFAULT") == 1) {
333             sblock.fs_minfree = 10;
334             sbdirty();
335         }
336     }
337 #ifdef  AFS_HPUX_ENV
338     /*
339      * Do we need to continue ?
340      */
341     if (pclean && sblock.fs_clean == FS_CLEAN)
342         return (-1);
343     if (pclean && hotroot && sblock.fs_clean == FS_OK)
344         return (-1);
345 #endif
346 #ifdef AFS_NEWCG_ENV
347 # ifndef AFS_SUN59_ENV
348     if (sblock.fs_interleave < 1) {
349         pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK", sblock.fs_interleave);
350         sblock.fs_interleave = 1;
351         if (preen)
352             msgprintf(" (FIXED)\n");
353         if (preen || reply("SET TO DEFAULT") == 1) {
354             sbdirty();
355             dirty(&asblk);
356         }
357     }
358 # endif /* AFS_SUN59_ENV */
359 #endif /* AFS_NEWCG_ENV */
360 #ifdef AFS_NEWCG_ENV
361     if (sblock.fs_npsect < sblock.fs_nsect) {
362         pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK", sblock.fs_npsect);
363         sblock.fs_npsect = sblock.fs_nsect;
364         if (preen)
365             msgprintf(" (FIXED)\n");
366         if (preen || reply("SET TO DEFAULT") == 1) {
367             sbdirty();
368             dirty(&asblk);
369         }
370     }
371 #endif /* AFS_NEWCG_ENV */
372 #ifdef AFS_NEWCG_ENV
373     if (cvtflag) {
374         if (sblock.fs_postblformat == FS_42POSTBLFMT) {
375             /*
376              * Requested to convert from old format to new format
377              */
378             if (preen)
379                 pwarn("CONVERTING TO NEW FILE SYSTEM FORMAT\n");
380             else if (!reply("CONVERT TO NEW FILE SYSTEM FORMAT"))
381                 return (0);
382             isconvert = 1;
383             sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
384             sblock.fs_nrpos = 8;
385             sblock.fs_postbloff =
386                 (char *)(&sblock.fs_opostbl[0][0]) -
387                 (char *)(&sblock.fs_link);
388             sblock.fs_rotbloff =
389                 &sblock.fs_space[0] - (u_char *) (&sblock.fs_link);
390             sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
391             /*
392              * Planning now for future expansion.
393              */
394 #                       if (BYTE_ORDER == BIG_ENDIAN)
395             sblock.fs_qbmask.val[0] = 0;
396             sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
397             sblock.fs_qfmask.val[0] = 0;
398             sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
399 #                       endif /* BIG_ENDIAN */
400 #                       if (BYTE_ORDER == LITTLE_ENDIAN)
401             sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
402             sblock.fs_qbmask.val[1] = 0;
403             sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
404             sblock.fs_qfmask.val[1] = 0;
405 #                       endif /* LITTLE_ENDIAN */
406 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
407 #ifdef  AFS_SUN5_ENV
408             sblock.fs_state = FSOKAY - sblock.fs_time;  /* make mountable */
409 #else
410             fs_set_state(&sblock, FSOKAY - sblock.fs_time);
411 #endif
412             sblock.fs_clean = FSCLEAN;
413 #endif
414             sbdirty();
415             dirty(&asblk);
416         } else if (sblock.fs_postblformat == FS_DYNAMICPOSTBLFMT) {
417             /*
418              * Requested to convert from new format to old format
419              */
420             if (sblock.fs_nrpos != 8 || sblock.fs_ipg > 2048
421                 || sblock.fs_cpg > 32 || sblock.fs_cpc > 16) {
422                 msgprintf("PARAMETERS OF CURRENT FILE SYSTEM DO NOT\n\t");
423                 msgprintf("ALLOW CONVERSION TO OLD FILE SYSTEM FORMAT\n");
424                 errexit("");
425
426             }
427             if (preen)
428                 pwarn("CONVERTING TO OLD FILE SYSTEM FORMAT\n");
429             else if (!reply("CONVERT TO OLD FILE SYSTEM FORMAT"))
430                 return (0);
431             isconvert = 1;
432             sblock.fs_postblformat = FS_42POSTBLFMT;
433             sblock.fs_cgsize =
434                 fragroundup(&sblock,
435                             sizeof(struct ocg) + howmany(sblock.fs_fpg,
436                                                          NBBY));
437 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
438 #ifdef  AFS_SUN5_ENV
439             sblock.fs_npsect = 0;
440 # ifndef AFS_SUN59_ENV
441             sblock.fs_interleave = 0;
442 # endif
443             sblock.fs_state = FSOKAY - sblock.fs_time;  /* make mountable */
444 #else
445             fs_set_state(&sblock, FSOKAY - sblock.fs_time);
446 #endif
447             sblock.fs_clean = FSCLEAN;
448 #endif
449             sbdirty();
450             dirty(&asblk);
451         } else {
452             errexit("UNKNOWN FILE SYSTEM FORMAT\n");
453         }
454     }
455 #endif /* AFS_NEWCG_ENV */
456     if (asblk.b_dirty) {
457         memcpy((char *)&altsblock, (char *)&sblock, (int)sblock.fs_sbsize);
458         flush(fswritefd, &asblk);
459     }
460     /*
461      * read in the summary info.
462      */
463     asked = 0;
464 #if     defined(AFS_SUN5_ENV)
465     {
466         caddr_t sip;
467         sip = calloc(1, sblock.fs_cssize);
468         sblock.fs_u.fs_csp = (struct csum *)sip;
469         for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
470             size =
471                 sblock.fs_cssize - i <
472                 sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize;
473             if (bread
474                 (fsreadfd, sip,
475                  fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
476                  size) != 0 && !asked) {
477                 pfatal("BAD SUMMARY INFORMATION");
478                 if (reply("CONTINUE") == 0)
479                     errexit("");
480                 return (0);
481             }
482             sip += size;
483         }
484     }
485 #else /* AFS_SUN5_ENV */
486 #if     defined(AFS_HPUX110_ENV)
487     size = fragroundup(&sblock, sblock.fs_cssize);
488     sblock.fs_csp = calloc(1, (unsigned)size);
489     if ((bread
490          (fsreadfd, (char *)sblock.fs_csp, fsbtodb(&sblock, sblock.fs_csaddr),
491           size) != 0) && !asked) {
492         pfatal("BAD SUMMARY INFORMATION");
493         if (reply("CONTINUE") == 0)
494             errexit("");
495         asked++;
496     }
497 #else /* AFS_HPUX110_ENV */
498 #if     defined(AFS_HPUX101_ENV)
499     {
500         j = 0;
501         size = fragroundup(&sblock, sblock.fs_cssize);
502 #else
503     for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
504         size =
505             sblock.fs_cssize - i <
506             sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize;
507 #endif /* AFS_HPUX101_ENV */
508         sblock.fs_csp[j] = calloc(1, (unsigned)size);
509         if (bread
510             (fsreadfd, (char *)sblock.fs_csp[j],
511              fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
512              size) != 0 && !asked) {
513             pfatal("BAD SUMMARY INFORMATION");
514             if (reply("CONTINUE") == 0)
515                 errexit("");
516 #ifdef  AFS_SUN_ENV
517             return (0);
518 #else
519             asked++;
520 #endif
521         }
522     }
523 #endif /* else AFS_HPUX110_ENV */
524 #endif /* else AFS_SUN5_ENV */
525
526 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
527     /*
528      * if not forced, preening, not converting, and is clean; stop checking
529      */
530 #ifdef  AFS_SUN5_ENV
531     if ((fflag == 0) && preen && (isconvert == 0)
532         && (FSOKAY == (sblock.fs_state + sblock.fs_time)) &&
533 #else
534     if (preen && (isconvert == 0)
535         && (FSOKAY == (fs_get_state(&sblock) + sblock.fs_time)) &&
536 #endif
537         ((sblock.fs_clean == FSCLEAN) || (sblock.fs_clean == FSSTABLE))) {
538         iscorrupt = 0;
539         printclean();
540         return (0);
541     }
542 #endif
543
544     /*
545      * allocate and initialize the necessary maps
546      */
547     bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short));
548     blockmap = calloc((unsigned)bmapsize, sizeof(char));
549     if (blockmap == NULL) {
550         msgprintf("cannot alloc %d bytes for blockmap\n", bmapsize);
551         goto badsb;
552     }
553     statemap = calloc((unsigned)(maxino + 1), sizeof(char));
554     if (statemap == NULL) {
555         msgprintf("cannot alloc %d bytes for statemap\n", maxino + 1);
556         goto badsb;
557     }
558     lncntp = calloc((unsigned)(maxino + 1), sizeof(short));
559     if (lncntp == NULL) {
560         msgprintf("cannot alloc %d bytes for lncntp\n",
561                   (maxino + 1) * sizeof(short));
562         goto badsb;
563     }
564
565     bufinit();
566     return (1);
567
568   badsb:
569     ckfini();
570     return (0);
571 }
572
573 /*
574  * Read in the super block and its summary info.
575  */
576 readsb(listerr)
577      int listerr;
578 {
579 #ifdef AFS_NEWCG_ENV
580     daddr_t super = bflag ? bflag : SBOFF / dev_bsize;
581 #else /* AFS_NEWCG_ENV */
582     daddr_t super = bflag ? bflag : SBLOCK;
583
584 #endif /* AFS_NEWCG_ENV */
585     if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0)
586         return (0);
587     sblk.b_bno = super;
588     sblk.b_size = SBSIZE;
589     /*
590      * run a few consistency checks of the super block
591      */
592 #ifdef  AFS_HPUX_ENV
593 #if defined(FD_FSMAGIC)
594     if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN)
595         && (sblock.fs_magic != FD_FSMAGIC)
596 #if     defined(AFS_HPUX101_ENV)
597         && (sblock.fs_magic != FD_FSMAGIC_2)
598 #endif
599         )
600 #else /* not new magic number */
601     if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN))
602 #endif /* new magic number */
603 #else
604     if (sblock.fs_magic != FS_MAGIC)
605 #endif
606     {
607         badsb(listerr, "MAGIC NUMBER WRONG");
608         return (0);
609     }
610     if (sblock.fs_ncg < 1) {
611         badsb(listerr, "NCG OUT OF RANGE");
612         return (0);
613     }
614     if (sblock.fs_cpg < 1) {
615         printf("fs_cpg= %d\n", sblock.fs_cpg);
616         badsb(listerr, "CPG OUT OF RANGE");
617         return (0);
618     }
619     if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl
620         || (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) {
621         badsb(listerr, "NCYL LESS THAN NCG*CPG");
622         return (0);
623     }
624     if (sblock.fs_sbsize > SBSIZE) {
625         badsb(listerr, "SIZE PREPOSTEROUSLY LARGE");
626         return (0);
627     }
628     /*
629      * Compute block size that the filesystem is based on,
630      * according to fsbtodb, and adjust superblock block number
631      * so we can tell if this is an alternate later.
632      */
633     super *= dev_bsize;
634     dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
635     sblk.b_bno = super / dev_bsize;
636     /*
637      * Set all possible fields that could differ, then do check
638      * of whole super block against an alternate super block.
639      * When an alternate super-block is specified this check is skipped.
640      */
641     getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize);
642     if (asblk.b_errs)
643         return (0);
644     if (bflag) {
645         havesb = 1;
646         return (1);
647     }
648     altsblock.fs_link = sblock.fs_link;
649 #ifdef STRUCT_FS_HAS_FS_ROLLED
650     altsblock.fs_rolled = sblock.fs_rolled;
651 #else
652     altsblock.fs_rlink = sblock.fs_rlink;
653 #endif
654     altsblock.fs_time = sblock.fs_time;
655     altsblock.fs_cstotal = sblock.fs_cstotal;
656     altsblock.fs_cgrotor = sblock.fs_cgrotor;
657     altsblock.fs_fmod = sblock.fs_fmod;
658
659     altsblock.fs_clean = sblock.fs_clean;
660 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN3_ENV)
661 #ifdef  AFS_SUN5_ENV
662     altsblock.fs_state = sblock.fs_state;
663 #else
664     fs_set_state(&altsblock, fs_get_state(&sblock));
665 #endif
666 #endif
667     altsblock.fs_ronly = sblock.fs_ronly;
668     altsblock.fs_flags = sblock.fs_flags;
669     altsblock.fs_maxcontig = sblock.fs_maxcontig;
670     altsblock.fs_minfree = sblock.fs_minfree;
671     altsblock.fs_optim = sblock.fs_optim;
672     altsblock.fs_rotdelay = sblock.fs_rotdelay;
673     altsblock.fs_maxbpg = sblock.fs_maxbpg;
674 #if     !defined(__alpha) && !defined(AFS_SUN5_ENV)
675 #if !defined(AFS_HPUX110_ENV)
676     /* HPUX110 will use UpdateAlternateSuper() below */
677     memcpy((char *)altsblock.fs_csp, (char *)sblock.fs_csp,
678            sizeof sblock.fs_csp);
679 #endif /* ! AFS_HPUX110_ENV */
680 #endif /* ! __alpha */
681 #if     defined(AFS_SUN5_ENV)
682     memcpy((char *)altsblock.fs_u.fs_csp_pad, (char *)sblock.fs_u.fs_csp_pad,
683            sizeof(sblock.fs_u.fs_csp_pad));
684 #endif
685     memcpy((char *)altsblock.fs_fsmnt, (char *)sblock.fs_fsmnt,
686            sizeof sblock.fs_fsmnt);
687 #ifndef AFS_HPUX_ENV
688     memcpy((char *)altsblock.fs_sparecon, (char *)sblock.fs_sparecon,
689            sizeof sblock.fs_sparecon);
690 #endif
691     /*
692      * The following should not have to be copied.
693      */
694     altsblock.fs_fsbtodb = sblock.fs_fsbtodb;
695 #ifdef AFS_NEWCG_ENV
696 # if defined(AFS_SUN59_ENV) && defined(FS_SI_OK)
697     /* fs_interleave replaced with fs_si and FS_SI_OK defined in */
698     /* ufs_fs.h version 2.63 don't need to compare either */
699     altsblock.fs_si = sblock.fs_si;
700 # else
701     altsblock.fs_interleave = sblock.fs_interleave;
702 # endif
703     altsblock.fs_npsect = sblock.fs_npsect;
704     altsblock.fs_nrpos = sblock.fs_nrpos;
705 #endif /* AFS_NEWCG_ENV */
706 #if     defined(AFS_HPUX110_ENV)
707     UpdateAlternateSuper(&sblock, &altsblock);
708 #endif /* AFS_HPUX110_ENV */
709     if (memcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) {
710 #ifdef  __alpha
711         if (memcmp
712             ((char *)&sblock.fs_blank[0], (char *)&altsblock.fs_blank[0],
713              MAXCSBUFS * sizeof(int))) {
714             memset(sblock.fs_blank, 0, sizeof(sblock.fs_blank));
715         } else {
716 #endif /* __alpha */
717             badsb(listerr,
718                   "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
719             return (0);
720 #ifdef  __alpha
721         }
722 #endif /* __alpha */
723     }
724     havesb = 1;
725     return (1);
726 }
727
728 badsb(listerr, s)
729      int listerr;
730      char *s;
731 {
732
733     if (!listerr)
734         return;
735     if (preen)
736         msgprintf("%s: ", devname);
737     pfatal("BAD SUPER BLOCK: %s\n", s);
738 #ifdef  AFS_SUN5_ENV
739     pwarn("USE AN ALTERNATE SUPER-BLOCK TO SUPPLY NEEDED INFORMATION;\n");
740     pwarn("eg. fsck [-F ufs] -o b=# [special ...] \n");
741     pfatal("where # is the alternate super block. SEE fsck_ufs(1M). \n");
742 #endif
743 }
744
745 /* dummy function that fails if ever called */
746 calcsb(dev, devfd, fs)
747      char *dev;
748      int devfd;
749      struct fs *fs;
750 {
751     return 0;
752 }
753
754 #include <sys/ustat.h>
755 #ifdef  AFS_HPUX_ENV
756 #include <sys/pstat.h>
757 #endif
758 #include <sys/errno.h>
759
760 extern int errno;
761
762 is_mounted(device, dev_st)
763      char *device;
764      struct stat *dev_st;
765 {
766     char blockdev[BUFSIZ];
767     struct ustat ust;
768     char *dp;
769
770     strcpy(blockdev, device);
771     if (stat(blockdev, dev_st) < 0)
772         return (0);
773
774     if (is_pre_init(dev_st->st_rdev))
775         return (0);
776
777     if ((dev_st->st_mode & S_IFMT) == S_IFCHR) {
778         dp = strrchr(blockdev, '/');
779         if (strncmp(dp, "/r", 2) != 0)
780             while (dp >= blockdev && *--dp != '/');
781         if (*(dp + 1) == 'r')
782             (void)strcpy(dp + 1, dp + 2);
783         if (stat(blockdev, dev_st) < 0)
784             return (0);
785     }
786     if (ustat(dev_st->st_rdev, &ust) >= 0) {
787         /* make sure we are not in pre_init_rc. If we are 0 should be returned in here. */
788         if ((is_root(dev_st->st_rdev)) && is_roroot())
789             return (0);
790         return (1);
791     }
792     return (0);
793 }
794
795 #ifdef  AFS_HPUX_ENV
796
797 #define PS_BURST 1
798 #ifdef AFS_HPUX102_ENV
799 #define PSTAT(P, N, I) pstat_getswap(P, sizeof(*P), (size_t)N, I)
800 #else
801 #define PSTAT(P, N, I) pstat(PSTAT_SWAPINFO, P, sizeof(*P), (size_t)N, I)
802 #endif
803 is_swap(devno)
804      dev_t devno;
805 {
806     struct pst_swapinfo pst[PS_BURST];
807     struct pst_swapinfo *psp = &pst[0];
808     int idx = 0, count, match = 0;
809
810     while ((count = PSTAT(psp, PS_BURST, idx) != 0)) {
811         idx = pst[count - 1].pss_idx + 1;
812         if ((psp->pss_flags & SW_BLOCK) && (psp->pss_major == major(devno))
813             && (psp->pss_minor == minor(devno))) {
814             match = 1;
815             break;
816         }
817     }
818     return (match);
819 }
820
821 #endif /* AFS_HPUX_ENV */
822
823
824 is_pre_init(rdevnum)
825      dev_t rdevnum;
826 {
827     if (rdevnum == -1)
828         return (1);
829     return (0);
830 }
831
832 is_roroot()
833 {
834 #ifndef UID_NO_CHANGE
835     struct stat stslash;
836
837     if (stat("/", &stslash) < 0)
838         return (0);
839     if (chown("/", stslash.st_uid, stslash.st_gid) == 0)
840         return (0);
841 #else
842     if (chown("/", UID_NO_CHANGE, GID_NO_CHANGE) == 0)
843         return (0);
844 #endif
845     else if (errno != EROFS) {
846         printf("fsck: chown failed: %d\n", errno);
847         return (0);
848     }
849     return (1);
850 }
851
852 is_hotroot(fs_device)
853      char *fs_device;
854 {
855     struct stat stslash, stblock, stchar;
856     char blockdev[BUFSIZ];
857
858     strcpy(blockdev, fs_device);
859     if (stat("/", &stslash) < 0) {
860         pfatal("Can't stat root\n");
861         return (0);
862     }
863
864     if (stat(blockdev, &stblock) < 0) {
865         pfatal("Can't stat %s\n", blockdev);
866         return (0);
867     }
868
869     if (is_pre_init(stblock.st_rdev))
870         return (0);
871
872     /* convert the device name to be block device name */
873     if ((stblock.st_mode & S_IFMT) == S_IFCHR) {
874         unrawname(blockdev);
875         if (stat(blockdev, &stblock) < 0)
876             return (0);
877     }
878     if ((stblock.st_mode & S_IFMT) != S_IFBLK)
879         return (0);
880     if (stslash.st_dev != stblock.st_rdev)
881         return (0);
882     /* is root file system mounted read only? */
883     if (is_roroot())
884         return (0);
885     return (1);
886 }
887
888 is_root(rdev_num)
889      dev_t rdev_num;
890 {
891     struct stat stslash;
892
893     if (stat("/", &stslash) < 0)
894         return (0);
895     if (stslash.st_dev != rdev_num)
896         return (0);
897     return (1);
898 }
899
900 vfsck_getline(fp, loc, maxlen)
901      FILE *fp;
902      char *loc;
903 {
904     int n;
905     char *p, *lastloc;
906
907     p = loc;
908     lastloc = &p[maxlen - 1];
909     while ((n = getc(fp)) != '\n') {
910         if (n == EOF)
911             return (EOF);
912         if (!isspace(n) && p < lastloc)
913             *p++ = n;
914     }
915     *p = 0;
916     return (p - loc);
917 }
918
919 /*
920  * freply - prints the string, s, gets a reply fromterminal and returns
921  * 0 - no (don't continue), and 1 - yes (continue)
922  */
923 freply(s)
924      char *s;
925 {
926     char line[80];
927
928     if (!isatty(0))
929         errexit("exiting\n");
930     printf("\n%s? ", s);
931     if (vfsck_getline(stdin, line, sizeof(line)) == EOF)
932         errexit("\n");
933     if (line[0] == 'y' || line[0] == 'Y')
934         return (1);
935     return (0);
936 }
937
938
939 #if   defined(AFS_HPUX110_ENV)
940 /*
941  *  Refer to function compare_sblocks() in HP's fsck.c
942  *
943  *  DESCRIPTION:
944  *     This routine will compare the primary superblock (PRIM_SBLOCK) to the
945  *     alternate superblock (ALT_SBLOCK).  This routine will take into account
946  *     that certain fields in the alternate superblock could be different than
947  *     in the primary superblock.  This routine checks the "static" fields
948  *     and ignores the "dynamic" fields.  Superblocks with the same "static"
949  *     fields are considered equivalent.
950  *
951  */
952 UpdateAlternateSuper(prim_sblock, alt_sblock)
953      struct fs *prim_sblock;
954      struct fs *alt_sblock;     /* will be modified */
955 {
956     /*
957      * Set all possible fields that could differ, then do check
958      * of whole super block against an alternate super block.
959      *
960      * Copy dynamic fields of prim_sblock into alt_sblock
961      */
962     alt_sblock->fs_time = prim_sblock->fs_time;
963     alt_sblock->fs_minfree = prim_sblock->fs_minfree;
964     alt_sblock->fs_rotdelay = prim_sblock->fs_rotdelay;
965     alt_sblock->fs_maxcontig = prim_sblock->fs_maxcontig;
966     alt_sblock->fs_maxbpg = prim_sblock->fs_maxbpg;
967     alt_sblock->fs_mirror = prim_sblock->fs_mirror;
968     alt_sblock->fs_cstotal = prim_sblock->fs_cstotal;
969     alt_sblock->fs_fmod = prim_sblock->fs_fmod;
970     alt_sblock->fs_clean = prim_sblock->fs_clean;
971     alt_sblock->fs_ronly = prim_sblock->fs_ronly;
972     alt_sblock->fs_flags = prim_sblock->fs_flags;
973     alt_sblock->fs_cgrotor = prim_sblock->fs_cgrotor;
974 #ifdef __LP64__
975     alt_sblock->fs_csp = prim_sblock->fs_csp;
976 #else /* not __LP64__ */
977     alt_sblock->fs_csp = prim_sblock->fs_csp;
978     alt_sblock->fs_csp_pad = prim_sblock->fs_csp_pad;
979 #endif /* not __LP64__ */
980     memcpy((char *)alt_sblock->fs_fsmnt, (char *)prim_sblock->fs_fsmnt,
981            sizeof prim_sblock->fs_fsmnt);
982     memcpy((char *)alt_sblock->fs_fname, (char *)prim_sblock->fs_fname,
983            sizeof prim_sblock->fs_fname);
984     memcpy((char *)alt_sblock->fs_fpack, (char *)prim_sblock->fs_fpack,
985            sizeof prim_sblock->fs_fpack);
986     if (prim_sblock->fs_featurebits & FSF_LARGEUIDS)
987         alt_sblock->fs_featurebits |= FSF_LARGEUIDS;
988     else
989         alt_sblock->fs_featurebits &= ~FSF_LARGEUIDS;
990 }
991 #endif /* AFS_HPUX110_ENV */