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: #ifndef lint 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, ndb, offset; 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: ndb = howmany(dino.di_size, sblock.fs_bsize); 33: for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 34: if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 35: idesc->id_numfrags = 36: numfrags(&sblock, fragroundup(&sblock, offset)); 37: else 38: idesc->id_numfrags = sblock.fs_frag; 39: if (*ap == 0) 40: continue; 41: idesc->id_blkno = *ap; 42: if (idesc->id_type == ADDR) 43: ret = (*idesc->id_func)(idesc); 44: else 45: ret = dirscan(idesc); 46: if (ret & STOP) 47: return (ret); 48: } 49: idesc->id_numfrags = sblock.fs_frag; 50: for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 51: if (*ap) { 52: idesc->id_blkno = *ap; 53: ret = iblock(idesc, n, 54: dino.di_size - sblock.fs_bsize * NDADDR); 55: if (ret & STOP) 56: return (ret); 57: } 58: } 59: return (KEEPON); 60: } 61: 62: iblock(idesc, ilevel, isize) 63: struct inodesc *idesc; 64: register ilevel; 65: long isize; 66: { 67: register daddr_t *ap; 68: register daddr_t *aplim; 69: int i, n, (*func)(), nif, sizepb; 70: BUFAREA ib; 71: char buf[BUFSIZ]; 72: extern int pass1check(); 73: 74: if (idesc->id_type == ADDR) { 75: func = idesc->id_func; 76: if (((n = (*func)(idesc)) & KEEPON) == 0) 77: return (n); 78: } else 79: func = dirscan; 80: if (outrange(idesc->id_blkno, idesc->id_numfrags)) /* protect thyself */ 81: return (SKIP); 82: initbarea(&ib); 83: getblk(&ib, idesc->id_blkno, sblock.fs_bsize); 84: if (ib.b_errs != NULL) 85: return (SKIP); 86: ilevel--; 87: for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 88: sizepb *= NINDIR(&sblock); 89: nif = isize / sizepb + 1; 90: if (nif > NINDIR(&sblock)) 91: nif = NINDIR(&sblock); 92: if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 93: aplim = &ib.b_un.b_indir[NINDIR(&sblock)]; 94: for (ap = &ib.b_un.b_indir[nif]; ap < aplim; ap++) { 95: if (*ap == 0) 96: continue; 97: sprintf(buf, "PARTIALLY TRUNCATED INODE I=%d", 98: idesc->id_number); 99: if (dofix(idesc, buf)) { 100: *ap = 0; 101: dirty(&ib); 102: } 103: } 104: flush(&dfile, &ib); 105: } 106: aplim = &ib.b_un.b_indir[nif]; 107: for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) 108: if (*ap) { 109: idesc->id_blkno = *ap; 110: if (ilevel > 0) 111: n = iblock(idesc, ilevel, isize - i * sizepb); 112: else 113: n = (*func)(idesc); 114: if (n & STOP) 115: return (n); 116: } 117: return (KEEPON); 118: } 119: 120: outrange(blk, cnt) 121: daddr_t blk; 122: int cnt; 123: { 124: register int c; 125: 126: if ((unsigned)(blk+cnt) > fmax) 127: return (1); 128: c = dtog(&sblock, blk); 129: if (blk < cgdmin(&sblock, c)) { 130: if ((blk+cnt) > cgsblock(&sblock, c)) { 131: if (debug) { 132: printf("blk %d < cgdmin %d;", 133: blk, cgdmin(&sblock, c)); 134: printf(" blk+cnt %d > cgsbase %d\n", 135: blk+cnt, cgsblock(&sblock, c)); 136: } 137: return (1); 138: } 139: } else { 140: if ((blk+cnt) > cgbase(&sblock, c+1)) { 141: if (debug) { 142: printf("blk %d >= cgdmin %d;", 143: blk, cgdmin(&sblock, c)); 144: printf(" blk+cnt %d > sblock.fs_fpg %d\n", 145: blk+cnt, sblock.fs_fpg); 146: } 147: return (1); 148: } 149: } 150: return (0); 151: } 152: 153: DINODE * 154: ginode(inumber) 155: ino_t inumber; 156: { 157: daddr_t iblk; 158: static ino_t startinum = 0; /* blk num of first in raw area */ 159: 160: if (inumber < ROOTINO || inumber > imax) 161: errexit("bad inode number %d to ginode\n", inumber); 162: if (startinum == 0 || 163: inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 164: iblk = itod(&sblock, inumber); 165: getblk(&inoblk, iblk, sblock.fs_bsize); 166: startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 167: } 168: return (&inoblk.b_un.b_dinode[inumber % INOPB(&sblock)]); 169: } 170: 171: clri(idesc, s, flg) 172: register struct inodesc *idesc; 173: char *s; 174: int flg; 175: { 176: register DINODE *dp; 177: 178: dp = ginode(idesc->id_number); 179: if (flg == 1) { 180: pwarn("%s %s", s, DIRCT(dp) ? "DIR" : "FILE"); 181: pinode(idesc->id_number); 182: } 183: if (preen || reply("CLEAR") == 1) { 184: if (preen) 185: printf(" (CLEARED)\n"); 186: n_files--; 187: (void)ckinode(dp, idesc); 188: zapino(dp); 189: statemap[idesc->id_number] = USTATE; 190: inodirty(); 191: } 192: } 193: 194: findname(idesc) 195: struct inodesc *idesc; 196: { 197: register DIRECT *dirp = idesc->id_dirp; 198: 199: if (dirp->d_ino != idesc->id_parent) 200: return (KEEPON); 201: bcopy(dirp->d_name, idesc->id_name, dirp->d_namlen + 1); 202: return (STOP); 203: } 204: 205: findino(idesc) 206: struct inodesc *idesc; 207: { 208: register DIRECT *dirp = idesc->id_dirp; 209: 210: if (dirp->d_ino == 0) 211: return (KEEPON); 212: if (strcmp(dirp->d_name, idesc->id_name) == 0 && 213: dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) { 214: idesc->id_parent = dirp->d_ino; 215: return (STOP); 216: } 217: return (KEEPON); 218: } 219: 220: pinode(ino) 221: ino_t ino; 222: { 223: register DINODE *dp; 224: register char *p; 225: struct passwd *pw; 226: char *ctime(); 227: 228: printf(" I=%u ", ino); 229: if (ino < ROOTINO || ino > imax) 230: return; 231: dp = ginode(ino); 232: printf(" OWNER="); 233: if ((pw = getpwuid((int)dp->di_uid)) != 0) 234: printf("%s ", pw->pw_name); 235: else 236: printf("%d ", dp->di_uid); 237: printf("MODE=%o\n", dp->di_mode); 238: if (preen) 239: printf("%s: ", devname); 240: printf("SIZE=%ld ", dp->di_size); 241: p = ctime(&dp->di_mtime); 242: printf("MTIME=%12.12s %4.4s ", p+4, p+20); 243: } 244: 245: blkerr(ino, s, blk) 246: ino_t ino; 247: char *s; 248: daddr_t blk; 249: { 250: 251: pfatal("%ld %s I=%u", blk, s, ino); 252: printf("\n"); 253: switch (statemap[ino]) { 254: 255: case FSTATE: 256: statemap[ino] = FCLEAR; 257: return; 258: 259: case DSTATE: 260: statemap[ino] = DCLEAR; 261: return; 262: 263: case FCLEAR: 264: case DCLEAR: 265: return; 266: 267: default: 268: errexit("BAD STATE %d TO BLKERR", statemap[ino]); 269: /* NOTREACHED */ 270: } 271: } 272: 273: /* 274: * allocate an unused inode 275: */ 276: ino_t 277: allocino(request, type) 278: ino_t request; 279: int type; 280: { 281: register ino_t ino; 282: register DINODE *dp; 283: 284: if (request == 0) 285: request = ROOTINO; 286: else if (statemap[request] != USTATE) 287: return (0); 288: for (ino = request; ino < imax; ino++) 289: if (statemap[ino] == USTATE) 290: break; 291: if (ino == imax) 292: return (0); 293: switch (type & IFMT) { 294: case IFDIR: 295: statemap[ino] = DSTATE; 296: break; 297: case IFREG: 298: case IFLNK: 299: statemap[ino] = FSTATE; 300: break; 301: default: 302: return (0); 303: } 304: dp = ginode(ino); 305: dp->di_db[0] = allocblk(1); 306: if (dp->di_db[0] == 0) { 307: statemap[ino] = USTATE; 308: return (0); 309: } 310: dp->di_mode = type; 311: time(&dp->di_atime); 312: dp->di_mtime = dp->di_ctime = dp->di_atime; 313: dp->di_size = sblock.fs_fsize; 314: dp->di_blocks = btodb(sblock.fs_fsize); 315: n_files++; 316: inodirty(); 317: return (ino); 318: } 319: 320: /* 321: * deallocate an inode 322: */ 323: freeino(ino) 324: ino_t ino; 325: { 326: struct inodesc idesc; 327: extern int pass4check(); 328: DINODE *dp; 329: 330: bzero((char *)&idesc, sizeof(struct inodesc)); 331: idesc.id_type = ADDR; 332: idesc.id_func = pass4check; 333: idesc.id_number = ino; 334: dp = ginode(ino); 335: (void)ckinode(dp, &idesc); 336: zapino(dp); 337: inodirty(); 338: statemap[ino] = USTATE; 339: n_files--; 340: }