Home | History | Annotate | Line # | Download | only in fsck_ffs
inode.c revision 1.64
      1 /*	$NetBSD: inode.c,v 1.64 2011/03/06 17:08:16 bouyer 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.64 2011/03/06 17:08:16 bouyer 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 < NDADDR; i++) {
     97 		if (--ndb == 0 &&
     98 		    (offset = blkoff(sblock, iswap64(DIP(&dino, size)))) != 0)
     99 			idesc->id_numfrags =
    100 				numfrags(sblock, 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 * NDADDR;
    136 	sizepb = sblock->fs_bsize;
    137 	for (i = 0; i < 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 *= 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 *= NINDIR(sblock);
    196 	if (howmany(isize, sizepb) > (size_t)NINDIR(sblock))
    197 		nif = 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 < NINDIR(sblock)) {
    214 		for (i = nif; i < 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 	    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)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 < 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 + 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 / INOPB(sblock)) * INOPB(sblock);
    336 	}
    337 	if (is_ufs2) {
    338 		blkoff = (inumber % INOPB(sblock)) * DINODE2_SIZE;
    339 		return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff));
    340 	}
    341 	blkoff = (inumber % 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 < (NDADDR + NIADDR); j++)
    362 			    dp1->di_db[j] = bswap32(dp1->di_db[j]);
    363 		}
    364 	}
    365 }
    366 
    367 static void
    368 swap_dinode2(union dinode *dp, int n)
    369 {
    370 	int i, j;
    371 	struct ufs2_dinode *dp2;
    372 
    373 	dp2 = (struct ufs2_dinode *)&dp->dp2;
    374 	for (i = 0; i < n; i++, dp2++) {
    375 		ffs_dinode2_swap(dp2, dp2);
    376 		if ((iswap16(dp2->di_mode) & IFMT) != IFLNK) {
    377 			for (j = 0; j < (NDADDR + NIADDR + NXADDR); j++)
    378 				dp2->di_extb[j] = bswap64(dp2->di_extb[j]);
    379 		}
    380 	}
    381 }
    382 
    383 /*
    384  * Special purpose version of ginode used to optimize first pass
    385  * over all the inodes in numerical order.
    386  */
    387 ino_t nextino, lastinum, lastvalidinum;
    388 long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
    389 union dinode *inodebuf;
    390 
    391 union dinode *
    392 getnextinode(ino_t inumber)
    393 {
    394 	long size;
    395 	daddr_t dblk;
    396 	static union dinode *dp;
    397 	union dinode *ret;
    398 
    399 	if (inumber != nextino++ || inumber > lastvalidinum)
    400 		errexit("bad inode number %llu to nextinode",
    401 		    (unsigned long long)inumber);
    402 
    403 	if (inumber >= lastinum) {
    404 		readcnt++;
    405 		dblk = fsbtodb(sblock, ino_to_fsba(sblock, lastinum));
    406 		if (readcnt % readpercg == 0) {
    407 			size = partialsize;
    408 			lastinum += partialcnt;
    409 		} else {
    410 			size = inobufsize;
    411 			lastinum += fullcnt;
    412 		}
    413 		(void)bread(fsreadfd, (caddr_t)inodebuf, dblk, size);
    414 		if (doswap) {
    415 			if (is_ufs2)
    416 				swap_dinode2(inodebuf, lastinum - inumber);
    417 			else
    418 				swap_dinode1(inodebuf, lastinum - inumber);
    419 			bwrite(fswritefd, (char *)inodebuf, dblk, size);
    420 		}
    421 		dp = (union dinode *)inodebuf;
    422 	}
    423 	ret = dp;
    424 	dp = (union dinode *)
    425 	    ((char *)dp + (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE));
    426 	return ret;
    427 }
    428 
    429 void
    430 setinodebuf(ino_t inum)
    431 {
    432 
    433 	if (inum % sblock->fs_ipg != 0)
    434 		errexit("bad inode number %llu to setinodebuf",
    435 		    (unsigned long long)inum);
    436 
    437 	lastvalidinum = inum + sblock->fs_ipg - 1;
    438 	startinum = 0;
    439 	nextino = inum;
    440 	lastinum = inum;
    441 	readcnt = 0;
    442 	if (inodebuf != NULL)
    443 		return;
    444 	inobufsize = blkroundup(sblock, INOBUFSIZE);
    445 	fullcnt = inobufsize / (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE);
    446 	readpercg = sblock->fs_ipg / fullcnt;
    447 	partialcnt = sblock->fs_ipg % fullcnt;
    448 	partialsize = partialcnt * (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE);
    449 	if (partialcnt != 0) {
    450 		readpercg++;
    451 	} else {
    452 		partialcnt = fullcnt;
    453 		partialsize = inobufsize;
    454 	}
    455 	if (inodebuf == NULL &&
    456 	    (inodebuf = malloc((unsigned)inobufsize)) == NULL)
    457 		errexit("Cannot allocate space for inode buffer");
    458 }
    459 
    460 void
    461 freeinodebuf(void)
    462 {
    463 
    464 	if (inodebuf != NULL)
    465 		free((char *)inodebuf);
    466 	inodebuf = NULL;
    467 }
    468 
    469 /*
    470  * Routines to maintain information about directory inodes.
    471  * This is built during the first pass and used during the
    472  * second and third passes.
    473  *
    474  * Enter inodes into the cache.
    475  */
    476 void
    477 cacheino(union dinode *dp, ino_t inumber)
    478 {
    479 	struct inoinfo *inp;
    480 	struct inoinfo **inpp, **ninpsort;
    481 	unsigned int i, blks, extra;
    482 	int64_t size;
    483 
    484 	size = iswap64(DIP(dp, size));
    485 	blks = howmany(size, sblock->fs_bsize);
    486 	if (blks > NDADDR)
    487 		blks = NDADDR + NIADDR;
    488 	if (blks > 0)
    489 		extra = (blks - 1) * sizeof (int64_t);
    490 	else
    491 		extra = 0;
    492 	inp = malloc(sizeof(*inp) + extra);
    493 	if (inp == NULL)
    494 		return;
    495 	inpp = &inphead[inumber % dirhash];
    496 	inp->i_nexthash = *inpp;
    497 	*inpp = inp;
    498 	inp->i_child = inp->i_sibling = 0;
    499 	if (inumber == ROOTINO)
    500 		inp->i_parent = ROOTINO;
    501 	else
    502 		inp->i_parent = (ino_t)0;
    503 	inp->i_dotdot = (ino_t)0;
    504 	inp->i_number = inumber;
    505 	inp->i_isize = size;
    506 	inp->i_numblks = blks;
    507 	for (i = 0; i < (blks < NDADDR ? blks : NDADDR); i++)
    508 		inp->i_blks[i] = DIP(dp, db[i]);
    509 	if (blks > NDADDR)
    510 		for (i = 0; i < NIADDR; i++)
    511 			inp->i_blks[NDADDR + i] = DIP(dp, ib[i]);
    512 	if (inplast == listmax) {
    513 		ninpsort = (struct inoinfo **)realloc((char *)inpsort,
    514 		    (unsigned)(listmax + 100) * sizeof(struct inoinfo *));
    515 		if (inpsort == NULL)
    516 			errexit("cannot increase directory list");
    517 		inpsort = ninpsort;
    518 		listmax += 100;
    519 	}
    520 	inpsort[inplast++] = inp;
    521 }
    522 
    523 /*
    524  * Look up an inode cache structure.
    525  */
    526 struct inoinfo *
    527 getinoinfo(ino_t inumber)
    528 {
    529 	struct inoinfo *inp;
    530 
    531 	for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) {
    532 		if (inp->i_number != inumber)
    533 			continue;
    534 		return (inp);
    535 	}
    536 	errexit("cannot find inode %llu", (unsigned long long)inumber);
    537 	return ((struct inoinfo *)0);
    538 }
    539 
    540 /*
    541  * Clean up all the inode cache structure.
    542  */
    543 void
    544 inocleanup(void)
    545 {
    546 	struct inoinfo **inpp;
    547 
    548 	if (inphead == NULL)
    549 		return;
    550 	for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
    551 		free((char *)(*inpp));
    552 	free((char *)inphead);
    553 	free((char *)inpsort);
    554 	inphead = inpsort = NULL;
    555 }
    556 
    557 void
    558 inodirty(void)
    559 {
    560 
    561 	dirty(pbp);
    562 }
    563 
    564 void
    565 clri(struct inodesc *idesc, const char *type, int flag)
    566 {
    567 	union dinode *dp;
    568 
    569 	dp = ginode(idesc->id_number);
    570 	if (flag == 1) {
    571 		pwarn("%s %s", type,
    572 		    (iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? "DIR" : "FILE");
    573 		pinode(idesc->id_number);
    574 	}
    575 	if (preen || reply("CLEAR") == 1) {
    576 		if (preen)
    577 			printf(" (CLEARED)\n");
    578 		n_files--;
    579 		/*
    580 		 * ckinode will call id_func (actually always pass4check)
    581 		 * which will update the block count
    582 		 */
    583 		if (idesc->id_type != SNAP)
    584 			update_uquot(idesc->id_number,
    585 			    idesc->id_uid, idesc->id_gid, 0, -1);
    586 		(void)ckinode(dp, idesc);
    587 		clearinode(dp);
    588 		inoinfo(idesc->id_number)->ino_state = USTATE;
    589 		inodirty();
    590 	} else
    591 		markclean = 0;
    592 }
    593 
    594 int
    595 findname(struct inodesc *idesc)
    596 {
    597 	struct direct *dirp = idesc->id_dirp;
    598 	size_t len;
    599 	char *buf;
    600 
    601 	if (iswap32(dirp->d_ino) != idesc->id_parent || idesc->id_entryno < 2) {
    602 		idesc->id_entryno++;
    603 		return (KEEPON);
    604 	}
    605 	if ((len = dirp->d_namlen + 1) > MAXPATHLEN) {
    606 		/* XXX: We don't fix but we ignore */
    607 		len = MAXPATHLEN;
    608 	}
    609 	/* this is namebuf from utilities.c */
    610 	buf = __UNCONST(idesc->id_name);
    611 	(void)memcpy(buf, dirp->d_name, (size_t)dirp->d_namlen + 1);
    612 	return (STOP|FOUND);
    613 }
    614 
    615 int
    616 findino(struct inodesc *idesc)
    617 {
    618 	struct direct *dirp = idesc->id_dirp;
    619 
    620 	if (dirp->d_ino == 0)
    621 		return (KEEPON);
    622 	if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
    623 	    iswap32(dirp->d_ino) >= ROOTINO && iswap32(dirp->d_ino) <= maxino) {
    624 		idesc->id_parent = iswap32(dirp->d_ino);
    625 		return (STOP|FOUND);
    626 	}
    627 	return (KEEPON);
    628 }
    629 
    630 int
    631 clearentry(struct inodesc *idesc)
    632 {
    633 	struct direct *dirp = idesc->id_dirp;
    634 
    635 	if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) {
    636 		idesc->id_entryno++;
    637 		return (KEEPON);
    638 	}
    639 	dirp->d_ino = 0;
    640 	return (STOP|FOUND|ALTERED);
    641 }
    642 
    643 void
    644 pinode(ino_t ino)
    645 {
    646 	union dinode *dp;
    647 	struct passwd *pw;
    648 
    649 	printf(" I=%llu ", (unsigned long long)ino);
    650 	if (ino < ROOTINO || ino > maxino)
    651 		return;
    652 	dp = ginode(ino);
    653 	printf(" OWNER=");
    654 #ifndef SMALL
    655 	if (Uflag && (pw = getpwuid((int)iswap32(DIP(dp, uid)))) != 0)
    656 		printf("%s ", pw->pw_name);
    657 	else
    658 #endif
    659 		printf("%u ", (unsigned)iswap32(DIP(dp, uid)));
    660 	printf("MODE=%o\n", iswap16(DIP(dp, mode)));
    661 	if (preen)
    662 		printf("%s: ", cdevname());
    663 	printf("SIZE=%llu ", (unsigned long long)iswap64(DIP(dp, size)));
    664 	printf("MTIME=%s ", print_mtime(iswap32(DIP(dp, mtime))));
    665 }
    666 
    667 void
    668 blkerror(ino_t ino, const char *type, daddr_t blk)
    669 {
    670 	struct inostat *info;
    671 
    672 	pfatal("%lld %s I=%llu", (long long)blk, type, (unsigned long long)ino);
    673 	printf("\n");
    674 	info = inoinfo(ino);
    675 	switch (info->ino_state) {
    676 
    677 	case FSTATE:
    678 		info->ino_state = FCLEAR;
    679 		return;
    680 
    681 	case DSTATE:
    682 		info->ino_state = DCLEAR;
    683 		return;
    684 
    685 	case FCLEAR:
    686 	case DCLEAR:
    687 		return;
    688 
    689 	default:
    690 		errexit("BAD STATE %d TO BLKERR", info->ino_state);
    691 		/* NOTREACHED */
    692 	}
    693 }
    694 
    695 /*
    696  * allocate an unused inode
    697  */
    698 ino_t
    699 allocino(ino_t request, int type)
    700 {
    701 	ino_t ino;
    702 	union dinode *dp;
    703 	struct ufs1_dinode *dp1;
    704 	struct ufs2_dinode *dp2;
    705 	time_t t;
    706 	struct cg *cgp = cgrp;
    707 	int cg;
    708 	struct inostat *info = NULL;
    709 	int nfrags;
    710 
    711 	if (request == 0)
    712 		request = ROOTINO;
    713 	else if (inoinfo(request)->ino_state != USTATE)
    714 		return (0);
    715 	for (ino = request; ino < maxino; ino++) {
    716 		info = inoinfo(ino);
    717 		if (info->ino_state == USTATE)
    718 			break;
    719 	}
    720 	if (ino == maxino)
    721 		return (0);
    722 	cg = ino_to_cg(sblock, ino);
    723 	/* If necessary, extend the inoinfo array. grow exponentially */
    724 	if ((ino % sblock->fs_ipg) >= (uint64_t)inostathead[cg].il_numalloced) {
    725 		unsigned long newalloced, i;
    726 		newalloced = MIN(sblock->fs_ipg,
    727 			MAX(2 * inostathead[cg].il_numalloced, 10));
    728 		info = calloc(newalloced, sizeof(struct inostat));
    729 		if (info == NULL) {
    730 			pwarn("cannot alloc %lu bytes to extend inoinfo\n",
    731 				sizeof(struct inostat) * newalloced);
    732 			return 0;
    733 		}
    734 		memmove(info, inostathead[cg].il_stat,
    735 			inostathead[cg].il_numalloced * sizeof(*info));
    736 		for (i = inostathead[cg].il_numalloced; i < newalloced; i++) {
    737 			info[i].ino_state = USTATE;
    738 		}
    739 		if (inostathead[cg].il_numalloced)
    740 			free(inostathead[cg].il_stat);
    741 		inostathead[cg].il_stat = info;
    742 		inostathead[cg].il_numalloced = newalloced;
    743 		info = inoinfo(ino);
    744 	}
    745 	getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
    746 	memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
    747 	if ((doswap && !needswap) || (!doswap && needswap))
    748 		ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
    749 	if (!cg_chkmagic(cgp, 0))
    750 		pfatal("CG %d: ALLOCINO: BAD MAGIC NUMBER\n", cg);
    751 	if (doswap)
    752 		cgdirty();
    753 	setbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg);
    754 	cgp->cg_cs.cs_nifree--;
    755 	sblock->fs_cstotal.cs_nifree--;
    756 	sblock->fs_cs(fs, cg).cs_nifree--;
    757 	sbdirty();
    758 	switch (type & IFMT) {
    759 	case IFDIR:
    760 		info->ino_state = DSTATE;
    761 		cgp->cg_cs.cs_ndir++;
    762 		nfrags = 1;
    763 		break;
    764 	case IFREG:
    765 		info->ino_state = FSTATE;
    766 		nfrags = sblock->fs_frag;
    767 		break;
    768 	case IFLNK:
    769 		info->ino_state = FSTATE;
    770 		nfrags = 1;
    771 		break;
    772 	default:
    773 		return (0);
    774 	}
    775 	cgdirty();
    776 	dp = ginode(ino);
    777 	if (is_ufs2) {
    778 		dp2 = &dp->dp2;
    779 		dp2->di_db[0] = iswap64(allocblk(nfrags));
    780 		if (dp2->di_db[0] == 0) {
    781 			info->ino_state = USTATE;
    782 			return (0);
    783 		}
    784 		dp2->di_mode = iswap16(type);
    785 		dp2->di_flags = 0;
    786 		(void)time(&t);
    787 		dp2->di_atime = iswap64(t);
    788 		dp2->di_mtime = dp2->di_ctime = dp2->di_atime;
    789 		dp2->di_size = iswap64(lfragtosize(sblock, nfrags));
    790 		dp2->di_blocks = iswap64(btodb(lfragtosize(sblock, nfrags)));
    791 	} else {
    792 		dp1 = &dp->dp1;
    793 		dp1->di_db[0] = iswap32(allocblk(nfrags));
    794 		if (dp1->di_db[0] == 0) {
    795 			info->ino_state = USTATE;
    796 			return (0);
    797 		}
    798 		dp1->di_mode = iswap16(type);
    799 		dp1->di_flags = 0;
    800 		(void)time(&t);
    801 		dp1->di_atime = iswap32(t);
    802 		dp1->di_mtime = dp1->di_ctime = dp1->di_atime;
    803 		dp1->di_size = iswap64(lfragtosize(sblock, nfrags));
    804 		dp1->di_blocks = iswap32(btodb(lfragtosize(sblock, nfrags)));
    805 	}
    806 	n_files++;
    807 	inodirty();
    808 	if (newinofmt)
    809 		info->ino_type = IFTODT(type);
    810 	return (ino);
    811 }
    812 
    813 /*
    814  * deallocate an inode
    815  */
    816 void
    817 freeino(ino_t ino)
    818 {
    819 	struct inodesc idesc;
    820 	union dinode *dp;
    821 	struct cg *cgp = cgrp;
    822 	int cg;
    823 
    824 	cg = ino_to_cg(sblock, ino);
    825 	getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize);
    826 	memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
    827 	if ((doswap && !needswap) || (!doswap && needswap))
    828 		ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
    829 	if (!cg_chkmagic(cgp, 0)) {
    830 		pwarn("CG %d: FREEINO: BAD MAGIC NUMBER\n", cg);
    831 		cgp = NULL;
    832 	}
    833 
    834 	memset(&idesc, 0, sizeof(struct inodesc));
    835 	idesc.id_func = pass4check;
    836 	idesc.id_number = ino;
    837 	dp = ginode(ino);
    838 	idesc.id_uid = iswap32(DIP(dp, uid));
    839 	idesc.id_gid = iswap32(DIP(dp, gid));
    840 	if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT)
    841 		idesc.id_type = SNAP;
    842 	else
    843 		idesc.id_type = ADDR;
    844 	(void)ckinode(dp, &idesc);
    845 	clearinode(dp);
    846 	inodirty();
    847 	inoinfo(ino)->ino_state = USTATE;
    848 	if (idesc.id_type != SNAP)
    849 		update_uquot(idesc.id_number,
    850 		    idesc.id_uid, idesc.id_gid, 0, -1);
    851 	n_files--;
    852 	if (cgp) {
    853 		clrbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg);
    854 		cgp->cg_cs.cs_nifree++;
    855 		sblock->fs_cstotal.cs_nifree++;
    856 		sblock->fs_cs(fs, cg).cs_nifree++;
    857 		sbdirty();
    858 		cgdirty();
    859 	}
    860 }
    861 
    862 /* read a data block from inode */
    863 ssize_t
    864 readblk(union dinode *dp, off_t offset, struct bufarea **bp)
    865 {
    866 	daddr_t blkno = lblkno(sblock, offset);
    867 	daddr_t iblkno;
    868 	int type = IFMT & iswap16(DIP(dp, mode));
    869 	ssize_t filesize = iswap64(DIP(dp, size));
    870 	int ilevel;
    871 	daddr_t nblks;
    872 	const daddr_t naddrperblk = sblock->fs_bsize /
    873 	    (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t));
    874 	struct bufarea *ibp;
    875 
    876 	*bp = NULL;
    877 	offset &= ~(sblock->fs_bsize - 1);
    878 
    879 	if (type != IFREG)
    880 		return 0;
    881 	if (offset >= filesize)
    882 		return 0; /* short read */
    883 	if (blkno < NDADDR) {
    884 		blkno = is_ufs2 ? iswap64(dp->dp2.di_db[blkno]) :
    885 		    iswap32(dp->dp1.di_db[blkno]);
    886 		if (blkno == 0)
    887 			return 0;
    888 		*bp = getdatablk(blkno, sblock->fs_bsize);
    889 		return (bp != NULL) ? sblock->fs_bsize : 0;
    890 	}
    891 	blkno -= NDADDR;
    892 	/* find indir level */
    893 	for (ilevel = 1, nblks = naddrperblk;
    894 	     ilevel <= NIADDR;
    895 	     ilevel++, nblks *= naddrperblk) {
    896 		if (blkno < nblks)
    897 			break;
    898 		else
    899 			blkno -= nblks;
    900 	}
    901 	if (ilevel > NIADDR)
    902 		errexit("bad ofsset %" PRIu64 " to readblk", offset);
    903 
    904 	/* get the first indirect block */
    905 	iblkno = is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
    906 		    iswap32(dp->dp1.di_ib[ilevel - 1]);
    907 	if (iblkno == 0)
    908 		return 0;
    909 	ibp = getdatablk(iblkno, sblock->fs_bsize);
    910 	/* walk indirect blocks up to the data block */
    911 	for (; ilevel >0 ; ilevel--) {
    912 		nblks = nblks / naddrperblk;
    913 		if (is_ufs2)
    914 			iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]);
    915 		else
    916 			iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]);
    917 		if (iblkno == 0)
    918 			return 0;
    919 		blkno = blkno % nblks;
    920 		ibp->b_flags &= ~B_INUSE;
    921 		ibp = getdatablk(iblkno, sblock->fs_bsize);
    922 	}
    923 	*bp = ibp;
    924 	return sblock->fs_bsize;
    925 }
    926 
    927 static struct bufarea * getnewblk(daddr_t *);
    928 static struct bufarea *
    929 getnewblk(daddr_t *blkno)
    930 {
    931 	struct bufarea *bp;
    932 	*blkno = allocblk(sblock->fs_frag);
    933 	if (*blkno == 0)
    934 		return NULL;
    935 	bp = getdatablk(*blkno, sblock->fs_bsize);
    936 	memset(bp->b_un.b_buf, 0, sblock->fs_bsize);
    937 	return bp;
    938 }
    939 
    940 /* expand given inode by one full fs block */
    941 struct bufarea *
    942 expandfile(union dinode *dp)
    943 {
    944 	uint64_t filesize = iswap64(DIP(dp, size));
    945 	daddr_t newblk, blkno, iblkno, nblks;
    946 	daddr_t di_blocks;
    947 	int ilevel;
    948 	const daddr_t naddrperblk = sblock->fs_bsize /
    949 	    (is_ufs2 ? sizeof(uint64_t) : sizeof(uint32_t));
    950 	struct bufarea *ibp, *bp = NULL;
    951 
    952 	di_blocks = is_ufs2 ? iswap64(dp->dp2.di_blocks) :
    953 	    iswap32(dp->dp1.di_blocks);
    954 	/* compute location of new block */
    955 	blkno = lblkno(sblock, filesize);
    956 
    957 	if (blkno < NDADDR) {
    958 		/* easy way: allocate a direct block */
    959 		if ((bp = getnewblk(&newblk)) == NULL) {
    960 			return NULL;
    961 		}
    962 		di_blocks += btodb(sblock->fs_bsize);
    963 
    964 		if (is_ufs2) {
    965 			dp->dp2.di_db[blkno] = iswap64(newblk);
    966 		} else {
    967 			dp->dp1.di_db[blkno] = iswap32(newblk);
    968 		}
    969 		goto out;
    970 	}
    971 	blkno -= NDADDR;
    972 	/* find indir level */
    973 	for (ilevel = 1, nblks = naddrperblk;
    974 	     ilevel <= NIADDR;
    975 	     ilevel++, nblks *= naddrperblk) {
    976 		if (blkno < nblks)
    977 			break;
    978 		else
    979 			blkno -= nblks;
    980 	}
    981 	if (ilevel > NIADDR)
    982 		errexit("bad filesize %" PRIu64 " to expandfile", filesize);
    983 
    984 	/* get the first indirect block, allocating if needed */
    985 	if ((is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
    986 		iswap32(dp->dp1.di_ib[ilevel - 1])) == 0) {
    987 		if ((ibp = getnewblk(&newblk)) == NULL)
    988 			return 0;
    989 		di_blocks += btodb(sblock->fs_bsize);
    990 		if (is_ufs2)
    991 			dp->dp2.di_ib[ilevel - 1] = iswap64(newblk);
    992 		else
    993 			dp->dp1.di_ib[ilevel - 1] = iswap32(newblk);
    994 	} else {
    995 		ibp = getdatablk(is_ufs2 ? iswap64(dp->dp2.di_ib[ilevel - 1]) :
    996 		    iswap32(dp->dp2.di_ib[ilevel - 1]), sblock->fs_bsize);
    997 	}
    998 	/* walk indirect blocks up to the data block */
    999 	for (; ilevel >0 ; ilevel--) {
   1000 		nblks = nblks / naddrperblk;
   1001 		if (is_ufs2)
   1002 			iblkno = iswap64(ibp->b_un.b_indir2[blkno / nblks]);
   1003 		else
   1004 			iblkno = iswap32(ibp->b_un.b_indir1[blkno / nblks]);
   1005 		if (iblkno == 0) {
   1006 			if ((bp = getnewblk(&newblk)) == NULL)
   1007 				return NULL;
   1008 			di_blocks += btodb(sblock->fs_bsize);
   1009 			if (is_ufs2)
   1010 				ibp->b_un.b_indir2[blkno / nblks] =
   1011 				    iswap64(newblk);
   1012 			else
   1013 				ibp->b_un.b_indir1[blkno / nblks] =
   1014 				    iswap32(newblk);
   1015 			dirty(ibp);
   1016 			ibp->b_flags &= ~B_INUSE;
   1017 			ibp = bp;
   1018 		} else {
   1019 			ibp->b_flags &= ~B_INUSE;
   1020 			ibp = getdatablk(iblkno, sblock->fs_bsize);
   1021 			bp = NULL;
   1022 		}
   1023 		blkno = blkno % nblks;
   1024 	}
   1025 	if (bp == NULL) {
   1026 		errexit("INTERNAL ERROR: "
   1027 		    "expandfile() failed to allocate a new block\n");
   1028 	}
   1029 
   1030 out:
   1031 	filesize += sblock->fs_bsize;
   1032 	if (is_ufs2) {
   1033 		dp->dp2.di_size = iswap64(filesize);
   1034 		dp->dp2.di_blocks = iswap64(di_blocks);
   1035 	} else {
   1036 		dp->dp1.di_size = iswap64(filesize);
   1037 		dp->dp1.di_blocks = iswap32(di_blocks);
   1038 	}
   1039 	inodirty();
   1040 	return bp;
   1041 }
   1042