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[] = "@(#)inode.c 5.2 (Berkeley) 7/17/85"; 9: #endif not lint 10: 11: #include <pwd.h> 12: #include <sys/param.h> 13: #include <sys/inode.h> 14: #include <sys/fs.h> 15: #include <sys/dir.h> 16: #include "fsck.h" 17: 18: ckinode(dp, idesc) 19: DINODE *dp; 20: register struct inodesc *idesc; 21: { 22: register daddr_t *ap; 23: int ret, n; 24: DINODE dino; 25: 26: idesc->id_fix = DONTKNOW; 27: idesc->id_entryno = 0; 28: idesc->id_filesize = dp->di_size; 29: if (SPECIAL(dp)) 30: return (KEEPON); 31: dino = *dp; 32: for (ap = &dino.di_addr[0]; ap < &dino.di_addr[NDADDR]; ap++) { 33: if (*ap == 0) 34: continue; 35: idesc->id_blkno = *ap; 36: if (idesc->id_type == ADDR) 37: ret = (*idesc->id_func)(idesc); 38: else 39: ret = dirscan(idesc); 40: if (ret & STOP) 41: return (ret); 42: } 43: for (ap = &dino.di_addr[NDADDR], n = 1; n <= NIADDR; ap++, n++) { 44: if (*ap) { 45: idesc->id_blkno = *ap; 46: ret = iblock(idesc, n, 47: dino.di_size - DEV_BSIZE * NDADDR); 48: if (ret & STOP) 49: return (ret); 50: } 51: } 52: return (KEEPON); 53: } 54: 55: iblock(idesc, ilevel, isize) 56: struct inodesc *idesc; 57: register ilevel; 58: long isize; 59: { 60: register daddr_t *ap; 61: register daddr_t *aplim; 62: int i, n, (*func)(), nif; 63: long sizepb; 64: BUFAREA ib; 65: char buf[128]; 66: extern int pass1check(), dirscan(); 67: 68: if (idesc->id_type == ADDR) { 69: func = idesc->id_func; 70: if (((n = (*func)(idesc)) & KEEPON) == 0) 71: return (n); 72: } else 73: func = dirscan; 74: if (outrange(idesc->id_blkno)) /* protect thyself */ 75: return (SKIP); 76: initbarea(&ib); 77: getblk(&ib, idesc->id_blkno); 78: if (ib.b_errs != NULL) 79: return (SKIP); 80: ilevel--; 81: for (sizepb = DEV_BSIZE, i = 0; i < ilevel; i++) 82: sizepb *= NINDIR; 83: nif = isize / sizepb + 1; 84: if (nif > NINDIR) 85: nif = NINDIR; 86: if (idesc->id_func == pass1check && nif < NINDIR) { 87: aplim = &ib.b_un.b_indir[NINDIR]; 88: for (ap = &ib.b_un.b_indir[nif]; ap < aplim; ap++) { 89: if (*ap == 0) 90: continue; 91: sprintf(buf, "PARTIALLY TRUNCATED INODE I=%u", 92: idesc->id_number); 93: if (dofix(idesc, buf)) { 94: *ap = 0; 95: dirty(&ib); 96: } 97: } 98: flush(&dfile, &ib); 99: } 100: aplim = &ib.b_un.b_indir[nif]; 101: for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) 102: if (*ap) { 103: idesc->id_blkno = *ap; 104: if (ilevel > 0) 105: n = iblock(idesc, ilevel, isize - i * sizepb); 106: else 107: n = (*func)(idesc); 108: if (n & STOP) 109: return (n); 110: } 111: return (KEEPON); 112: } 113: 114: DINODE * 115: ginode(inumber) 116: register ino_t inumber; 117: { 118: daddr_t iblk; 119: register DINODE *dp; 120: 121: if (inumber < ROOTINO || inumber > imax) 122: errexit("bad inode number %u to ginode\n", inumber); 123: iblk = itod(inumber); 124: if (iblk < startib || iblk >= startib + NINOBLK) { 125: if (inoblk.b_dirty) { 126: bwrite(&dfile, inobuf, startib, NINOBLK * DEV_BSIZE); 127: inoblk.b_dirty = 0; 128: } 129: if (bread(&dfile, inobuf, iblk, NINOBLK * DEV_BSIZE)) 130: return(NULL); 131: startib = iblk; 132: } 133: dp = (DINODE *) &inobuf[(unsigned)((iblk-startib)<<DEV_BSHIFT)]; 134: return (dp + itoo(inumber)); 135: } 136: 137: clri(idesc, s, flg) 138: register struct inodesc *idesc; 139: char *s; 140: int flg; 141: { 142: register DINODE *dp; 143: 144: dp = ginode(idesc->id_number); 145: if (flg == 1) { 146: pwarn("%s %s", s, DIRCT(dp) ? "DIR" : "FILE"); 147: pinode(idesc->id_number); 148: } 149: if (preen || reply("CLEAR") == 1) { 150: if (preen) 151: printf(" (CLEARED)\n"); 152: n_files--; 153: (void)ckinode(dp, idesc); 154: zapino(dp); 155: setstate(idesc->id_number, USTATE); 156: inodirty(); 157: } 158: } 159: 160: findname(idesc) 161: struct inodesc *idesc; 162: { 163: register DIRECT *dirp = idesc->id_dirp; 164: 165: if (dirp->d_ino != idesc->id_parent) 166: return (KEEPON); 167: bcopy(dirp->d_name, idesc->id_name, dirp->d_namlen + 1); 168: return (STOP); 169: } 170: 171: findino(idesc) 172: struct inodesc *idesc; 173: { 174: register DIRECT *dirp = idesc->id_dirp; 175: 176: if (dirp->d_ino == 0) 177: return (KEEPON); 178: if (strcmp(dirp->d_name, idesc->id_name) == 0 && 179: dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) { 180: idesc->id_parent = dirp->d_ino; 181: return (STOP); 182: } 183: return (KEEPON); 184: } 185: 186: pinode(ino) 187: ino_t ino; 188: { 189: register DINODE *dp; 190: register char *p; 191: struct passwd *pw; 192: char *ctime(); 193: 194: printf(" I=%u ", ino); 195: if (ino < ROOTINO || ino > imax) 196: return; 197: dp = ginode(ino); 198: printf(" OWNER="); 199: if ((pw = getpwuid((int)dp->di_uid)) != 0) 200: printf("%s ", pw->pw_name); 201: else 202: printf("%u ", dp->di_uid); 203: printf("MODE=%o\n", dp->di_mode); 204: if (preen) 205: printf("%s: ", devname); 206: printf("SIZE=%ld ", dp->di_size); 207: p = ctime(&dp->di_mtime); 208: printf("MTIME=%12.12s %4.4s ", p+4, p+20); 209: } 210: 211: blkerr(ino, s, blk) 212: ino_t ino; 213: char *s; 214: daddr_t blk; 215: { 216: 217: pfatal("%ld %s I=%u", blk, s, ino); 218: printf("\n"); 219: switch (getstate(ino)) { 220: 221: case FSTATE: 222: setstate(ino, FCLEAR); 223: return; 224: 225: case DSTATE: 226: setstate(ino, DCLEAR); 227: return; 228: 229: case FCLEAR: 230: case DCLEAR: 231: return; 232: 233: default: 234: errexit("BAD STATE %d TO BLKERR", getstate(ino)); 235: /* NOTREACHED */ 236: } 237: } 238: 239: /* 240: * allocate an unused inode 241: */ 242: ino_t 243: allocino(request, type) 244: ino_t request; 245: int type; 246: { 247: register ino_t ino; 248: register DINODE *dp; 249: 250: if (request == 0) 251: request = ROOTINO; 252: else if (getstate(request) != USTATE) 253: return (0); 254: for (ino = request; ino < imax; ino++) 255: if (getstate(ino) == USTATE) 256: break; 257: if (ino == imax) 258: return (0); 259: switch (type & IFMT) { 260: case IFDIR: 261: setstate(ino, DSTATE); 262: break; 263: case IFREG: 264: case IFLNK: 265: setstate(ino, FSTATE); 266: break; 267: default: 268: return (0); 269: } 270: dp = ginode(ino); 271: dp->di_addr[0] = allocblk(); 272: if (dp->di_addr[0] == 0) { 273: setstate(ino, USTATE); 274: return (0); 275: } 276: dp->di_mode = type; 277: time(&dp->di_atime); 278: dp->di_mtime = dp->di_ctime = dp->di_atime; 279: dp->di_size = DEV_BSIZE; 280: n_files++; 281: inodirty(); 282: return (ino); 283: } 284: 285: /* 286: * deallocate an inode 287: */ 288: freeino(ino) 289: ino_t ino; 290: { 291: struct inodesc idesc; 292: extern int pass4check(); 293: DINODE *dp; 294: 295: bzero((char *)&idesc, sizeof(struct inodesc)); 296: idesc.id_type = ADDR; 297: idesc.id_func = pass4check; 298: idesc.id_number = ino; 299: dp = ginode(ino); 300: (void)ckinode(dp, &idesc); 301: zapino(dp); 302: inodirty(); 303: setstate(ino, USTATE); 304: n_files--; 305: }