116c0c8eeSKirk McKusick /* 216c0c8eeSKirk McKusick * Copyright (c) 1998, 2003, 2013, 2018 Marshall Kirk McKusick. 316c0c8eeSKirk McKusick * All Rights Reserved. 416c0c8eeSKirk McKusick * 516c0c8eeSKirk McKusick * Redistribution and use in source and binary forms, with or without 616c0c8eeSKirk McKusick * modification, are permitted provided that the following conditions 716c0c8eeSKirk McKusick * are met: 816c0c8eeSKirk McKusick * 1. Redistributions of source code must retain the above copyright 916c0c8eeSKirk McKusick * notice, this list of conditions and the following disclaimer. 1016c0c8eeSKirk McKusick * 2. Redistributions in binary form must reproduce the above copyright 1116c0c8eeSKirk McKusick * notice, this list of conditions and the following disclaimer in the 1216c0c8eeSKirk McKusick * documentation and/or other materials provided with the distribution. 1316c0c8eeSKirk McKusick * 1416c0c8eeSKirk McKusick * THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND 1516c0c8eeSKirk McKusick * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1616c0c8eeSKirk McKusick * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1716c0c8eeSKirk McKusick * ARE DISCLAIMED. IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE 1816c0c8eeSKirk McKusick * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1916c0c8eeSKirk McKusick * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2016c0c8eeSKirk McKusick * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2116c0c8eeSKirk McKusick * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2216c0c8eeSKirk McKusick * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2316c0c8eeSKirk McKusick * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2416c0c8eeSKirk McKusick * SUCH DAMAGE. 2516c0c8eeSKirk McKusick * 2616c0c8eeSKirk McKusick * $FreeBSD$ 2716c0c8eeSKirk McKusick */ 2816c0c8eeSKirk McKusick 2916c0c8eeSKirk McKusick #include <sys/param.h> 3016c0c8eeSKirk McKusick #include <ufs/ffs/fs.h> 3116c0c8eeSKirk McKusick 3216c0c8eeSKirk McKusick #include <err.h> 3316c0c8eeSKirk McKusick #include <stdio.h> 3468d7185bSKirk McKusick #include <string.h> 350e3f58b6SKirk McKusick #include <libufs.h> 3616c0c8eeSKirk McKusick 3768d7185bSKirk McKusick #ifdef PRTBLKNOS 3816c0c8eeSKirk McKusick union dinode { 390e3f58b6SKirk McKusick struct ufs1_dinode dp1; 400e3f58b6SKirk McKusick struct ufs2_dinode dp2; 4116c0c8eeSKirk McKusick }; 4268d7185bSKirk McKusick extern struct uufsd disk; 4368d7185bSKirk McKusick #else /* used by fsdb */ 4468d7185bSKirk McKusick #include <fsck.h> 4568d7185bSKirk McKusick static struct bufarea *bp; 4668d7185bSKirk McKusick #endif 4716c0c8eeSKirk McKusick 4868d7185bSKirk McKusick void prtblknos(struct fs *fs, union dinode *dp); 4916c0c8eeSKirk McKusick 50d3009da8SKirk McKusick static const char *distance(struct fs *, ufs2_daddr_t, ufs2_daddr_t); 51d3009da8SKirk McKusick static void printblk(struct fs *, ufs_lbn_t, ufs2_daddr_t, int, ufs_lbn_t); 5268d7185bSKirk McKusick static void indirprt(struct fs *, int, ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t, 53d3009da8SKirk McKusick ufs_lbn_t); 5416c0c8eeSKirk McKusick 550e3f58b6SKirk McKusick void 5668d7185bSKirk McKusick prtblknos(fs, dp) 5768d7185bSKirk McKusick struct fs *fs; 580e3f58b6SKirk McKusick union dinode *dp; 5916c0c8eeSKirk McKusick { 60d3009da8SKirk McKusick int i, mode, frags; 61d3009da8SKirk McKusick ufs_lbn_t lbn, lastlbn, len, blksperindir; 6216c0c8eeSKirk McKusick ufs2_daddr_t blkno; 630e3f58b6SKirk McKusick off_t size; 6416c0c8eeSKirk McKusick 6515e4030eSKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) { 660e3f58b6SKirk McKusick size = dp->dp1.di_size; 6715e4030eSKirk McKusick mode = dp->dp1.di_mode; 6815e4030eSKirk McKusick } else { 690e3f58b6SKirk McKusick size = dp->dp2.di_size; 7015e4030eSKirk McKusick mode = dp->dp2.di_mode; 7115e4030eSKirk McKusick } 7215e4030eSKirk McKusick switch (mode & IFMT) { 73d3009da8SKirk McKusick default: 74d3009da8SKirk McKusick printf("unknown inode type 0%d\n", (mode & IFMT)); 75d3009da8SKirk McKusick return; 76d3009da8SKirk McKusick case 0: 77d3009da8SKirk McKusick printf("unallocated inode\n"); 78d3009da8SKirk McKusick return; 7915e4030eSKirk McKusick case IFIFO: 8015e4030eSKirk McKusick printf("fifo\n"); 8115e4030eSKirk McKusick return; 8215e4030eSKirk McKusick case IFCHR: 8315e4030eSKirk McKusick printf("character device\n"); 8415e4030eSKirk McKusick return; 8515e4030eSKirk McKusick case IFBLK: 8615e4030eSKirk McKusick printf("block device\n"); 8715e4030eSKirk McKusick return; 8815e4030eSKirk McKusick case IFSOCK: 8915e4030eSKirk McKusick printf("socket\n"); 9015e4030eSKirk McKusick return; 9115e4030eSKirk McKusick case IFWHT: 9215e4030eSKirk McKusick printf("whiteout\n"); 9315e4030eSKirk McKusick return; 9415e4030eSKirk McKusick case IFLNK: 9515e4030eSKirk McKusick if (size == 0) { 9615e4030eSKirk McKusick printf("empty symbolic link\n"); 9715e4030eSKirk McKusick return; 9815e4030eSKirk McKusick } 9915e4030eSKirk McKusick if (size < fs->fs_maxsymlinklen) { 10015e4030eSKirk McKusick printf("symbolic link referencing %s\n", 10115e4030eSKirk McKusick (fs->fs_magic == FS_UFS1_MAGIC) ? 1025b13fa79SJessica Clarke dp->dp1.di_shortlink : 1035b13fa79SJessica Clarke dp->dp2.di_shortlink); 10415e4030eSKirk McKusick return; 10515e4030eSKirk McKusick } 10615e4030eSKirk McKusick printf("symbolic link\n"); 10715e4030eSKirk McKusick break; 10815e4030eSKirk McKusick case IFREG: 10915e4030eSKirk McKusick if (size == 0) { 11016c0c8eeSKirk McKusick printf("empty file\n"); 1110e3f58b6SKirk McKusick return; 11216c0c8eeSKirk McKusick } 113d3009da8SKirk McKusick printf("regular file, size %jd\n", (intmax_t)size); 11415e4030eSKirk McKusick break; 11515e4030eSKirk McKusick case IFDIR: 11615e4030eSKirk McKusick if (size == 0) { 11715e4030eSKirk McKusick printf("empty directory\n"); 11815e4030eSKirk McKusick return; 11915e4030eSKirk McKusick } 120d3009da8SKirk McKusick printf("directory, size %jd\n", (intmax_t)size); 12115e4030eSKirk McKusick break; 12215e4030eSKirk McKusick } 123d3009da8SKirk McKusick lastlbn = howmany(size, fs->fs_bsize); 124d3009da8SKirk McKusick len = lastlbn < UFS_NDADDR ? lastlbn : UFS_NDADDR; 12516c0c8eeSKirk McKusick for (i = 0; i < len; i++) { 126d3009da8SKirk McKusick if (i < lastlbn - 1) 1270e3f58b6SKirk McKusick frags = fs->fs_frag; 12816c0c8eeSKirk McKusick else 12928ac2238SKirk McKusick frags = howmany(size - (lastlbn - 1) * fs->fs_bsize, 1300e3f58b6SKirk McKusick fs->fs_fsize); 1310e3f58b6SKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) 1320e3f58b6SKirk McKusick blkno = dp->dp1.di_db[i]; 13316c0c8eeSKirk McKusick else 1340e3f58b6SKirk McKusick blkno = dp->dp2.di_db[i]; 135d3009da8SKirk McKusick printblk(fs, i, blkno, frags, lastlbn); 13616c0c8eeSKirk McKusick } 13716c0c8eeSKirk McKusick 13816c0c8eeSKirk McKusick blksperindir = 1; 139d3009da8SKirk McKusick len = lastlbn - UFS_NDADDR; 14016c0c8eeSKirk McKusick lbn = UFS_NDADDR; 14116c0c8eeSKirk McKusick for (i = 0; len > 0 && i < UFS_NIADDR; i++) { 1420e3f58b6SKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) 1430e3f58b6SKirk McKusick blkno = dp->dp1.di_ib[i]; 14416c0c8eeSKirk McKusick else 1450e3f58b6SKirk McKusick blkno = dp->dp2.di_ib[i]; 14668d7185bSKirk McKusick indirprt(fs, i, blksperindir, lbn, blkno, lastlbn); 1470e3f58b6SKirk McKusick blksperindir *= NINDIR(fs); 14816c0c8eeSKirk McKusick lbn += blksperindir; 14916c0c8eeSKirk McKusick len -= blksperindir; 15016c0c8eeSKirk McKusick } 15116c0c8eeSKirk McKusick 15216c0c8eeSKirk McKusick /* dummy print to flush out last extent */ 153d3009da8SKirk McKusick printblk(fs, lastlbn, 0, frags, 0); 15416c0c8eeSKirk McKusick } 15516c0c8eeSKirk McKusick 1560e3f58b6SKirk McKusick static void 15768d7185bSKirk McKusick indirprt(fs, level, blksperindir, lbn, blkno, lastlbn) 15868d7185bSKirk McKusick struct fs *fs; 15916c0c8eeSKirk McKusick int level; 160d3009da8SKirk McKusick ufs_lbn_t blksperindir; 161d3009da8SKirk McKusick ufs_lbn_t lbn; 16216c0c8eeSKirk McKusick ufs2_daddr_t blkno; 163d3009da8SKirk McKusick ufs_lbn_t lastlbn; 16416c0c8eeSKirk McKusick { 16516c0c8eeSKirk McKusick char indir[MAXBSIZE]; 166d3009da8SKirk McKusick ufs_lbn_t i, last; 16716c0c8eeSKirk McKusick 16815e4030eSKirk McKusick if (blkno == 0) { 16915e4030eSKirk McKusick printblk(fs, lbn, blkno, 17015e4030eSKirk McKusick blksperindir * NINDIR(fs) * fs->fs_frag, lastlbn); 17115e4030eSKirk McKusick return; 17215e4030eSKirk McKusick } 1730e3f58b6SKirk McKusick printblk(fs, lbn, blkno, fs->fs_frag, -level); 17416c0c8eeSKirk McKusick /* read in the indirect block. */ 17568d7185bSKirk McKusick #ifdef PRTBLKNOS 17668d7185bSKirk McKusick if (bread(&disk, fsbtodb(fs, blkno), indir, fs->fs_bsize) == -1) { 17768d7185bSKirk McKusick #else /* used by fsdb */ 17868d7185bSKirk McKusick bp = getdatablk(blkno, fs->fs_bsize, BT_LEVEL1 + level); 17968d7185bSKirk McKusick if (bp->b_errs == 0) { 18068d7185bSKirk McKusick memcpy(indir, bp->b_un.b_buf, fs->fs_bsize); 18168d7185bSKirk McKusick } else { 18268d7185bSKirk McKusick #endif 183c343fa81SKirk McKusick warn("Read of indirect block %jd failed", (intmax_t)blkno); 184c343fa81SKirk McKusick /* List the unreadable part as a hole */ 185c343fa81SKirk McKusick printblk(fs, lbn, 0, 186c343fa81SKirk McKusick blksperindir * NINDIR(fs) * fs->fs_frag, lastlbn); 187c343fa81SKirk McKusick return; 188c343fa81SKirk McKusick } 1890e3f58b6SKirk McKusick last = howmany(lastlbn - lbn, blksperindir) < NINDIR(fs) ? 1900e3f58b6SKirk McKusick howmany(lastlbn - lbn, blksperindir) : NINDIR(fs); 19116c0c8eeSKirk McKusick if (blksperindir == 1) { 19216c0c8eeSKirk McKusick for (i = 0; i < last; i++) { 1930e3f58b6SKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) 19416c0c8eeSKirk McKusick blkno = ((ufs1_daddr_t *)indir)[i]; 19516c0c8eeSKirk McKusick else 19616c0c8eeSKirk McKusick blkno = ((ufs2_daddr_t *)indir)[i]; 1970e3f58b6SKirk McKusick printblk(fs, lbn + i, blkno, fs->fs_frag, lastlbn); 19816c0c8eeSKirk McKusick } 19916c0c8eeSKirk McKusick return; 20016c0c8eeSKirk McKusick } 20116c0c8eeSKirk McKusick for (i = 0; i < last; i++) { 2020e3f58b6SKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) 20316c0c8eeSKirk McKusick blkno = ((ufs1_daddr_t *)indir)[i]; 20416c0c8eeSKirk McKusick else 20516c0c8eeSKirk McKusick blkno = ((ufs2_daddr_t *)indir)[i]; 20668d7185bSKirk McKusick indirprt(fs, level - 1, blksperindir / NINDIR(fs), 20716c0c8eeSKirk McKusick lbn + blksperindir * i, blkno, lastlbn); 20816c0c8eeSKirk McKusick } 20916c0c8eeSKirk McKusick } 21016c0c8eeSKirk McKusick 211d3009da8SKirk McKusick static const char * 2120e3f58b6SKirk McKusick distance(fs, lastblk, firstblk) 2130e3f58b6SKirk McKusick struct fs *fs; 214d3009da8SKirk McKusick ufs2_daddr_t lastblk; 215d3009da8SKirk McKusick ufs2_daddr_t firstblk; 21616c0c8eeSKirk McKusick { 217d3009da8SKirk McKusick ufs2_daddr_t delta; 21816c0c8eeSKirk McKusick int firstcg, lastcg; 21916c0c8eeSKirk McKusick static char buf[100]; 22016c0c8eeSKirk McKusick 22116c0c8eeSKirk McKusick if (lastblk == 0) 22216c0c8eeSKirk McKusick return (""); 22316c0c8eeSKirk McKusick delta = firstblk - lastblk - 1; 2240e3f58b6SKirk McKusick firstcg = dtog(fs, firstblk); 2250e3f58b6SKirk McKusick lastcg = dtog(fs, lastblk); 22616c0c8eeSKirk McKusick if (firstcg == lastcg) { 22716c0c8eeSKirk McKusick snprintf(buf, 100, " distance %jd", (intmax_t)delta); 22816c0c8eeSKirk McKusick return (&buf[0]); 22916c0c8eeSKirk McKusick } 23016c0c8eeSKirk McKusick snprintf(buf, 100, " cg %d blk %jd to cg %d blk %jd", 231f33fbc18SKirk McKusick lastcg, (intmax_t)dtogd(fs, lastblk), firstcg, 232f33fbc18SKirk McKusick (intmax_t)dtogd(fs, firstblk)); 23316c0c8eeSKirk McKusick return (&buf[0]); 23416c0c8eeSKirk McKusick } 23516c0c8eeSKirk McKusick 23616c0c8eeSKirk McKusick 237d3009da8SKirk McKusick static const char *indirname[UFS_NIADDR] = { "First", "Second", "Third" }; 23816c0c8eeSKirk McKusick 2390e3f58b6SKirk McKusick static void 240d3009da8SKirk McKusick printblk(fs, lbn, blkno, numfrags, lastlbn) 2410e3f58b6SKirk McKusick struct fs *fs; 242d3009da8SKirk McKusick ufs_lbn_t lbn; 24316c0c8eeSKirk McKusick ufs2_daddr_t blkno; 244d3009da8SKirk McKusick int numfrags; 245d3009da8SKirk McKusick ufs_lbn_t lastlbn; 24616c0c8eeSKirk McKusick { 24716c0c8eeSKirk McKusick static int seq; 248d3009da8SKirk McKusick static ufs2_daddr_t totfrags, lastindirblk, lastblk, firstblk; 24916c0c8eeSKirk McKusick 25016c0c8eeSKirk McKusick if (lastlbn <= 0) 25116c0c8eeSKirk McKusick goto flush; 25216c0c8eeSKirk McKusick if (seq == 0) { 253d3009da8SKirk McKusick seq = howmany(numfrags, fs->fs_frag); 254d3009da8SKirk McKusick totfrags = numfrags; 25516c0c8eeSKirk McKusick firstblk = blkno; 25616c0c8eeSKirk McKusick return; 25716c0c8eeSKirk McKusick } 25816c0c8eeSKirk McKusick if (lbn == 0) { 259d3009da8SKirk McKusick seq = howmany(numfrags, fs->fs_frag); 260d3009da8SKirk McKusick totfrags = numfrags; 26116c0c8eeSKirk McKusick lastblk = 0; 26216c0c8eeSKirk McKusick firstblk = blkno; 26316c0c8eeSKirk McKusick lastindirblk = 0; 26416c0c8eeSKirk McKusick return; 26516c0c8eeSKirk McKusick } 26616c0c8eeSKirk McKusick if (lbn < lastlbn && ((firstblk == 0 && blkno == 0) || 26716c0c8eeSKirk McKusick (firstblk == BLK_NOCOPY && blkno == BLK_NOCOPY) || 26816c0c8eeSKirk McKusick (firstblk == BLK_SNAP && blkno == BLK_SNAP) || 26915e4030eSKirk McKusick blkno == firstblk + seq * fs->fs_frag)) { 270d3009da8SKirk McKusick seq += howmany(numfrags, fs->fs_frag); 271d3009da8SKirk McKusick totfrags += numfrags; 27216c0c8eeSKirk McKusick return; 27316c0c8eeSKirk McKusick } 27416c0c8eeSKirk McKusick flush: 27516c0c8eeSKirk McKusick if (seq == 0) 27616c0c8eeSKirk McKusick goto prtindir; 27716c0c8eeSKirk McKusick if (firstblk <= BLK_SNAP) { 27816c0c8eeSKirk McKusick if (seq == 1) 279d3009da8SKirk McKusick printf("\tlbn %jd %s\n", (intmax_t)(lbn - seq), 28016c0c8eeSKirk McKusick firstblk == 0 ? "hole" : 28116c0c8eeSKirk McKusick firstblk == BLK_NOCOPY ? "nocopy" : 28216c0c8eeSKirk McKusick "snapblk"); 28316c0c8eeSKirk McKusick else 284d3009da8SKirk McKusick printf("\tlbn %jd-%jd %s\n", 285d3009da8SKirk McKusick (intmax_t)lbn - seq, (intmax_t)lbn - 1, 28616c0c8eeSKirk McKusick firstblk == 0 ? "hole" : 28716c0c8eeSKirk McKusick firstblk == BLK_NOCOPY ? "nocopy" : 28816c0c8eeSKirk McKusick "snapblk"); 28916c0c8eeSKirk McKusick } else if (seq == 1) { 290d3009da8SKirk McKusick if (totfrags == 1) 291d3009da8SKirk McKusick printf("\tlbn %jd blkno %jd%s\n", (intmax_t)(lbn - seq), 2920e3f58b6SKirk McKusick (intmax_t)firstblk, distance(fs, lastblk, firstblk)); 29316c0c8eeSKirk McKusick else 294d3009da8SKirk McKusick printf("\tlbn %jd blkno %jd-%jd%s\n", 295d3009da8SKirk McKusick (intmax_t)(lbn - seq), (intmax_t)firstblk, 296d3009da8SKirk McKusick (intmax_t)(firstblk + totfrags - 1), 2970e3f58b6SKirk McKusick distance(fs, lastblk, firstblk)); 298d3009da8SKirk McKusick lastblk = firstblk + totfrags - 1; 29916c0c8eeSKirk McKusick } else { 300d3009da8SKirk McKusick printf("\tlbn %jd-%jd blkno %jd-%jd%s\n", (intmax_t)(lbn - seq), 301d3009da8SKirk McKusick (intmax_t)(lbn - 1), (intmax_t)firstblk, 302d3009da8SKirk McKusick (intmax_t)(firstblk + totfrags - 1), 3030e3f58b6SKirk McKusick distance(fs, lastblk, firstblk)); 304d3009da8SKirk McKusick lastblk = firstblk + totfrags - 1; 30516c0c8eeSKirk McKusick } 30616c0c8eeSKirk McKusick if (lastlbn > 0 || blkno == 0) { 30716c0c8eeSKirk McKusick seq = 1; 308d3009da8SKirk McKusick totfrags = numfrags; 30916c0c8eeSKirk McKusick firstblk = blkno; 31016c0c8eeSKirk McKusick return; 31116c0c8eeSKirk McKusick } 31216c0c8eeSKirk McKusick prtindir: 3130e3f58b6SKirk McKusick if (seq != 0 && (fs->fs_metaspace == 0 || lastindirblk == 0)) 31416c0c8eeSKirk McKusick lastindirblk = lastblk; 31516c0c8eeSKirk McKusick printf("%s-level indirect, blkno %jd-%jd%s\n", indirname[-lastlbn], 316d3009da8SKirk McKusick (intmax_t)blkno, (intmax_t)(blkno + numfrags - 1), 3170e3f58b6SKirk McKusick distance(fs, lastindirblk, blkno)); 318d3009da8SKirk McKusick lastindirblk = blkno + numfrags - 1; 3190e3f58b6SKirk McKusick if (fs->fs_metaspace == 0) 32016c0c8eeSKirk McKusick lastblk = lastindirblk; 32116c0c8eeSKirk McKusick seq = 0; 32216c0c8eeSKirk McKusick } 323