1df57947fSPedro F. Giffuni /*- 2df57947fSPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause 3df57947fSPedro F. Giffuni * 43d500078SThomas-Henning von Kamptz * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz 53d500078SThomas-Henning von Kamptz * Copyright (c) 1980, 1989, 1993 The Regents of the University of California. 63d500078SThomas-Henning von Kamptz * All rights reserved. 73d500078SThomas-Henning von Kamptz * 83d500078SThomas-Henning von Kamptz * This code is derived from software contributed to Berkeley by 93d500078SThomas-Henning von Kamptz * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt. 103d500078SThomas-Henning von Kamptz * 113d500078SThomas-Henning von Kamptz * Redistribution and use in source and binary forms, with or without 123d500078SThomas-Henning von Kamptz * modification, are permitted provided that the following conditions 133d500078SThomas-Henning von Kamptz * are met: 143d500078SThomas-Henning von Kamptz * 1. Redistributions of source code must retain the above copyright 153d500078SThomas-Henning von Kamptz * notice, this list of conditions and the following disclaimer. 163d500078SThomas-Henning von Kamptz * 2. Redistributions in binary form must reproduce the above copyright 173d500078SThomas-Henning von Kamptz * notice, this list of conditions and the following disclaimer in the 183d500078SThomas-Henning von Kamptz * documentation and/or other materials provided with the distribution. 193d500078SThomas-Henning von Kamptz * 3. All advertising materials mentioning features or use of this software 203d500078SThomas-Henning von Kamptz * must display the following acknowledgment: 213d500078SThomas-Henning von Kamptz * This product includes software developed by the University of 223d500078SThomas-Henning von Kamptz * California, Berkeley and its contributors, as well as Christoph 233d500078SThomas-Henning von Kamptz * Herrmann and Thomas-Henning von Kamptz. 243d500078SThomas-Henning von Kamptz * 4. Neither the name of the University nor the names of its contributors 253d500078SThomas-Henning von Kamptz * may be used to endorse or promote products derived from this software 263d500078SThomas-Henning von Kamptz * without specific prior written permission. 273d500078SThomas-Henning von Kamptz * 283d500078SThomas-Henning von Kamptz * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 293d500078SThomas-Henning von Kamptz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 303d500078SThomas-Henning von Kamptz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 313d500078SThomas-Henning von Kamptz * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 323d500078SThomas-Henning von Kamptz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 333d500078SThomas-Henning von Kamptz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 343d500078SThomas-Henning von Kamptz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 353d500078SThomas-Henning von Kamptz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 363d500078SThomas-Henning von Kamptz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 373d500078SThomas-Henning von Kamptz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 383d500078SThomas-Henning von Kamptz * SUCH DAMAGE. 393d500078SThomas-Henning von Kamptz * 404020c5bcSThomas-Henning von Kamptz * $TSHeader: src/sbin/ffsinfo/ffsinfo.c,v 1.4 2000/12/12 19:30:55 tomsoft Exp $ 413d500078SThomas-Henning von Kamptz * 423d500078SThomas-Henning von Kamptz */ 433d500078SThomas-Henning von Kamptz 443d500078SThomas-Henning von Kamptz #ifndef lint 453d500078SThomas-Henning von Kamptz static const char copyright[] = 463d500078SThomas-Henning von Kamptz "@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\ 473d500078SThomas-Henning von Kamptz Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\ 483d500078SThomas-Henning von Kamptz All rights reserved.\n"; 493d500078SThomas-Henning von Kamptz #endif /* not lint */ 503d500078SThomas-Henning von Kamptz 513d500078SThomas-Henning von Kamptz #ifndef lint 523d500078SThomas-Henning von Kamptz static const char rcsid[] = 533d500078SThomas-Henning von Kamptz "$FreeBSD$"; 543d500078SThomas-Henning von Kamptz #endif /* not lint */ 553d500078SThomas-Henning von Kamptz 563d500078SThomas-Henning von Kamptz /* ********************************************************** INCLUDES ***** */ 573d500078SThomas-Henning von Kamptz #include <sys/param.h> 583d500078SThomas-Henning von Kamptz #include <sys/disklabel.h> 59942d2e02SRobert Watson #include <sys/mount.h> 603d500078SThomas-Henning von Kamptz #include <sys/stat.h> 613d500078SThomas-Henning von Kamptz 62*d485c77fSKonstantin Belousov #include <ufs/ufs/extattr.h> 63*d485c77fSKonstantin Belousov #include <ufs/ufs/quota.h> 64942d2e02SRobert Watson #include <ufs/ufs/ufsmount.h> 65942d2e02SRobert Watson #include <ufs/ufs/dinode.h> 66942d2e02SRobert Watson #include <ufs/ffs/fs.h> 67942d2e02SRobert Watson 683d500078SThomas-Henning von Kamptz #include <ctype.h> 693d500078SThomas-Henning von Kamptz #include <err.h> 707bb84191SRobert Watson #include <errno.h> 713d500078SThomas-Henning von Kamptz #include <fcntl.h> 72942d2e02SRobert Watson #include <libufs.h> 73942d2e02SRobert Watson #include <paths.h> 749b337054SGleb Kurtsou #include <stdint.h> 75942d2e02SRobert Watson #include <stdio.h> 763d500078SThomas-Henning von Kamptz #include <stdlib.h> 773d500078SThomas-Henning von Kamptz #include <string.h> 783d500078SThomas-Henning von Kamptz #include <unistd.h> 793d500078SThomas-Henning von Kamptz 803d500078SThomas-Henning von Kamptz #include "debug.h" 813d500078SThomas-Henning von Kamptz 823d500078SThomas-Henning von Kamptz /* *********************************************************** GLOBALS ***** */ 833d500078SThomas-Henning von Kamptz #ifdef FS_DEBUG 843d500078SThomas-Henning von Kamptz int _dbg_lvl_ = (DL_INFO); /* DL_TRC */ 853d500078SThomas-Henning von Kamptz #endif /* FS_DEBUG */ 863d500078SThomas-Henning von Kamptz 871efe3c6bSEd Schouten static struct uufsd disk; 88942d2e02SRobert Watson 89942d2e02SRobert Watson #define sblock disk.d_fs 90942d2e02SRobert Watson #define acg disk.d_cg 91942d2e02SRobert Watson 923d500078SThomas-Henning von Kamptz static union { 933d500078SThomas-Henning von Kamptz struct fs fs; 94942d2e02SRobert Watson char pad[SBLOCKSIZE]; 95942d2e02SRobert Watson } fsun; 963d500078SThomas-Henning von Kamptz 97942d2e02SRobert Watson #define osblock fsun.fs 983d500078SThomas-Henning von Kamptz 993d500078SThomas-Henning von Kamptz static char i1blk[MAXBSIZE]; 1003d500078SThomas-Henning von Kamptz static char i2blk[MAXBSIZE]; 1013d500078SThomas-Henning von Kamptz static char i3blk[MAXBSIZE]; 1023d500078SThomas-Henning von Kamptz 1033d500078SThomas-Henning von Kamptz static struct csum *fscs; 1043d500078SThomas-Henning von Kamptz 1053d500078SThomas-Henning von Kamptz /* ******************************************************** PROTOTYPES ***** */ 1064020c5bcSThomas-Henning von Kamptz static void usage(void); 107942d2e02SRobert Watson static void dump_whole_ufs1_inode(ino_t, int); 108942d2e02SRobert Watson static void dump_whole_ufs2_inode(ino_t, int); 1093d500078SThomas-Henning von Kamptz 110942d2e02SRobert Watson #define DUMP_WHOLE_INODE(A,B) \ 111942d2e02SRobert Watson ( disk.d_ufs == 1 \ 112942d2e02SRobert Watson ? dump_whole_ufs1_inode((A),(B)) : dump_whole_ufs2_inode((A),(B)) ) 1133d500078SThomas-Henning von Kamptz 1143d500078SThomas-Henning von Kamptz /* ************************************************************** main ***** */ 1153d500078SThomas-Henning von Kamptz /* 1163d500078SThomas-Henning von Kamptz * ffsinfo(8) is a tool to dump all metadata of a file system. It helps to find 1173d500078SThomas-Henning von Kamptz * errors is the file system much easier. You can run ffsinfo before and after 1183d500078SThomas-Henning von Kamptz * an fsck(8), and compare the two ascii dumps easy with diff, and you see 1193d500078SThomas-Henning von Kamptz * directly where the problem is. You can control how much detail you want to 1203d500078SThomas-Henning von Kamptz * see with some command line arguments. You can also easy check the status 1213d500078SThomas-Henning von Kamptz * of a file system, like is there is enough space for growing a file system, 1223d500078SThomas-Henning von Kamptz * or how many active snapshots do we have. It provides much more detailed 1233d500078SThomas-Henning von Kamptz * information then dumpfs. Snapshots, as they are very new, are not really 1243d500078SThomas-Henning von Kamptz * supported. They are just mentioned currently, but it is planned to run 1253d500078SThomas-Henning von Kamptz * also over active snapshots, to even get that output. 1263d500078SThomas-Henning von Kamptz */ 1273d500078SThomas-Henning von Kamptz int 1283d500078SThomas-Henning von Kamptz main(int argc, char **argv) 1293d500078SThomas-Henning von Kamptz { 1303d500078SThomas-Henning von Kamptz DBG_FUNC("main") 131942d2e02SRobert Watson char *device, *special; 132f901ebcfSStefan Farfeleder int ch; 1333d500078SThomas-Henning von Kamptz size_t len; 1343d500078SThomas-Henning von Kamptz struct stat st; 1353d500078SThomas-Henning von Kamptz struct csum *dbg_csp; 1363d500078SThomas-Henning von Kamptz int dbg_csc; 1373d500078SThomas-Henning von Kamptz char dbg_line[80]; 1383d500078SThomas-Henning von Kamptz int cylno,i; 1393d500078SThomas-Henning von Kamptz int cfg_cg, cfg_in, cfg_lv; 1403d500078SThomas-Henning von Kamptz int cg_start, cg_stop; 1413d500078SThomas-Henning von Kamptz ino_t in; 1423d500078SThomas-Henning von Kamptz char *out_file; 1433d500078SThomas-Henning von Kamptz 1443d500078SThomas-Henning von Kamptz DBG_ENTER; 1453d500078SThomas-Henning von Kamptz 1463d500078SThomas-Henning von Kamptz cfg_lv = 0xff; 1473d500078SThomas-Henning von Kamptz cfg_in = -2; 1483d500078SThomas-Henning von Kamptz cfg_cg = -2; 1495c68d108SXin LI out_file = strdup("-"); 1503d500078SThomas-Henning von Kamptz 151942d2e02SRobert Watson while ((ch = getopt(argc, argv, "g:i:l:o:")) != -1) { 1523d500078SThomas-Henning von Kamptz switch (ch) { 1533d500078SThomas-Henning von Kamptz case 'g': 1547bb84191SRobert Watson cfg_cg = strtol(optarg, NULL, 0); 1557bb84191SRobert Watson if (errno == EINVAL || errno == ERANGE) 1567bb84191SRobert Watson err(1, "%s", optarg); 15789f0730dSBrian Somers if (cfg_cg < -1) 1584020c5bcSThomas-Henning von Kamptz usage(); 1593d500078SThomas-Henning von Kamptz break; 1603d500078SThomas-Henning von Kamptz case 'i': 1617bb84191SRobert Watson cfg_in = strtol(optarg, NULL, 0); 1627bb84191SRobert Watson if (errno == EINVAL || errno == ERANGE) 1637bb84191SRobert Watson err(1, "%s", optarg); 16489f0730dSBrian Somers if (cfg_in < 0) 1654020c5bcSThomas-Henning von Kamptz usage(); 1663d500078SThomas-Henning von Kamptz break; 1673d500078SThomas-Henning von Kamptz case 'l': 1687bb84191SRobert Watson cfg_lv = strtol(optarg, NULL, 0); 1697bb84191SRobert Watson if (errno == EINVAL||errno == ERANGE) 1707bb84191SRobert Watson err(1, "%s", optarg); 17189f0730dSBrian Somers if (cfg_lv < 0x1 || cfg_lv > 0x3ff) 1724020c5bcSThomas-Henning von Kamptz usage(); 1733d500078SThomas-Henning von Kamptz break; 1743d500078SThomas-Henning von Kamptz case 'o': 1753d500078SThomas-Henning von Kamptz free(out_file); 1763d500078SThomas-Henning von Kamptz out_file = strdup(optarg); 17789f0730dSBrian Somers if (out_file == NULL) 1784020c5bcSThomas-Henning von Kamptz errx(1, "strdup failed"); 1793d500078SThomas-Henning von Kamptz break; 1803d500078SThomas-Henning von Kamptz case '?': 1813d500078SThomas-Henning von Kamptz /* FALLTHROUGH */ 1823d500078SThomas-Henning von Kamptz default: 1834020c5bcSThomas-Henning von Kamptz usage(); 1843d500078SThomas-Henning von Kamptz } 1853d500078SThomas-Henning von Kamptz } 1863d500078SThomas-Henning von Kamptz argc -= optind; 1873d500078SThomas-Henning von Kamptz argv += optind; 1883d500078SThomas-Henning von Kamptz 18989f0730dSBrian Somers if (argc != 1) 1904020c5bcSThomas-Henning von Kamptz usage(); 1913d500078SThomas-Henning von Kamptz device = *argv; 1923d500078SThomas-Henning von Kamptz 1933d500078SThomas-Henning von Kamptz /* 1943d500078SThomas-Henning von Kamptz * Now we try to guess the (raw)device name. 1953d500078SThomas-Henning von Kamptz */ 19689f0730dSBrian Somers if (0 == strrchr(device, '/') && stat(device, &st) == -1) { 19789f0730dSBrian Somers /*- 19889f0730dSBrian Somers * No path prefix was given, so try in this order: 1993d500078SThomas-Henning von Kamptz * /dev/r%s 2003d500078SThomas-Henning von Kamptz * /dev/%s 2013d500078SThomas-Henning von Kamptz * /dev/vinum/r%s 2023d500078SThomas-Henning von Kamptz * /dev/vinum/%s. 2033d500078SThomas-Henning von Kamptz * 2043d500078SThomas-Henning von Kamptz * FreeBSD now doesn't distinguish between raw and block 2053d500078SThomas-Henning von Kamptz * devices any longer, but it should still work this way. 2063d500078SThomas-Henning von Kamptz */ 2073d500078SThomas-Henning von Kamptz len = strlen(device) + strlen(_PATH_DEV) + 2 + strlen("vinum/"); 2083d500078SThomas-Henning von Kamptz special = (char *)malloc(len); 20989f0730dSBrian Somers if (special == NULL) 2104020c5bcSThomas-Henning von Kamptz errx(1, "malloc failed"); 2113d500078SThomas-Henning von Kamptz snprintf(special, len, "%sr%s", _PATH_DEV, device); 2123d500078SThomas-Henning von Kamptz if (stat(special, &st) == -1) { 2133d500078SThomas-Henning von Kamptz snprintf(special, len, "%s%s", _PATH_DEV, device); 2143d500078SThomas-Henning von Kamptz if (stat(special, &st) == -1) { 2153d500078SThomas-Henning von Kamptz snprintf(special, len, "%svinum/r%s", 2163d500078SThomas-Henning von Kamptz _PATH_DEV, device); 21789f0730dSBrian Somers if (stat(special, &st) == -1) 21889f0730dSBrian Somers /* For now this is the 'last resort' */ 2193d500078SThomas-Henning von Kamptz snprintf(special, len, "%svinum/%s", 2203d500078SThomas-Henning von Kamptz _PATH_DEV, device); 2213d500078SThomas-Henning von Kamptz } 2223d500078SThomas-Henning von Kamptz } 2233d500078SThomas-Henning von Kamptz device = special; 2243d500078SThomas-Henning von Kamptz } 2253d500078SThomas-Henning von Kamptz 226942d2e02SRobert Watson if (ufs_disk_fillout(&disk, device) == -1) 227942d2e02SRobert Watson err(1, "ufs_disk_fillout(%s) failed: %s", device, disk.d_error); 2283d500078SThomas-Henning von Kamptz 2293d500078SThomas-Henning von Kamptz DBG_OPEN(out_file); /* already here we need a superblock */ 2303d500078SThomas-Henning von Kamptz 23189f0730dSBrian Somers if (cfg_lv & 0x001) 23289f0730dSBrian Somers DBG_DUMP_FS(&sblock, "primary sblock"); 2333d500078SThomas-Henning von Kamptz 23489f0730dSBrian Somers /* Determine here what cylinder groups to dump */ 2353d500078SThomas-Henning von Kamptz if (cfg_cg==-2) { 2363d500078SThomas-Henning von Kamptz cg_start = 0; 2373d500078SThomas-Henning von Kamptz cg_stop = sblock.fs_ncg; 2383d500078SThomas-Henning von Kamptz } else if (cfg_cg == -1) { 2393d500078SThomas-Henning von Kamptz cg_start = sblock.fs_ncg - 1; 2403d500078SThomas-Henning von Kamptz cg_stop = sblock.fs_ncg; 2413d500078SThomas-Henning von Kamptz } else if (cfg_cg < sblock.fs_ncg) { 2423d500078SThomas-Henning von Kamptz cg_start = cfg_cg; 2433d500078SThomas-Henning von Kamptz cg_stop = cfg_cg + 1; 2443d500078SThomas-Henning von Kamptz } else { 2453d500078SThomas-Henning von Kamptz cg_start = sblock.fs_ncg; 2463d500078SThomas-Henning von Kamptz cg_stop = sblock.fs_ncg; 2473d500078SThomas-Henning von Kamptz } 2483d500078SThomas-Henning von Kamptz 2493d500078SThomas-Henning von Kamptz if (cfg_lv & 0x004) { 250adcaff07SThomas-Henning von Kamptz fscs = (struct csum *)calloc((size_t)1, 251adcaff07SThomas-Henning von Kamptz (size_t)sblock.fs_cssize); 25289f0730dSBrian Somers if (fscs == NULL) 2534020c5bcSThomas-Henning von Kamptz errx(1, "calloc failed"); 2543d500078SThomas-Henning von Kamptz 25589f0730dSBrian Somers /* get the cylinder summary into the memory ... */ 2563d500078SThomas-Henning von Kamptz for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) { 25789f0730dSBrian Somers if (bread(&disk, fsbtodb(&sblock, 25889f0730dSBrian Somers sblock.fs_csaddr + numfrags(&sblock, i)), 259942d2e02SRobert Watson (void *)(((char *)fscs)+i), 26089f0730dSBrian Somers (size_t)(sblock.fs_cssize-i < sblock.fs_bsize ? 26189f0730dSBrian Somers sblock.fs_cssize - i : sblock.fs_bsize)) == -1) 262942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 263942d2e02SRobert Watson } 2643d500078SThomas-Henning von Kamptz 2653d500078SThomas-Henning von Kamptz dbg_csp = fscs; 26689f0730dSBrian Somers /* ... and dump it */ 2673d500078SThomas-Henning von Kamptz for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) { 268adcaff07SThomas-Henning von Kamptz snprintf(dbg_line, sizeof(dbg_line), 269adcaff07SThomas-Henning von Kamptz "%d. csum in fscs", dbg_csc); 2704020c5bcSThomas-Henning von Kamptz DBG_DUMP_CSUM(&sblock, 2714020c5bcSThomas-Henning von Kamptz dbg_line, 2724020c5bcSThomas-Henning von Kamptz dbg_csp++); 2733d500078SThomas-Henning von Kamptz } 2743d500078SThomas-Henning von Kamptz } 2753d500078SThomas-Henning von Kamptz 27630e3c0faSBrian Somers if (cfg_lv & 0xf8) { 27789f0730dSBrian Somers /* for each requested cylinder group ... */ 2783d500078SThomas-Henning von Kamptz for (cylno = cg_start; cylno < cg_stop; cylno++) { 279adcaff07SThomas-Henning von Kamptz snprintf(dbg_line, sizeof(dbg_line), "cgr %d", cylno); 2803d500078SThomas-Henning von Kamptz if (cfg_lv & 0x002) { 28189f0730dSBrian Somers /* dump the superblock copies */ 28289f0730dSBrian Somers if (bread(&disk, fsbtodb(&sblock, 28389f0730dSBrian Somers cgsblock(&sblock, cylno)), 28489f0730dSBrian Somers (void *)&osblock, SBLOCKSIZE) == -1) 285942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 28689f0730dSBrian Somers DBG_DUMP_FS(&osblock, dbg_line); 287942d2e02SRobert Watson } 28889f0730dSBrian Somers 2893d500078SThomas-Henning von Kamptz /* 29089f0730dSBrian Somers * Read the cylinder group and dump whatever was 29189f0730dSBrian Somers * requested. 2923d500078SThomas-Henning von Kamptz */ 29389f0730dSBrian Somers if (bread(&disk, fsbtodb(&sblock, 29489f0730dSBrian Somers cgtod(&sblock, cylno)), (void *)&acg, 29589f0730dSBrian Somers (size_t)sblock.fs_cgsize) == -1) 296942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 29789f0730dSBrian Somers 29889f0730dSBrian Somers if (cfg_lv & 0x008) 29989f0730dSBrian Somers DBG_DUMP_CG(&sblock, dbg_line, &acg); 30089f0730dSBrian Somers if (cfg_lv & 0x010) 30189f0730dSBrian Somers DBG_DUMP_INMAP(&sblock, dbg_line, &acg); 30289f0730dSBrian Somers if (cfg_lv & 0x020) 30389f0730dSBrian Somers DBG_DUMP_FRMAP(&sblock, dbg_line, &acg); 3043d500078SThomas-Henning von Kamptz if (cfg_lv & 0x040) { 30589f0730dSBrian Somers DBG_DUMP_CLMAP(&sblock, dbg_line, &acg); 30689f0730dSBrian Somers DBG_DUMP_CLSUM(&sblock, dbg_line, &acg); 3073d500078SThomas-Henning von Kamptz } 308942d2e02SRobert Watson #ifdef NOT_CURRENTLY 309942d2e02SRobert Watson /* 310942d2e02SRobert Watson * See the comment in sbin/growfs/debug.c for why this 311942d2e02SRobert Watson * is currently disabled, and what needs to be done to 312942d2e02SRobert Watson * re-enable it. 313942d2e02SRobert Watson */ 31489f0730dSBrian Somers if (disk.d_ufs == 1 && cfg_lv & 0x080) 31589f0730dSBrian Somers DBG_DUMP_SPTBL(&sblock, dbg_line, &acg); 316942d2e02SRobert Watson #endif 3173d500078SThomas-Henning von Kamptz } 31830e3c0faSBrian Somers } 31989f0730dSBrian Somers 32030e3c0faSBrian Somers if (cfg_lv & 0x300) { 32189f0730dSBrian Somers /* Dump the requested inode(s) */ 32289f0730dSBrian Somers if (cfg_in != -2) 323942d2e02SRobert Watson DUMP_WHOLE_INODE((ino_t)cfg_in, cfg_lv); 32489f0730dSBrian Somers else { 32589f0730dSBrian Somers for (in = cg_start * sblock.fs_ipg; 32689f0730dSBrian Somers in < (ino_t)cg_stop * sblock.fs_ipg; 32789f0730dSBrian Somers in++) 328942d2e02SRobert Watson DUMP_WHOLE_INODE(in, cfg_lv); 3293d500078SThomas-Henning von Kamptz } 33030e3c0faSBrian Somers } 3313d500078SThomas-Henning von Kamptz 3323d500078SThomas-Henning von Kamptz DBG_CLOSE; 3333d500078SThomas-Henning von Kamptz DBG_LEAVE; 33489f0730dSBrian Somers 3353d500078SThomas-Henning von Kamptz return 0; 3363d500078SThomas-Henning von Kamptz } 3373d500078SThomas-Henning von Kamptz 338942d2e02SRobert Watson /* ********************************************** dump_whole_ufs1_inode ***** */ 3393d500078SThomas-Henning von Kamptz /* 3403d500078SThomas-Henning von Kamptz * Here we dump a list of all blocks allocated by this inode. We follow 3413d500078SThomas-Henning von Kamptz * all indirect blocks. 3423d500078SThomas-Henning von Kamptz */ 3433d500078SThomas-Henning von Kamptz void 344942d2e02SRobert Watson dump_whole_ufs1_inode(ino_t inode, int level) 3453d500078SThomas-Henning von Kamptz { 346942d2e02SRobert Watson DBG_FUNC("dump_whole_ufs1_inode") 3479fc5d538SKirk McKusick union dinodep dp; 3489fc5d538SKirk McKusick int rb; 3493d500078SThomas-Henning von Kamptz unsigned int ind2ctr, ind3ctr; 350942d2e02SRobert Watson ufs1_daddr_t *ind2ptr, *ind3ptr; 3513d500078SThomas-Henning von Kamptz char comment[80]; 3523d500078SThomas-Henning von Kamptz 3533d500078SThomas-Henning von Kamptz DBG_ENTER; 3543d500078SThomas-Henning von Kamptz 3553d500078SThomas-Henning von Kamptz /* 3563d500078SThomas-Henning von Kamptz * Read the inode from disk/cache. 3573d500078SThomas-Henning von Kamptz */ 3589fc5d538SKirk McKusick if (getinode(&disk, &dp, inode) == -1) 3599fc5d538SKirk McKusick err(1, "getinode: %s", disk.d_error); 3603d500078SThomas-Henning von Kamptz 3619fc5d538SKirk McKusick if (dp.dp1->di_nlink == 0) { 3623d500078SThomas-Henning von Kamptz DBG_LEAVE; 3633d500078SThomas-Henning von Kamptz return; /* inode not in use */ 3643d500078SThomas-Henning von Kamptz } 3653d500078SThomas-Henning von Kamptz 3663d500078SThomas-Henning von Kamptz /* 3673d500078SThomas-Henning von Kamptz * Dump the main inode structure. 3683d500078SThomas-Henning von Kamptz */ 3699b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx", (uintmax_t)inode); 3703d500078SThomas-Henning von Kamptz if (level & 0x100) { 3714020c5bcSThomas-Henning von Kamptz DBG_DUMP_INO(&sblock, 3724020c5bcSThomas-Henning von Kamptz comment, 3739fc5d538SKirk McKusick dp.dp1); 3743d500078SThomas-Henning von Kamptz } 3753d500078SThomas-Henning von Kamptz 3763d500078SThomas-Henning von Kamptz if (!(level & 0x200)) { 3773d500078SThomas-Henning von Kamptz DBG_LEAVE; 3783d500078SThomas-Henning von Kamptz return; 3793d500078SThomas-Henning von Kamptz } 3803d500078SThomas-Henning von Kamptz 3813d500078SThomas-Henning von Kamptz /* 3823d500078SThomas-Henning von Kamptz * Ok, now prepare for dumping all direct and indirect pointers. 3833d500078SThomas-Henning von Kamptz */ 3849fc5d538SKirk McKusick rb = howmany(dp.dp1->di_size, sblock.fs_bsize) - UFS_NDADDR; 3853d500078SThomas-Henning von Kamptz if (rb > 0) { 3863d500078SThomas-Henning von Kamptz /* 3873d500078SThomas-Henning von Kamptz * Dump single indirect block. 3883d500078SThomas-Henning von Kamptz */ 3899fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, dp.dp1->di_ib[0]), 3909fc5d538SKirk McKusick (void *)&i1blk, (size_t)sblock.fs_bsize) == -1) { 391942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 392942d2e02SRobert Watson } 3939b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 0", 3949b337054SGleb Kurtsou (uintmax_t)inode); 3954020c5bcSThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, 3964020c5bcSThomas-Henning von Kamptz comment, 3974020c5bcSThomas-Henning von Kamptz i1blk, 3984020c5bcSThomas-Henning von Kamptz (size_t)rb); 399942d2e02SRobert Watson rb -= howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t)); 4003d500078SThomas-Henning von Kamptz } 4013d500078SThomas-Henning von Kamptz if (rb > 0) { 4023d500078SThomas-Henning von Kamptz /* 4033d500078SThomas-Henning von Kamptz * Dump double indirect blocks. 4043d500078SThomas-Henning von Kamptz */ 4059fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, dp.dp1->di_ib[1]), 4069fc5d538SKirk McKusick (void *)&i2blk, (size_t)sblock.fs_bsize) == -1) { 407942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 408942d2e02SRobert Watson } 4099b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1", 4109b337054SGleb Kurtsou (uintmax_t)inode); 4114020c5bcSThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, 4124020c5bcSThomas-Henning von Kamptz comment, 4134020c5bcSThomas-Henning von Kamptz i2blk, 414942d2e02SRobert Watson howmany(rb, howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t)))); 4153d500078SThomas-Henning von Kamptz for (ind2ctr = 0; ((ind2ctr < howmany(sblock.fs_bsize, 416942d2e02SRobert Watson sizeof(ufs1_daddr_t))) && (rb > 0)); ind2ctr++) { 417942d2e02SRobert Watson ind2ptr = &((ufs1_daddr_t *)(void *)&i2blk)[ind2ctr]; 4183d500078SThomas-Henning von Kamptz 4199fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, *ind2ptr), 4209fc5d538SKirk McKusick (void *)&i1blk, (size_t)sblock.fs_bsize) == -1) { 421942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 422942d2e02SRobert Watson } 423adcaff07SThomas-Henning von Kamptz snprintf(comment, sizeof(comment), 4249b337054SGleb Kurtsou "Inode 0x%08jx: indirect 1->%d", (uintmax_t)inode, 4259b337054SGleb Kurtsou ind2ctr); 4264020c5bcSThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, 4274020c5bcSThomas-Henning von Kamptz comment, 4284020c5bcSThomas-Henning von Kamptz i1blk, 4294020c5bcSThomas-Henning von Kamptz (size_t)rb); 430942d2e02SRobert Watson rb -= howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t)); 4313d500078SThomas-Henning von Kamptz } 4323d500078SThomas-Henning von Kamptz } 4333d500078SThomas-Henning von Kamptz if (rb > 0) { 4343d500078SThomas-Henning von Kamptz /* 4353d500078SThomas-Henning von Kamptz * Dump triple indirect blocks. 4363d500078SThomas-Henning von Kamptz */ 4379fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, dp.dp1->di_ib[2]), 4389fc5d538SKirk McKusick (void *)&i3blk, (size_t)sblock.fs_bsize) == -1) { 439942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 440942d2e02SRobert Watson } 4419b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2", 4429b337054SGleb Kurtsou (uintmax_t)inode); 4433d500078SThomas-Henning von Kamptz #define SQUARE(a) ((a)*(a)) 4444020c5bcSThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, 4454020c5bcSThomas-Henning von Kamptz comment, 4464020c5bcSThomas-Henning von Kamptz i3blk, 4474020c5bcSThomas-Henning von Kamptz howmany(rb, 448942d2e02SRobert Watson SQUARE(howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t))))); 4493d500078SThomas-Henning von Kamptz #undef SQUARE 4503d500078SThomas-Henning von Kamptz for (ind3ctr = 0; ((ind3ctr < howmany(sblock.fs_bsize, 451942d2e02SRobert Watson sizeof(ufs1_daddr_t))) && (rb > 0)); ind3ctr++) { 452942d2e02SRobert Watson ind3ptr = &((ufs1_daddr_t *)(void *)&i3blk)[ind3ctr]; 4533d500078SThomas-Henning von Kamptz 4549fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, *ind3ptr), 4559fc5d538SKirk McKusick (void *)&i2blk, (size_t)sblock.fs_bsize) == -1) { 456942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 457942d2e02SRobert Watson } 458adcaff07SThomas-Henning von Kamptz snprintf(comment, sizeof(comment), 4599b337054SGleb Kurtsou "Inode 0x%08jx: indirect 2->%d", (uintmax_t)inode, 4609b337054SGleb Kurtsou ind3ctr); 4614020c5bcSThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, 4624020c5bcSThomas-Henning von Kamptz comment, 4634020c5bcSThomas-Henning von Kamptz i2blk, 4644020c5bcSThomas-Henning von Kamptz howmany(rb, 465942d2e02SRobert Watson howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t)))); 4663d500078SThomas-Henning von Kamptz for (ind2ctr = 0; ((ind2ctr < howmany(sblock.fs_bsize, 467942d2e02SRobert Watson sizeof(ufs1_daddr_t))) && (rb > 0)); ind2ctr++) { 468942d2e02SRobert Watson ind2ptr=&((ufs1_daddr_t *)(void *)&i2blk) 469adcaff07SThomas-Henning von Kamptz [ind2ctr]; 470942d2e02SRobert Watson if (bread(&disk, fsbtodb(&sblock, *ind2ptr), 471942d2e02SRobert Watson (void *)&i1blk, (size_t)sblock.fs_bsize) 472942d2e02SRobert Watson == -1) { 473942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 474942d2e02SRobert Watson } 475adcaff07SThomas-Henning von Kamptz snprintf(comment, sizeof(comment), 4769b337054SGleb Kurtsou "Inode 0x%08jx: indirect 2->%d->%d", 4779b337054SGleb Kurtsou (uintmax_t)inode, ind3ctr, ind3ctr); 4784020c5bcSThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, 4794020c5bcSThomas-Henning von Kamptz comment, 4804020c5bcSThomas-Henning von Kamptz i1blk, 4814020c5bcSThomas-Henning von Kamptz (size_t)rb); 4823d500078SThomas-Henning von Kamptz rb -= howmany(sblock.fs_bsize, 483942d2e02SRobert Watson sizeof(ufs1_daddr_t)); 4843d500078SThomas-Henning von Kamptz } 4853d500078SThomas-Henning von Kamptz } 4863d500078SThomas-Henning von Kamptz } 4873d500078SThomas-Henning von Kamptz 4883d500078SThomas-Henning von Kamptz DBG_LEAVE; 4893d500078SThomas-Henning von Kamptz return; 4903d500078SThomas-Henning von Kamptz } 4913d500078SThomas-Henning von Kamptz 492942d2e02SRobert Watson /* ********************************************** dump_whole_ufs2_inode ***** */ 4933d500078SThomas-Henning von Kamptz /* 494942d2e02SRobert Watson * Here we dump a list of all blocks allocated by this inode. We follow 495942d2e02SRobert Watson * all indirect blocks. 4963d500078SThomas-Henning von Kamptz */ 497942d2e02SRobert Watson void 498942d2e02SRobert Watson dump_whole_ufs2_inode(ino_t inode, int level) 4993d500078SThomas-Henning von Kamptz { 500942d2e02SRobert Watson DBG_FUNC("dump_whole_ufs2_inode") 5019fc5d538SKirk McKusick union dinodep dp; 5029fc5d538SKirk McKusick int rb; 503942d2e02SRobert Watson unsigned int ind2ctr, ind3ctr; 504942d2e02SRobert Watson ufs2_daddr_t *ind2ptr, *ind3ptr; 505942d2e02SRobert Watson char comment[80]; 5063d500078SThomas-Henning von Kamptz 5073d500078SThomas-Henning von Kamptz DBG_ENTER; 5083d500078SThomas-Henning von Kamptz 509942d2e02SRobert Watson /* 510942d2e02SRobert Watson * Read the inode from disk/cache. 511942d2e02SRobert Watson */ 5129fc5d538SKirk McKusick if (getinode(&disk, &dp, inode) == -1) 5139fc5d538SKirk McKusick err(1, "getinode: %s", disk.d_error); 514942d2e02SRobert Watson 5159fc5d538SKirk McKusick if (dp.dp2->di_nlink == 0) { 516942d2e02SRobert Watson DBG_LEAVE; 517942d2e02SRobert Watson return; /* inode not in use */ 5183d500078SThomas-Henning von Kamptz } 519942d2e02SRobert Watson 520942d2e02SRobert Watson /* 521942d2e02SRobert Watson * Dump the main inode structure. 522942d2e02SRobert Watson */ 5239b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx", (uintmax_t)inode); 524942d2e02SRobert Watson if (level & 0x100) { 5259fc5d538SKirk McKusick DBG_DUMP_INO(&sblock, comment, dp.dp2); 526942d2e02SRobert Watson } 527942d2e02SRobert Watson 528942d2e02SRobert Watson if (!(level & 0x200)) { 529942d2e02SRobert Watson DBG_LEAVE; 530942d2e02SRobert Watson return; 531942d2e02SRobert Watson } 532942d2e02SRobert Watson 533942d2e02SRobert Watson /* 534942d2e02SRobert Watson * Ok, now prepare for dumping all direct and indirect pointers. 535942d2e02SRobert Watson */ 5369fc5d538SKirk McKusick rb = howmany(dp.dp2->di_size, sblock.fs_bsize) - UFS_NDADDR; 537942d2e02SRobert Watson if (rb > 0) { 538942d2e02SRobert Watson /* 539942d2e02SRobert Watson * Dump single indirect block. 540942d2e02SRobert Watson */ 5419fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, dp.dp2->di_ib[0]), 5429fc5d538SKirk McKusick (void *)&i1blk, (size_t)sblock.fs_bsize) == -1) { 543942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 544942d2e02SRobert Watson } 5459b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 0", 5469b337054SGleb Kurtsou (uintmax_t)inode); 547942d2e02SRobert Watson DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); 548942d2e02SRobert Watson rb -= howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)); 549942d2e02SRobert Watson } 550942d2e02SRobert Watson if (rb > 0) { 551942d2e02SRobert Watson /* 552942d2e02SRobert Watson * Dump double indirect blocks. 553942d2e02SRobert Watson */ 5549fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, dp.dp2->di_ib[1]), 5559fc5d538SKirk McKusick (void *)&i2blk, (size_t)sblock.fs_bsize) == -1) { 556942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 557942d2e02SRobert Watson } 5589b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1", 5599b337054SGleb Kurtsou (uintmax_t)inode); 560942d2e02SRobert Watson DBG_DUMP_IBLK(&sblock, 561942d2e02SRobert Watson comment, 562942d2e02SRobert Watson i2blk, 563942d2e02SRobert Watson howmany(rb, howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)))); 564942d2e02SRobert Watson for (ind2ctr = 0; ((ind2ctr < howmany(sblock.fs_bsize, 565942d2e02SRobert Watson sizeof(ufs2_daddr_t))) && (rb>0)); ind2ctr++) { 566942d2e02SRobert Watson ind2ptr = &((ufs2_daddr_t *)(void *)&i2blk)[ind2ctr]; 567942d2e02SRobert Watson 5689fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, *ind2ptr), 5699fc5d538SKirk McKusick (void *)&i1blk, (size_t)sblock.fs_bsize) == -1) { 570942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 571942d2e02SRobert Watson } 572942d2e02SRobert Watson snprintf(comment, sizeof(comment), 5739b337054SGleb Kurtsou "Inode 0x%08jx: indirect 1->%d", 5749b337054SGleb Kurtsou (uintmax_t)inode, ind2ctr); 575942d2e02SRobert Watson DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); 576942d2e02SRobert Watson rb -= howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)); 577942d2e02SRobert Watson } 578942d2e02SRobert Watson } 579942d2e02SRobert Watson if (rb > 0) { 580942d2e02SRobert Watson /* 581942d2e02SRobert Watson * Dump triple indirect blocks. 582942d2e02SRobert Watson */ 5839fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, dp.dp2->di_ib[2]), 5849fc5d538SKirk McKusick (void *)&i3blk, (size_t)sblock.fs_bsize) == -1) { 585942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 586942d2e02SRobert Watson } 5879b337054SGleb Kurtsou snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2", 5889b337054SGleb Kurtsou (uintmax_t)inode); 589942d2e02SRobert Watson #define SQUARE(a) ((a)*(a)) 590942d2e02SRobert Watson DBG_DUMP_IBLK(&sblock, 591942d2e02SRobert Watson comment, 592942d2e02SRobert Watson i3blk, 593942d2e02SRobert Watson howmany(rb, 594942d2e02SRobert Watson SQUARE(howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t))))); 595942d2e02SRobert Watson #undef SQUARE 596942d2e02SRobert Watson for (ind3ctr = 0; ((ind3ctr < howmany(sblock.fs_bsize, 597942d2e02SRobert Watson sizeof(ufs2_daddr_t))) && (rb > 0)); ind3ctr++) { 598942d2e02SRobert Watson ind3ptr = &((ufs2_daddr_t *)(void *)&i3blk)[ind3ctr]; 599942d2e02SRobert Watson 6009fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, *ind3ptr), 6019fc5d538SKirk McKusick (void *)&i2blk, (size_t)sblock.fs_bsize) == -1) { 602942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 603942d2e02SRobert Watson } 604942d2e02SRobert Watson snprintf(comment, sizeof(comment), 6059b337054SGleb Kurtsou "Inode 0x%08jx: indirect 2->%d", 6069b337054SGleb Kurtsou (uintmax_t)inode, ind3ctr); 607942d2e02SRobert Watson DBG_DUMP_IBLK(&sblock, 608942d2e02SRobert Watson comment, 609942d2e02SRobert Watson i2blk, 610942d2e02SRobert Watson howmany(rb, 611942d2e02SRobert Watson howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)))); 612942d2e02SRobert Watson for (ind2ctr = 0; ((ind2ctr < howmany(sblock.fs_bsize, 613942d2e02SRobert Watson sizeof(ufs2_daddr_t))) && (rb > 0)); ind2ctr++) { 614942d2e02SRobert Watson ind2ptr = &((ufs2_daddr_t *)(void *)&i2blk) [ind2ctr]; 6159fc5d538SKirk McKusick if (bread(&disk, fsbtodb(&sblock, *ind2ptr), 6169fc5d538SKirk McKusick (void *)&i1blk, (size_t)sblock.fs_bsize) 6179fc5d538SKirk McKusick == -1) { 618942d2e02SRobert Watson err(1, "bread: %s", disk.d_error); 619942d2e02SRobert Watson } 620942d2e02SRobert Watson snprintf(comment, sizeof(comment), 6219b337054SGleb Kurtsou "Inode 0x%08jx: indirect 2->%d->%d", 6229b337054SGleb Kurtsou (uintmax_t)inode, ind3ctr, ind3ctr); 623942d2e02SRobert Watson DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); 624942d2e02SRobert Watson rb -= howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)); 625942d2e02SRobert Watson } 626942d2e02SRobert Watson } 6273d500078SThomas-Henning von Kamptz } 6283d500078SThomas-Henning von Kamptz 6293d500078SThomas-Henning von Kamptz DBG_LEAVE; 630942d2e02SRobert Watson return; 6313d500078SThomas-Henning von Kamptz } 6323d500078SThomas-Henning von Kamptz 6333d500078SThomas-Henning von Kamptz /* ************************************************************* usage ***** */ 6343d500078SThomas-Henning von Kamptz /* 6353d500078SThomas-Henning von Kamptz * Dump a line of usage. 6363d500078SThomas-Henning von Kamptz */ 6373d500078SThomas-Henning von Kamptz void 6384020c5bcSThomas-Henning von Kamptz usage(void) 6393d500078SThomas-Henning von Kamptz { 6403d500078SThomas-Henning von Kamptz DBG_FUNC("usage") 6413d500078SThomas-Henning von Kamptz 6423d500078SThomas-Henning von Kamptz DBG_ENTER; 6433d500078SThomas-Henning von Kamptz 6443d500078SThomas-Henning von Kamptz fprintf(stderr, 6458d646af5SRuslan Ermilov "usage: ffsinfo [-g cylinder_group] [-i inode] [-l level] " 6464020c5bcSThomas-Henning von Kamptz "[-o outfile]\n" 6474020c5bcSThomas-Henning von Kamptz " special | file\n"); 6483d500078SThomas-Henning von Kamptz 6493d500078SThomas-Henning von Kamptz DBG_LEAVE; 6504020c5bcSThomas-Henning von Kamptz exit(1); 6513d500078SThomas-Henning von Kamptz } 652