|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)setup.c 5.19 (Berkeley) 5/7/88"; ! 9: #endif not lint ! 10: ! 11: #define DKTYPENAMES ! 12: #include <sys/param.h> ! 13: #include <sys/inode.h> ! 14: #include <sys/fs.h> ! 15: #include <sys/stat.h> ! 16: #include <sys/ioctl.h> ! 17: #include <sys/disklabel.h> ! 18: #include <sys/file.h> ! 19: #include <machine/endian.h> ! 20: #include <ctype.h> ! 21: #include "fsck.h" ! 22: ! 23: BUFAREA asblk; ! 24: #define altsblock (*asblk.b_un.b_fs) ! 25: #define POWEROF2(num) (((num) & ((num) - 1)) == 0) ! 26: ! 27: char *calloc(); ! 28: char *index(); ! 29: ! 30: setup(dev) ! 31: char *dev; ! 32: { ! 33: dev_t rootdev; ! 34: long cg, ncg, size, asked, i, j; ! 35: struct disklabel *getdisklabel(), *lp; ! 36: struct stat statb; ! 37: struct fs proto; ! 38: ! 39: havesb = 0; ! 40: if (stat("/", &statb) < 0) ! 41: errexit("Can't stat root\n"); ! 42: rootdev = statb.st_dev; ! 43: if (stat(dev, &statb) < 0) { ! 44: perror(dev); ! 45: printf("Can't stat %s\n", dev); ! 46: return (0); ! 47: } ! 48: rawflg = 0; ! 49: if ((statb.st_mode & S_IFMT) == S_IFBLK) ! 50: ; ! 51: else if ((statb.st_mode & S_IFMT) == S_IFCHR) ! 52: rawflg++; ! 53: else { ! 54: if (reply("file is not a block or character device; OK") == 0) ! 55: return (0); ! 56: } ! 57: if (rootdev == statb.st_rdev) ! 58: hotroot++; ! 59: if ((dfile.rfdes = open(dev, O_RDONLY)) < 0) { ! 60: perror(dev); ! 61: printf("Can't open %s\n", dev); ! 62: return (0); ! 63: } ! 64: if (preen == 0) ! 65: printf("** %s", dev); ! 66: if (nflag || (dfile.wfdes = open(dev, O_WRONLY)) < 0) { ! 67: dfile.wfdes = -1; ! 68: if (preen) ! 69: pfatal("NO WRITE ACCESS"); ! 70: printf(" (NO WRITE)"); ! 71: } ! 72: if (preen == 0) ! 73: printf("\n"); ! 74: dfile.mod = 0; ! 75: lfdir = 0; ! 76: initbarea(&sblk); ! 77: initbarea(&asblk); ! 78: sblk.b_un.b_buf = (char *)malloc(SBSIZE); ! 79: asblk.b_un.b_buf = (char *)malloc(SBSIZE); ! 80: if (sblk.b_un.b_buf == 0 || asblk.b_un.b_buf == 0) ! 81: errexit("cannot allocate space for superblock\n"); ! 82: if (lp = getdisklabel((char *)NULL, dfile.rfdes)) ! 83: dev_bsize = secsize = lp->d_secsize; ! 84: else ! 85: dev_bsize = secsize = DEV_BSIZE; ! 86: /* ! 87: * Read in the superblock, looking for alternates if necessary ! 88: */ ! 89: if (readsb(1) == 0) { ! 90: if (bflag || preen || calcsb(dev, dfile.rfdes, &proto) == 0) ! 91: return(0); ! 92: if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) ! 93: return (0); ! 94: for (cg = 0; cg < proto.fs_ncg; cg++) { ! 95: bflag = fsbtodb(&proto, cgsblock(&proto, cg)); ! 96: if (readsb(0) != 0) ! 97: break; ! 98: } ! 99: if (cg >= proto.fs_ncg) { ! 100: printf("%s %s\n%s %s\n%s %s\n", ! 101: "SEARCH FOR ALTERNATE SUPER-BLOCK", ! 102: "FAILED. YOU MUST USE THE", ! 103: "-b OPTION TO FSCK TO SPECIFY THE", ! 104: "LOCATION OF AN ALTERNATE", ! 105: "SUPER-BLOCK TO SUPPLY NEEDED", ! 106: "INFORMATION; SEE fsck(8)."); ! 107: return(0); ! 108: } ! 109: pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); ! 110: } ! 111: fmax = sblock.fs_size; ! 112: imax = sblock.fs_ncg * sblock.fs_ipg; ! 113: /* ! 114: * Check and potentially fix certain fields in the super block. ! 115: */ ! 116: if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { ! 117: pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); ! 118: if (reply("SET TO DEFAULT") == 1) { ! 119: sblock.fs_optim = FS_OPTTIME; ! 120: sbdirty(); ! 121: } ! 122: } ! 123: if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { ! 124: pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", ! 125: sblock.fs_minfree); ! 126: if (reply("SET TO DEFAULT") == 1) { ! 127: sblock.fs_minfree = 10; ! 128: sbdirty(); ! 129: } ! 130: } ! 131: if (sblock.fs_interleave < 1) { ! 132: pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK", ! 133: sblock.fs_interleave); ! 134: sblock.fs_interleave = 1; ! 135: if (preen) ! 136: printf(" (FIXED)\n"); ! 137: if (preen || reply("SET TO DEFAULT") == 1) { ! 138: sbdirty(); ! 139: dirty(&asblk); ! 140: } ! 141: } ! 142: if (sblock.fs_npsect < sblock.fs_nsect) { ! 143: pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK", ! 144: sblock.fs_npsect); ! 145: sblock.fs_npsect = sblock.fs_nsect; ! 146: if (preen) ! 147: printf(" (FIXED)\n"); ! 148: if (preen || reply("SET TO DEFAULT") == 1) { ! 149: sbdirty(); ! 150: dirty(&asblk); ! 151: } ! 152: } ! 153: if (cvtflag) { ! 154: if (sblock.fs_postblformat == FS_42POSTBLFMT) { ! 155: /* ! 156: * Requested to convert from old format to new format ! 157: */ ! 158: if (preen) ! 159: pwarn("CONVERTING TO NEW FILE SYSTEM FORMAT\n"); ! 160: else if (!reply("CONVERT TO NEW FILE SYSTEM FORMAT")) ! 161: return(0); ! 162: sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; ! 163: sblock.fs_nrpos = 8; ! 164: sblock.fs_postbloff = ! 165: (char *)(&sblock.fs_opostbl[0][0]) - ! 166: (char *)(&sblock.fs_link); ! 167: sblock.fs_rotbloff = &sblock.fs_space[0] - ! 168: (u_char *)(&sblock.fs_link); ! 169: /* ! 170: * Planning now for future expansion. ! 171: */ ! 172: # if (BYTE_ORDER == BIG_ENDIAN) ! 173: sblock.fs_qbmask.val[0] = 0; ! 174: sblock.fs_qbmask.val[1] = ~sblock.fs_bmask; ! 175: sblock.fs_qfmask.val[0] = 0; ! 176: sblock.fs_qfmask.val[1] = ~sblock.fs_fmask; ! 177: # endif /* BIG_ENDIAN */ ! 178: # if (BYTE_ORDER == LITTLE_ENDIAN) ! 179: sblock.fs_qbmask.val[0] = ~sblock.fs_bmask; ! 180: sblock.fs_qbmask.val[1] = 0; ! 181: sblock.fs_qfmask.val[0] = ~sblock.fs_fmask; ! 182: sblock.fs_qfmask.val[1] = 0; ! 183: # endif /* LITTLE_ENDIAN */ ! 184: sbdirty(); ! 185: dirty(&asblk); ! 186: } else if (sblock.fs_postblformat == FS_DYNAMICPOSTBLFMT) { ! 187: /* ! 188: * Requested to convert from new format to old format ! 189: */ ! 190: if (sblock.fs_nrpos != 8 || sblock.fs_ipg > 2048 || ! 191: sblock.fs_cpg > 32 || sblock.fs_cpc > 16) { ! 192: printf( ! 193: "PARAMETERS OF CURRENT FILE SYSTEM DO NOT\n\t"); ! 194: errexit( ! 195: "ALLOW CONVERSION TO OLD FILE SYSTEM FORMAT\n"); ! 196: } ! 197: if (preen) ! 198: pwarn("CONVERTING TO OLD FILE SYSTEM FORMAT\n"); ! 199: else if (!reply("CONVERT TO OLD FILE SYSTEM FORMAT")) ! 200: return(0); ! 201: sblock.fs_postblformat = FS_42POSTBLFMT; ! 202: sbdirty(); ! 203: dirty(&asblk); ! 204: } else { ! 205: errexit("UNKNOWN FILE SYSTEM FORMAT\n"); ! 206: } ! 207: } ! 208: if (asblk.b_dirty) { ! 209: bcopy((char *)&sblock, (char *)&altsblock, sblock.fs_sbsize); ! 210: flush(&dfile, &asblk); ! 211: } ! 212: /* ! 213: * read in the summary info. ! 214: */ ! 215: asked = 0; ! 216: for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { ! 217: size = sblock.fs_cssize - i < sblock.fs_bsize ? ! 218: sblock.fs_cssize - i : sblock.fs_bsize; ! 219: sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size); ! 220: if (bread(&dfile, (char *)sblock.fs_csp[j], ! 221: fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), ! 222: size) != 0 && !asked) { ! 223: pfatal("BAD SUMMARY INFORMATION"); ! 224: if (reply("CONTINUE") == 0) ! 225: errexit(""); ! 226: asked++; ! 227: } ! 228: } ! 229: /* ! 230: * allocate and initialize the necessary maps ! 231: */ ! 232: bmapsz = roundup(howmany(fmax, NBBY), sizeof(short)); ! 233: blockmap = calloc((unsigned)bmapsz, sizeof (char)); ! 234: if (blockmap == NULL) { ! 235: printf("cannot alloc %d bytes for blockmap\n", bmapsz); ! 236: goto badsb; ! 237: } ! 238: statemap = calloc((unsigned)(imax + 1), sizeof(char)); ! 239: if (statemap == NULL) { ! 240: printf("cannot alloc %d bytes for statemap\n", imax + 1); ! 241: goto badsb; ! 242: } ! 243: lncntp = (short *)calloc((unsigned)(imax + 1), sizeof(short)); ! 244: if (lncntp == NULL) { ! 245: printf("cannot alloc %d bytes for lncntp\n", ! 246: (imax + 1) * sizeof(short)); ! 247: goto badsb; ! 248: } ! 249: ! 250: bufinit(); ! 251: return (1); ! 252: ! 253: badsb: ! 254: ckfini(); ! 255: return (0); ! 256: } ! 257: ! 258: /* ! 259: * Read in the super block and its summary info. ! 260: */ ! 261: readsb(listerr) ! 262: int listerr; ! 263: { ! 264: off_t sboff; ! 265: daddr_t super = bflag ? bflag : SBOFF / dev_bsize; ! 266: ! 267: if (bread(&dfile, (char *)&sblock, super, (long)SBSIZE) != 0) ! 268: return (0); ! 269: sblk.b_bno = super; ! 270: sblk.b_size = SBSIZE; ! 271: /* ! 272: * run a few consistency checks of the super block ! 273: */ ! 274: if (sblock.fs_magic != FS_MAGIC) ! 275: { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); } ! 276: if (sblock.fs_ncg < 1) ! 277: { badsb(listerr, "NCG OUT OF RANGE"); return (0); } ! 278: if (sblock.fs_cpg < 1) ! 279: { badsb(listerr, "CPG OUT OF RANGE"); return (0); } ! 280: if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || ! 281: (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) ! 282: { badsb(listerr, "NCYL LESS THAN NCG*CPG"); return (0); } ! 283: if (sblock.fs_sbsize > SBSIZE) ! 284: { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); } ! 285: /* ! 286: * Compute block size that the filesystem is based on, ! 287: * according to fsbtodb, and adjust superblock block number ! 288: * so we can tell if this is an alternate later. ! 289: */ ! 290: super *= dev_bsize; ! 291: dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); ! 292: sblk.b_bno = super / dev_bsize; ! 293: /* ! 294: * Set all possible fields that could differ, then do check ! 295: * of whole super block against an alternate super block. ! 296: * When an alternate super-block is specified this check is skipped. ! 297: */ ! 298: getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize); ! 299: if (asblk.b_errs != NULL) ! 300: return (0); ! 301: if (bflag) { ! 302: havesb = 1; ! 303: return (1); ! 304: } ! 305: altsblock.fs_link = sblock.fs_link; ! 306: altsblock.fs_rlink = sblock.fs_rlink; ! 307: altsblock.fs_time = sblock.fs_time; ! 308: altsblock.fs_cstotal = sblock.fs_cstotal; ! 309: altsblock.fs_cgrotor = sblock.fs_cgrotor; ! 310: altsblock.fs_fmod = sblock.fs_fmod; ! 311: altsblock.fs_clean = sblock.fs_clean; ! 312: altsblock.fs_ronly = sblock.fs_ronly; ! 313: altsblock.fs_flags = sblock.fs_flags; ! 314: altsblock.fs_maxcontig = sblock.fs_maxcontig; ! 315: altsblock.fs_minfree = sblock.fs_minfree; ! 316: altsblock.fs_optim = sblock.fs_optim; ! 317: altsblock.fs_rotdelay = sblock.fs_rotdelay; ! 318: altsblock.fs_maxbpg = sblock.fs_maxbpg; ! 319: bcopy((char *)sblock.fs_csp, (char *)altsblock.fs_csp, ! 320: sizeof sblock.fs_csp); ! 321: bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt, ! 322: sizeof sblock.fs_fsmnt); ! 323: bcopy((char *)sblock.fs_sparecon, (char *)altsblock.fs_sparecon, ! 324: sizeof sblock.fs_sparecon); ! 325: /* ! 326: * The following should not have to be copied. ! 327: */ ! 328: altsblock.fs_fsbtodb = sblock.fs_fsbtodb; ! 329: altsblock.fs_interleave = sblock.fs_interleave; ! 330: altsblock.fs_npsect = sblock.fs_npsect; ! 331: altsblock.fs_nrpos = sblock.fs_nrpos; ! 332: if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) { ! 333: badsb(listerr, ! 334: "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); ! 335: return (0); ! 336: } ! 337: havesb = 1; ! 338: return (1); ! 339: } ! 340: ! 341: badsb(listerr, s) ! 342: int listerr; ! 343: char *s; ! 344: { ! 345: ! 346: if (!listerr) ! 347: return; ! 348: if (preen) ! 349: printf("%s: ", devname); ! 350: pfatal("BAD SUPER BLOCK: %s\n", s); ! 351: } ! 352: ! 353: /* ! 354: * Calculate a prototype superblock based on information in the disk label. ! 355: * When done the cgsblock macro can be calculated and the fs_ncg field ! 356: * can be used. Do NOT attempt to use other macros without verifying that ! 357: * their needed information is available! ! 358: */ ! 359: calcsb(dev, devfd, fs) ! 360: char *dev; ! 361: int devfd; ! 362: register struct fs *fs; ! 363: { ! 364: register struct disklabel *lp; ! 365: register struct partition *pp; ! 366: register char *cp; ! 367: int i; ! 368: struct disklabel *getdisklabel(); ! 369: ! 370: cp = index(dev, '\0') - 1; ! 371: if (cp == (char *)-1 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) { ! 372: pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); ! 373: return (0); ! 374: } ! 375: lp = getdisklabel(dev, devfd); ! 376: if (isdigit(*cp)) ! 377: pp = &lp->d_partitions[0]; ! 378: else ! 379: pp = &lp->d_partitions[*cp - 'a']; ! 380: if (pp->p_fstype != FS_BSDFFS) { ! 381: pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", ! 382: dev, pp->p_fstype < FSMAXTYPES ? ! 383: fstypenames[pp->p_fstype] : "unknown"); ! 384: return (0); ! 385: } ! 386: bzero(fs, sizeof(struct fs)); ! 387: fs->fs_fsize = pp->p_fsize; ! 388: fs->fs_frag = pp->p_frag; ! 389: fs->fs_cpg = pp->p_cpg; ! 390: fs->fs_size = pp->p_size; ! 391: fs->fs_ntrak = lp->d_ntracks; ! 392: fs->fs_nsect = lp->d_nsectors; ! 393: fs->fs_spc = lp->d_secpercyl; ! 394: fs->fs_nspf = fs->fs_fsize / lp->d_secsize; ! 395: fs->fs_sblkno = roundup( ! 396: howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize), ! 397: fs->fs_frag); ! 398: fs->fs_cgmask = 0xffffffff; ! 399: for (i = fs->fs_ntrak; i > 1; i >>= 1) ! 400: fs->fs_cgmask <<= 1; ! 401: if (!POWEROF2(fs->fs_ntrak)) ! 402: fs->fs_cgmask <<= 1; ! 403: fs->fs_cgoffset = roundup( ! 404: howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag); ! 405: fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs); ! 406: fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg); ! 407: for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1) ! 408: fs->fs_fsbtodb++; ! 409: dev_bsize = lp->d_secsize; ! 410: return (1); ! 411: } ! 412: ! 413: struct disklabel * ! 414: getdisklabel(s, fd) ! 415: char *s; ! 416: int fd; ! 417: { ! 418: static struct disklabel lab; ! 419: ! 420: if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { ! 421: if (s == NULL) ! 422: return ((struct disklabel *)NULL); ! 423: pwarn(""); ! 424: perror("ioctl (GDINFO)"); ! 425: errexit("%s: can't read disk label", s); ! 426: } ! 427: return (&lab); ! 428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.