|
|
1.1 ! root 1: /* ! 2: * phase 2 of fsck - Check Pathnames ! 3: */ ! 4: ! 5: #include "fsck.h" ! 6: #include <pwd.h> ! 7: ! 8: #define MAXDEPTH 50 ! 9: struct direct *path[MAXDEPTH]; ! 10: int depth; ! 11: int fixflag; /* flags when must rewrite databuf */ ! 12: daddr_t blocknum; /* Current block num read in */ ! 13: ! 14: typedef struct list { ! 15: struct direct d_entry; ! 16: struct list *next; ! 17: } list; ! 18: ! 19: char buf2[BSIZE]; /* buffer for blocks */ ! 20: daddr_t cdbn; /* current logical block number */ ! 21: ! 22: /* Format errors, args to blkerr() */ ! 23: ! 24: #define NULLNAME 5 ! 25: #define NULLPAD 6 ! 26: #define SLASHES 7 ! 27: #define DOT 8 ! 28: #define DOTDOT 9 ! 29: ! 30: phase2() ! 31: { ! 32: if (!qflag) ! 33: printf("Phase 2 : Check Pathnames\n"); ! 34: checkroot(); ! 35: depth = 0; ! 36: checkpath(ROOTIN); ! 37: } ! 38: ! 39: ! 40: checkroot() ! 41: { ! 42: if ( (flags(ROOTIN)&MODEMASK) == UNALLOC ) ! 43: fatal("Root i-node is unallocated. Terminating"); ! 44: ! 45: if ( (flags(ROOTIN)&MODEMASK) != IDIR ) { ! 46: switch ( query("Root i-node is not a directory (FIX)") ){ ! 47: case YES: ! 48: fixroot(); ! 49: break; ! 50: case NO: ! 51: abort(); ! 52: } ! 53: } ! 54: ! 55: if ( badblks(ROOTIN) ){ ! 56: switch ( query("Dup/Bad blocks in root i-node (Continue)") ) { ! 57: case YES: ! 58: break; ! 59: case NO: ! 60: abort(); ! 61: } ! 62: } ! 63: linkincr(ROOTIN); /* (?) Feature (?) of mkfs is */ ! 64: /* that root inode of a file */ ! 65: /* system has a link count one */ ! 66: /* too large. */ ! 67: } ! 68: ! 69: fixroot() ! 70: { ! 71: register struct dinode *dip; ! 72: ! 73: if (!writeflg) ! 74: fatal("File System Read-Only (NO WRITE)\n"); ! 75: ! 76: setflags(ROOTIN, (flags(ROOTIN) & ~MODEMASK) | IDIR); ! 77: ! 78: /* Save change to disk */ ! 79: ! 80: dip = ptrino(ROOTIN, databuf); ! 81: dip->di_mode &= (~IFMT); ! 82: dip->di_mode |= IFDIR; ! 83: writeino(ROOTIN, databuf); ! 84: } ! 85: ! 86: #define myinum ( (depth>0) ? path[depth-1]->d_ino : ROOTIN ) ! 87: #define popinum ( (depth>1) ? path[depth-2]->d_ino : ROOTIN ) ! 88: ! 89: char *memory = "Can't malloc memory, phase 2"; ! 90: ! 91: list * ! 92: procfiles(addrs, length) ! 93: daddr_t *addrs; ! 94: fsize_t length; ! 95: { ! 96: register struct direct *elemnt; ! 97: register list *first, *ptr; ! 98: ! 99: if ((first=ptr=(list *)malloc(sizeof(list)))==NULL) ! 100: fatal(memory); ! 101: first->d_entry.d_ino = 0; ! 102: first->next = NULL; ! 103: if ( length < DSIZE ) ! 104: return( first ); ! 105: cdbn = 0; ! 106: nextblock(addrs); ! 107: fixflag = FALSE; ! 108: elemnt = (struct direct *) databuf; ! 109: cdots(elemnt++, ".", myinum, DOT); ! 110: ++numfiles; ! 111: if ( (length-=DSIZE) < DSIZE ) ! 112: return( first ); ! 113: cdots(elemnt++, "..", popinum, DOTDOT); ! 114: ++numfiles; ! 115: length -= DSIZE; ! 116: ! 117: while ( length >= DSIZE ) { ! 118: while ( (elemnt<&databuf[BSIZE]) && (length>=DSIZE) ) { ! 119: if (chck(elemnt)==IDIR) { ! 120: copy(elemnt, &ptr->d_entry, ! 121: sizeof(struct direct)); ! 122: if ((ptr->next=(list *)malloc(sizeof(list))) == ! 123: NULL) ! 124: fatal(memory); ! 125: ptr = ptr->next; ! 126: ptr->d_entry.d_ino = 0; ! 127: ptr->next = NULL; ! 128: } ! 129: elemnt++; ! 130: length -= DSIZE; ! 131: } ! 132: if (fixflag && (fixblock(addrs) == NUL) ) ! 133: fixblkerr(); ! 134: nextblock(addrs); ! 135: fixflag = FALSE; ! 136: elemnt = (struct direct *) databuf; ! 137: } ! 138: return(first); ! 139: } ! 140: ! 141: candblock(dptr) ! 142: register struct direct *dptr; ! 143: { ! 144: register int num, i; ! 145: ! 146: num = BSIZE/sizeof(struct direct); ! 147: for (i=0; i<num; i++) ! 148: canino(dptr[i].d_ino); ! 149: } ! 150: ! 151: nextblock(addrs) ! 152: register daddr_t *addrs; ! 153: { ! 154: register daddr_t bn; ! 155: ! 156: if ( (bn=imap(addrs, cdbn++)) == 0 ) { ! 157: bclear(databuf, BSIZE); ! 158: return; ! 159: } ! 160: bread(bn, databuf); ! 161: candblock(databuf); ! 162: blocknum = bn; ! 163: } ! 164: ! 165: fixblock(addrs) ! 166: daddr_t *addrs; ! 167: { ! 168: daddr_t bn; ! 169: ! 170: if ( (bn=imap(addrs, cdbn-1)) == 0 ) ! 171: return(NUL); ! 172: candblock(databuf); ! 173: bwrite(bn, databuf); ! 174: return(TRUE); ! 175: } ! 176: ! 177: fixblkerr() ! 178: { ! 179: fatal("Fixblock error."); ! 180: } ! 181: ! 182: copy(from, to, size) ! 183: register char *from, *to; ! 184: register int size; ! 185: { ! 186: while (size--) ! 187: *to++=*from++; ! 188: } ! 189: ! 190: cdots(elemnt, dots, ino, type) ! 191: register struct direct *elemnt; ! 192: char *dots; ! 193: ino_t ino; /* what the inode number should be */ ! 194: int type; ! 195: { ! 196: register char *name = elemnt->d_name; ! 197: register ino_t inum; ! 198: ! 199: inum = elemnt->d_ino; ! 200: if ( (strcmp(name, dots) != 0) || (inum != ino) || ! 201: (format(name) != GOOD) ) { ! 202: blkerr(type); ! 203: return; ! 204: } ! 205: linkincr(inum); ! 206: } ! 207: ! 208: format(name) ! 209: register char *name; ! 210: { ! 211: register char *ptr=name; ! 212: register char *end=&name[DIRSIZ]; ! 213: ! 214: while ( (ptr<end) && (*ptr++ != '\0') ) ; ! 215: ! 216: if ( (ptr-1) == name ) ! 217: return(NULLNAME); ! 218: ! 219: if (ptr<end) { ! 220: while ( (ptr<end) && (*ptr++ == '\0') ) ; ! 221: if (ptr!=end) ! 222: return(NULLPAD); ! 223: } ! 224: ! 225: ptr = name; ! 226: while (ptr < end) ! 227: if (*ptr++ == '/') ! 228: return(SLASHES); ! 229: ! 230: return(GOOD); ! 231: } ! 232: ! 233: ! 234: blkerr(type) ! 235: int type; ! 236: { ! 237: char *errname; ! 238: ! 239: switch(type) { ! 240: case NULLNAME: ! 241: errname = "Null name"; ! 242: break; ! 243: case NULLPAD: ! 244: errname = "Non null padded"; ! 245: break; ! 246: case SLASHES: ! 247: errname = "Embedded slashes in"; ! 248: break; ! 249: case DOT: ! 250: errname = "Inconsistent ."; ! 251: break; ! 252: case DOTDOT: ! 253: errname = "Inconsistent .."; ! 254: break; ! 255: default: ! 256: errname = "Bad"; ! 257: break; ! 258: } ! 259: ! 260: printf("%s entry in block %lu in directory\n", errname, blocknum); ! 261: pinfo(myinum); ! 262: pname(path[--depth]->d_name); ! 263: depth++; ! 264: } ! 265: ! 266: chck(elemnt) ! 267: register struct direct *elemnt; ! 268: { ! 269: register ino_t inum; ! 270: register char *name; ! 271: int type; ! 272: ! 273: inum = elemnt->d_ino; ! 274: if ( inum == 0 ) ! 275: return(UNALLOC); ! 276: ! 277: name = elemnt->d_name; ! 278: if ( (type=format(name)) != GOOD ) ! 279: blkerr(type); ! 280: ! 281: if (inum>ninodes) { ! 282: if ( irange(inum, name) ) ! 283: zeroent(elemnt); ! 284: return(UNALLOC); ! 285: } ! 286: ! 287: if ( (flags(inum)&ALLOCMASK)==UNALLOC ) { ! 288: if ( unalloc(inum, name) ) ! 289: zeroent(elemnt); ! 290: return(UNALLOC); ! 291: } ! 292: ! 293: if ( badblks(inum) ) { ! 294: if ( baddup(inum, name) ) { ! 295: zeroent(elemnt); ! 296: return(UNALLOC); ! 297: } ! 298: if ( (flags(inum)&MODEMASK)==IDIR ) { ! 299: linkincr(inum); ! 300: numfiles++; ! 301: return(UNALLOC); /* Don't traverse this baby */ ! 302: } ! 303: } ! 304: ! 305: linkincr(inum); ! 306: numfiles++; ! 307: return( flags(inum)&MODEMASK ); ! 308: } ! 309: ! 310: zeroent(elemnt) ! 311: struct direct *elemnt; ! 312: { ! 313: elemnt->d_ino = 0; ! 314: fixflag = TRUE; ! 315: } ! 316: ! 317: pname(name) ! 318: char *name; ! 319: { ! 320: int i=0; ! 321: ! 322: while (i<depth) ! 323: prdirsize(path[i++]->d_name); ! 324: prdirsize(name); ! 325: putchar('\n'); ! 326: } ! 327: ! 328: prdirsize(name) ! 329: char *name; ! 330: { ! 331: if (name[DIRSIZ-1] == '\0') ! 332: printf("/%s", name); ! 333: else ! 334: printf("/%*s", DIRSIZ, name); ! 335: } ! 336: ! 337: fsize_t ! 338: pinfo(inum) ! 339: ino_t inum; ! 340: { ! 341: register struct dinode *dip; ! 342: register struct passwd *pwd; ! 343: ! 344: if ( (dip=ptrino(inum, buf2)) == NULL ) { ! 345: printf("i-number = %u is in a bad inode block.\n", inum); ! 346: return(0); ! 347: } ! 348: ! 349: printf("i-number = %u, ", inum); ! 350: if ( (pwd=getpwuid(dip->di_uid)) != NULL ) ! 351: printf("Owner=%s, ", pwd->pw_name); ! 352: else ! 353: printf("Owner=%u, ", dip->di_uid); ! 354: printf(" Mode=0%o\n", dip->di_mode); ! 355: printf("Size=%lu, Mtime=%s", dip->di_size, ctime(&dip->di_mtime)); ! 356: return(dip->di_size); ! 357: } ! 358: ! 359: char *remove = "(Remove)"; ! 360: ! 361: irange(inum, name) ! 362: ino_t inum; ! 363: char *name; ! 364: { ! 365: printf("I-number is out of range I=%u\n", inum); ! 366: pname(name); ! 367: return(action(remove)); ! 368: } ! 369: ! 370: unalloc(inum, name) ! 371: ino_t inum; ! 372: char *name; ! 373: { ! 374: fsize_t size; ! 375: ! 376: printf("Unallocated\n"); ! 377: size = pinfo(inum); ! 378: pname(name); ! 379: if ( (daction != NO) && (size == 0) && (mounted == FALSE) ) { ! 380: printf("%s [Forced - Yes]\n", remove); ! 381: return(YES); ! 382: } ! 383: return(action(remove)); ! 384: } ! 385: ! 386: baddup(inum, name) ! 387: ino_t inum; ! 388: char *name; ! 389: { ! 390: register int mode = flags(inum)&MODEMASK; ! 391: ! 392: printf("Bad or Dup blocks in %s\n", typename(inum)); ! 393: pinfo(inum); ! 394: pname(name); ! 395: return(action(remove)); ! 396: } ! 397: ! 398: checkpath(ino) ! 399: register ino_t ino; ! 400: { ! 401: static daddr_t addrs[NADDR]; ! 402: static struct dinode *dip; ! 403: static list *temp; ! 404: register list *ptr; ! 405: ! 406: if ( (flags(ino)&VISITED)==VISITED ) { ! 407: circle(ino); ! 408: return; ! 409: } else ! 410: orflags(ino, VISITED); ! 411: ! 412: dip = ptrino(ino, databuf); ! 413: l3tol(addrs, dip->di_addr, NADDR); ! 414: ! 415: if ( (dip->di_mode&IFMT) != IFDIR ) ! 416: fatal("Tried to checkpath i-node %u which is not dir.\n", ino); ! 417: ! 418: ptr = procfiles(addrs, dip->di_size); ! 419: ! 420: while (ptr->d_entry.d_ino) { ! 421: if (depth >= MAXDEPTH) ! 422: toolong(); ! 423: path[depth++] = &ptr->d_entry; ! 424: checkpath(ptr->d_entry.d_ino); ! 425: depth--; ! 426: temp = ptr; ! 427: ptr = ptr->next; ! 428: free(temp); ! 429: } ! 430: free(ptr); ! 431: } ! 432: ! 433: circle(ino) ! 434: ino_t ino; ! 435: { ! 436: printf("I-node %u is a multiply referenced directory i-node.\n", ino); ! 437: } ! 438: ! 439: toolong() ! 440: { ! 441: printf("Name too long.\n"); ! 442: pname("\0"); ! 443: abort(); ! 444: } ! 445: ! 446:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.