4.3BSD beta release manual page
[unix-history] / usr / src / sbin / fsck / inode.c
index 5e09b97..a6c724f 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef lint
 #ifndef lint
-static char version[] = "@(#)inode.c   3.1 (Berkeley) %G%";
+static char version[] = "@(#)inode.c   3.10 (Berkeley) %G%";
 #endif
 
 #endif
 
+#include <pwd.h>
 #include <sys/param.h>
 #include <sys/inode.h>
 #include <sys/fs.h>
 #include <sys/param.h>
 #include <sys/inode.h>
 #include <sys/fs.h>
@@ -16,11 +17,12 @@ ckinode(dp, idesc)
        int ret, n, ndb, offset;
        DINODE dino;
 
        int ret, n, ndb, offset;
        DINODE dino;
 
-       if (SPECIAL)
-               return (KEEPON);
-       dino = *dp;
        idesc->id_fix = DONTKNOW;
        idesc->id_entryno = 0;
        idesc->id_fix = DONTKNOW;
        idesc->id_entryno = 0;
+       idesc->id_filesize = dp->di_size;
+       if (SPECIAL(dp))
+               return (KEEPON);
+       dino = *dp;
        ndb = howmany(dino.di_size, sblock.fs_bsize);
        for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
                if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
        ndb = howmany(dino.di_size, sblock.fs_bsize);
        for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
                if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
@@ -39,7 +41,7 @@ ckinode(dp, idesc)
                        return (ret);
        }
        idesc->id_numfrags = sblock.fs_frag;
                        return (ret);
        }
        idesc->id_numfrags = sblock.fs_frag;
