+/*
+ * 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 <sys/param.h>
#include <sys/inode.h>
struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." };
DIRECT *fsck_readdir();
+BUFAREA *getdirblk();
descend(parentino, inumber)
struct inodesc *parentino;
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];
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);
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;
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);
idesc->id_loc += size;
idesc->id_filesize -= size;
if (dofix(idesc, "DIRECTORY CORRUPTED"))
- dirty(&fileblk);
+ dirty(bp);
}
return (dp);
}
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");
}
lncntp[orphan]--;
*pathp++ = '/';
- bcopy(idesc.id_name, pathp, len + 1);
+ bcopy(tempname, pathp, len + 1);
pathp += len;
if (lostdir) {
dp = ginode(orphan);
register DINODE *dp;
{
daddr_t lastbn, newblk;
+ register BUFAREA *bp;
char *cp, firstblk[DIRBLKSIZ];
lastbn = lblkno(&sblock, dp->di_size);
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:
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) {
*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);
+}