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