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 "$FreeBSD$"; 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 int ret; 66 long n, ndb, offset; 67 struct dinode dino; 68 quad_t remsize, sizepb; 69 mode_t mode; 70 char pathbuf[MAXPATHLEN + 1]; 71 72 if (idesc->id_fix != IGNORE) 73 idesc->id_fix = DONTKNOW; 74 idesc->id_lbn = -1; 75 idesc->id_entryno = 0; 76 idesc->id_filesize = dp->di_size; 77 mode = dp->di_mode & IFMT; 78 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 79 dp->di_size < (unsigned)sblock.fs_maxsymlinklen)) 80 return (KEEPON); 81 dino = *dp; 82 ndb = howmany(dino.di_size, sblock.fs_bsize); 83 for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 84 idesc->id_lbn++; 85 if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 86 idesc->id_numfrags = 87 numfrags(&sblock, fragroundup(&sblock, offset)); 88 else 89 idesc->id_numfrags = sblock.fs_frag; 90 if (*ap == 0) { 91 if (idesc->id_type == DATA && ndb >= 0) { 92 /* An empty block in a directory XXX */ 93 getpathname(pathbuf, idesc->id_number, 94 idesc->id_number); 95 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 96 pathbuf); 97 if (reply("ADJUST LENGTH") == 1) { 98 dp = ginode(idesc->id_number); 99 dp->di_size = (ap - &dino.di_db[0]) * 100 sblock.fs_bsize; 101 printf( 102 "YOU MUST RERUN FSCK AFTERWARDS\n"); 103 rerun = 1; 104 inodirty(); 105 106 } 107 } 108 continue; 109 } 110 idesc->id_blkno = *ap; 111 if (idesc->id_type != DATA) 112 ret = (*idesc->id_func)(idesc); 113 else 114 ret = dirscan(idesc); 115 if (ret & STOP) 116 return (ret); 117 } 118 idesc->id_numfrags = sblock.fs_frag; 119 remsize = dino.di_size - sblock.fs_bsize * NDADDR; 120 sizepb = sblock.fs_bsize; 121 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 122 sizepb *= NINDIR(&sblock); 123 if (*ap) { 124 idesc->id_blkno = *ap; 125 ret = iblock(idesc, n, remsize); 126 if (ret & STOP) 127 return (ret); 128 } else { 129 idesc->id_lbn += sizepb / sblock.fs_bsize; 130 if (idesc->id_type == DATA && remsize > 0) { 131 /* An empty block in a directory XXX */ 132 getpathname(pathbuf, idesc->id_number, 133 idesc->id_number); 134 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 135 pathbuf); 136 if (reply("ADJUST LENGTH") == 1) { 137 dp = ginode(idesc->id_number); 138 dp->di_size -= remsize; 139 remsize = 0; 140 printf( 141 "YOU MUST RERUN FSCK AFTERWARDS\n"); 142 rerun = 1; 143 inodirty(); 144 break; 145 } 146 } 147 } 148 remsize -= sizepb; 149 } 150 return (KEEPON); 151 } 152 153 static int 154 iblock(idesc, ilevel, isize) 155 struct inodesc *idesc; 156 long ilevel; 157 quad_t isize; 158 { 159 ufs_daddr_t *ap; 160 ufs_daddr_t *aplim; 161 struct bufarea *bp; 162 int i, n, (*func)(), nif; 163 quad_t sizepb; 164 char buf[BUFSIZ]; 165 char pathbuf[MAXPATHLEN + 1]; 166 struct dinode *dp; 167 168 if (idesc->id_type != DATA) { 169 func = idesc->id_func; 170 if (((n = (*func)(idesc)) & KEEPON) == 0) 171 return (n); 172 } else 173 func = dirscan; 174 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 175 return (SKIP); 176 bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); 177 ilevel--; 178 for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 179 sizepb *= NINDIR(&sblock); 180 nif = howmany(isize , sizepb); 181 if (nif > NINDIR(&sblock)) 182 nif = NINDIR(&sblock); 183 if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 184 aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; 185 for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { 186 if (*ap == 0) 187 continue; 188 (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", 189 (u_long)idesc->id_number); 190 if (dofix(idesc, buf)) { 191 *ap = 0; 192 dirty(bp); 193 } 194 } 195 flush(fswritefd, bp); 196 } 197 aplim = &bp->b_un.b_indir[nif]; 198 for (ap = bp->b_un.b_indir; ap < aplim; ap++) { 199 if (ilevel == 0) 200 idesc->id_lbn++; 201 if (*ap) { 202 idesc->id_blkno = *ap; 203 if (ilevel == 0) 204 n = (*func)(idesc); 205 else 206 n = iblock(idesc, ilevel, isize); 207 if (n & STOP) { 208 bp->b_flags &= ~B_INUSE; 209 return (n); 210 } 211 } else { 212 if (idesc->id_type == DATA && isize > 0) { 213 /* An empty block in a directory XXX */ 214 getpathname(pathbuf, idesc->id_number, 215 idesc->id_number); 216 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 217 pathbuf); 218 if (reply("ADJUST LENGTH") == 1) { 219 dp = ginode(idesc->id_number); 220 dp->di_size -= isize; 221 isize = 0; 222 printf( 223 "YOU MUST RERUN FSCK AFTERWARDS\n"); 224 rerun = 1; 225 inodirty(); 226 bp->b_flags &= ~B_INUSE; 227 return(STOP); 228 } 229 } 230 } 231 isize -= sizepb; 232 } 233 bp->b_flags &= ~B_INUSE; 234 return (KEEPON); 235 } 236 237 /* 238 * Check that a block in a legal block number. 239 * Return 0 if in range, 1 if out of range. 240 */ 241 int 242 chkrange(blk, cnt) 243 ufs_daddr_t blk; 244 int cnt; 245 { 246 register int c; 247 248 if (cnt <= 0 || blk <= 0 || blk > maxfsblock || 249 cnt - 1 > maxfsblock - blk) 250 return (1); 251 if (cnt > sblock.fs_frag || 252 fragnum(&sblock, blk) + cnt > sblock.fs_frag) { 253 if (debug) 254 printf("bad size: blk %ld, offset %ld, size %ld\n", 255 blk, fragnum(&sblock, blk), cnt); 256 return (1); 257 } 258 c = dtog(&sblock, blk); 259 if (blk < cgdmin(&sblock, c)) { 260 if ((blk + cnt) > cgsblock(&sblock, c)) { 261 if (debug) { 262 printf("blk %ld < cgdmin %ld;", 263 (long)blk, (long)cgdmin(&sblock, c)); 264 printf(" blk + cnt %ld > cgsbase %ld\n", 265 (long)(blk + cnt), 266 (long)cgsblock(&sblock, c)); 267 } 268 return (1); 269 } 270 } else { 271 if ((blk + cnt) > cgbase(&sblock, c+1)) { 272 if (debug) { 273 printf("blk %ld >= cgdmin %ld;", 274 (long)blk, (long)cgdmin(&sblock, c)); 275 printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", 276 (long)(blk + cnt), (long)sblock.fs_fpg); 277 } 278 return (1); 279 } 280 } 281 return (0); 282 } 283 284 /* 285 * General purpose interface for reading inodes. 286 */ 287 struct dinode * 288 ginode(inumber) 289 ino_t inumber; 290 { 291 ufs_daddr_t iblk; 292 293 if (inumber < ROOTINO || inumber > maxino) 294 errx(EEXIT, "bad inode number %d to ginode", inumber); 295 if (startinum == 0 || 296 inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 297 iblk = ino_to_fsba(&sblock, inumber); 298 if (pbp != 0) 299 pbp->b_flags &= ~B_INUSE; 300 pbp = getdatablk(iblk, sblock.fs_bsize); 301 startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 302 } 303 return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); 304 } 305 306 /* 307 * Special purpose version of ginode used to optimize first pass 308 * over all the inodes in numerical order. 309 */ 310 ino_t nextino, lastinum, lastvalidinum; 311 long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 312 struct dinode *inodebuf; 313 314 struct dinode * 315 getnextinode(inumber) 316 ino_t inumber; 317 { 318 long size; 319 ufs_daddr_t dblk; 320 static struct dinode *dp; 321 322 if (inumber != nextino++ || inumber > lastvalidinum) 323 errx(EEXIT, "bad inode number %d to nextinode", inumber); 324 if (inumber >= lastinum) { 325 readcnt++; 326 dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); 327 if (readcnt % readpercg == 0) { 328 size = partialsize; 329 lastinum += partialcnt; 330 } else { 331 size = inobufsize; 332 lastinum += fullcnt; 333 } 334 /* 335 * If bread returns an error, it will already have zeroed 336 * out the buffer, so we do not need to do so here. 337 */ 338 (void)bread(fsreadfd, (char *)inodebuf, dblk, size); 339 dp = inodebuf; 340 } 341 return (dp++); 342 } 343 344 void 345 setinodebuf(inum) 346 ino_t inum; 347 { 348 349 if (inum % sblock.fs_ipg != 0) 350 errx(EEXIT, "bad inode number %d to setinodebuf", inum); 351 lastvalidinum = inum + sblock.fs_ipg - 1; 352 startinum = 0; 353 nextino = inum; 354 lastinum = inum; 355 readcnt = 0; 356 if (inodebuf != NULL) 357 return; 358 inobufsize = blkroundup(&sblock, INOBUFSIZE); 359 fullcnt = inobufsize / sizeof(struct dinode); 360 readpercg = sblock.fs_ipg / fullcnt; 361 partialcnt = sblock.fs_ipg % fullcnt; 362 partialsize = partialcnt * sizeof(struct dinode); 363 if (partialcnt != 0) { 364 readpercg++; 365 } else { 366 partialcnt = fullcnt; 367 partialsize = inobufsize; 368 } 369 if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) 370 errx(EEXIT, "cannot allocate space for inode buffer"); 371 } 372 373 void 374 freeinodebuf() 375 { 376 377 if (inodebuf != NULL) 378 free((char *)inodebuf); 379 inodebuf = NULL; 380 } 381 382 /* 383 * Routines to maintain information about directory inodes. 384 * This is built during the first pass and used during the 385 * second and third passes. 386 * 387 * Enter inodes into the cache. 388 */ 389 void 390 cacheino(dp, inumber) 391 register struct dinode *dp; 392 ino_t inumber; 393 { 394 register struct inoinfo *inp; 395 struct inoinfo **inpp; 396 int blks; 397 398 blks = howmany(dp->di_size, sblock.fs_bsize); 399 if (blks > NDADDR) 400 blks = NDADDR + NIADDR; 401 inp = (struct inoinfo *) 402 malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); 403 if (inp == NULL) 404 errx(EEXIT, "cannot increase directory list"); 405 inpp = &inphead[inumber % dirhash]; 406 inp->i_nexthash = *inpp; 407 *inpp = inp; 408 inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0; 409 inp->i_dotdot = (ino_t)0; 410 inp->i_number = inumber; 411 inp->i_isize = dp->di_size; 412 inp->i_numblks = blks * sizeof(ufs_daddr_t); 413 memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks); 414 if (inplast == listmax) { 415 listmax += 100; 416 inpsort = (struct inoinfo **)realloc((char *)inpsort, 417 (unsigned)listmax * sizeof(struct inoinfo *)); 418 if (inpsort == NULL) 419 errx(EEXIT, "cannot increase directory list"); 420 } 421 inpsort[inplast++] = inp; 422 } 423 424 /* 425 * Look up an inode cache structure. 426 */ 427 struct inoinfo * 428 getinoinfo(inumber) 429 ino_t inumber; 430 { 431 register struct inoinfo *inp; 432 433 for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) { 434 if (inp->i_number != inumber) 435 continue; 436 return (inp); 437 } 438 errx(EEXIT, "cannot find inode %d", inumber); 439 return ((struct inoinfo *)0); 440 } 441 442 /* 443 * Clean up all the inode cache structure. 444 */ 445 void 446 inocleanup() 447 { 448 register struct inoinfo **inpp; 449 450 if (inphead == NULL) 451 return; 452 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 453 free((char *)(*inpp)); 454 free((char *)inphead); 455 free((char *)inpsort); 456 inphead = inpsort = NULL; 457 } 458 459 void 460 inodirty() 461 { 462 463 dirty(pbp); 464 } 465 466 void 467 clri(idesc, type, flag) 468 register struct inodesc *idesc; 469 char *type; 470 int flag; 471 { 472 register struct dinode *dp; 473 474 dp = ginode(idesc->id_number); 475 if (flag == 1) { 476 pwarn("%s %s", type, 477 (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 478 pinode(idesc->id_number); 479 } 480 if (preen || reply("CLEAR") == 1) { 481 if (preen) 482 printf(" (CLEARED)\n"); 483 n_files--; 484 (void)ckinode(dp, idesc); 485 clearinode(dp); 486 inoinfo(idesc->id_number)->ino_state = USTATE; 487 inodirty(); 488 } 489 } 490 491 int 492 findname(idesc) 493 struct inodesc *idesc; 494 { 495 register struct direct *dirp = idesc->id_dirp; 496 497 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 498 idesc->id_entryno++; 499 return (KEEPON); 500 } 501 memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); 502 return (STOP|FOUND); 503 } 504 505 int 506 findino(idesc) 507 struct inodesc *idesc; 508 { 509 register struct direct *dirp = idesc->id_dirp; 510 511 if (dirp->d_ino == 0) 512 return (KEEPON); 513 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 514 dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { 515 idesc->id_parent = dirp->d_ino; 516 return (STOP|FOUND); 517 } 518 return (KEEPON); 519 } 520 521 int 522 clearentry(idesc) 523 struct inodesc *idesc; 524 { 525 register struct direct *dirp = idesc->id_dirp; 526 527 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 528 idesc->id_entryno++; 529 return (KEEPON); 530 } 531 dirp->d_ino = 0; 532 return (STOP|FOUND|ALTERED); 533 } 534 535 void 536 pinode(ino) 537 ino_t ino; 538 { 539 register struct dinode *dp; 540 register char *p; 541 struct passwd *pw; 542 time_t t; 543 544 printf(" I=%lu ", (u_long)ino); 545 if (ino < ROOTINO || ino > maxino) 546 return; 547 dp = ginode(ino); 548 printf(" OWNER="); 549 if ((pw = getpwuid((int)dp->di_uid)) != 0) 550 printf("%s ", pw->pw_name); 551 else 552 printf("%u ", (unsigned)dp->di_uid); 553 printf("MODE=%o\n", dp->di_mode); 554 if (preen) 555 printf("%s: ", cdevname); 556 printf("SIZE=%qu ", dp->di_size); 557 t = dp->di_mtime; 558 p = ctime(&t); 559 printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 560 } 561 562 void 563 blkerror(ino, type, blk) 564 ino_t ino; 565 char *type; 566 ufs_daddr_t blk; 567 { 568 569 pfatal("%ld %s I=%lu", blk, type, ino); 570 printf("\n"); 571 switch (inoinfo(ino)->ino_state) { 572 573 case FSTATE: 574 inoinfo(ino)->ino_state = FCLEAR; 575 return; 576 577 case DSTATE: 578 inoinfo(ino)->ino_state = DCLEAR; 579 return; 580 581 case FCLEAR: 582 case DCLEAR: 583 return; 584 585 default: 586 errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state); 587 /* NOTREACHED */ 588 } 589 } 590 591 /* 592 * allocate an unused inode 593 */ 594 ino_t 595 allocino(request, type) 596 ino_t request; 597 int type; 598 { 599 register ino_t ino; 600 register struct dinode *dp; 601 struct cg *cgp = &cgrp; 602 int cg; 603 604 if (request == 0) 605 request = ROOTINO; 606 else if (inoinfo(request)->ino_state != USTATE) 607 return (0); 608 for (ino = request; ino < maxino; ino++) 609 if (inoinfo(ino)->ino_state == USTATE) 610 break; 611 if (ino == maxino) 612 return (0); 613 cg = ino_to_cg(&sblock, ino); 614 getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 615 if (!cg_chkmagic(cgp)) 616 pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 617 setbit(cg_inosused(cgp), ino % sblock.fs_ipg); 618 cgp->cg_cs.cs_nifree--; 619 switch (type & IFMT) { 620 case IFDIR: 621 inoinfo(ino)->ino_state = DSTATE; 622 cgp->cg_cs.cs_ndir++; 623 break; 624 case IFREG: 625 case IFLNK: 626 inoinfo(ino)->ino_state = FSTATE; 627 break; 628 default: 629 return (0); 630 } 631 cgdirty(); 632 dp = ginode(ino); 633 dp->di_db[0] = allocblk((long)1); 634 if (dp->di_db[0] == 0) { 635 inoinfo(ino)->ino_state = USTATE; 636 return (0); 637 } 638 dp->di_mode = type; 639 dp->di_flags = 0; 640 dp->di_atime = time(NULL); 641 dp->di_mtime = dp->di_ctime = dp->di_atime; 642 dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0; 643 dp->di_size = sblock.fs_fsize; 644 dp->di_blocks = btodb(sblock.fs_fsize); 645 n_files++; 646 inodirty(); 647 if (newinofmt) 648 inoinfo(ino)->ino_type = IFTODT(type); 649 return (ino); 650 } 651 652 /* 653 * deallocate an inode 654 */ 655 void 656 freeino(ino) 657 ino_t ino; 658 { 659 struct inodesc idesc; 660 struct dinode *dp; 661 662 memset(&idesc, 0, sizeof(struct inodesc)); 663 idesc.id_type = ADDR; 664 idesc.id_func = pass4check; 665 idesc.id_number = ino; 666 dp = ginode(ino); 667 (void)ckinode(dp, &idesc); 668 clearinode(dp); 669 inodirty(); 670 inoinfo(ino)->ino_state = USTATE; 671 n_files--; 672 } 673