-       for (ap = &dino.di_ib[0], n = 1; n <= 2; ap++, n++) {
+       for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
                if (*ap) {
                        idesc->id_blkno = *ap;
                        ret = iblock(idesc, n,
                if (*ap) {
                        idesc->id_blkno = *ap;
                        ret = iblock(idesc, n,
@@ -58,8 +60,9 @@ iblock(idesc, ilevel, isize)
 {
        register daddr_t *ap;
        register daddr_t *aplim;
 {
        register daddr_t *ap;
        register daddr_t *aplim;
-       int i, n, (*func)(), nif;
+       int i, n, (*func)(), nif, sizepb;
        BUFAREA ib;
        BUFAREA ib;
+       extern int pass1check();
 
        if (idesc->id_type == ADDR) {
                func = idesc->id_func;
 
        if (idesc->id_type == ADDR) {
                func = idesc->id_func;
@@ -73,20 +76,29 @@ iblock(idesc, ilevel, isize)
        if (getblk(&ib, idesc->id_blkno, sblock.fs_bsize) == NULL)
                return (SKIP);
        ilevel--;
        if (getblk(&ib, idesc->id_blkno, sblock.fs_bsize) == NULL)
                return (SKIP);
        ilevel--;
-       if (ilevel == 0) {
-               nif = lblkno(&sblock, isize) + 1;
-       } else /* ilevel == 1 */ {
-               nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1;
-       }
+       for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
+               sizepb *= NINDIR(&sblock);
+       nif = isize / sizepb + 1;
        if (nif > NINDIR(&sblock))
                nif = NINDIR(&sblock);
        if (nif > NINDIR(&sblock))
                nif = NINDIR(&sblock);
+       if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
+               aplim = &ib.b_un.b_indir[NINDIR(&sblock)];
+               for (ap = &ib.b_un.b_indir[nif]; ap < aplim; ap++) {
+                       if (*ap == 0)
+                               continue;
+                       if (dofix(idesc, "PARTIALLY TRUNCATED INODE")) {
+                               *ap = 0;
+                               dirty(&ib);
+                       }
+               }
+               flush(&dfile, &ib);
+       }
        aplim = &ib.b_un.b_indir[nif];
        for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
                if (*ap) {
                        idesc->id_blkno = *ap;
                        if (ilevel > 0)
        aplim = &ib.b_un.b_indir[nif];
        for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
                if (*ap) {
                        idesc->id_blkno = *ap;
                        if (ilevel > 0)
-                               n = iblock(idesc, ilevel,
-                                   isize - i*NINDIR(&sblock)*sblock.fs_bsize);
+                               n = iblock(idesc, ilevel, isize - i * sizepb);
                        else
                                n = (*func)(idesc);
                        if (n & STOP)
                        else
                                n = (*func)(idesc);
                        if (n & STOP)
@@ -136,11 +148,8 @@ ginode(inumber)
        static ino_t startinum = 0;     /* blk num of first in raw area */
 
 
        static ino_t startinum = 0;     /* blk num of first in raw area */
 
 
-       if (inumber < ROOTINO || inumber > imax) {
-               if (debug && inumber > imax)
-                       printf("inumber out of range (%d)\n", inumber);
-               return (NULL);
-       }
+       if (inumber < ROOTINO || inumber > imax)
+               errexit("bad inode number %d to ginode\n", inumber);
        if (startinum == 0 ||
            inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
                iblk = itod(&sblock, inumber);
        if (startinum == 0 ||
            inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
                iblk = itod(&sblock, inumber);
@@ -159,10 +168,9 @@ clri(idesc, s, flg)
 {
        register DINODE *dp;
 
 {
        register DINODE *dp;
 
-       if ((dp = ginode(idesc->id_number)) == NULL)
-               return;
+       dp = ginode(idesc->id_number);
        if (flg == 1) {
        if (flg == 1) {
-               pwarn("%s %s", s, DIRCT?"DIR":"FILE");
+               pwarn("%s %s", s, DIRCT(dp) ? "DIR" : "FILE");
                pinode(idesc->id_number);
        }
        if (preen || reply("CLEAR") == 1) {
                pinode(idesc->id_number);
        }
        if (preen || reply("CLEAR") == 1) {
@@ -173,10 +181,20 @@ clri(idesc, s, flg)
                zapino(dp);
                statemap[idesc->id_number] = USTATE;
                inodirty();
                zapino(dp);
                statemap[idesc->id_number] = USTATE;
                inodirty();
-               inosumbad++;
        }
 }
 
        }
 }
 
+findname(idesc)
+       struct inodesc *idesc;
+{
+       register DIRECT *dirp = idesc->id_dirp;
+
+       if (dirp->d_ino != idesc->id_parent)
+               return (KEEPON);
+       bcopy(dirp->d_name, idesc->id_name, dirp->d_namlen + 1);
+       return (STOP);
+}
+
 findino(idesc)
        struct inodesc *idesc;
 {
 findino(idesc)
        struct inodesc *idesc;
 {
@@ -184,9 +202,9 @@ findino(idesc)
 
        if (dirp->d_ino == 0)
                return (KEEPON);
 
        if (dirp->d_ino == 0)
                return (KEEPON);
-       if (!strcmp(dirp->d_name, srchname)) {
-               if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax)
-                       idesc->id_parent = dirp->d_ino;
+       if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
+           dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) {
+               idesc->id_parent = dirp->d_ino;
                return (STOP);
        }
        return (KEEPON);
                return (STOP);
        }
        return (KEEPON);
@@ -197,21 +215,18 @@ pinode(ino)
 {
        register DINODE *dp;
        register char *p;
 {
        register DINODE *dp;
        register char *p;
-       char uidbuf[BUFSIZ];
+       struct passwd *pw;
        char *ctime();
 
        printf(" I=%u ", ino);
        char *ctime();
 
        printf(" I=%u ", ino);
-       if ((dp = ginode(ino)) == NULL)
+       if (ino < ROOTINO || ino > imax)
                return;
                return;
+       dp = ginode(ino);
        printf(" OWNER=");
        printf(" OWNER=");
-       if (getpw((int)dp->di_uid, uidbuf) == 0) {
-               for (p = uidbuf; *p != ':'; p++);
-               *p = 0;
-               printf("%s ", uidbuf);
-       }
-       else {
+       if ((pw = getpwuid((int)dp->di_uid)) != 0)
+               printf("%s ", pw->pw_name);
+       else
                printf("%d ", dp->di_uid);
                printf("%d ", dp->di_uid);
-       }
        printf("MODE=%o\n", dp->di_mode);
        if (preen)
                printf("%s: ", devname);
        printf("MODE=%o\n", dp->di_mode);
        if (preen)
                printf("%s: ", devname);
@@ -228,5 +243,91 @@ blkerr(ino, s, blk)
 
        pfatal("%ld %s I=%u", blk, s, ino);
        printf("\n");
 
        pfatal("%ld %s I=%u", blk, s, ino);
        printf("\n");
-       statemap[ino] = CLEAR;
+       switch (statemap[ino]) {
+
+       case FSTATE:
+               statemap[ino] = FCLEAR;
+               return;
+
+       case DSTATE:
+               statemap[ino] = DCLEAR;
+               return;
+
+       case FCLEAR:
+       case DCLEAR:
+               return;
+
+       default:
+               errexit("BAD STATE %d TO BLKERR", statemap[ino]);
+               /* NOTREACHED */
+       }
+}
+
+/*
+ * allocate an unused inode
+ */
+ino_t
+allocino(request, type)
+       ino_t request;
+       int type;
+{
+       register ino_t ino;
+       register DINODE *dp;
+
+       if (request == 0)
+               request = ROOTINO;
+       else if (statemap[request] != USTATE)
+               return (0);
+       for (ino = request; ino < imax; ino++)
+               if (statemap[ino] == USTATE)
+                       break;
+       if (ino == imax)
+               return (0);
+       switch (type & IFMT) {
+       case IFDIR:
+               statemap[ino] = DSTATE;
+               break;
+       case IFREG:
+       case IFLNK:
+               statemap[ino] = FSTATE;
+               break;
+       default:
+               return (0);
+       }
+       dp = ginode(ino);
+       dp->di_db[0] = allocblk(1);
+       if (dp->di_db[0] == 0) {
+               statemap[ino] = USTATE;
+               return (0);
+       }
+       dp->di_mode = type;
+       time(&dp->di_atime);
+       dp->di_mtime = dp->di_ctime = dp->di_atime;
+       dp->di_size = sblock.fs_fsize;
+       dp->di_blocks = btodb(sblock.fs_fsize);
+       n_files++;
+       inodirty();
+       return (ino);
+}
+
+/*
+ * deallocate an inode
+ */
+freeino(ino)
+       ino_t ino;
+{
+       struct inodesc idesc;
+       extern int pass4check();
+       DINODE *dp;
+
+       bzero((char *)&idesc, sizeof(struct inodesc));
+       idesc.id_type = ADDR;
+       idesc.id_func = pass4check;
+       idesc.id_number = ino;
+       dp = ginode(ino);
+       (void)ckinode(dp, &idesc);
+       zapino(dp);
+       inodirty();
+       statemap[ino] = USTATE;
+       n_files--;
 }
 }