|
|
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[] = "@(#)dir.c 5.18 (Berkeley) 7/20/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #include <sys/param.h> ! 25: #include <ufs/dinode.h> ! 26: #include <ufs/fs.h> ! 27: #define KERNEL ! 28: #include <ufs/dir.h> ! 29: #undef KERNEL ! 30: #include <stdlib.h> ! 31: #include <string.h> ! 32: #include "fsck.h" ! 33: ! 34: char *lfname = "lost+found"; ! 35: int lfmode = 01777; ! 36: struct dirtemplate emptydir = { 0, DIRBLKSIZ }; ! 37: struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." }; ! 38: ! 39: struct direct *fsck_readdir(); ! 40: struct bufarea *getdirblk(); ! 41: ! 42: /* ! 43: * Propagate connected state through the tree. ! 44: */ ! 45: propagate() ! 46: { ! 47: register struct inoinfo **inpp, *inp; ! 48: struct inoinfo **inpend; ! 49: long change; ! 50: ! 51: inpend = &inpsort[inplast]; ! 52: do { ! 53: change = 0; ! 54: for (inpp = inpsort; inpp < inpend; inpp++) { ! 55: inp = *inpp; ! 56: if (inp->i_parent == 0) ! 57: continue; ! 58: if (statemap[inp->i_parent] == DFOUND && ! 59: statemap[inp->i_number] == DSTATE) { ! 60: statemap[inp->i_number] = DFOUND; ! 61: change++; ! 62: } ! 63: } ! 64: } while (change > 0); ! 65: } ! 66: ! 67: /* ! 68: * Scan each entry in a directory block. ! 69: */ ! 70: dirscan(idesc) ! 71: register struct inodesc *idesc; ! 72: { ! 73: register struct direct *dp; ! 74: register struct bufarea *bp; ! 75: int dsize, n; ! 76: long blksiz; ! 77: char dbuf[DIRBLKSIZ]; ! 78: ! 79: if (idesc->id_type != DATA) ! 80: errexit("wrong type to dirscan %d\n", idesc->id_type); ! 81: if (idesc->id_entryno == 0 && ! 82: (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0) ! 83: idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ); ! 84: blksiz = idesc->id_numfrags * sblock.fs_fsize; ! 85: if (chkrange(idesc->id_blkno, idesc->id_numfrags)) { ! 86: idesc->id_filesize -= blksiz; ! 87: return (SKIP); ! 88: } ! 89: idesc->id_loc = 0; ! 90: for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) { ! 91: dsize = dp->d_reclen; ! 92: bcopy((char *)dp, dbuf, (size_t)dsize); ! 93: idesc->id_dirp = (struct direct *)dbuf; ! 94: if ((n = (*idesc->id_func)(idesc)) & ALTERED) { ! 95: bp = getdirblk(idesc->id_blkno, blksiz); ! 96: bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize, ! 97: (size_t)dsize); ! 98: dirty(bp); ! 99: sbdirty(); ! 100: } ! 101: if (n & STOP) ! 102: return (n); ! 103: } ! 104: return (idesc->id_filesize > 0 ? KEEPON : STOP); ! 105: } ! 106: ! 107: /* ! 108: * get next entry in a directory. ! 109: */ ! 110: struct direct * ! 111: fsck_readdir(idesc) ! 112: register struct inodesc *idesc; ! 113: { ! 114: register struct direct *dp, *ndp; ! 115: register struct bufarea *bp; ! 116: long size, blksiz, fix; ! 117: ! 118: blksiz = idesc->id_numfrags * sblock.fs_fsize; ! 119: bp = getdirblk(idesc->id_blkno, blksiz); ! 120: if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && ! 121: idesc->id_loc < blksiz) { ! 122: dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); ! 123: if (dircheck(idesc, dp)) ! 124: goto dpok; ! 125: idesc->id_loc += DIRBLKSIZ; ! 126: idesc->id_filesize -= DIRBLKSIZ; ! 127: fix = dofix(idesc, "DIRECTORY CORRUPTED"); ! 128: bp = getdirblk(idesc->id_blkno, blksiz); ! 129: dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); ! 130: dp->d_reclen = DIRBLKSIZ; ! 131: dp->d_ino = 0; ! 132: dp->d_namlen = 0; ! 133: dp->d_name[0] = '\0'; ! 134: if (fix) ! 135: dirty(bp); ! 136: return (dp); ! 137: } ! 138: dpok: ! 139: if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) ! 140: return NULL; ! 141: dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); ! 142: idesc->id_loc += dp->d_reclen; ! 143: idesc->id_filesize -= dp->d_reclen; ! 144: if ((idesc->id_loc % DIRBLKSIZ) == 0) ! 145: return (dp); ! 146: ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); ! 147: if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && ! 148: dircheck(idesc, ndp) == 0) { ! 149: size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); ! 150: idesc->id_loc += size; ! 151: idesc->id_filesize -= size; ! 152: fix = dofix(idesc, "DIRECTORY CORRUPTED"); ! 153: bp = getdirblk(idesc->id_blkno, blksiz); ! 154: dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); ! 155: dp->d_reclen += size; ! 156: if (fix) ! 157: dirty(bp); ! 158: } ! 159: return (dp); ! 160: } ! 161: ! 162: /* ! 163: * Verify that a directory entry is valid. ! 164: * This is a superset of the checks made in the kernel. ! 165: */ ! 166: dircheck(idesc, dp) ! 167: struct inodesc *idesc; ! 168: register struct direct *dp; ! 169: { ! 170: register int size; ! 171: register char *cp; ! 172: int spaceleft; ! 173: ! 174: size = DIRSIZ(dp); ! 175: spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); ! 176: if (dp->d_ino < maxino && ! 177: dp->d_reclen != 0 && ! 178: dp->d_reclen <= spaceleft && ! 179: (dp->d_reclen & 0x3) == 0 && ! 180: dp->d_reclen >= size && ! 181: idesc->id_filesize >= size && ! 182: dp->d_namlen <= MAXNAMLEN) { ! 183: if (dp->d_ino == 0) ! 184: return (1); ! 185: for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++) ! 186: if (*cp == 0 || (*cp++ == '/')) ! 187: return (0); ! 188: if (*cp == 0) ! 189: return (1); ! 190: } ! 191: return (0); ! 192: } ! 193: ! 194: direrror(ino, errmesg) ! 195: ino_t ino; ! 196: char *errmesg; ! 197: { ! 198: ! 199: fileerror(ino, ino, errmesg); ! 200: } ! 201: ! 202: fileerror(cwd, ino, errmesg) ! 203: ino_t cwd, ino; ! 204: char *errmesg; ! 205: { ! 206: register struct dinode *dp; ! 207: char pathbuf[MAXPATHLEN + 1]; ! 208: ! 209: pwarn("%s ", errmesg); ! 210: pinode(ino); ! 211: printf("\n"); ! 212: getpathname(pathbuf, cwd, ino); ! 213: if (ino < ROOTINO || ino > maxino) { ! 214: pfatal("NAME=%s\n", pathbuf); ! 215: return; ! 216: } ! 217: dp = ginode(ino); ! 218: if (ftypeok(dp)) ! 219: pfatal("%s=%s\n", ! 220: (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); ! 221: else ! 222: pfatal("NAME=%s\n", pathbuf); ! 223: } ! 224: ! 225: adjust(idesc, lcnt) ! 226: register struct inodesc *idesc; ! 227: short lcnt; ! 228: { ! 229: register struct dinode *dp; ! 230: ! 231: dp = ginode(idesc->id_number); ! 232: if (dp->di_nlink == lcnt) { ! 233: if (linkup(idesc->id_number, (ino_t)0) == 0) ! 234: clri(idesc, "UNREF", 0); ! 235: } else { ! 236: pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : ! 237: ((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE")); ! 238: pinode(idesc->id_number); ! 239: printf(" COUNT %d SHOULD BE %d", ! 240: dp->di_nlink, dp->di_nlink - lcnt); ! 241: if (preen) { ! 242: if (lcnt < 0) { ! 243: printf("\n"); ! 244: pfatal("LINK COUNT INCREASING"); ! 245: } ! 246: printf(" (ADJUSTED)\n"); ! 247: } ! 248: if (preen || reply("ADJUST") == 1) { ! 249: dp->di_nlink -= lcnt; ! 250: inodirty(); ! 251: } ! 252: } ! 253: } ! 254: ! 255: mkentry(idesc) ! 256: struct inodesc *idesc; ! 257: { ! 258: register struct direct *dirp = idesc->id_dirp; ! 259: struct direct newent; ! 260: int newlen, oldlen; ! 261: ! 262: newent.d_namlen = strlen(idesc->id_name); ! 263: newlen = DIRSIZ(&newent); ! 264: if (dirp->d_ino != 0) ! 265: oldlen = DIRSIZ(dirp); ! 266: else ! 267: oldlen = 0; ! 268: if (dirp->d_reclen - oldlen < newlen) ! 269: return (KEEPON); ! 270: newent.d_reclen = dirp->d_reclen - oldlen; ! 271: dirp->d_reclen = oldlen; ! 272: dirp = (struct direct *)(((char *)dirp) + oldlen); ! 273: dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ ! 274: dirp->d_reclen = newent.d_reclen; ! 275: dirp->d_namlen = newent.d_namlen; ! 276: bcopy(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); ! 277: return (ALTERED|STOP); ! 278: } ! 279: ! 280: chgino(idesc) ! 281: struct inodesc *idesc; ! 282: { ! 283: register struct direct *dirp = idesc->id_dirp; ! 284: ! 285: if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1)) ! 286: return (KEEPON); ! 287: dirp->d_ino = idesc->id_parent; ! 288: return (ALTERED|STOP); ! 289: } ! 290: ! 291: linkup(orphan, parentdir) ! 292: ino_t orphan; ! 293: ino_t parentdir; ! 294: { ! 295: register struct dinode *dp; ! 296: int lostdir; ! 297: ino_t oldlfdir; ! 298: struct inodesc idesc; ! 299: char tempname[BUFSIZ]; ! 300: extern int pass4check(); ! 301: ! 302: bzero((char *)&idesc, sizeof(struct inodesc)); ! 303: dp = ginode(orphan); ! 304: lostdir = (dp->di_mode & IFMT) == IFDIR; ! 305: pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); ! 306: pinode(orphan); ! 307: if (preen && dp->di_size == 0) ! 308: return (0); ! 309: if (preen) ! 310: printf(" (RECONNECTED)\n"); ! 311: else ! 312: if (reply("RECONNECT") == 0) ! 313: return (0); ! 314: if (lfdir == 0) { ! 315: dp = ginode(ROOTINO); ! 316: idesc.id_name = lfname; ! 317: idesc.id_type = DATA; ! 318: idesc.id_func = findino; ! 319: idesc.id_number = ROOTINO; ! 320: if ((ckinode(dp, &idesc) & FOUND) != 0) { ! 321: lfdir = idesc.id_parent; ! 322: } else { ! 323: pwarn("NO lost+found DIRECTORY"); ! 324: if (preen || reply("CREATE")) { ! 325: lfdir = allocdir(ROOTINO, (ino_t)0, lfmode); ! 326: if (lfdir != 0) { ! 327: if (makeentry(ROOTINO, lfdir, lfname) != 0) { ! 328: if (preen) ! 329: printf(" (CREATED)\n"); ! 330: } else { ! 331: freedir(lfdir, ROOTINO); ! 332: lfdir = 0; ! 333: if (preen) ! 334: printf("\n"); ! 335: } ! 336: } ! 337: } ! 338: } ! 339: if (lfdir == 0) { ! 340: pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY"); ! 341: printf("\n\n"); ! 342: return (0); ! 343: } ! 344: } ! 345: dp = ginode(lfdir); ! 346: if ((dp->di_mode & IFMT) != IFDIR) { ! 347: pfatal("lost+found IS NOT A DIRECTORY"); ! 348: if (reply("REALLOCATE") == 0) ! 349: return (0); ! 350: oldlfdir = lfdir; ! 351: if ((lfdir = allocdir(ROOTINO, (ino_t)0, lfmode)) == 0) { ! 352: pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); ! 353: return (0); ! 354: } ! 355: if ((changeino(ROOTINO, lfname, lfdir) & ALTERED) == 0) { ! 356: pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); ! 357: return (0); ! 358: } ! 359: inodirty(); ! 360: idesc.id_type = ADDR; ! 361: idesc.id_func = pass4check; ! 362: idesc.id_number = oldlfdir; ! 363: adjust(&idesc, lncntp[oldlfdir] + 1); ! 364: lncntp[oldlfdir] = 0; ! 365: dp = ginode(lfdir); ! 366: } ! 367: if (statemap[lfdir] != DFOUND) { ! 368: pfatal("SORRY. NO lost+found DIRECTORY\n\n"); ! 369: return (0); ! 370: } ! 371: (void)lftempname(tempname, orphan); ! 372: if (makeentry(lfdir, orphan, tempname) == 0) { ! 373: pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); ! 374: printf("\n\n"); ! 375: return (0); ! 376: } ! 377: lncntp[orphan]--; ! 378: if (lostdir) { ! 379: if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 && ! 380: parentdir != (ino_t)-1) ! 381: (void)makeentry(orphan, lfdir, ".."); ! 382: dp = ginode(lfdir); ! 383: dp->di_nlink++; ! 384: inodirty(); ! 385: lncntp[lfdir]++; ! 386: pwarn("DIR I=%lu CONNECTED. ", orphan); ! 387: if (parentdir != (ino_t)-1) ! 388: printf("PARENT WAS I=%lu\n", parentdir); ! 389: if (preen == 0) ! 390: printf("\n"); ! 391: } ! 392: return (1); ! 393: } ! 394: ! 395: /* ! 396: * fix an entry in a directory. ! 397: */ ! 398: changeino(dir, name, newnum) ! 399: ino_t dir; ! 400: char *name; ! 401: ino_t newnum; ! 402: { ! 403: struct inodesc idesc; ! 404: ! 405: bzero((char *)&idesc, sizeof(struct inodesc)); ! 406: idesc.id_type = DATA; ! 407: idesc.id_func = chgino; ! 408: idesc.id_number = dir; ! 409: idesc.id_fix = DONTKNOW; ! 410: idesc.id_name = name; ! 411: idesc.id_parent = newnum; /* new value for name */ ! 412: return (ckinode(ginode(dir), &idesc)); ! 413: } ! 414: ! 415: /* ! 416: * make an entry in a directory ! 417: */ ! 418: makeentry(parent, ino, name) ! 419: ino_t parent, ino; ! 420: char *name; ! 421: { ! 422: struct dinode *dp; ! 423: struct inodesc idesc; ! 424: char pathbuf[MAXPATHLEN + 1]; ! 425: ! 426: if (parent < ROOTINO || parent >= maxino || ! 427: ino < ROOTINO || ino >= maxino) ! 428: return (0); ! 429: bzero((char *)&idesc, sizeof(struct inodesc)); ! 430: idesc.id_type = DATA; ! 431: idesc.id_func = mkentry; ! 432: idesc.id_number = parent; ! 433: idesc.id_parent = ino; /* this is the inode to enter */ ! 434: idesc.id_fix = DONTKNOW; ! 435: idesc.id_name = name; ! 436: dp = ginode(parent); ! 437: if (dp->di_size % DIRBLKSIZ) { ! 438: dp->di_size = roundup(dp->di_size, DIRBLKSIZ); ! 439: inodirty(); ! 440: } ! 441: if ((ckinode(dp, &idesc) & ALTERED) != 0) ! 442: return (1); ! 443: getpathname(pathbuf, parent, parent); ! 444: dp = ginode(parent); ! 445: if (expanddir(dp, pathbuf) == 0) ! 446: return (0); ! 447: return (ckinode(dp, &idesc) & ALTERED); ! 448: } ! 449: ! 450: /* ! 451: * Attempt to expand the size of a directory ! 452: */ ! 453: expanddir(dp, name) ! 454: register struct dinode *dp; ! 455: char *name; ! 456: { ! 457: daddr_t lastbn, newblk; ! 458: register struct bufarea *bp; ! 459: char *cp, firstblk[DIRBLKSIZ]; ! 460: ! 461: lastbn = lblkno(&sblock, dp->di_size); ! 462: if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0) ! 463: return (0); ! 464: if ((newblk = allocblk(sblock.fs_frag)) == 0) ! 465: return (0); ! 466: dp->di_db[lastbn + 1] = dp->di_db[lastbn]; ! 467: dp->di_db[lastbn] = newblk; ! 468: dp->di_size += sblock.fs_bsize; ! 469: dp->di_blocks += btodb(sblock.fs_bsize); ! 470: bp = getdirblk(dp->di_db[lastbn + 1], ! 471: (long)dblksize(&sblock, dp, lastbn + 1)); ! 472: if (bp->b_errs) ! 473: goto bad; ! 474: bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ); ! 475: bp = getdirblk(newblk, sblock.fs_bsize); ! 476: if (bp->b_errs) ! 477: goto bad; ! 478: bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ); ! 479: for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; ! 480: cp < &bp->b_un.b_buf[sblock.fs_bsize]; ! 481: cp += DIRBLKSIZ) ! 482: bcopy((char *)&emptydir, cp, sizeof emptydir); ! 483: dirty(bp); ! 484: bp = getdirblk(dp->di_db[lastbn + 1], ! 485: (long)dblksize(&sblock, dp, lastbn + 1)); ! 486: if (bp->b_errs) ! 487: goto bad; ! 488: bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir); ! 489: pwarn("NO SPACE LEFT IN %s", name); ! 490: if (preen) ! 491: printf(" (EXPANDED)\n"); ! 492: else if (reply("EXPAND") == 0) ! 493: goto bad; ! 494: dirty(bp); ! 495: inodirty(); ! 496: return (1); ! 497: bad: ! 498: dp->di_db[lastbn] = dp->di_db[lastbn + 1]; ! 499: dp->di_db[lastbn + 1] = 0; ! 500: dp->di_size -= sblock.fs_bsize; ! 501: dp->di_blocks -= btodb(sblock.fs_bsize); ! 502: freeblk(newblk, sblock.fs_frag); ! 503: return (0); ! 504: } ! 505: ! 506: /* ! 507: * allocate a new directory ! 508: */ ! 509: allocdir(parent, request, mode) ! 510: ino_t parent, request; ! 511: int mode; ! 512: { ! 513: ino_t ino; ! 514: char *cp; ! 515: struct dinode *dp; ! 516: register struct bufarea *bp; ! 517: ! 518: ino = allocino(request, IFDIR|mode); ! 519: dirhead.dot_ino = ino; ! 520: dirhead.dotdot_ino = parent; ! 521: dp = ginode(ino); ! 522: bp = getdirblk(dp->di_db[0], sblock.fs_fsize); ! 523: if (bp->b_errs) { ! 524: freeino(ino); ! 525: return (0); ! 526: } ! 527: bcopy((char *)&dirhead, bp->b_un.b_buf, sizeof dirhead); ! 528: for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; ! 529: cp < &bp->b_un.b_buf[sblock.fs_fsize]; ! 530: cp += DIRBLKSIZ) ! 531: bcopy((char *)&emptydir, cp, sizeof emptydir); ! 532: dirty(bp); ! 533: dp->di_nlink = 2; ! 534: inodirty(); ! 535: if (ino == ROOTINO) { ! 536: lncntp[ino] = dp->di_nlink; ! 537: return(ino); ! 538: } ! 539: if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) { ! 540: freeino(ino); ! 541: return (0); ! 542: } ! 543: statemap[ino] = statemap[parent]; ! 544: if (statemap[ino] == DSTATE) { ! 545: lncntp[ino] = dp->di_nlink; ! 546: lncntp[parent]++; ! 547: } ! 548: dp = ginode(parent); ! 549: dp->di_nlink++; ! 550: inodirty(); ! 551: return (ino); ! 552: } ! 553: ! 554: /* ! 555: * free a directory inode ! 556: */ ! 557: freedir(ino, parent) ! 558: ino_t ino, parent; ! 559: { ! 560: struct dinode *dp; ! 561: ! 562: if (ino != parent) { ! 563: dp = ginode(parent); ! 564: dp->di_nlink--; ! 565: inodirty(); ! 566: } ! 567: freeino(ino); ! 568: } ! 569: ! 570: /* ! 571: * generate a temporary name for the lost+found directory. ! 572: */ ! 573: lftempname(bufp, ino) ! 574: char *bufp; ! 575: ino_t ino; ! 576: { ! 577: register ino_t in; ! 578: register char *cp; ! 579: int namlen; ! 580: ! 581: cp = bufp + 2; ! 582: for (in = maxino; in > 0; in /= 10) ! 583: cp++; ! 584: *--cp = 0; ! 585: namlen = cp - bufp; ! 586: in = ino; ! 587: while (cp > bufp) { ! 588: *--cp = (in % 10) + '0'; ! 589: in /= 10; ! 590: } ! 591: *cp = '#'; ! 592: return (namlen); ! 593: } ! 594: ! 595: /* ! 596: * Get a directory block. ! 597: * Insure that it is held until another is requested. ! 598: */ ! 599: struct bufarea * ! 600: getdirblk(blkno, size) ! 601: daddr_t blkno; ! 602: long size; ! 603: { ! 604: ! 605: if (pdirbp != 0) ! 606: pdirbp->b_flags &= ~B_INUSE; ! 607: pdirbp = getdatablk(blkno, size); ! 608: return (pdirbp); ! 609: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.