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