Home | History | Annotate | Line # | Download | only in fsck_ffs
inode.c revision 1.64.4.2
      1 /*	$NetBSD: inode.c,v 1.64.4.2 2014/05/22 11:37:28 yamt 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.4.2 2014/05/22 11:37:28 yamt 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