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) 07/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 } 341