|
|
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[] = "@(#)inode.c 5.17 (Berkeley) 7/27/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #include <sys/param.h> ! 25: #include <ufs/dinode.h> ! 26: #include <ufs/fs.h> ! 27: #include <ufs/dir.h> ! 28: #include <pwd.h> ! 29: #include <stdlib.h> ! 30: #include <string.h> ! 31: #include "fsck.h" ! 32: ! 33: static ino_t startinum; ! 34: ! 35: ckinode(dp, idesc) ! 36: struct dinode *dp; ! 37: register struct inodesc *idesc; ! 38: { ! 39: register daddr_t *ap; ! 40: long ret, n, ndb, offset; ! 41: struct dinode dino; ! 42: ! 43: if (idesc->id_fix != IGNORE) ! 44: idesc->id_fix = DONTKNOW; ! 45: idesc->id_entryno = 0; ! 46: idesc->id_filesize = dp->di_size; ! 47: if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR) ! 48: return (KEEPON); ! 49: dino = *dp; ! 50: ndb = howmany(dino.di_size, sblock.fs_bsize); ! 51: for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { ! 52: if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) ! 53: idesc->id_numfrags = ! 54: numfrags(&sblock, fragroundup(&sblock, offset)); ! 55: else ! 56: idesc->id_numfrags = sblock.fs_frag; ! 57: if (*ap == 0) ! 58: continue; ! 59: idesc->id_blkno = *ap; ! 60: if (idesc->id_type == ADDR) ! 61: ret = (*idesc->id_func)(idesc); ! 62: else ! 63: ret = dirscan(idesc); ! 64: if (ret & STOP) ! 65: return (ret); ! 66: } ! 67: idesc->id_numfrags = sblock.fs_frag; ! 68: for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { ! 69: if (*ap) { ! 70: idesc->id_blkno = *ap; ! 71: ret = iblock(idesc, n, ! 72: dino.di_size - sblock.fs_bsize * NDADDR); ! 73: if (ret & STOP) ! 74: return (ret); ! 75: } ! 76: } ! 77: return (KEEPON); ! 78: } ! 79: ! 80: iblock(idesc, ilevel, isize) ! 81: struct inodesc *idesc; ! 82: register long ilevel; ! 83: u_long isize; ! 84: { ! 85: register daddr_t *ap; ! 86: register daddr_t *aplim; ! 87: int i, n, (*func)(), nif, sizepb; ! 88: register struct bufarea *bp; ! 89: char buf[BUFSIZ]; ! 90: extern int dirscan(), pass1check(); ! 91: ! 92: if (idesc->id_type == ADDR) { ! 93: func = idesc->id_func; ! 94: if (((n = (*func)(idesc)) & KEEPON) == 0) ! 95: return (n); ! 96: } else ! 97: func = dirscan; ! 98: if (chkrange(idesc->id_blkno, idesc->id_numfrags)) ! 99: return (SKIP); ! 100: bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); ! 101: ilevel--; ! 102: for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) ! 103: sizepb *= NINDIR(&sblock); ! 104: nif = isize / sizepb + 1; ! 105: if (nif > NINDIR(&sblock)) ! 106: nif = NINDIR(&sblock); ! 107: if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { ! 108: aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; ! 109: for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { ! 110: if (*ap == 0) ! 111: continue; ! 112: (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", ! 113: idesc->id_number); ! 114: if (dofix(idesc, buf)) { ! 115: *ap = 0; ! 116: dirty(bp); ! 117: } ! 118: } ! 119: flush(fswritefd, bp); ! 120: } ! 121: aplim = &bp->b_un.b_indir[nif]; ! 122: for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) { ! 123: if (*ap) { ! 124: idesc->id_blkno = *ap; ! 125: if (ilevel > 0) ! 126: n = iblock(idesc, ilevel, isize - i * sizepb); ! 127: else ! 128: n = (*func)(idesc); ! 129: if (n & STOP) { ! 130: bp->b_flags &= ~B_INUSE; ! 131: return (n); ! 132: } ! 133: } ! 134: } ! 135: bp->b_flags &= ~B_INUSE; ! 136: return (KEEPON); ! 137: } ! 138: ! 139: /* ! 140: * Check that a block in a legal block number. ! 141: * Return 0 if in range, 1 if out of range. ! 142: */ ! 143: chkrange(blk, cnt) ! 144: daddr_t blk; ! 145: int cnt; ! 146: { ! 147: register int c; ! 148: ! 149: if ((unsigned)(blk + cnt) > maxfsblock) ! 150: return (1); ! 151: c = dtog(&sblock, blk); ! 152: if (blk < cgdmin(&sblock, c)) { ! 153: if ((blk + cnt) > cgsblock(&sblock, c)) { ! 154: if (debug) { ! 155: printf("blk %ld < cgdmin %ld;", ! 156: blk, cgdmin(&sblock, c)); ! 157: printf(" blk + cnt %ld > cgsbase %ld\n", ! 158: blk + cnt, cgsblock(&sblock, c)); ! 159: } ! 160: return (1); ! 161: } ! 162: } else { ! 163: if ((blk + cnt) > cgbase(&sblock, c+1)) { ! 164: if (debug) { ! 165: printf("blk %ld >= cgdmin %ld;", ! 166: blk, cgdmin(&sblock, c)); ! 167: printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", ! 168: blk+cnt, sblock.fs_fpg); ! 169: } ! 170: return (1); ! 171: } ! 172: } ! 173: return (0); ! 174: } ! 175: ! 176: /* ! 177: * General purpose interface for reading inodes. ! 178: */ ! 179: struct dinode * ! 180: ginode(inumber) ! 181: ino_t inumber; ! 182: { ! 183: daddr_t iblk; ! 184: ! 185: if (inumber < ROOTINO || inumber > maxino) ! 186: errexit("bad inode number %d to ginode\n", inumber); ! 187: if (startinum == 0 || ! 188: inumber < startinum || inumber >= startinum + INOPB(&sblock)) { ! 189: iblk = itod(&sblock, inumber); ! 190: if (pbp != 0) ! 191: pbp->b_flags &= ~B_INUSE; ! 192: pbp = getdatablk(iblk, sblock.fs_bsize); ! 193: startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); ! 194: } ! 195: return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); ! 196: } ! 197: ! 198: /* ! 199: * Special purpose version of ginode used to optimize first pass ! 200: * over all the inodes in numerical order. ! 201: */ ! 202: ino_t nextino, lastinum; ! 203: long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; ! 204: struct dinode *inodebuf; ! 205: ! 206: struct dinode * ! 207: getnextinode(inumber) ! 208: ino_t inumber; ! 209: { ! 210: long size; ! 211: daddr_t dblk; ! 212: static struct dinode *dp; ! 213: ! 214: if (inumber != nextino++ || inumber > maxino) ! 215: errexit("bad inode number %d to nextinode\n", inumber); ! 216: if (inumber >= lastinum) { ! 217: readcnt++; ! 218: dblk = fsbtodb(&sblock, itod(&sblock, lastinum)); ! 219: if (readcnt % readpercg == 0) { ! 220: size = partialsize; ! 221: lastinum += partialcnt; ! 222: } else { ! 223: size = inobufsize; ! 224: lastinum += fullcnt; ! 225: } ! 226: (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */ ! 227: dp = inodebuf; ! 228: } ! 229: return (dp++); ! 230: } ! 231: ! 232: resetinodebuf() ! 233: { ! 234: ! 235: startinum = 0; ! 236: nextino = 0; ! 237: lastinum = 0; ! 238: readcnt = 0; ! 239: inobufsize = blkroundup(&sblock, INOBUFSIZE); ! 240: fullcnt = inobufsize / sizeof(struct dinode); ! 241: readpercg = sblock.fs_ipg / fullcnt; ! 242: partialcnt = sblock.fs_ipg % fullcnt; ! 243: partialsize = partialcnt * sizeof(struct dinode); ! 244: if (partialcnt != 0) { ! 245: readpercg++; ! 246: } else { ! 247: partialcnt = fullcnt; ! 248: partialsize = inobufsize; ! 249: } ! 250: if (inodebuf == NULL && ! 251: (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) ! 252: errexit("Cannot allocate space for inode buffer\n"); ! 253: while (nextino < ROOTINO) ! 254: (void)getnextinode(nextino); ! 255: } ! 256: ! 257: freeinodebuf() ! 258: { ! 259: ! 260: if (inodebuf != NULL) ! 261: free((char *)inodebuf); ! 262: inodebuf = NULL; ! 263: } ! 264: ! 265: /* ! 266: * Routines to maintain information about directory inodes. ! 267: * This is built during the first pass and used during the ! 268: * second and third passes. ! 269: * ! 270: * Enter inodes into the cache. ! 271: */ ! 272: cacheino(dp, inumber) ! 273: register struct dinode *dp; ! 274: ino_t inumber; ! 275: { ! 276: register struct inoinfo *inp; ! 277: struct inoinfo **inpp; ! 278: unsigned int blks; ! 279: ! 280: blks = howmany(dp->di_size, sblock.fs_bsize); ! 281: if (blks > NDADDR) ! 282: blks = NDADDR + NIADDR; ! 283: inp = (struct inoinfo *) ! 284: malloc(sizeof(*inp) + (blks - 1) * sizeof(daddr_t)); ! 285: if (inp == NULL) ! 286: return; ! 287: inpp = &inphead[inumber % numdirs]; ! 288: inp->i_nexthash = *inpp; ! 289: *inpp = inp; ! 290: inp->i_parent = (ino_t)0; ! 291: inp->i_dotdot = (ino_t)0; ! 292: inp->i_number = inumber; ! 293: inp->i_isize = dp->di_size; ! 294: inp->i_numblks = blks * sizeof(daddr_t); ! 295: bcopy((char *)&dp->di_db[0], (char *)&inp->i_blks[0], ! 296: (size_t)inp->i_numblks); ! 297: if (inplast == listmax) { ! 298: listmax += 100; ! 299: inpsort = (struct inoinfo **)realloc((char *)inpsort, ! 300: (unsigned)listmax * sizeof(struct inoinfo *)); ! 301: if (inpsort == NULL) ! 302: errexit("cannot increase directory list"); ! 303: } ! 304: inpsort[inplast++] = inp; ! 305: } ! 306: ! 307: /* ! 308: * Look up an inode cache structure. ! 309: */ ! 310: struct inoinfo * ! 311: getinoinfo(inumber) ! 312: ino_t inumber; ! 313: { ! 314: register struct inoinfo *inp; ! 315: ! 316: for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { ! 317: if (inp->i_number != inumber) ! 318: continue; ! 319: return (inp); ! 320: } ! 321: errexit("cannot find inode %d\n", inumber); ! 322: return ((struct inoinfo *)0); ! 323: } ! 324: ! 325: /* ! 326: * Clean up all the inode cache structure. ! 327: */ ! 328: inocleanup() ! 329: { ! 330: register struct inoinfo **inpp; ! 331: ! 332: if (inphead == NULL) ! 333: return; ! 334: for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) ! 335: free((char *)(*inpp)); ! 336: free((char *)inphead); ! 337: free((char *)inpsort); ! 338: inphead = inpsort = NULL; ! 339: } ! 340: ! 341: inodirty() ! 342: { ! 343: ! 344: dirty(pbp); ! 345: } ! 346: ! 347: clri(idesc, type, flag) ! 348: register struct inodesc *idesc; ! 349: char *type; ! 350: int flag; ! 351: { ! 352: register struct dinode *dp; ! 353: ! 354: dp = ginode(idesc->id_number); ! 355: if (flag == 1) { ! 356: pwarn("%s %s", type, ! 357: (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); ! 358: pinode(idesc->id_number); ! 359: } ! 360: if (preen || reply("CLEAR") == 1) { ! 361: if (preen) ! 362: printf(" (CLEARED)\n"); ! 363: n_files--; ! 364: (void)ckinode(dp, idesc); ! 365: clearinode(dp); ! 366: statemap[idesc->id_number] = USTATE; ! 367: inodirty(); ! 368: } ! 369: } ! 370: ! 371: findname(idesc) ! 372: struct inodesc *idesc; ! 373: { ! 374: register struct direct *dirp = idesc->id_dirp; ! 375: ! 376: if (dirp->d_ino != idesc->id_parent) ! 377: return (KEEPON); ! 378: bcopy(dirp->d_name, idesc->id_name, (size_t)dirp->d_namlen + 1); ! 379: return (STOP|FOUND); ! 380: } ! 381: ! 382: findino(idesc) ! 383: struct inodesc *idesc; ! 384: { ! 385: register struct direct *dirp = idesc->id_dirp; ! 386: ! 387: if (dirp->d_ino == 0) ! 388: return (KEEPON); ! 389: if (strcmp(dirp->d_name, idesc->id_name) == 0 && ! 390: dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { ! 391: idesc->id_parent = dirp->d_ino; ! 392: return (STOP|FOUND); ! 393: } ! 394: return (KEEPON); ! 395: } ! 396: ! 397: pinode(ino) ! 398: ino_t ino; ! 399: { ! 400: register struct dinode *dp; ! 401: register char *p; ! 402: struct passwd *pw; ! 403: char *ctime(); ! 404: ! 405: printf(" I=%lu ", ino); ! 406: if (ino < ROOTINO || ino > maxino) ! 407: return; ! 408: dp = ginode(ino); ! 409: printf(" OWNER="); ! 410: if ((pw = getpwuid((int)dp->di_uid)) != 0) ! 411: printf("%s ", pw->pw_name); ! 412: else ! 413: printf("%u ", (unsigned)dp->di_uid); ! 414: printf("MODE=%o\n", dp->di_mode); ! 415: if (preen) ! 416: printf("%s: ", devname); ! 417: printf("SIZE=%lu ", dp->di_size); ! 418: p = ctime(&dp->di_mtime); ! 419: printf("MTIME=%12.12s %4.4s ", p + 4, p + 20); ! 420: } ! 421: ! 422: blkerror(ino, type, blk) ! 423: ino_t ino; ! 424: char *type; ! 425: daddr_t blk; ! 426: { ! 427: ! 428: pfatal("%ld %s I=%lu", blk, type, ino); ! 429: printf("\n"); ! 430: switch (statemap[ino]) { ! 431: ! 432: case FSTATE: ! 433: statemap[ino] = FCLEAR; ! 434: return; ! 435: ! 436: case DSTATE: ! 437: statemap[ino] = DCLEAR; ! 438: return; ! 439: ! 440: case FCLEAR: ! 441: case DCLEAR: ! 442: return; ! 443: ! 444: default: ! 445: errexit("BAD STATE %d TO BLKERR", statemap[ino]); ! 446: /* NOTREACHED */ ! 447: } ! 448: } ! 449: ! 450: /* ! 451: * allocate an unused inode ! 452: */ ! 453: ino_t ! 454: allocino(request, type) ! 455: ino_t request; ! 456: int type; ! 457: { ! 458: register ino_t ino; ! 459: register struct dinode *dp; ! 460: ! 461: if (request == 0) ! 462: request = ROOTINO; ! 463: else if (statemap[request] != USTATE) ! 464: return (0); ! 465: for (ino = request; ino < maxino; ino++) ! 466: if (statemap[ino] == USTATE) ! 467: break; ! 468: if (ino == maxino) ! 469: return (0); ! 470: switch (type & IFMT) { ! 471: case IFDIR: ! 472: statemap[ino] = DSTATE; ! 473: break; ! 474: case IFREG: ! 475: case IFLNK: ! 476: statemap[ino] = FSTATE; ! 477: break; ! 478: default: ! 479: return (0); ! 480: } ! 481: dp = ginode(ino); ! 482: dp->di_db[0] = allocblk((long)1); ! 483: if (dp->di_db[0] == 0) { ! 484: statemap[ino] = USTATE; ! 485: return (0); ! 486: } ! 487: dp->di_mode = type; ! 488: (void)time(&dp->di_atime); ! 489: dp->di_mtime = dp->di_ctime = dp->di_atime; ! 490: dp->di_size = sblock.fs_fsize; ! 491: dp->di_blocks = btodb(sblock.fs_fsize); ! 492: n_files++; ! 493: inodirty(); ! 494: return (ino); ! 495: } ! 496: ! 497: /* ! 498: * deallocate an inode ! 499: */ ! 500: freeino(ino) ! 501: ino_t ino; ! 502: { ! 503: struct inodesc idesc; ! 504: extern int pass4check(); ! 505: struct dinode *dp; ! 506: ! 507: bzero((char *)&idesc, sizeof(struct inodesc)); ! 508: idesc.id_type = ADDR; ! 509: idesc.id_func = pass4check; ! 510: idesc.id_number = ino; ! 511: dp = ginode(ino); ! 512: (void)ckinode(dp, &idesc); ! 513: clearinode(dp); ! 514: inodirty(); ! 515: statemap[ino] = USTATE; ! 516: n_files--; ! 517: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.