|
|
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 %U 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: return(UNALLOC); ! 300: } ! 301: ! 302: linkincr(inum); ! 303: numfiles++; ! 304: return( flags(inum)&MODEMASK ); ! 305: } ! 306: ! 307: zeroent(elemnt) ! 308: struct direct *elemnt; ! 309: { ! 310: elemnt->d_ino = 0; ! 311: fixflag = TRUE; ! 312: } ! 313: ! 314: pname(name) ! 315: char *name; ! 316: { ! 317: int i=0; ! 318: ! 319: while (i<depth) ! 320: prdirsize(path[i++]->d_name); ! 321: prdirsize(name); ! 322: putchar('\n'); ! 323: } ! 324: ! 325: prdirsize(name) ! 326: char *name; ! 327: { ! 328: if (name[DIRSIZ-1] == '\0') ! 329: printf("/%s", name); ! 330: else ! 331: printf("/%*s", DIRSIZ, name); ! 332: } ! 333: ! 334: fsize_t ! 335: pinfo(inum) ! 336: ino_t inum; ! 337: { ! 338: register struct dinode *dip; ! 339: register struct passwd *pwd; ! 340: ! 341: if ( (dip=ptrino(inum, buf2)) == NULL ) { ! 342: printf("i-number = %u is in a bad inode block.\n", inum); ! 343: return(0); ! 344: } ! 345: ! 346: printf("i-number = %u, ", inum); ! 347: if ( (pwd=getpwuid(dip->di_uid)) != NULL ) ! 348: printf("Owner=%s, ", pwd->pw_name); ! 349: else ! 350: printf("Owner=%u, ", dip->di_uid); ! 351: printf(" Mode=0%o\n", dip->di_mode); ! 352: printf("Size=%U, Mtime=%s", dip->di_size, ctime(&dip->di_mtime)); ! 353: return(dip->di_size); ! 354: } ! 355: ! 356: char *remove = "(Remove)"; ! 357: ! 358: irange(inum, name) ! 359: ino_t inum; ! 360: char *name; ! 361: { ! 362: printf("I-number is out of range I=%u\n", inum); ! 363: pname(name); ! 364: return(action(remove)); ! 365: } ! 366: ! 367: unalloc(inum, name) ! 368: ino_t inum; ! 369: char *name; ! 370: { ! 371: fsize_t size; ! 372: ! 373: printf("Unallocated\n"); ! 374: size = pinfo(inum); ! 375: pname(name); ! 376: if ( (daction != NO) && (size == 0) && (mounted == FALSE) ) { ! 377: printf("%s [Forced - Yes]\n", remove); ! 378: return(YES); ! 379: } ! 380: return(action(remove)); ! 381: } ! 382: ! 383: baddup(inum, name) ! 384: ino_t inum; ! 385: char *name; ! 386: { ! 387: register int mode = flags(inum)&MODEMASK; ! 388: ! 389: printf("Bad or Dup blocks in %s\n",(mode==IDIR) ? "Directory" : "File"); ! 390: pinfo(inum); ! 391: pname(name); ! 392: return(action(remove)); ! 393: } ! 394: ! 395: checkpath(ino) ! 396: register ino_t ino; ! 397: { ! 398: static daddr_t addrs[NADDR]; ! 399: static struct dinode *dip; ! 400: static list *temp; ! 401: register list *ptr; ! 402: ! 403: if ( (flags(ino)&VISITED)==VISITED ) { ! 404: circle(ino); ! 405: return; ! 406: } else ! 407: orflags(ino, VISITED); ! 408: ! 409: dip = ptrino(ino, databuf); ! 410: l3tol(addrs, dip->di_addr, NADDR); ! 411: ! 412: if ( (dip->di_mode&IFMT) != IFDIR ) ! 413: fatal("Tried to checkpath i-node %u which is not dir.\n", ino); ! 414: ! 415: ptr = procfiles(addrs, dip->di_size); ! 416: ! 417: while (ptr->d_entry.d_ino) { ! 418: if (depth >= MAXDEPTH) ! 419: toolong(); ! 420: path[depth++] = &ptr->d_entry; ! 421: checkpath(ptr->d_entry.d_ino); ! 422: depth--; ! 423: temp = ptr; ! 424: ptr = ptr->next; ! 425: free(temp); ! 426: } ! 427: free(ptr); ! 428: } ! 429: ! 430: circle(ino) ! 431: ino_t ino; ! 432: { ! 433: printf("I-node %u is a multiply referenced directory i-node.\n", ino); ! 434: } ! 435: ! 436: toolong() ! 437: { ! 438: printf("Name too long.\n"); ! 439: pname("\0"); ! 440: abort(); ! 441: } ! 442: ! 443:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.