1 /* $NetBSD: inode.c,v 1.71 2014/04/05 12:32:27 justin Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 36 #else 37 __RCSID("$NetBSD: inode.c,v 1.71 2014/04/05 12:32:27 justin Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <sys/param.h> 42 #include <sys/time.h> 43 #include <sys/stat.h> 44 45 #include <ufs/ufs/dinode.h> 46 #include <ufs/ufs/dir.h> 47 #include <ufs/ffs/fs.h> 48 #include <ufs/ffs/ffs_extern.h> 49 #include <ufs/ufs/ufs_bswap.h> 50 51 #ifndef SMALL 52 #include <err.h> 53 #include <pwd.h> 54 #endif 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <time.h> 59 60 #include "fsck.h" 61 #include "fsutil.h" 62 #include "extern.h" 63 64 static ino_t startinum; 65 66 static int iblock(struct inodesc *, long, u_int64_t); 67 static void swap_dinode1(union dinode *, int); 68 static void swap_dinode2(union dinode *, int); 69 70 int 71 ckinode(union dinode *dp, struct inodesc *idesc) 72 { 73 int ret, offset, i; 74 union dinode dino; 75 u_int64_t sizepb; 76 int64_t remsize; 77 daddr_t ndb; 78 mode_t mode; 79 char pathbuf[MAXPATHLEN + 1]; 80 81 if (idesc->id_fix != IGNORE) 82 idesc->id_fix = DONTKNOW; 83 idesc->id_entryno = 0; 84 idesc->id_filesize = iswap64(DIP(dp, size)); 85 mode = iswap16(DIP(dp, mode)) & IFMT; 86 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 87 (idesc->id_filesize < sblock->fs_maxsymlinklen || 88 (isappleufs && (idesc->id_filesize < APPLEUFS_MAXSYMLINKLEN)) || 89 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)))) 90 return (KEEPON); 91 if (is_ufs2) 92 dino.dp2 = dp->dp2; 93 else 94 dino.dp1 = dp->dp1; 95 ndb = howmany(iswap64(DIP(&dino, size)), sblock->fs_bsize); 96 for (i = 0; i < UFS_NDADDR; i++) { 97 if (--ndb == 0 && 98 (offset = ffs_blkoff(sblock, iswap64(DIP(&dino, size)))) != 0) 99 idesc->id_numfrags = 100 ffs_numfrags(sblock, ffs_fragroundup(sblock, offset)); 101 else 102 idesc->id_numfrags = sblock->fs_frag; 103 if (DIP(&dino, db[i]) == 0) { 104 if (idesc->id_type == DATA && ndb >= 0) { 105 /* An empty block in a directory XXX */ 106 markclean = 0; 107 getpathname(pathbuf, sizeof(pathbuf), 108 idesc->id_number, 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 DIP_SET(dp, size, iswap64(i * 114 sblock->fs_bsize)); 115 printf( 116 "YOU MUST RERUN FSCK AFTERWARDS\n"); 117 rerun = 1; 118 inodirty(); 119 } 120 } 121 continue; 122 } 123 if (is_ufs2) 124 idesc->id_blkno = iswap64(dino.dp2.di_db[i]); 125 else 126 idesc->id_blkno = iswap32(dino.dp1.di_db[i]); 127 if (idesc->id_type != DATA) 128 ret = (*idesc->id_func)(idesc); 129 else 130 ret = dirscan(idesc); 131 if (ret & STOP) 132 return (ret); 133 } 134 idesc->id_numfrags = sblock->fs_frag; 135 remsize = iswap64(DIP(&dino, size)) - sblock->fs_bsize * UFS_NDADDR; 136 sizepb = sblock->fs_bsize; 137 for (i = 0; i < UFS_NIADDR; i++) { 138 if (DIP(&dino, ib[i])) { 139 if (is_ufs2) 140 idesc->id_blkno = iswap64(dino.dp2.di_ib[i]); 141 else 142 idesc->id_blkno = iswap32(dino.dp1.di_ib[i]); 143 ret = iblock(idesc, i + 1, remsize); 144 if (ret & STOP) 145 return (ret); 146 } else { 147 if (idesc->id_type == DATA && remsize > 0) { 148 /* An empty block in a directory XXX */ 149 markclean = 0; 150 getpathname(pathbuf, sizeof(pathbuf), 151 idesc->id_number, idesc->id_number); 152 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 153 pathbuf); 154 if (reply("ADJUST LENGTH") == 1) { 155 dp = ginode(idesc->id_number); 156 DIP_SET(dp, size, 157 iswap64(iswap64(DIP(dp, size)) 158 - remsize)); 159 remsize = 0; 160 printf( 161 "YOU MUST RERUN FSCK AFTERWARDS\n"); 162 rerun = 1; 163 inodirty(); 164 break; 165 } 166 } 167 } 168 sizepb *= FFS_NINDIR(sblock); 169 remsize -= sizepb; 170 } 171 return (KEEPON); 172 } 173 174 static int 175 iblock(struct inodesc *idesc, long ilevel, u_int64_t isize) 176 { 177 struct bufarea *bp; 178 int i, n, (*func) (struct inodesc *), nif; 179 u_int64_t sizepb; 180 char buf[BUFSIZ]; 181 char pathbuf[MAXPATHLEN + 1]; 182 union dinode *dp; 183 184 if (idesc->id_type != DATA) { 185 func = idesc->id_func; 186 if (((n = (*func)(idesc)) & KEEPON) == 0) 187 return (n); 188 } else 189 func = dirscan; 190 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 191 return (SKIP); 192 bp = getdatablk(idesc->id_blkno, sblock->fs_bsize); 193 ilevel--; 194 for (sizepb = sblock->fs_bsize, i = 0; i < ilevel; i++) 195 sizepb *= FFS_NINDIR(sblock); 196 if (howmany(isize, sizepb) > (size_t)FFS_NINDIR(sblock)) 197 nif = FFS_NINDIR(sblock); 198 else 199 nif = howmany(isize, sizepb); 200 if (do_blkswap) { /* swap byte order of the whole blk */ 201 if (is_ufs2) { 202 for (i = 0; i < nif; i++) 203 bp->b_un.b_indir2[i] = 204 bswap64(bp->b_un.b_indir2[i]); 205 } else { 206 for (i = 0; i < nif; i++) 207 bp->b_un.b_indir1[i] = 208 bswap32(bp->b_un.b_indir1[i]); 209 } 210 dirty(bp); 211 flush(fswritefd, bp); 212 } 213 if (idesc->id_func == pass1check && nif < FFS_NINDIR(sblock)) { 214 for (i = nif; i < FFS_NINDIR(sblock); i++) { 215 if (IBLK(bp, i) == 0) 216 continue; 217 (void)snprintf(buf, sizeof(buf), 218 "PARTIALLY TRUNCATED INODE I=%llu", 219 (unsigned long long)idesc->id_number); 220 if (dofix(idesc, buf)) { 221 IBLK_SET(bp, i, 0); 222 dirty(bp); 223 } else 224 markclean = 0; 225 } 226 flush(fswritefd, bp); 227 } 228 for (i = 0; i < nif; i++) { 229 if (IBLK(bp, i)) { 230 if (is_ufs2) 231 idesc->id_blkno = iswap64(bp->b_un.b_indir2[i]); 232 else 233 idesc->id_blkno = iswap32(bp->b_un.b_indir1[i]); 234 if (ilevel == 0) 235 n = (*func)(idesc); 236 else 237 n = iblock(idesc, ilevel, isize); 238 if (n & STOP) { 239 bp->b_flags &= ~B_INUSE; 240 return (n); 241 } 242 } else { 243 if (idesc->id_type == DATA && isize > 0) { 244 /* An empty block in a directory XXX */ 245 markclean = 0; 246 getpathname(pathbuf, sizeof(pathbuf), 247 idesc->id_number, idesc->id_number); 248 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 249 pathbuf); 250 if (reply("ADJUST LENGTH") == 1) { 251 dp = ginode(idesc->id_number); 252 DIP_SET(dp, size, 253 iswap64(iswap64(DIP(dp, size)) 254 - isize)); 255 isize = 0; 256 printf( 257 "YOU MUST RERUN FSCK AFTERWARDS\n"); 258 rerun = 1; 259 inodirty(); 260 bp->b_flags &= ~B_INUSE; 261 return(STOP); 262 } 263 } 264 } 265 isize -= sizepb; 266 } 267 bp->b_flags &= ~B_INUSE; 268 return (KEEPON); 269 } 270 271 /* 272 * Check that a block in a legal block number. 273 * Return 0 if in range, 1 if out of range. 274 */ 275 int 276 chkrange(daddr_t blk, int cnt) 277 { 278 int c; 279 280 if (cnt <= 0 || blk <= 0 || blk > maxfsblock || 281 cnt - 1 > maxfsblock - blk) 282 return (1); 283 if (cnt > sblock->fs_frag || 284 ffs_fragnum(sblock, blk) + cnt > sblock->fs_frag) { 285 if (debug) 286 printf("bad size: blk %lld, offset %d, size %d\n", 287 (long long)blk, (int)ffs_fragnum(sblock, blk), cnt); 288 } 289 c = dtog(sblock, blk); 290 if (blk < cgdmin(sblock, c)) { 291 if ((blk + cnt) > cgsblock(sblock, c)) { 292 if (debug) { 293 printf("blk %lld < cgdmin %lld;", 294 (long long)blk, 295 (long long)cgdmin(sblock, c)); 296 printf(" blk + cnt %lld > cgsbase %lld\n", 297 (long long)(blk + cnt), 298 (long long)cgsblock(sblock, c)); 299 } 300 return (1); 301 } 302 } else { 303 if ((blk + cnt) > cgbase(sblock, c+1)) { 304 if (debug) { 305 printf("blk %lld >= cgdmin %lld;", 306 (long long)blk, 307 (long long)cgdmin(sblock, c)); 308 printf(" blk + cnt %lld > sblock->fs_fpg %d\n", 309 (long long)(blk+cnt), sblock->fs_fpg); 310 } 311 return (1); 312 } 313 } 314 return (0); 315 } 316 317 /* 318 * General purpose interface for reading inodes. 319 */ 320 union dinode * 321 ginode(ino_t inumber) 322 { 323 daddr_t iblk; 324 int blkoff; 325 326 if (inumber < UFS_ROOTINO || inumber > maxino) 327 errexit("bad inode number %llu to ginode", 328 (unsigned long long)inumber); 329 if (startinum == 0 || 330 inumber < startinum || inumber >= startinum + FFS_INOPB(sblock)) { 331 iblk = ino_to_fsba(sblock, inumber); 332 if (pbp != 0) 333 pbp->b_flags &= ~B_INUSE; 334 pbp = getdatablk(iblk, sblock->fs_bsize); 335 startinum = (inumber / FFS_INOPB(sblock)) * FFS_INOPB(sblock); 336 } 337 if (is_ufs2) { 338 blkoff = (inumber % FFS_INOPB(sblock)) * DINODE2_SIZE; 339 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff)); 340 } 341 blkoff = (inumber % FFS_INOPB(sblock)) * DINODE1_SIZE; 342 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff)); 343 } 344 345 static void 346 swap_dinode1(union dinode *dp, int n) 347 { 348 int i, j; 349 struct ufs1_dinode *dp1; 350 int32_t maxsymlinklen = sblock->fs_maxsymlinklen; 351 if (isappleufs) 352 maxsymlinklen = APPLEUFS_MAXSYMLINKLEN; 353 354 dp1 = (struct ufs1_dinode *)&dp->dp1; 355 for (i = 0; i < n; i++, dp1++) { 356 ffs_dinode1_swap(dp1, dp1); 357 if (((iswap16(dp1->di_mode) & IFMT) != IFLNK) || 358 doinglevel2 || 359 (maxsymlinklen < 0) || 360 (iswap64(dp1->di_size) > (uint64_t)maxsymlinklen)) { 361 for (j = 0; j < UFS_NDADDR; j++) 362 dp1->di_db[j] = bswap32(dp1->di_db[j]); 363 for (j = 0; j < UFS_NIADDR; j++) 364 dp1->di_ib[j] = bswap32(dp1->di_ib[j]); 365 } 366 } 367 } 368 369 static void 370 swap_dinode2(union dinode *dp, int n) 371 { 372 int i, j; 373 struct ufs2_dinode *dp2; 374 375 dp2 = (struct ufs2_dinode *)&dp->dp2; 376 for (i = 0; i < n; i++, dp2++) { 377 ffs_dinode2_swap(dp2, dp2); 378 if ((iswap16(dp2->di_mode) & IFMT) != IFLNK) { 379 for (j = 0; j < UFS_NXADDR; j++) 380 dp2->di_extb[j] = bswap64(dp2->di_extb[j]); 381 for (j = 0; j < UFS_NDADDR; j++) 382 dp2->di_db[j] = bswap64(dp2->di_db[j]); 383 for (j = 0; j < UFS_NIADDR; j++) 384 dp2->di_ib[j] = bswap64(dp2->di_ib[j]); 385 } 386 } 387 } 388 389 /* 390 * Special purpose version of ginode used to optimize first pass 391 * over all the inodes in numerical order. 392 */ 393 ino_t nextino, lastinum, lastvalidinum; 394 long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 395 union dinode *inodebuf; 396 397 union dinode * 398 getnextinode(ino_t inumber) 399 { 400 long size; 401 daddr_t dblk; 402 static union dinode *dp; 403 union dinode *ret; 404 405 if (inumber != nextino++ || inumber > lastvalidinum) 406 errexit("bad inode number %llu to nextinode", 407 (unsigned long long)inumber); 408 409 if (inumber >= lastinum) { 410 readcnt++; 411 dblk = FFS_FSBTODB(sblock, ino_to_fsba(sblock, lastinum)); 412 if (readcnt % readpercg == 0) { 413 size = partialsize; 414 lastinum += partialcnt; 415 } else { 416 size = inobufsize; 417 lastinum += fullcnt; 418 } 419 (void)bread(fsreadfd, (caddr_t)inodebuf, dblk, size); 420 if (doswap) { 421 if (is_ufs2) 422 swap_dinode2(inodebuf, lastinum - inumber); 423 else 424 swap_dinode1(inodebuf, lastinum - inumber); 425 bwrite(fswritefd, (char *)inodebuf, dblk, size); 426 } 427 dp = (union dinode *)inodebuf; 428 } 429 ret = dp; 430 dp = (union dinode *) 431 ((char *)dp + (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE)); 432 return ret; 433 } 434 435 void 436 setinodebuf(ino_t inum) 437 { 438 439 if (inum % sblock->fs_ipg != 0) 440 errexit("bad inode number %llu to setinodebuf", 441 (unsigned long long)inum); 442 443 lastvalidinum = inum + sblock->fs_ipg - 1; 444 startinum = 0; 445 nextino = inum; 446 lastinum = inum; 447 readcnt = 0; 448 if (inodebuf != NULL) 449 return; 450 inobufsize = ffs_blkroundup(sblock, INOBUFSIZE); 451 fullcnt = inobufsize / (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE); 452 readpercg = sblock->fs_ipg / fullcnt; 453 partialcnt = sblock->fs_ipg % fullcnt; 454 partialsize = partialcnt * (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE); 455 if (partialcnt != 0) { 456 readpercg++; 457 } else { 458 partialcnt = fullcnt; 459 partialsize = inobufsize; 460 } 461 if (inodebuf == NULL && 462 (inodebuf = malloc((unsigned)inobufsize)) == NULL) 463 errexit("Cannot allocate space for inode buffer"); 464 } 465 466 void 467 freeinodebuf(void) 468 { 469 470 if (inodebuf != NULL) 471 free((char *)inodebuf); 472 inodebuf = NULL; 473 } 474 475 /* 476 * Routines to maintain information about directory inodes. 477 * This is built during the first pass and used during the 478 * second and third passes. 479 * 480 * Enter inodes into the cache. 481 */ 482 void 483 cacheino(union dinode *dp, ino_t inumber) 484 { 485 struct inoinfo *inp; 486 struct inoinfo **inpp, **ninpsort; 487 unsigned int i, blks, extra; 488 int64_t size; 489 490 size = iswap64(DIP(dp, size)); 491 blks = howmany(size, sblock->fs_bsize); 492 if (blks > UFS_NDADDR) 493 blks = UFS_NDADDR + UFS_NIADDR; 494 if (blks > 0) 495 extra = (blks - 1) * sizeof (int64_t); 496 else 497 extra = 0; 498 inp = malloc(sizeof(*inp) + extra); 499 if (inp == NULL) 500 return; 501 inpp = &inphead[inumber % dirhash]; 502 inp->i_nexthash = *inpp; 503 *inpp = inp; 504 inp->i_child = inp->i_sibling = 0; 505 if (inumber == UFS_ROOTINO) 506 inp->i_parent = UFS_ROOTINO; 507 else 508 inp->i_parent = (ino_t)0; 509 inp->i_dotdot = (ino_t)0; 510 inp->i_number = inumber; 511 inp->i_isize = size; 512 inp->i_numblks = blks; 513 for (i = 0; i < (blks < UFS_NDADDR ? blks : UFS_NDADDR); i++) 514 inp->i_blks[i] = DIP(dp, db[i]); 515 if (blks > UFS_NDADDR) 516 for (i = 0; i < UFS_NIADDR; i++) 517 inp->i_blks[UFS_NDADDR + i] = DIP(dp, ib[i]); 518 if (inplast == listmax) { 519 ninpsort = (struct inoinfo **)realloc((char *)inpsort, 520 (unsigned)(listmax + 100) * sizeof(struct inoinfo *)); 521 if (inpsort == NULL) 522 errexit("cannot increase directory list"); 523 inpsort = ninpsort; 524 listmax += 100; 525 } 526 inpsort[inplast++] = inp; 527 } 528 529 /* 530 * Look up an inode cache structure. 531 */ 532 struct inoinfo * 533 getinoinfo(ino_t inumber) 534 { 535 struct inoinfo *inp; 536 537 for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) { 538 if (inp->i_number != inumber) 539 continue; 540 return (inp); 541 } 542 errexit("cannot find inode %llu", (unsigned long long)inumber); 543 return ((struct inoinfo *)0); 544 } 545 546 /* 547 * Clean up all the inode cache structure. 548 */ 549 void 550 inocleanup(void) 551 { 552 struct inoinfo **inpp; 553 554 if (inphead == NULL) 555 return; 556 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 557 free((char *)(*inpp)); 558 free((char *)inphead); 559 free((char *)inpsort); 560 inphead = inpsort = NULL; 561 } 562 563 void 564 inodirty(void) 565 { 566 567 dirty(pbp); 568 } 569 570 void 571 clri(struct inodesc *idesc, const char *type, int flag) 572 { 573 union dinode *dp; 574 575 dp = ginode(idesc->id_number); 576 if (flag == 1) { 577 pwarn("%s %s", type, 578 (iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? "DIR" : "FILE"); 579 pinode(idesc->id_number); 580 } 581 if (preen || reply("CLEAR") == 1) { 582 if (preen) 583 printf(" (CLEARED)\n"); 584 n_files--; 585 /* 586 * ckinode will call id_func (actually always pass4check) 587 * which will update the block count 588 */ 589 if (idesc->id_type != SNAP) 590 update_uquot(idesc->id_number, 591 idesc->id_uid, idesc->id_gid, 0, -1); 592 (void)ckinode(dp, idesc); 593 clearinode(dp); 594 inoinfo(idesc->id_number)->ino_state = USTATE; 595 inodirty(); 596 } else 597 markclean = 0; 598 } 599 600 int 601 findname(struct inodesc *idesc) 602 { 603 struct direct *dirp = idesc->id_dirp; 604 size_t len; 605 char *buf; 606 607 if (iswap32(dirp->d_ino) != idesc->id_parent || idesc->id_entryno < 2) { 608 idesc->id_entryno++; 609 return (KEEPON); 610 } 611 if ((len = dirp->d_namlen + 1) > MAXPATHLEN) { 612 /* XXX: We don't fix but we ignore */ 613 len = MAXPATHLEN; 614 } 615 /* this is namebuf from utilities.c */ 616 buf = __UNCONST(idesc->id_name); 617 (void)memcpy(buf, dirp->d_name, (size_t)dirp->d_namlen + 1); 618 return (STOP|FOUND); 619 } 620 621 int 622 findino(struct inodesc *idesc) 623 { 624 struct direct *dirp = idesc->id_dirp; 625 626 if (dirp->d_ino == 0) 627 return (KEEPON); 628 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 629 iswap32(dirp->d_ino) >= UFS_ROOTINO && iswap32(dirp->d_ino) <= maxino) { 630 idesc->id_parent = iswap32(dirp->d_ino); 631 return (STOP|FOUND); 632 } 633 return (KEEPON); 634 } 635 636 int 637 clearentry(struct inodesc *idesc) 638 { 639 struct direct *dirp = idesc->id_dirp; 640 641 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 642 idesc->id_entryno++; 643 return (KEEPON); 644 } 645 dirp->d_ino = 0; 646 return (STOP|FOUND|ALTERED); 647 } 648 649 void 650 pinode(ino_t ino) 651 { 652 union dinode *dp; 653 struct passwd *pw; 654 655 printf(" I=%llu ", (unsigned long long)ino); 656 if (ino < UFS_ROOTINO || ino > maxino) 657 return; 658 dp = ginode(ino); 659 printf(" OWNER="); 660 #ifndef SMALL 661 if (Uflag && (pw = getpwuid((int)iswap32(DIP(dp, uid)))) != 0) 662 printf("%s ", pw->pw_name); 663 else 664 #endif 665 printf("%u ", (unsigned)iswap32(DIP(dp, uid))); 666 printf("MODE=%o\n", iswap16(DIP(dp, mode))); 667 if (preen) 668 printf("%s: ", cdevname()); 669 printf("SIZE=%llu ", (unsigned long long)iswap64(DIP(dp, size))); 670 printf("MTIME=%s ", print_mtime(iswap32(DIP(dp, mtime)))); 671 } 672 673 void 674 blkerror(ino_t ino, const char *type, daddr_t blk) 675 { 676 struct inostat *info; 677 678 pfatal("%lld %s I=%llu", (long long)blk, type, (unsigned long long)ino); 679 printf("\n"); 680 info = inoinfo(ino); 681 switch (info->ino_state) { 682 683 case FSTATE: 684 info->ino_state = FCLEAR; 685 return; 686 687 case DSTATE: 688 info->ino_state = DCLEAR; 689 return; 690 691 case FCLEAR: 692 case DCLEAR: 693 return; 694 695 default: 696 errexit("BAD STATE %d TO BLKERR", info->ino_state); 697 /* NOTREACHED */ 698 } 699 } 700 701 /* 702 * allocate an unused inode 703 */ 704 ino_t 705 allocino(ino_t request, int type) 706 { 707 ino_t ino; 708 union dinode *dp; 709 struct ufs1_dinode *dp1; 710 struct ufs2_dinode *dp2; 711 time_t t; 712 struct cg *cgp = cgrp; 713 int cg; 714 struct inostat *info = NULL; 715 int nfrags; 716 717 if (request == 0) 718 request = UFS_ROOTINO; 719 else if (inoinfo(request)->ino_state != USTATE) 720 return (0); 721 for (ino = request; ino < maxino; ino++) { 722 info = inoinfo(ino); 723 if (info->ino_state == USTATE) 724 break; 725 } 726 if (ino == maxino) 727 return (0); 728 cg = ino_to_cg(sblock, ino); 729 /* If necessary, extend the inoinfo array. grow exponentially */ 730 if ((ino % sblock->fs_ipg) >= (uint64_t)inostathead[cg].il_numalloced) { 731 unsigned long newalloced, i; 732 newalloced = MIN(sblock->fs_ipg, 733 MAX(2 * inostathead[cg].il_numalloced, 10)); 734 info = calloc(newalloced, sizeof(struct inostat)); 735 if (info == NULL) { 736 pwarn("cannot alloc %lu bytes to extend inoinfo\n", 737 sizeof(struct inostat) * newalloced); 738 return 0; 739 } 740 memmove(info, inostathead[cg].il_stat, 741 inostathead[cg].il_numalloced * sizeof(*info)); 742 for (i = inostathead[cg].il_numalloced; i < newalloced; i++) { 743 info[i].ino_state = USTATE; 744 } 745 if (inostathead[cg].il_numalloced) 746 free(inostathead[cg].il_stat); 747 inostathead[cg].il_stat = info; 748 inostathead[cg].il_numalloced = newalloced; 749 info = inoinfo(ino); 750 } 751 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize); 752 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 753 if ((doswap && !needswap) || (!doswap && needswap)) 754 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 755 if (!cg_chkmagic(cgp, 0)) 756 pfatal("CG %d: ALLOCINO: BAD MAGIC NUMBER\n", cg); 757 if (doswap) 758 cgdirty(); 759 setbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg); 760 cgp->cg_cs.cs_nifree--; 761 sblock->fs_cstotal.cs_nifree--; 762 sblock->fs_cs(fs, cg).cs_nifree--; 763 sbdirty(); 764 switch (type & IFMT) { 765 case IFDIR: 766 info->ino_state = DSTATE; 767 cgp->cg_cs.cs_ndir++; 768 nfrags = 1; 769 break; 770 case IFREG: 771 info->ino_state = FSTATE; 772 nfrags = sblock->fs_frag; 773 break; 774 case IFLNK: 775 info->ino_state = FSTATE; 776 nfrags = 1; 777 break; 778 default: 779 return (0); 780 } 781 cgdirty(); 782 dp = ginode(ino); 783 if (is_ufs2) { 784 dp2 = &dp->dp2; 785 dp2->di_db[0] = iswap64(allocblk(nfrags)); 786 if (dp2->di_db[0] == 0) { 787 info->ino_state = USTATE; 788 return (0); 789 } 790 dp2->di_mode = iswap16(type); 791 dp2->di_flags = 0; 792 (void)time(&t); 793 dp2->di_atime = iswap64(t); 794 dp2->di_mtime = dp2->di_ctime = dp2->di_atime; 795 dp2->di_size = iswap64(ffs_lfragtosize(sblock, nfrags)); 796 dp2->di_blocks = iswap64(btodb(ffs_lfragtosize(sblock, nfrags))); 797 } else { 798 dp1 = &dp->dp1; 799 dp1->di_db[0] = iswap32(allocblk(nfrags)); 800 if (dp1->di_db[0] == 0) { 801 info->ino_state = USTATE; 802 return (0); 803 } 804 dp1->di_mode = iswap16(type); 805 dp1->di_flags = 0; 806 (void)time(&t); 807 dp1->di_atime = iswap32(t); 808 dp1->di_mtime = dp1->di_ctime = dp1->di_atime; 809 dp1->di_size = iswap64(ffs_lfragtosize(sblock, nfrags)); 810 dp1->di_blocks = iswap32(btodb(ffs_lfragtosize(sblock, nfrags))); 811 } 812 n_files++; 813 inodirty(); 814 if (newinofmt) 815 info->ino_type = IFTODT(type); 816 return (ino); 817 } 818 819 /* 820 * deallocate an inode 821 */ 822 void 823 freeino(ino_t ino) 824 { 825 struct inodesc idesc; 826 union dinode *dp; 827 struct cg *cgp = cgrp; 828 int cg; 829 830 cg = ino_to_cg(sblock, ino); 831 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize); 832 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 833 if ((doswap && !needswap) || (!doswap && needswap)) 834 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 835 if (!cg_chkmagic(cgp, 0)) { 836 pwarn("CG %d: FREEINO: BAD MAGIC NUMBER\n", cg); 837 cgp = NULL; 838 } 839 840 memset(&idesc, 0, sizeof(struct inodesc)); 841 idesc.id_func = pass4check; 842 idesc.id_number = ino; 843 dp = ginode(ino); 844 idesc.id_uid = iswap32(DIP(dp, uid)); 845 idesc.id_gid = iswap32(DIP(dp, gid)); 846 if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT) 847 idesc.id_type = SNAP; 848 else 849 idesc.id_type = ADDR; 850 (void)ckinode(dp, &idesc); 851 clearinode(dp); 852 inodirty(); 853 inoinfo(ino)->ino_state = USTATE; 854 if (idesc.id_type != SNAP) 855 update_uquot(idesc.id_number, 856 idesc.id_uid, idesc.id_gid, 0, -1); 857 n_files--; 858 if (cgp) { 859 clrbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg); 860 cgp->cg_cs.cs_nifree++; 861 sblock->fs_cstotal.cs_nifree++; 862 sblock->fs_cs(fs, cg).cs_nifree++; 863 sbdirty(); 864 cgdirty(); 865 } 866 } 867 868 /* read a data block from inode */ 869 ssize_t 870 readblk(union dinode *dp, off_t offset, struct bufarea **bp) 871 { 872 daddr_t blkno = ffs_lblkno(sblock, offset); 873 daddr_t iblkno; 874 int type = IFMT & iswap16(DIP(dp, mode)); 875 ssize_t filesize = iswap64(DIP(dp, size)); 876 int ilevel; 877 daddr_t nblks; 878 const daddr_t naddrperblk = sblock->fs_bsize / 879 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t)); 880 struct bufarea *ibp; 881 882 *bp = NULL; 883 offset &= ~(sblock->fs_bsize - 1); 884 885 if (type != IFREG) 886 return 0; 887 if (offset >= filesize) 888 return 0; /* short read */ 889 if (blkno < UFS_NDADDR) { 890 blkno = is_ufs2 ? iswap64(dp->dp2.di_db[blkno]) : 891 iswap32(dp->dp1.di_db[blkno]); 892 if (blkno == 0) 893 return 0; 894 *bp = getdatablk(blkno, sblock->fs_bsize); 895 return (bp != NULL) ? sblock->fs_bsize : 0; 896 } 897 blkno -= UFS_NDADDR; 898 /* find indir level */ 899 for (ilevel = 1, nblks = naddrperblk; 900 ilevel <= UFS_NIADDR; 901 ilevel++, nblks *= naddrperblk) { 902 if (blkno < nblks) 903 break; 904 else 905 blkno -= nblks; 906 } 907 if (ilevel > UFS_NIADDR) 908 errexit("bad ofsset %" PRIu64 " to readblk", offset); 909 910 /* get the first indirect block */ 911 iblkno = is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) : 912 iswap32(dp->dp1.di_ib[ilevel - 1]); 913 if (iblkno == 0) 914 return 0; 915 ibp = getdatablk(iblkno, sblock->fs_bsize); 916 /* walk indirect blocks up to the data block */ 917 for (; ilevel >0 ; ilevel--) { 918 nblks = nblks / naddrperblk; 919 if (is_ufs2) 920 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]); 921 else 922 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]); 923 if (iblkno == 0) 924 return 0; 925 blkno = blkno % nblks; 926 ibp->b_flags &= ~B_INUSE; 927 ibp = getdatablk(iblkno, sblock->fs_bsize); 928 } 929 *bp = ibp; 930 return sblock->fs_bsize; 931 } 932 933 static struct bufarea * getnewblk(daddr_t *); 934 static struct bufarea * 935 getnewblk(daddr_t *blkno) 936 { 937 struct bufarea *bp; 938 *blkno = allocblk(sblock->fs_frag); 939 if (*blkno == 0) 940 return NULL; 941 bp = getdatablk(*blkno, sblock->fs_bsize); 942 memset(bp->b_un.b_buf, 0, sblock->fs_bsize); 943 return bp; 944 } 945 946 /* expand given inode by one full fs block */ 947 struct bufarea * 948 expandfile(union dinode *dp) 949 { 950 uint64_t filesize = iswap64(DIP(dp, size)); 951 daddr_t newblk, blkno, iblkno, nblks; 952 daddr_t di_blocks; 953 int ilevel; 954 const daddr_t naddrperblk = sblock->fs_bsize / 955 (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t)); 956 struct bufarea *ibp, *bp = NULL; 957 958 di_blocks = is_ufs2 ? iswap64(dp->dp2.di_blocks) : 959 iswap32(dp->dp1.di_blocks); 960 /* compute location of new block */ 961 blkno = ffs_lblkno(sblock, filesize); 962 963 if (blkno < UFS_NDADDR) { 964 /* easy way: allocate a direct block */ 965 if ((bp = getnewblk(&newblk)) == NULL) { 966 return NULL; 967 } 968 di_blocks += btodb(sblock->fs_bsize); 969 970 if (is_ufs2) { 971 dp->dp2.di_db[blkno] = iswap64(newblk); 972 } else { 973 dp->dp1.di_db[blkno] = iswap32(newblk); 974 } 975 goto out; 976 } 977 blkno -= UFS_NDADDR; 978 /* find indir level */ 979 for (ilevel = 1, nblks = naddrperblk; 980 ilevel <= UFS_NIADDR; 981 ilevel++, nblks *= naddrperblk) { 982 if (blkno < nblks) 983 break; 984 else 985 blkno -= nblks; 986 } 987 if (ilevel > UFS_NIADDR) 988 errexit("bad filesize %" PRIu64 " to expandfile", filesize); 989 990 /* get the first indirect block, allocating if needed */ 991 if ((is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) : 992 iswap32(dp->dp1.di_ib[ilevel - 1])) == 0) { 993 if ((ibp = getnewblk(&newblk)) == NULL) 994 return 0; 995 di_blocks += btodb(sblock->fs_bsize); 996 if (is_ufs2) 997 dp->dp2.di_ib[ilevel - 1] = iswap64(newblk); 998 else 999 dp->dp1.di_ib[ilevel - 1] = iswap32(newblk); 1000 } else { 1001 ibp = getdatablk(is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) : 1002 iswap32(dp->dp1.di_ib[ilevel - 1]), sblock->fs_bsize); 1003 } 1004 /* walk indirect blocks up to the data block */ 1005 for (; ilevel >0 ; ilevel--) { 1006 nblks = nblks / naddrperblk; 1007 if (is_ufs2) 1008 iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]); 1009 else 1010 iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]); 1011 if (iblkno == 0) { 1012 if ((bp = getnewblk(&newblk)) == NULL) 1013 return NULL; 1014 di_blocks += btodb(sblock->fs_bsize); 1015 if (is_ufs2) 1016 ibp->b_un.b_indir2[blkno / nblks] = 1017 iswap64(newblk); 1018 else 1019 ibp->b_un.b_indir1[blkno / nblks] = 1020 iswap32(newblk); 1021 dirty(ibp); 1022 ibp->b_flags &= ~B_INUSE; 1023 ibp = bp; 1024 } else { 1025 ibp->b_flags &= ~B_INUSE; 1026 ibp = getdatablk(iblkno, sblock->fs_bsize); 1027 bp = NULL; 1028 } 1029 blkno = blkno % nblks; 1030 } 1031 if (bp == NULL) { 1032 errexit("INTERNAL ERROR: " 1033 "expandfile() failed to allocate a new block\n"); 1034 } 1035 1036 out: 1037 filesize += sblock->fs_bsize; 1038 if (is_ufs2) { 1039 dp->dp2.di_size = iswap64(filesize); 1040 dp->dp2.di_blocks = iswap64(di_blocks); 1041 } else { 1042 dp->dp1.di_size = iswap64(filesize); 1043 dp->dp1.di_blocks = iswap32(di_blocks); 1044 } 1045 inodirty(); 1046 return bp; 1047 } 1048