1 /* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 #if 0 36 static const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 37 #endif 38 static const char rcsid[] = 39 "$Id: inode.c,v 1.15 1998/06/28 19:23:02 bde Exp $"; 40 #endif /* not lint */ 41 42 #include <sys/param.h> 43 #include <sys/time.h> 44 45 #include <ufs/ufs/dinode.h> 46 #include <ufs/ufs/dir.h> 47 #include <ufs/ffs/fs.h> 48 49 #include <err.h> 50 #include <pwd.h> 51 #include <string.h> 52 53 #include "fsck.h" 54 55 static ino_t startinum; 56 57 static int iblock __P((struct inodesc *, long ilevel, quad_t isize)); 58 59 int 60 ckinode(dp, idesc) 61 struct dinode *dp; 62 register struct inodesc *idesc; 63 { 64 ufs_daddr_t *ap; 65 long ret, n, ndb, offset; 66 struct dinode dino; 67 quad_t remsize, sizepb; 68 mode_t mode; 69 char pathbuf[MAXPATHLEN + 1]; 70 71 if (idesc->id_fix != IGNORE) 72 idesc->id_fix = DONTKNOW; 73 idesc->id_entryno = 0; 74 idesc->id_filesize = dp->di_size; 75 mode = dp->di_mode & IFMT; 76 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 77 (dp->di_size < sblock.fs_maxsymlinklen || dp->di_blocks == 0))) 78 return (KEEPON); 79 dino = *dp; 80 ndb = howmany(dino.di_size, sblock.fs_bsize); 81 for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 82 if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 83 idesc->id_numfrags = 84 numfrags(&sblock, fragroundup(&sblock, offset)); 85 else 86 idesc->id_numfrags = sblock.fs_frag; 87 if (*ap == 0) { 88 if (idesc->id_type == DATA && ndb >= 0) { 89 /* An empty block in a directory XXX */ 90 getpathname(pathbuf, idesc->id_number, 91 idesc->id_number); 92 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 93 pathbuf); 94 if (reply("ADJUST LENGTH") == 1) { 95 dp = ginode(idesc->id_number); 96 dp->di_size = (ap - &dino.di_db[0]) * 97 sblock.fs_bsize; 98 printf( 99 "YOU MUST RERUN FSCK AFTERWARDS\n"); 100 rerun = 1; 101 inodirty(); 102 103 } 104 } 105 continue; 106 } 107 idesc->id_blkno = *ap; 108 if (idesc->id_type == ADDR) 109 ret = (*idesc->id_func)(idesc); 110 else 111 ret = dirscan(idesc); 112 if (ret & STOP) 113 return (ret); 114 } 115 idesc->id_numfrags = sblock.fs_frag; 116 remsize = dino.di_size - sblock.fs_bsize * NDADDR; 117 sizepb = sblock.fs_bsize; 118 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 119 if (*ap) { 120 idesc->id_blkno = *ap; 121 ret = iblock(idesc, n, remsize); 122 if (ret & STOP) 123 return (ret); 124 } else { 125 if (idesc->id_type == DATA && remsize > 0) { 126 /* An empty block in a directory XXX */ 127 getpathname(pathbuf, idesc->id_number, 128 idesc->id_number); 129 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 130 pathbuf); 131 if (reply("ADJUST LENGTH") == 1) { 132 dp = ginode(idesc->id_number); 133 dp->di_size -= remsize; 134 remsize = 0; 135 printf( 136 "YOU MUST RERUN FSCK AFTERWARDS\n"); 137 rerun = 1; 138 inodirty(); 139 break; 140 } 141 } 142 } 143 sizepb *= NINDIR(&sblock); 144 remsize -= sizepb; 145 } 146 return (KEEPON); 147 } 148 149 static int 150 iblock(idesc, ilevel, isize) 151 struct inodesc *idesc; 152 long ilevel; 153 quad_t isize; 154 { 155 ufs_daddr_t *ap; 156 ufs_daddr_t *aplim; 157 struct bufarea *bp; 158 int i, n, (*func)(), nif; 159 quad_t sizepb; 160 char buf[BUFSIZ]; 161 char pathbuf[MAXPATHLEN + 1]; 162 struct dinode *dp; 163 164 if (idesc->id_type == ADDR) { 165 func = idesc->id_func; 166 if (((n = (*func)(idesc)) & KEEPON) == 0) 167 return (n); 168 } else 169 func = dirscan; 170 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 171 return (SKIP); 172 bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); 173 ilevel--; 174 for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 175 sizepb *= NINDIR(&sblock); 176 nif = howmany(isize , sizepb); 177 if (nif > NINDIR(&sblock)) 178 nif = NINDIR(&sblock); 179 if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 180 aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; 181 for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { 182 if (*ap == 0) 183 continue; 184 (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", 185 (u_long)idesc->id_number); 186 if (dofix(idesc, buf)) { 187 *ap = 0; 188 dirty(bp); 189 } 190 } 191 flush(fswritefd, bp); 192 } 193 aplim = &bp->b_un.b_indir[nif]; 194 for (ap = bp->b_un.b_indir; ap < aplim; ap++) { 195 if (*ap) { 196 idesc->id_blkno = *ap; 197 if (ilevel == 0) 198 n = (*func)(idesc); 199 else 200 n = iblock(idesc, ilevel, isize); 201 if (n & STOP) { 202 bp->b_flags &= ~B_INUSE; 203 return (n); 204 } 205 } else { 206 if (idesc->id_type == DATA && isize > 0) { 207 /* An empty block in a directory XXX */ 208 getpathname(pathbuf, idesc->id_number, 209 idesc->id_number); 210 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 211 pathbuf); 212 if (reply("ADJUST LENGTH") == 1) { 213 dp = ginode(idesc->id_number); 214 dp->di_size -= isize; 215 isize = 0; 216 printf( 217 "YOU MUST RERUN FSCK AFTERWARDS\n"); 218 rerun = 1; 219 inodirty(); 220 bp->b_flags &= ~B_INUSE; 221 return(STOP); 222 } 223 } 224 } 225 isize -= sizepb; 226 } 227 bp->b_flags &= ~B_INUSE; 228 return (KEEPON); 229 } 230 231 /* 232 * Check that a block in a legal block number. 233 * Return 0 if in range, 1 if out of range. 234 */ 235 int 236 chkrange(blk, cnt) 237 ufs_daddr_t blk; 238 int cnt; 239 { 240 register int c; 241 242 if (blk < 0 || blk >= maxfsblock || cnt < 0 || cnt > maxfsblock - blk) 243 return (1); 244 c = dtog(&sblock, blk); 245 if (blk < cgdmin(&sblock, c)) { 246 if ((blk + cnt) > cgsblock(&sblock, c)) { 247 if (debug) { 248 printf("blk %ld < cgdmin %ld;", 249 (long)blk, (long)cgdmin(&sblock, c)); 250 printf(" blk + cnt %ld > cgsbase %ld\n", 251 (long)(blk + cnt), 252 (long)cgsblock(&sblock, c)); 253 } 254 return (1); 255 } 256 } else { 257 if ((blk + cnt) > cgbase(&sblock, c+1)) { 258 if (debug) { 259 printf("blk %ld >= cgdmin %ld;", 260 (long)blk, (long)cgdmin(&sblock, c)); 261 printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", 262 (long)(blk + cnt), (long)sblock.fs_fpg); 263 } 264 return (1); 265 } 266 } 267 return (0); 268 } 269 270 /* 271 * General purpose interface for reading inodes. 272 */ 273 struct dinode * 274 ginode(inumber) 275 ino_t inumber; 276 { 277 ufs_daddr_t iblk; 278 279 if (inumber < ROOTINO || inumber > maxino) 280 errx(EEXIT, "bad inode number %d to ginode", inumber); 281 if (startinum == 0 || 282 inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 283 iblk = ino_to_fsba(&sblock, inumber); 284 if (pbp != 0) 285 pbp->b_flags &= ~B_INUSE; 286 pbp = getdatablk(iblk, sblock.fs_bsize); 287 startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 288 } 289 return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); 290 } 291 292 /* 293 * Special purpose version of ginode used to optimize first pass 294 * over all the inodes in numerical order. 295 */ 296 ino_t nextino, lastinum; 297 long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 298 struct dinode *inodebuf; 299 300 struct dinode * 301 getnextinode(inumber) 302 ino_t inumber; 303 { 304 long size; 305 ufs_daddr_t dblk; 306 static struct dinode *dp; 307 308 if (inumber != nextino++ || inumber > maxino) 309 errx(EEXIT, "bad inode number %d to nextinode", inumber); 310 if (inumber >= lastinum) { 311 readcnt++; 312 dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); 313 if (readcnt % readpercg == 0) { 314 size = partialsize; 315 lastinum += partialcnt; 316 } else { 317 size = inobufsize; 318 lastinum += fullcnt; 319 } 320 (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */ 321 dp = inodebuf; 322 } 323 return (dp++); 324 } 325 326 void 327 resetinodebuf() 328 { 329 330 startinum = 0; 331 nextino = 0; 332 lastinum = 0; 333 readcnt = 0; 334 inobufsize = blkroundup(&sblock, INOBUFSIZE); 335 fullcnt = inobufsize / sizeof(struct dinode); 336 readpercg = sblock.fs_ipg / fullcnt; 337 partialcnt = sblock.fs_ipg % fullcnt; 338 partialsize = partialcnt * sizeof(struct dinode); 339 if (partialcnt != 0) { 340 readpercg++; 341 } else { 342 partialcnt = fullcnt; 343 partialsize = inobufsize; 344 } 345 if (inodebuf == NULL && 346 (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) 347 errx(EEXIT, "cannot allocate space for inode buffer"); 348 while (nextino < ROOTINO) 349 (void)getnextinode(nextino); 350 } 351 352 void 353 freeinodebuf() 354 { 355 356 if (inodebuf != NULL) 357 free((char *)inodebuf); 358 inodebuf = NULL; 359 } 360 361 /* 362 * Routines to maintain information about directory inodes. 363 * This is built during the first pass and used during the 364 * second and third passes. 365 * 366 * Enter inodes into the cache. 367 */ 368 void 369 cacheino(dp, inumber) 370 register struct dinode *dp; 371 ino_t inumber; 372 { 373 register struct inoinfo *inp; 374 struct inoinfo **inpp; 375 int blks; 376 377 blks = howmany(dp->di_size, sblock.fs_bsize); 378 if (blks > NDADDR) 379 blks = NDADDR + NIADDR; 380 inp = (struct inoinfo *) 381 malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); 382 if (inp == NULL) 383 return; 384 inpp = &inphead[inumber % numdirs]; 385 inp->i_nexthash = *inpp; 386 *inpp = inp; 387 if (inumber == ROOTINO) 388 inp->i_parent = ROOTINO; 389 else 390 inp->i_parent = (ino_t)0; 391 inp->i_dotdot = (ino_t)0; 392 inp->i_number = inumber; 393 inp->i_isize = dp->di_size; 394 inp->i_numblks = blks * sizeof(ufs_daddr_t); 395 memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks); 396 if (inplast == listmax) { 397 listmax += 100; 398 inpsort = (struct inoinfo **)realloc((char *)inpsort, 399 (unsigned)listmax * sizeof(struct inoinfo *)); 400 if (inpsort == NULL) 401 errx(EEXIT, "cannot increase directory list"); 402 } 403 inpsort[inplast++] = inp; 404 } 405 406 /* 407 * Look up an inode cache structure. 408 */ 409 struct inoinfo * 410 getinoinfo(inumber) 411 ino_t inumber; 412 { 413 register struct inoinfo *inp; 414 415 for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { 416 if (inp->i_number != inumber) 417 continue; 418 return (inp); 419 } 420 errx(EEXIT, "cannot find inode %d", inumber); 421 return ((struct inoinfo *)0); 422 } 423 424 /* 425 * Clean up all the inode cache structure. 426 */ 427 void 428 inocleanup() 429 { 430 register struct inoinfo **inpp; 431 432 if (inphead == NULL) 433 return; 434 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 435 free((char *)(*inpp)); 436 free((char *)inphead); 437 free((char *)inpsort); 438 inphead = inpsort = NULL; 439 } 440 441 void 442 inodirty() 443 { 444 445 dirty(pbp); 446 } 447 448 void 449 clri(idesc, type, flag) 450 register struct inodesc *idesc; 451 char *type; 452 int flag; 453 { 454 register struct dinode *dp; 455 456 dp = ginode(idesc->id_number); 457 if (flag == 1) { 458 pwarn("%s %s", type, 459 (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 460 pinode(idesc->id_number); 461 } 462 if (preen || reply("CLEAR") == 1) { 463 if (preen) 464 printf(" (CLEARED)\n"); 465 n_files--; 466 (void)ckinode(dp, idesc); 467 clearinode(dp); 468 statemap[idesc->id_number] = USTATE; 469 inodirty(); 470 } 471 } 472 473 int 474 findname(idesc) 475 struct inodesc *idesc; 476 { 477 register struct direct *dirp = idesc->id_dirp; 478 479 if (dirp->d_ino != idesc->id_parent) 480 return (KEEPON); 481 memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); 482 return (STOP|FOUND); 483 } 484 485 int 486 findino(idesc) 487 struct inodesc *idesc; 488 { 489 register struct direct *dirp = idesc->id_dirp; 490 491 if (dirp->d_ino == 0) 492 return (KEEPON); 493 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 494 dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { 495 idesc->id_parent = dirp->d_ino; 496 return (STOP|FOUND); 497 } 498 return (KEEPON); 499 } 500 501 void 502 pinode(ino) 503 ino_t ino; 504 { 505 register struct dinode *dp; 506 register char *p; 507 struct passwd *pw; 508 time_t t; 509 510 printf(" I=%lu ", (u_long)ino); 511 if (ino < ROOTINO || ino > maxino) 512 return; 513 dp = ginode(ino); 514 printf(" OWNER="); 515 if ((pw = getpwuid((int)dp->di_uid)) != 0) 516 printf("%s ", pw->pw_name); 517 else 518 printf("%u ", (unsigned)dp->di_uid); 519 printf("MODE=%o\n", dp->di_mode); 520 if (preen) 521 printf("%s: ", cdevname); 522 printf("SIZE=%qu ", dp->di_size); 523 t = dp->di_mtime; 524 p = ctime(&t); 525 printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 526 } 527 528 void 529 blkerror(ino, type, blk) 530 ino_t ino; 531 char *type; 532 ufs_daddr_t blk; 533 { 534 535 pfatal("%ld %s I=%lu", blk, type, ino); 536 printf("\n"); 537 switch (statemap[ino]) { 538 539 case FSTATE: 540 statemap[ino] = FCLEAR; 541 return; 542 543 case DSTATE: 544 statemap[ino] = DCLEAR; 545 return; 546 547 case FCLEAR: 548 case DCLEAR: 549 return; 550 551 default: 552 errx(EEXIT, "BAD STATE %d TO BLKERR", statemap[ino]); 553 /* NOTREACHED */ 554 } 555 } 556 557 /* 558 * allocate an unused inode 559 */ 560 ino_t 561 allocino(request, type) 562 ino_t request; 563 int type; 564 { 565 register ino_t ino; 566 register struct dinode *dp; 567 struct cg *cgp = &cgrp; 568 int cg; 569 570 if (request == 0) 571 request = ROOTINO; 572 else if (statemap[request] != USTATE) 573 return (0); 574 for (ino = request; ino < maxino; ino++) 575 if (statemap[ino] == USTATE) 576 break; 577 if (ino == maxino) 578 return (0); 579 cg = ino_to_cg(&sblock, ino); 580 getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 581 if (!cg_chkmagic(cgp)) 582 pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 583 setbit(cg_inosused(cgp), ino % sblock.fs_ipg); 584 cgp->cg_cs.cs_nifree--; 585 switch (type & IFMT) { 586 case IFDIR: 587 statemap[ino] = DSTATE; 588 cgp->cg_cs.cs_ndir++; 589 break; 590 case IFREG: 591 case IFLNK: 592 statemap[ino] = FSTATE; 593 break; 594 default: 595 return (0); 596 } 597 cgdirty(); 598 dp = ginode(ino); 599 dp->di_db[0] = allocblk((long)1); 600 if (dp->di_db[0] == 0) { 601 statemap[ino] = USTATE; 602 return (0); 603 } 604 dp->di_flags = 0; 605 dp->di_mode = type; 606 dp->di_atime = time(NULL); 607 dp->di_mtime = dp->di_ctime = dp->di_atime; 608 dp->di_size = sblock.fs_fsize; 609 dp->di_blocks = btodb(sblock.fs_fsize); 610 n_files++; 611 inodirty(); 612 if (newinofmt) 613 typemap[ino] = IFTODT(type); 614 return (ino); 615 } 616 617 /* 618 * deallocate an inode 619 */ 620 void 621 freeino(ino) 622 ino_t ino; 623 { 624 struct inodesc idesc; 625 struct dinode *dp; 626 627 memset(&idesc, 0, sizeof(struct inodesc)); 628 idesc.id_type = ADDR; 629 idesc.id_func = pass4check; 630 idesc.id_number = ino; 631 dp = ginode(ino); 632 (void)ckinode(dp, &idesc); 633 clearinode(dp); 634 inodirty(); 635 statemap[ino] = USTATE; 636 n_files--; 637 } 638