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