X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/042f816f70f6d4695c6ff152356fe4452d466aad..d53fc3db616522c41d9a8b98f122f5c03c71f70e:/usr/src/sbin/fsck/dir.c diff --git a/usr/src/sbin/fsck/dir.c b/usr/src/sbin/fsck/dir.c index f9771eedc4..56dc498b7d 100644 --- a/usr/src/sbin/fsck/dir.c +++ b/usr/src/sbin/fsck/dir.c @@ -1,6 +1,12 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + #ifndef lint -static char version[] = "@(#)dir.c 3.10 (Berkeley) %G%"; -#endif +static char sccsid[] = "@(#)dir.c 5.4 (Berkeley) %G%"; +#endif not lint #include #include @@ -18,6 +24,7 @@ struct dirtemplate emptydir = { 0, DIRBLKSIZ }; struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." }; DIRECT *fsck_readdir(); +BUFAREA *getdirblk(); descend(parentino, inumber) struct inodesc *parentino; @@ -43,17 +50,32 @@ descend(parentino, inumber) if (reply("FIX") == 1) inodirty(); } + if ((dp->di_size & (DIRBLKSIZ - 1)) != 0) { + pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d", + pathname, dp->di_size, DIRBLKSIZ); + dp->di_size = roundup(dp->di_size, DIRBLKSIZ); + if (preen) + printf(" (ADJUSTED)\n"); + if (preen || reply("ADJUST") == 1) + inodirty(); + } curino.id_type = DATA; curino.id_func = parentino->id_func; curino.id_parent = parentino->id_number; curino.id_number = inumber; (void)ckinode(dp, &curino); + if (curino.id_entryno < 2) { + direrr(inumber, "NULL DIRECTORY"); + if (reply("REMOVE") == 1) + statemap[inumber] = DCLEAR; + } } dirscan(idesc) register struct inodesc *idesc; { register DIRECT *dp; + register BUFAREA *bp; int dsize, n; long blksiz; char dbuf[DIRBLKSIZ]; @@ -74,12 +96,10 @@ dirscan(idesc) bcopy((char *)dp, dbuf, dsize); idesc->id_dirp = (DIRECT *)dbuf; if ((n = (*idesc->id_func)(idesc)) & ALTERED) { - if (getblk(&fileblk, idesc->id_blkno, blksiz) != NULL) { - bcopy(dbuf, (char *)dp, dsize); - dirty(&fileblk); - sbdirty(); - } else - n &= ~ALTERED; + bp = getdirblk(idesc->id_blkno, blksiz); + bcopy(dbuf, (char *)dp, dsize); + dirty(bp); + sbdirty(); } if (n & STOP) return (n); @@ -95,16 +115,14 @@ fsck_readdir(idesc) register struct inodesc *idesc; { register DIRECT *dp, *ndp; + register BUFAREA *bp; long size, blksiz; blksiz = idesc->id_numfrags * sblock.fs_fsize; - if (getblk(&fileblk, idesc->id_blkno, blksiz) == NULL) { - idesc->id_filesize -= blksiz - idesc->id_loc; - return NULL; - } + bp = getdirblk(idesc->id_blkno, blksiz); if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && idesc->id_loc < blksiz) { - dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); + dp = (DIRECT *)(bp->b_un.b_buf + idesc->id_loc); if (dircheck(idesc, dp)) goto dpok; idesc->id_loc += DIRBLKSIZ; @@ -114,18 +132,18 @@ fsck_readdir(idesc) dp->d_namlen = 0; dp->d_name[0] = '\0'; if (dofix(idesc, "DIRECTORY CORRUPTED")) - dirty(&fileblk); + dirty(bp); return (dp); } dpok: if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) return NULL; - dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); + dp = (DIRECT *)(bp->b_un.b_buf + idesc->id_loc); idesc->id_loc += dp->d_reclen; idesc->id_filesize -= dp->d_reclen; if ((idesc->id_loc % DIRBLKSIZ) == 0) return (dp); - ndp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); + ndp = (DIRECT *)(bp->b_un.b_buf + idesc->id_loc); if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && dircheck(idesc, ndp) == 0) { size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); @@ -133,7 +151,7 @@ dpok: idesc->id_loc += size; idesc->id_filesize -= size; if (dofix(idesc, "DIRECTORY CORRUPTED")) - dirty(&fileblk); + dirty(bp); } return (dp); } @@ -288,8 +306,7 @@ linkup(orphan, pdir) idesc.id_type = DATA; idesc.id_func = findino; idesc.id_number = ROOTINO; - (void)ckinode(dp, &idesc); - if (idesc.id_parent >= ROOTINO && idesc.id_parent < imax) { + if ((ckinode(dp, &idesc) & FOUND) != 0) { lfdir = idesc.id_parent; } else { pwarn("NO lost+found DIRECTORY"); @@ -356,7 +373,7 @@ linkup(orphan, pdir) } lncntp[orphan]--; *pathp++ = '/'; - bcopy(idesc.id_name, pathp, len + 1); + bcopy(tempname, pathp, len + 1); pathp += len; if (lostdir) { dp = ginode(orphan); @@ -417,6 +434,7 @@ expanddir(dp) register DINODE *dp; { daddr_t lastbn, newblk; + register BUFAREA *bp; char *cp, firstblk[DIRBLKSIZ]; lastbn = lblkno(&sblock, dp->di_size); @@ -428,28 +446,31 @@ expanddir(dp) dp->di_db[lastbn] = newblk; dp->di_size += sblock.fs_bsize; dp->di_blocks += btodb(sblock.fs_bsize); - if (getblk(&fileblk, dp->di_db[lastbn + 1], - dblksize(&sblock, dp, lastbn + 1)) == NULL) + bp = getdirblk(dp->di_db[lastbn + 1], + dblksize(&sblock, dp, lastbn + 1)); + if (bp->b_errs != NULL) goto bad; - bcopy(dirblk.b_buf, firstblk, DIRBLKSIZ); - if (getblk(&fileblk, newblk, sblock.fs_bsize) == NULL) + bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ); + bp = getdirblk(newblk, sblock.fs_bsize); + if (bp->b_errs != NULL) goto bad; - bcopy(firstblk, dirblk.b_buf, DIRBLKSIZ); - for (cp = &dirblk.b_buf[DIRBLKSIZ]; - cp < &dirblk.b_buf[sblock.fs_bsize]; + bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ); + for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; + cp < &bp->b_un.b_buf[sblock.fs_bsize]; cp += DIRBLKSIZ) bcopy((char *)&emptydir, cp, sizeof emptydir); - dirty(&fileblk); - if (getblk(&fileblk, dp->di_db[lastbn + 1], - dblksize(&sblock, dp, lastbn + 1)) == NULL) + dirty(bp); + bp = getdirblk(dp->di_db[lastbn + 1], + dblksize(&sblock, dp, lastbn + 1)); + if (bp->b_errs != NULL) goto bad; - bcopy((char *)&emptydir, dirblk.b_buf, sizeof emptydir); + bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir); pwarn("NO SPACE LEFT IN %s", pathname); if (preen) printf(" (EXPANDED)\n"); else if (reply("EXPAND") == 0) goto bad; - dirty(&fileblk); + dirty(bp); inodirty(); return (1); bad: @@ -470,21 +491,23 @@ allocdir(parent, request) ino_t ino; char *cp; DINODE *dp; + register BUFAREA *bp; ino = allocino(request, IFDIR|0755); dirhead.dot_ino = ino; dirhead.dotdot_ino = parent; dp = ginode(ino); - if (getblk(&fileblk, dp->di_db[0], sblock.fs_fsize) == NULL) { + bp = getdirblk(dp->di_db[0], sblock.fs_fsize); + if (bp->b_errs != NULL) { freeino(ino); return (0); } - bcopy((char *)&dirhead, dirblk.b_buf, sizeof dirhead); - for (cp = &dirblk.b_buf[DIRBLKSIZ]; - cp < &dirblk.b_buf[sblock.fs_fsize]; + bcopy((char *)&dirhead, bp->b_un.b_buf, sizeof dirhead); + for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; + cp < &bp->b_un.b_buf[sblock.fs_fsize]; cp += DIRBLKSIZ) bcopy((char *)&emptydir, cp, sizeof emptydir); - dirty(&fileblk); + dirty(bp); dp->di_nlink = 2; inodirty(); if (ino == ROOTINO) { @@ -546,3 +569,20 @@ lftempname(bufp, ino) *cp = '#'; return (namlen); } + +/* + * Get a directory block. + * Insure that it is held until another is requested. + */ +BUFAREA * +getdirblk(blkno, size) + daddr_t blkno; + long size; +{ + static BUFAREA *pbp = 0; + + if (pbp != 0) + pbp->b_flags &= ~B_INUSE; + pbp = getdatablk(blkno, size); + return (pbp); +}