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