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