1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if !defined(lint) && defined(DOSCCS)
   8: static char sccsid[] = "@(#)pass2.c	5.2 (Berkeley) 3/5/86";
   9: #endif not lint
  10: 
  11: #include <sys/param.h>
  12: #include <sys/inode.h>
  13: #include <sys/fs.h>
  14: #include <sys/dir.h>
  15: #include <strings.h>
  16: #include "fsck.h"
  17: 
  18: int pass2check();
  19: 
  20: pass2()
  21: {
  22:     register DINODE *dp;
  23:     struct inodesc rootdesc;
  24: 
  25:     bzero((char *)&rootdesc, sizeof(struct inodesc));
  26:     rootdesc.id_type = ADDR;
  27:     rootdesc.id_func = pass2check;
  28:     rootdesc.id_number = ROOTINO;
  29:     pathp = pathname;
  30:     switch (getstate(ROOTINO)) {
  31: 
  32:     case USTATE:
  33:         pfatal("ROOT INODE UNALLOCATED");
  34:         if (reply("ALLOCATE") == 0)
  35:             errexit("");
  36:         if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
  37:             errexit("CANNOT ALLOCATE ROOT INODE\n");
  38:         descend(&rootdesc, ROOTINO);
  39:         break;
  40: 
  41:     case DCLEAR:
  42:         pfatal("DUPS/BAD IN ROOT INODE");
  43:         if (reply("REALLOCATE")) {
  44:             freeino(ROOTINO);
  45:             if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
  46:                 errexit("CANNOT ALLOCATE ROOT INODE\n");
  47:             descend(&rootdesc, ROOTINO);
  48:             break;
  49:         }
  50:         if (reply("CONTINUE") == 0)
  51:             errexit("");
  52:         setstate(ROOTINO, DSTATE);
  53:         descend(&rootdesc, ROOTINO);
  54:         break;
  55: 
  56:     case FSTATE:
  57:     case FCLEAR:
  58:         pfatal("ROOT INODE NOT DIRECTORY");
  59:         if (reply("REALLOCATE")) {
  60:             freeino(ROOTINO);
  61:             if (allocdir(ROOTINO, ROOTINO) != ROOTINO)
  62:                 errexit("CANNOT ALLOCATE ROOT INODE\n");
  63:             descend(&rootdesc, ROOTINO);
  64:             break;
  65:         }
  66:         if (reply("FIX") == 0)
  67:             errexit("");
  68:         dp = ginode(ROOTINO);
  69:         dp->di_mode &= ~IFMT;
  70:         dp->di_mode |= IFDIR;
  71:         inodirty();
  72:         setstate(ROOTINO, DSTATE);
  73:         /* fall into ... */
  74: 
  75:     case DSTATE:
  76:         descend(&rootdesc, ROOTINO);
  77:         break;
  78: 
  79:     default:
  80:         errexit("BAD STATE %d FOR ROOT INODE", getstate(ROOTINO));
  81:     }
  82: }
  83: 
  84: pass2check(idesc)
  85:     struct inodesc *idesc;
  86: {
  87:     register DIRECT *dirp = idesc->id_dirp;
  88:     char *curpathloc;
  89:     int n, entrysize, ret = 0;
  90:     DINODE *dp;
  91:     static DIRECT proto;
  92:     static char namebuf[MAXPATHLEN];
  93: 
  94:     /*
  95: 	 * check for "."
  96: 	 */
  97:     if (idesc->id_entryno != 0)
  98:         goto chk1;
  99:     if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
 100:         if (dirp->d_ino != idesc->id_number) {
 101:             direrr(idesc->id_number, "BAD INODE NUMBER FOR '.'");
 102:             dirp->d_ino = idesc->id_number;
 103:             if (reply("FIX") == 1)
 104:                 ret |= ALTERED;
 105:         }
 106:         goto chk1;
 107:     }
 108:     direrr(idesc->id_number, "MISSING '.'");
 109:     proto.d_ino = idesc->id_number;
 110:     proto.d_namlen = 1;
 111:     (void)strcpy(proto.d_name, ".");
 112:     entrysize = DIRSIZ(&proto);
 113:     if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
 114:         pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
 115:             dirp->d_name);
 116:     } else if (dirp->d_reclen < entrysize) {
 117:         pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
 118:     } else if (dirp->d_reclen < 2 * entrysize) {
 119:         proto.d_reclen = dirp->d_reclen;
 120:         bcopy((char *)&proto, (char *)dirp, entrysize);
 121:         if (reply("FIX") == 1)
 122:             ret |= ALTERED;
 123:     } else {
 124:         n = dirp->d_reclen - entrysize;
 125:         proto.d_reclen = entrysize;
 126:         bcopy((char *)&proto, (char *)dirp, entrysize);
 127:         idesc->id_entryno++;
 128:         declncnt(dirp->d_ino);
 129:         dirp = (DIRECT *)((char *)(dirp) + entrysize);
 130:         bzero((char *)dirp, n);
 131:         dirp->d_reclen = n;
 132:         if (reply("FIX") == 1)
 133:             ret |= ALTERED;
 134:     }
 135: chk1:
 136:     if (idesc->id_entryno > 1)
 137:         goto chk2;
 138:     proto.d_ino = idesc->id_parent;
 139:     proto.d_namlen = 2;
 140:     (void)strcpy(proto.d_name, "..");
 141:     entrysize = DIRSIZ(&proto);
 142:     if (idesc->id_entryno == 0) {
 143:         n = DIRSIZ(dirp);
 144:         if (dirp->d_reclen < n + entrysize)
 145:             goto chk2;
 146:         proto.d_reclen = dirp->d_reclen - n;
 147:         dirp->d_reclen = n;
 148:         idesc->id_entryno++;
 149:         declncnt(dirp->d_ino);
 150:         dirp = (DIRECT *)((char *)(dirp) + n);
 151:         bzero((char *)dirp, n);
 152:         dirp->d_reclen = n;
 153:     }
 154:     if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
 155:         if (dirp->d_ino != idesc->id_parent) {
 156:             direrr(idesc->id_number, "BAD INODE NUMBER FOR '..'");
 157:             dirp->d_ino = idesc->id_parent;
 158:             if (reply("FIX") == 1)
 159:                 ret |= ALTERED;
 160:         }
 161:         goto chk2;
 162:     }
 163:     direrr(idesc->id_number, "MISSING '..'");
 164:     if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
 165:         pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
 166:             dirp->d_name);
 167:     } else if (dirp->d_reclen < entrysize) {
 168:         pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
 169:     } else {
 170:         proto.d_reclen = dirp->d_reclen;
 171:         bcopy((char *)&proto, (char *)dirp, entrysize);
 172:         if (reply("FIX") == 1)
 173:             ret |= ALTERED;
 174:     }
 175: chk2:
 176:     if (dirp->d_ino == 0)
 177:         return (ret|KEEPON);
 178:     if (dirp->d_namlen <= 2 &&
 179:         dirp->d_name[0] == '.' &&
 180:         idesc->id_entryno >= 2) {
 181:         if (dirp->d_namlen == 1) {
 182:             direrr(idesc->id_number, "EXTRA '.' ENTRY");
 183:             dirp->d_ino = 0;
 184:             if (reply("FIX") == 1)
 185:                 ret |= ALTERED;
 186:             return (KEEPON | ret);
 187:         }
 188:         if (dirp->d_name[1] == '.') {
 189:             direrr(idesc->id_number, "EXTRA '..' ENTRY");
 190:             dirp->d_ino = 0;
 191:             if (reply("FIX") == 1)
 192:                 ret |= ALTERED;
 193:             return (KEEPON | ret);
 194:         }
 195:     }
 196:     curpathloc = pathp;
 197:     *pathp++ = '/';
 198:     if (pathp + dirp->d_namlen >= endpathname) {
 199:         *pathp = '\0';
 200:         errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
 201:     }
 202:     bcopy(dirp->d_name, pathp, dirp->d_namlen + 1);
 203:     pathp += dirp->d_namlen;
 204:     idesc->id_entryno++;
 205:     n = 0;
 206:     if (dirp->d_ino > imax || dirp->d_ino <= 0) {
 207:         direrr(dirp->d_ino, "I OUT OF RANGE");
 208:         n = reply("REMOVE");
 209:     } else {
 210: again:
 211:         switch (getstate(dirp->d_ino)) {
 212:         case USTATE:
 213:             direrr(dirp->d_ino, "UNALLOCATED");
 214:             n = reply("REMOVE");
 215:             break;
 216: 
 217:         case DCLEAR:
 218:         case FCLEAR:
 219:             direrr(dirp->d_ino, "DUP/BAD");
 220:             if ((n = reply("REMOVE")) == 1)
 221:                 break;
 222:             dp = ginode(dirp->d_ino);
 223:             setstate(dirp->d_ino, DIRCT(dp) ? DSTATE : FSTATE);
 224:             goto again;
 225: 
 226:         case DFOUND:
 227:             if (idesc->id_entryno > 2) {
 228:                 getpathname(namebuf, dirp->d_ino, dirp->d_ino);
 229:                 pwarn("%s %s %s\n", pathname,
 230:                     "IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
 231:                     namebuf);
 232:                 if (preen)
 233:                     printf(" (IGNORED)\n");
 234:                 else if ((n = reply("REMOVE")) == 1)
 235:                     break;
 236:             }
 237:             /* fall through */
 238: 
 239:         case FSTATE:
 240:             declncnt(dirp->d_ino);
 241:             break;
 242: 
 243:         case DSTATE:
 244:             descend(idesc, dirp->d_ino);
 245:             if (getstate(dirp->d_ino) == DFOUND) {
 246:                 declncnt(dirp->d_ino);
 247:             } else if (getstate(dirp->d_ino) == DCLEAR) {
 248:                 dirp->d_ino = 0;
 249:                 ret |= ALTERED;
 250:             } else
 251:                 errexit("BAD RETURN STATE %d FROM DESCEND",
 252:                     getstate(dirp->d_ino));
 253:             break;
 254: 
 255:         default:
 256:             errexit("BAD STATE %d FOR INODE I=%u",
 257:                 getstate(dirp->d_ino), dirp->d_ino);
 258:         }
 259:     }
 260:     pathp = curpathloc;
 261:     *pathp = '\0';
 262:     if (n == 0)
 263:         return (ret|KEEPON);
 264:     dirp->d_ino = 0;
 265:     return (ret|KEEPON|ALTERED);
 266: }

Defined functions

pass2 defined in line 20; used 1 times
pass2check defined in line 84; used 4 times

Defined variables

sccsid defined in line 8; never used
Last modified: 1990-09-16
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2936
Valid CSS Valid XHTML 1.0 Strict