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