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