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