|
|
1.1 ! root 1: #include "fs.h" ! 2: int rerunmsg; ! 3: ! 4: attach(n) ! 5: { int lf; ! 6: char x[24]; ! 7: if(imap[n].type == Unalloc) { ! 8: pmesg("ino %d is unallocated, not put in lost+found\n", n); ! 9: return; ! 10: } ! 11: pmesg("re-attaching ino %d\n", n); ! 12: lf = nams(ROOTINO, "lost+found"); ! 13: if(lf <= 0) ! 14: lf = mkdir(ROOTINO, "lost+found"); ! 15: if(lf <= 0) { ! 16: pmesg("can't find or create /lost+found. HELP!\n"); ! 17: exitcode = 1; ! 18: return; ! 19: } ! 20: sprintf(x, "%d", n); ! 21: if(addtodir(lf, n, x) >= 0) { ! 22: imap[n].nrefs++; ! 23: fixlinks(n); ! 24: } ! 25: } ! 26: ! 27: mkdir(n, s) ! 28: char *s; ! 29: { int i, b; ! 30: struct dinode *dip; ! 31: struct direct *dp; ! 32: i = alloci(Dir); ! 33: dip = (struct dinode *) (buf + 2*bsize + (i-1)*sizeof(*dip)); ! 34: dip->di_mode = (IFDIR | 0777); ! 35: dip->di_uid = dip->di_gid = 0; ! 36: b = allocb(i, First); ! 37: dip->di_nlink = imap[i].nrefs = 2; /* a little lie */ ! 38: dip->di_ctime = dip->di_mtime = dip->di_atime = time(0); ! 39: /* now write . and .. */ ! 40: memset(buf, 0, bsize); ! 41: dp = (struct direct *) buf; ! 42: dp->d_ino = i; ! 43: strcpy(dp->d_name, "."); ! 44: dp++; ! 45: dp->d_ino = n; ! 46: strcpy(dp->d_name, ".."); ! 47: if(bwrite(b, buf, 1)) { ! 48: pmesg("write of new dir blk %d failed\n", b); ! 49: return(-1); ! 50: } ! 51: /* now stick it in its parent */ ! 52: if(addtodir(n, i, "lost+found") >= 0) { ! 53: wrti(i); ! 54: return(i); ! 55: } ! 56: pmesg("addtodir failed\n"); ! 57: return(-1); ! 58: } ! 59: ! 60: fndfr(dir, pbno, n) ! 61: int *pbno; ! 62: { struct direct *dp; ! 63: int i; ! 64: if(bread(n, buf, 1)) { ! 65: pmesg("couldn't read dir block %d\n", n); ! 66: return(-1); ! 67: } ! 68: *pbno = n; ! 69: dp = (struct direct *) buf; ! 70: for(i = 0; i < bsize/sizeof(*dp); i++, dp++) ! 71: if(dp->d_ino == 0) ! 72: return(i); ! 73: return(-1); ! 74: } ! 75: ! 76: addtodir(dir, ino, s) ! 77: char *s; ! 78: { int i, bno; ! 79: struct direct *dp; ! 80: i = nami(dir, ino); ! 81: if(i >= 0) { ! 82: pmesg("ino %d already in dir (%d,%s) (it's ok)\n", ino, dir, prname(dir)); ! 83: /* since you cared enough to ask for it: */ ! 84: imap[ino].parent = dir; ! 85: return(-1); ! 86: } ! 87: i = dirsrch(dir, &bno, fndfr); ! 88: if(i < 0) { ! 89: bno = allocb(dir, Other); ! 90: wrti(dir); ! 91: memset(buf, 0, bsize); ! 92: i = 0; ! 93: } ! 94: dp = (struct direct *)buf + i; ! 95: dp->d_ino = ino; ! 96: strncpy(dp->d_name, s, DIRSIZ); ! 97: imap[ino].parent = dir; ! 98: /* if ino was a directory, its wretched pointers are wrong */ ! 99: if(flags['w'] && bwrite(bno, buf, 1) < 0) { ! 100: pmesg("couldn't rewrite dir block %d\n", bno); ! 101: return(-1); ! 102: } ! 103: if(!rerunmsg++) ! 104: pmesg("!!counts may be wrong, RERUN chuck!\n"); ! 105: return(0); ! 106: } ! 107: ! 108: alloci(t) ! 109: { int i; ! 110: for(i = 2; i < ninode; i++) ! 111: if(imap[i].type == Unalloc) { ! 112: imap[i].type = t; ! 113: /* and adjust some counts? */ ! 114: return(i); ! 115: } ! 116: return(-1); ! 117: } ! 118: ! 119: /* doesn't understand about holes BUG*/ ! 120: allocb(ino, t) ! 121: { int i, j; ! 122: long addr[NADDR]; ! 123: struct dinode *dip; ! 124: dip = (struct dinode *) (buf + 2*bsize + (ino-1)*sizeof(*dip)); ! 125: l3tol(addr, dip->di_addr, NADDR); ! 126: for(j = 0; j < NADDR-3; j++) /* secret knowledge!! */ ! 127: if(!addr[j]) ! 128: break; ! 129: if(j >= NADDR-3) { ! 130: pmesg("won't allocate indirect block (bug)%d %d\n"); /* BUG */ ! 131: return(-1); ! 132: } ! 133: dip->di_size += 4096; ! 134: for(i = fblk; i < lblk; i++) ! 135: if(bmap[i].type == Free) { ! 136: bmap[i].ino = ino; ! 137: bmap[i].type = t; ! 138: addr[j] = i; ! 139: ltol3(dip->di_addr, addr, NADDR); ! 140: /* and adjust some counts? */ ! 141: return(i); ! 142: } ! 143: pmesg("no more free blocks\n"); ! 144: return(-1); ! 145: } ! 146: ! 147: expg(dir, x, n) ! 148: { struct direct *dp; ! 149: static struct direct nildp; ! 150: int i; ! 151: if(bread(n, buf, 1)) { ! 152: pmesg("expg read block %d failed\n", n); ! 153: return(-1); ! 154: } ! 155: dp = (struct direct *) buf; ! 156: for(i = 0; i < bsize/sizeof(*dp); i++ , dp++) ! 157: if(dp->d_ino == x) { ! 158: *dp = nildp; ! 159: if(flags['w'] && bwrite(n, buf, 1)) ! 160: pmesg("couldn't rewrite dir block\n"); ! 161: } ! 162: return(-1); /* in case it occurs many times in the directory */ ! 163: } ! 164: /* remove the ref to the inode from a directory it's in */ ! 165: /* if you want more than one, run it lots of times */ ! 166: expunge(n) ! 167: { int i, j; ! 168: j = imap[n].parent; ! 169: if(!j || imap[j].type != Dir) { ! 170: pmesg("parent is %d, not dir\n", j); ! 171: return(-1); ! 172: } ! 173: i = dirsrch(j, n, expg); ! 174: } ! 175: ! 176: fixdots(ino) ! 177: { struct dinode *dp = (struct dinode *)(buf + 2*bsize + (ino-1)*sizeof(*dp)); ! 178: int addr[NADDR], i; ! 179: if(imap[ino].type == Unalloc) /* someone else really fixed it */ ! 180: return; ! 181: pmesg("fixdots %s\n", prino(ino)); ! 182: if(imap[ino].type != Dir) { ! 183: pmesg("fixdir called on non-dir %s\n", prino(ino)); ! 184: return; ! 185: } ! 186: /* now redo all the checking and fix everything in sight */ ! 187: l3tol(addr, dp->di_addr, NADDR); ! 188: if(fixfirst(ino, dp, addr[0]) < 0) { ! 189: pmesg("too hard, try rerunning chuck\n"); ! 190: exitcode++; ! 191: rerunmsg++; ! 192: return; ! 193: } ! 194: for(i = 0; i < erptr; i++) ! 195: switch(erlist[i].type) { ! 196: case Enotdot: case Edotino: case Enotdotdot: case Ebadparent: ! 197: if(erlist[i].a == ino) ! 198: erlist[i].done = 1; ! 199: } ! 200: } ! 201: ! 202: fixfirst(ino, dp, addr) ! 203: struct dinode *dp; ! 204: { struct direct *d; ! 205: static struct direct nildir; ! 206: int i; ! 207: if(addr < fblk || addr >= lblk) { ! 208: pmesg("first block address %d bogus\n", addr); /* FIX */ ! 209: return(-1); ! 210: } ! 211: if(bread(addr, buf, 1) < 0) { ! 212: pmesg("couldn't read %d\n", addr); ! 213: return(-1); ! 214: } ! 215: d = (struct direct *) buf; ! 216: if(firstspace() < 0) /* make space at beginning for . and .. */ ! 217: return(-1); ! 218: /* this strategy may leave some link counts wrong, FIX */ ! 219: /* also, who made dp->d_size large enough? FIX */ ! 220: *d = nildir; ! 221: d->d_ino = ino; ! 222: strcpy(d->d_name, "."); ! 223: d++; ! 224: i = imap[ino].parent; /* what if we are a directory? FIX */ ! 225: if(i < ROOTINO || i >= ninode) { ! 226: pmesg("parent is %d, and so illegal\n", i); ! 227: return(-1); ! 228: } ! 229: *d = nildir; ! 230: d->d_ino = i; ! 231: strcpy(d->d_name, ".."); ! 232: if(flags['w'] && bwrite(addr, buf, 1) < 0) { ! 233: pmesg("couldn't rewrite %d\n"); ! 234: return(-1); ! 235: } ! 236: return(0); ! 237: } ! 238: ! 239: firstspace() ! 240: { struct direct *dp = (struct direct *)buf; ! 241: int i, cnt, baddot, baddotdot, fa, fb; ! 242: for(fa = fb = cnt = i = 0; i < bsize/sizeof(*dp); i++) { ! 243: if(dp->d_ino) ! 244: continue; ! 245: cnt++; ! 246: if(!fa) { ! 247: fa = i; ! 248: continue; ! 249: } ! 250: if(!fb) ! 251: fb = i; ! 252: } ! 253: dp = (struct direct *) buf; ! 254: baddot = strcmp(dp->d_name, "."); ! 255: baddotdot = strcmp(dp[1].d_name, ".."); ! 256: if(cnt - baddot - baddotdot < 0) { ! 257: pmesg("first block of directory overfull\n"); ! 258: return(-1); /* too hard FIX */ ! 259: } ! 260: if(baddot) ! 261: dp[fa] = dp[0]; ! 262: if(baddotdot) ! 263: dp[fb] = dp[1]; ! 264: return(0); ! 265: } ! 266: ! 267: xfxnm(dir, ret, n) ! 268: int *ret; ! 269: { struct direct *dp; ! 270: int i, j, cnt = 0; ! 271: if(bread(n, buf, 1)) { ! 272: pmesg("dir %d couldn't read dir block %d\n", dir, n); ! 273: return(*ret = -1); ! 274: } ! 275: dp = (struct direct *)buf; ! 276: for(i = 0; i < bsize/sizeof(*dp); i++, dp++) { ! 277: if(!dp->d_ino) ! 278: continue; ! 279: if(dp->d_ino == dir && dp->d_name[0] != '.') { /* FIX */ ! 280: dp->d_ino = 0; /* dirs can't refer to themselves */ ! 281: /* link count now wrong, in safe direction */ ! 282: } ! 283: if(dp->d_ino < 1 || dp->d_ino >= ninode) ! 284: dp->d_ino = 0; /* bad inumber */ ! 285: if(imap[dp->d_ino].type == Unalloc) { /* ambitious FIX*/ ! 286: if(cnt++ == 10) ! 287: pmesg("...\n"); ! 288: else if(cnt < 10) ! 289: pmesg("dir entry %d,%.16s unalloc inode\n", dp->d_ino, ! 290: dp->d_name); ! 291: dp->d_ino = 0; ! 292: } ! 293: for(j = 0; j < DIRSIZ; j++) { ! 294: if(!dp->d_name[j]) ! 295: break; ! 296: if(dp->d_name[j] & 0x80) { /* ascii! */ ! 297: dp->d_name[j] &= 0x7f; ! 298: j--; /* did we zero it? */ ! 299: continue; ! 300: } ! 301: } ! 302: if(j == 0) { ! 303: pmesg("ino %d in dir %d had no name\n", dp->d_ino, dir); ! 304: pmesg("being called #%d\n", dp->d_ino); ! 305: sprintf(dp->d_name, "#%d", dp->d_ino); ! 306: continue; ! 307: } ! 308: for(; j < DIRSIZ;j++) ! 309: dp->d_name[j] = 0; ! 310: } ! 311: if(flags['w'] && bwrite(n, buf, 1)) { ! 312: pmesg("couldn't rewrite blk %d ino %d\n", n, dir); ! 313: return(*ret = -1); ! 314: } ! 315: return(-1); ! 316: } ! 317: fixnames(ino) ! 318: { int retcode = 0, j; ! 319: (void) dirsrch(ino, &retcode, xfxnm); ! 320: if(retcode < 0) { ! 321: pmesg("fixnames failed\n"); ! 322: return; ! 323: } ! 324: for(j = 0; j < erptr; j++) ! 325: if(erlist[j].type == Ebadname && erlist[j].a == ino) ! 326: erlist[j].done = 1; ! 327: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.