13d500078SThomas-Henning von Kamptz /* 23d500078SThomas-Henning von Kamptz * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz 33d500078SThomas-Henning von Kamptz * Copyright (c) 1980, 1989, 1993 The Regents of the University of California. 43d500078SThomas-Henning von Kamptz * All rights reserved. 53d500078SThomas-Henning von Kamptz * 63d500078SThomas-Henning von Kamptz * This code is derived from software contributed to Berkeley by 73d500078SThomas-Henning von Kamptz * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt. 83d500078SThomas-Henning von Kamptz * 93d500078SThomas-Henning von Kamptz * Redistribution and use in source and binary forms, with or without 103d500078SThomas-Henning von Kamptz * modification, are permitted provided that the following conditions 113d500078SThomas-Henning von Kamptz * are met: 123d500078SThomas-Henning von Kamptz * 1. Redistributions of source code must retain the above copyright 133d500078SThomas-Henning von Kamptz * notice, this list of conditions and the following disclaimer. 143d500078SThomas-Henning von Kamptz * 2. Redistributions in binary form must reproduce the above copyright 153d500078SThomas-Henning von Kamptz * notice, this list of conditions and the following disclaimer in the 163d500078SThomas-Henning von Kamptz * documentation and/or other materials provided with the distribution. 173d500078SThomas-Henning von Kamptz * 3. All advertising materials mentioning features or use of this software 183d500078SThomas-Henning von Kamptz * must display the following acknowledgment: 193d500078SThomas-Henning von Kamptz * This product includes software developed by the University of 203d500078SThomas-Henning von Kamptz * California, Berkeley and its contributors, as well as Christoph 213d500078SThomas-Henning von Kamptz * Herrmann and Thomas-Henning von Kamptz. 223d500078SThomas-Henning von Kamptz * 4. Neither the name of the University nor the names of its contributors 233d500078SThomas-Henning von Kamptz * may be used to endorse or promote products derived from this software 243d500078SThomas-Henning von Kamptz * without specific prior written permission. 253d500078SThomas-Henning von Kamptz * 263d500078SThomas-Henning von Kamptz * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 273d500078SThomas-Henning von Kamptz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 283d500078SThomas-Henning von Kamptz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 293d500078SThomas-Henning von Kamptz * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 303d500078SThomas-Henning von Kamptz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 313d500078SThomas-Henning von Kamptz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 323d500078SThomas-Henning von Kamptz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 333d500078SThomas-Henning von Kamptz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 343d500078SThomas-Henning von Kamptz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 353d500078SThomas-Henning von Kamptz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 363d500078SThomas-Henning von Kamptz * SUCH DAMAGE. 373d500078SThomas-Henning von Kamptz * 383d500078SThomas-Henning von Kamptz * $TSHeader: src/sbin/ffsinfo/ffsinfo.c,v 1.3 2000/12/09 15:12:31 tomsoft Exp $ 393d500078SThomas-Henning von Kamptz * $FreeBSD$ 403d500078SThomas-Henning von Kamptz * 413d500078SThomas-Henning von Kamptz */ 423d500078SThomas-Henning von Kamptz 433d500078SThomas-Henning von Kamptz #ifndef lint 443d500078SThomas-Henning von Kamptz static const char copyright[] = 453d500078SThomas-Henning von Kamptz "@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\ 463d500078SThomas-Henning von Kamptz Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\ 473d500078SThomas-Henning von Kamptz All rights reserved.\n"; 483d500078SThomas-Henning von Kamptz #endif /* not lint */ 493d500078SThomas-Henning von Kamptz 503d500078SThomas-Henning von Kamptz #ifndef lint 513d500078SThomas-Henning von Kamptz static const char rcsid[] = 523d500078SThomas-Henning von Kamptz "$FreeBSD$"; 533d500078SThomas-Henning von Kamptz #endif /* not lint */ 543d500078SThomas-Henning von Kamptz 553d500078SThomas-Henning von Kamptz /* ********************************************************** INCLUDES ***** */ 563d500078SThomas-Henning von Kamptz #include <sys/param.h> 573d500078SThomas-Henning von Kamptz #include <sys/disklabel.h> 583d500078SThomas-Henning von Kamptz #include <sys/ioctl.h> 593d500078SThomas-Henning von Kamptz #include <sys/stat.h> 603d500078SThomas-Henning von Kamptz #include <sys/time.h> 613d500078SThomas-Henning von Kamptz 623d500078SThomas-Henning von Kamptz #include <stdio.h> 633d500078SThomas-Henning von Kamptz #include <paths.h> 643d500078SThomas-Henning von Kamptz #include <ctype.h> 653d500078SThomas-Henning von Kamptz #include <err.h> 663d500078SThomas-Henning von Kamptz #include <errno.h> 673d500078SThomas-Henning von Kamptz #include <fcntl.h> 683d500078SThomas-Henning von Kamptz #include <stdlib.h> 693d500078SThomas-Henning von Kamptz #include <string.h> 703d500078SThomas-Henning von Kamptz #include <unistd.h> 713d500078SThomas-Henning von Kamptz #include <ufs/ufs/dinode.h> 723d500078SThomas-Henning von Kamptz #include <ufs/ffs/fs.h> 733d500078SThomas-Henning von Kamptz #include <machine/param.h> 743d500078SThomas-Henning von Kamptz 753d500078SThomas-Henning von Kamptz #include "debug.h" 763d500078SThomas-Henning von Kamptz 773d500078SThomas-Henning von Kamptz /* *********************************************************** GLOBALS ***** */ 783d500078SThomas-Henning von Kamptz #ifdef FS_DEBUG 793d500078SThomas-Henning von Kamptz int _dbg_lvl_ = (DL_INFO); /* DL_TRC */ 803d500078SThomas-Henning von Kamptz #endif /* FS_DEBUG */ 813d500078SThomas-Henning von Kamptz 823d500078SThomas-Henning von Kamptz static union { 833d500078SThomas-Henning von Kamptz struct fs fs; 843d500078SThomas-Henning von Kamptz char pad[SBSIZE]; 853d500078SThomas-Henning von Kamptz } fsun1, fsun2; 863d500078SThomas-Henning von Kamptz #define sblock fsun1.fs 873d500078SThomas-Henning von Kamptz #define osblock fsun2.fs 883d500078SThomas-Henning von Kamptz 893d500078SThomas-Henning von Kamptz static union { 903d500078SThomas-Henning von Kamptz struct cg cg; 913d500078SThomas-Henning von Kamptz char pad[MAXBSIZE]; 923d500078SThomas-Henning von Kamptz } cgun1; 933d500078SThomas-Henning von Kamptz #define acg cgun1.cg 943d500078SThomas-Henning von Kamptz 953d500078SThomas-Henning von Kamptz static char ablk[MAXBSIZE]; 963d500078SThomas-Henning von Kamptz static char i1blk[MAXBSIZE]; 973d500078SThomas-Henning von Kamptz static char i2blk[MAXBSIZE]; 983d500078SThomas-Henning von Kamptz static char i3blk[MAXBSIZE]; 993d500078SThomas-Henning von Kamptz 1003d500078SThomas-Henning von Kamptz static struct csum *fscs; 1013d500078SThomas-Henning von Kamptz 1023d500078SThomas-Henning von Kamptz /* ******************************************************** PROTOTYPES ***** */ 1033d500078SThomas-Henning von Kamptz static void rdfs(daddr_t, int, char *, int); 1043d500078SThomas-Henning von Kamptz static void usage(char *); 1053d500078SThomas-Henning von Kamptz static struct disklabel *get_disklabel(int); 1063d500078SThomas-Henning von Kamptz static struct dinode *ginode(ino_t, int); 1073d500078SThomas-Henning von Kamptz static void dump_whole_inode(ino_t, int, int); 1083d500078SThomas-Henning von Kamptz 1093d500078SThomas-Henning von Kamptz /* ************************************************************** rdfs ***** */ 1103d500078SThomas-Henning von Kamptz /* 1113d500078SThomas-Henning von Kamptz * Here we read some block(s) from disk. 1123d500078SThomas-Henning von Kamptz */ 1133d500078SThomas-Henning von Kamptz void 1143d500078SThomas-Henning von Kamptz rdfs(daddr_t bno, int size, char *bf, int fsi) 1153d500078SThomas-Henning von Kamptz { 1163d500078SThomas-Henning von Kamptz DBG_FUNC("rdfs") 1173d500078SThomas-Henning von Kamptz int n; 1183d500078SThomas-Henning von Kamptz 1193d500078SThomas-Henning von Kamptz DBG_ENTER; 1203d500078SThomas-Henning von Kamptz 1213d500078SThomas-Henning von Kamptz if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) { 1223d500078SThomas-Henning von Kamptz fprintf(stderr, "seek error: %ld\n", (long)bno); 1233d500078SThomas-Henning von Kamptz err(33, "rdfs"); 1243d500078SThomas-Henning von Kamptz } 1253d500078SThomas-Henning von Kamptz n = read(fsi, bf, (size_t)size); 1263d500078SThomas-Henning von Kamptz if (n != size) { 1273d500078SThomas-Henning von Kamptz fprintf(stderr, "read error: %ld\n", (long)bno); 1283d500078SThomas-Henning von Kamptz err(34, "rdfs"); 1293d500078SThomas-Henning von Kamptz } 1303d500078SThomas-Henning von Kamptz 1313d500078SThomas-Henning von Kamptz DBG_LEAVE; 1323d500078SThomas-Henning von Kamptz return; 1333d500078SThomas-Henning von Kamptz } 1343d500078SThomas-Henning von Kamptz 1353d500078SThomas-Henning von Kamptz /* ************************************************************** main ***** */ 1363d500078SThomas-Henning von Kamptz /* 1373d500078SThomas-Henning von Kamptz * ffsinfo(8) is a tool to dump all metadata of a filesystem. It helps to find 1383d500078SThomas-Henning von Kamptz * errors is the filesystem much easier. You can run ffsinfo before and after 1393d500078SThomas-Henning von Kamptz * an fsck(8), and compare the two ascii dumps easy with diff, and you see 1403d500078SThomas-Henning von Kamptz * directly where the problem is. You can control how much detail you want to 1413d500078SThomas-Henning von Kamptz * see with some command line arguments. You can also easy check the status 1423d500078SThomas-Henning von Kamptz * of a filesystem, like is there is enough space for growing a filesystem, 1433d500078SThomas-Henning von Kamptz * or how many active snapshots do we have. It provides much more detailed 1443d500078SThomas-Henning von Kamptz * information then dumpfs. Snapshots, as they are very new, are not really 1453d500078SThomas-Henning von Kamptz * supported. They are just mentioned currently, but it is planned to run 1463d500078SThomas-Henning von Kamptz * also over active snapshots, to even get that output. 1473d500078SThomas-Henning von Kamptz */ 1483d500078SThomas-Henning von Kamptz int 1493d500078SThomas-Henning von Kamptz main(int argc, char **argv) 1503d500078SThomas-Henning von Kamptz { 1513d500078SThomas-Henning von Kamptz DBG_FUNC("main") 1523d500078SThomas-Henning von Kamptz char *a0, *device, *special, *cp; 1533d500078SThomas-Henning von Kamptz char ch; 1543d500078SThomas-Henning von Kamptz size_t len; 1553d500078SThomas-Henning von Kamptz struct stat st; 1563d500078SThomas-Henning von Kamptz struct disklabel *lp; 1573d500078SThomas-Henning von Kamptz struct partition *pp; 1583d500078SThomas-Henning von Kamptz int fsi; 1593d500078SThomas-Henning von Kamptz struct csum *dbg_csp; 1603d500078SThomas-Henning von Kamptz int dbg_csc; 1613d500078SThomas-Henning von Kamptz char dbg_line[80]; 1623d500078SThomas-Henning von Kamptz int cylno,i; 1633d500078SThomas-Henning von Kamptz int cfg_cg, cfg_in, cfg_lv; 1643d500078SThomas-Henning von Kamptz int cg_start, cg_stop; 1653d500078SThomas-Henning von Kamptz ino_t in; 1663d500078SThomas-Henning von Kamptz char *out_file; 1673d500078SThomas-Henning von Kamptz int Lflag=0; 1683d500078SThomas-Henning von Kamptz 1693d500078SThomas-Henning von Kamptz DBG_ENTER; 1703d500078SThomas-Henning von Kamptz 1713d500078SThomas-Henning von Kamptz cfg_lv=0xff; 1723d500078SThomas-Henning von Kamptz cfg_in=-2; 1733d500078SThomas-Henning von Kamptz cfg_cg=-2; 1743d500078SThomas-Henning von Kamptz out_file=strdup("/var/tmp/ffsinfo"); 1753d500078SThomas-Henning von Kamptz 1763d500078SThomas-Henning von Kamptz a0=*argv; /* save argv[0] for usage() */ 1773d500078SThomas-Henning von Kamptz while ((ch=getopt(argc, argv, "Lg:i:l:o:")) != -1) { 1783d500078SThomas-Henning von Kamptz switch(ch) { 1793d500078SThomas-Henning von Kamptz case 'L': 1803d500078SThomas-Henning von Kamptz Lflag=1; 1813d500078SThomas-Henning von Kamptz break; 1823d500078SThomas-Henning von Kamptz case 'g': 1833d500078SThomas-Henning von Kamptz cfg_cg=atol(optarg); 1843d500078SThomas-Henning von Kamptz if(cfg_cg < -1) { 1853d500078SThomas-Henning von Kamptz usage(a0); 1863d500078SThomas-Henning von Kamptz } 1873d500078SThomas-Henning von Kamptz break; 1883d500078SThomas-Henning von Kamptz case 'i': 1893d500078SThomas-Henning von Kamptz cfg_in=atol(optarg); 1903d500078SThomas-Henning von Kamptz if(cfg_in < 0) { 1913d500078SThomas-Henning von Kamptz usage(a0); 1923d500078SThomas-Henning von Kamptz } 1933d500078SThomas-Henning von Kamptz break; 1943d500078SThomas-Henning von Kamptz case 'l': 1953d500078SThomas-Henning von Kamptz cfg_lv=atol(optarg); 1963d500078SThomas-Henning von Kamptz if(cfg_lv < 0x1||cfg_lv > 0x3ff) { 1973d500078SThomas-Henning von Kamptz usage(a0); 1983d500078SThomas-Henning von Kamptz } 1993d500078SThomas-Henning von Kamptz break; 2003d500078SThomas-Henning von Kamptz case 'o': 2013d500078SThomas-Henning von Kamptz free(out_file); 2023d500078SThomas-Henning von Kamptz out_file=strdup(optarg); 2033d500078SThomas-Henning von Kamptz break; 2043d500078SThomas-Henning von Kamptz case '?': 2053d500078SThomas-Henning von Kamptz /* FALLTHROUGH */ 2063d500078SThomas-Henning von Kamptz default: 2073d500078SThomas-Henning von Kamptz usage(a0); 2083d500078SThomas-Henning von Kamptz } 2093d500078SThomas-Henning von Kamptz } 2103d500078SThomas-Henning von Kamptz argc -= optind; 2113d500078SThomas-Henning von Kamptz argv += optind; 2123d500078SThomas-Henning von Kamptz 2133d500078SThomas-Henning von Kamptz if(argc != 1) { 2143d500078SThomas-Henning von Kamptz usage(a0); 2153d500078SThomas-Henning von Kamptz } 2163d500078SThomas-Henning von Kamptz device=*argv; 2173d500078SThomas-Henning von Kamptz 2183d500078SThomas-Henning von Kamptz /* 2193d500078SThomas-Henning von Kamptz * Now we try to guess the (raw)device name. 2203d500078SThomas-Henning von Kamptz */ 2213d500078SThomas-Henning von Kamptz if (0 == strrchr(device, '/') && (stat(device, &st) == -1)) { 2223d500078SThomas-Henning von Kamptz /* 2233d500078SThomas-Henning von Kamptz * No path prefix was given, so try in that order: 2243d500078SThomas-Henning von Kamptz * /dev/r%s 2253d500078SThomas-Henning von Kamptz * /dev/%s 2263d500078SThomas-Henning von Kamptz * /dev/vinum/r%s 2273d500078SThomas-Henning von Kamptz * /dev/vinum/%s. 2283d500078SThomas-Henning von Kamptz * 2293d500078SThomas-Henning von Kamptz * FreeBSD now doesn't distinguish between raw and block 2303d500078SThomas-Henning von Kamptz * devices any longer, but it should still work this way. 2313d500078SThomas-Henning von Kamptz */ 2323d500078SThomas-Henning von Kamptz len=strlen(device)+strlen(_PATH_DEV)+2+strlen("vinum/"); 2333d500078SThomas-Henning von Kamptz special=(char *)malloc(len); 2343d500078SThomas-Henning von Kamptz snprintf(special, len, "%sr%s", _PATH_DEV, device); 2353d500078SThomas-Henning von Kamptz if (stat(special, &st) == -1) { 2363d500078SThomas-Henning von Kamptz snprintf(special, len, "%s%s", _PATH_DEV, device); 2373d500078SThomas-Henning von Kamptz if (stat(special, &st) == -1) { 2383d500078SThomas-Henning von Kamptz snprintf(special, len, "%svinum/r%s", 2393d500078SThomas-Henning von Kamptz _PATH_DEV, device); 2403d500078SThomas-Henning von Kamptz if (stat(special, &st) == -1) { 2413d500078SThomas-Henning von Kamptz /* 2423d500078SThomas-Henning von Kamptz * For now this is the 'last resort'. 2433d500078SThomas-Henning von Kamptz */ 2443d500078SThomas-Henning von Kamptz snprintf(special, len, "%svinum/%s", 2453d500078SThomas-Henning von Kamptz _PATH_DEV, device); 2463d500078SThomas-Henning von Kamptz } 2473d500078SThomas-Henning von Kamptz } 2483d500078SThomas-Henning von Kamptz } 2493d500078SThomas-Henning von Kamptz device = special; 2503d500078SThomas-Henning von Kamptz } 2513d500078SThomas-Henning von Kamptz 2523d500078SThomas-Henning von Kamptz /* 2533d500078SThomas-Henning von Kamptz * Open our device for reading. 2543d500078SThomas-Henning von Kamptz */ 2553d500078SThomas-Henning von Kamptz fsi = open(device, O_RDONLY); 2563d500078SThomas-Henning von Kamptz if (fsi < 0) { 2573d500078SThomas-Henning von Kamptz fprintf(stderr, "%s: %s\n", device, strerror(errno)); 2583d500078SThomas-Henning von Kamptz exit(-1); 2593d500078SThomas-Henning von Kamptz } 2603d500078SThomas-Henning von Kamptz 2613d500078SThomas-Henning von Kamptz stat(device, &st); 2623d500078SThomas-Henning von Kamptz 2633d500078SThomas-Henning von Kamptz if(S_ISREG(st.st_mode)) { /* label check not supported for files */ 2643d500078SThomas-Henning von Kamptz Lflag=1; 2653d500078SThomas-Henning von Kamptz } 2663d500078SThomas-Henning von Kamptz 2673d500078SThomas-Henning von Kamptz if(!Lflag) { 2683d500078SThomas-Henning von Kamptz /* 2693d500078SThomas-Henning von Kamptz * Try to read a label and gess the slice if not specified. 2703d500078SThomas-Henning von Kamptz * This code should guess the right thing and avaid to bother 2713d500078SThomas-Henning von Kamptz * the user user with the task of specifying the option -v on 2723d500078SThomas-Henning von Kamptz * vinum volumes. 2733d500078SThomas-Henning von Kamptz */ 2743d500078SThomas-Henning von Kamptz cp=device+strlen(device)-1; 2753d500078SThomas-Henning von Kamptz lp = get_disklabel(fsi); 2763d500078SThomas-Henning von Kamptz if(lp->d_type == DTYPE_VINUM) { 2773d500078SThomas-Henning von Kamptz pp = &lp->d_partitions[0]; 2783d500078SThomas-Henning von Kamptz } else if (isdigit(*cp)) { 2793d500078SThomas-Henning von Kamptz pp = &lp->d_partitions[2]; 2803d500078SThomas-Henning von Kamptz } else if (*cp>='a' && *cp<='h') { 2813d500078SThomas-Henning von Kamptz pp = &lp->d_partitions[*cp - 'a']; 2823d500078SThomas-Henning von Kamptz } else { 2833d500078SThomas-Henning von Kamptz fprintf(stderr, "unknown device\n"); 2843d500078SThomas-Henning von Kamptz exit(-1); 2853d500078SThomas-Henning von Kamptz } 2863d500078SThomas-Henning von Kamptz 2873d500078SThomas-Henning von Kamptz /* 2883d500078SThomas-Henning von Kamptz * Check if that partition looks suited for dumping. 2893d500078SThomas-Henning von Kamptz */ 2903d500078SThomas-Henning von Kamptz if (pp->p_size < 1) { 2913d500078SThomas-Henning von Kamptz fprintf(stderr, "partition is unavailable\n"); 2923d500078SThomas-Henning von Kamptz exit(-1); 2933d500078SThomas-Henning von Kamptz } 2943d500078SThomas-Henning von Kamptz if (pp->p_fstype != FS_BSDFFS) { 2953d500078SThomas-Henning von Kamptz fprintf(stderr, "partition not 4.2BSD\n"); 2963d500078SThomas-Henning von Kamptz exit(-1); 2973d500078SThomas-Henning von Kamptz } 2983d500078SThomas-Henning von Kamptz } 2993d500078SThomas-Henning von Kamptz 3003d500078SThomas-Henning von Kamptz /* 3013d500078SThomas-Henning von Kamptz * Read the current superblock. 3023d500078SThomas-Henning von Kamptz */ 3033d500078SThomas-Henning von Kamptz rdfs((daddr_t)(SBOFF/DEV_BSIZE), SBSIZE, (char *)&(sblock), fsi); 3043d500078SThomas-Henning von Kamptz if (sblock.fs_magic != FS_MAGIC) { 3053d500078SThomas-Henning von Kamptz fprintf(stderr, "superblock not recognized\n"); 3063d500078SThomas-Henning von Kamptz exit(-1); 3073d500078SThomas-Henning von Kamptz } 3083d500078SThomas-Henning von Kamptz 3093d500078SThomas-Henning von Kamptz DBG_OPEN(out_file); /* already here we need a superblock */ 3103d500078SThomas-Henning von Kamptz 3113d500078SThomas-Henning von Kamptz if(cfg_lv & 0x001) { 3123d500078SThomas-Henning von Kamptz DBG_DUMP_FS(&sblock, "primary sblock"); 3133d500078SThomas-Henning von Kamptz } 3143d500078SThomas-Henning von Kamptz 3153d500078SThomas-Henning von Kamptz /* 3163d500078SThomas-Henning von Kamptz * Determine here what cylinder groups to dump. 3173d500078SThomas-Henning von Kamptz */ 3183d500078SThomas-Henning von Kamptz if(cfg_cg==-2) { 3193d500078SThomas-Henning von Kamptz cg_start=0; 3203d500078SThomas-Henning von Kamptz cg_stop=sblock.fs_ncg; 3213d500078SThomas-Henning von Kamptz } else if (cfg_cg==-1) { 3223d500078SThomas-Henning von Kamptz cg_start=sblock.fs_ncg-1; 3233d500078SThomas-Henning von Kamptz cg_stop=sblock.fs_ncg; 3243d500078SThomas-Henning von Kamptz } else if (cfg_cg<sblock.fs_ncg) { 3253d500078SThomas-Henning von Kamptz cg_start=cfg_cg; 3263d500078SThomas-Henning von Kamptz cg_stop=cfg_cg+1; 3273d500078SThomas-Henning von Kamptz } else { 3283d500078SThomas-Henning von Kamptz cg_start=sblock.fs_ncg; 3293d500078SThomas-Henning von Kamptz cg_stop=sblock.fs_ncg; 3303d500078SThomas-Henning von Kamptz } 3313d500078SThomas-Henning von Kamptz 3323d500078SThomas-Henning von Kamptz if (cfg_lv & 0x004) { 3333d500078SThomas-Henning von Kamptz fscs = (struct csum *)calloc(1, (size_t)sblock.fs_cssize); 3343d500078SThomas-Henning von Kamptz 3353d500078SThomas-Henning von Kamptz /* 3363d500078SThomas-Henning von Kamptz * Get the cylinder summary into the memory ... 3373d500078SThomas-Henning von Kamptz */ 3383d500078SThomas-Henning von Kamptz for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) { 3393d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, sblock.fs_csaddr + 3403d500078SThomas-Henning von Kamptz numfrags(&sblock, i)), sblock.fs_cssize - i < 3413d500078SThomas-Henning von Kamptz sblock.fs_bsize ? sblock.fs_cssize - i : 3423d500078SThomas-Henning von Kamptz sblock.fs_bsize, ((char *)fscs) + i, fsi); 3433d500078SThomas-Henning von Kamptz } 3443d500078SThomas-Henning von Kamptz 3453d500078SThomas-Henning von Kamptz dbg_csp=fscs; 3463d500078SThomas-Henning von Kamptz /* 3473d500078SThomas-Henning von Kamptz * ... and dump it. 3483d500078SThomas-Henning von Kamptz */ 3493d500078SThomas-Henning von Kamptz for(dbg_csc=0; dbg_csc<sblock.fs_ncg; dbg_csc++) { 3503d500078SThomas-Henning von Kamptz snprintf(dbg_line, 80, "%d. csum in fscs", 3513d500078SThomas-Henning von Kamptz dbg_csc); 3523d500078SThomas-Henning von Kamptz DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++); 3533d500078SThomas-Henning von Kamptz } 3543d500078SThomas-Henning von Kamptz } 3553d500078SThomas-Henning von Kamptz 3563d500078SThomas-Henning von Kamptz /* 3573d500078SThomas-Henning von Kamptz * For each requested cylinder group ... 3583d500078SThomas-Henning von Kamptz */ 3593d500078SThomas-Henning von Kamptz for(cylno=cg_start; cylno<cg_stop; cylno++) { 3603d500078SThomas-Henning von Kamptz snprintf(dbg_line, 80, "cgr %d", cylno); 3613d500078SThomas-Henning von Kamptz if(cfg_lv & 0x002) { 3623d500078SThomas-Henning von Kamptz /* 3633d500078SThomas-Henning von Kamptz * ... dump the superblock copies ... 3643d500078SThomas-Henning von Kamptz */ 3653d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 3663d500078SThomas-Henning von Kamptz SBSIZE, (char *)&osblock, fsi); 3673d500078SThomas-Henning von Kamptz DBG_DUMP_FS(&osblock, dbg_line); 3683d500078SThomas-Henning von Kamptz } 3693d500078SThomas-Henning von Kamptz /* 3703d500078SThomas-Henning von Kamptz * ... read the cylinder group and dump whatever was requested. 3713d500078SThomas-Henning von Kamptz */ 3723d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), sblock.fs_cgsize, 3733d500078SThomas-Henning von Kamptz (char *)&acg, fsi); 3743d500078SThomas-Henning von Kamptz if(cfg_lv & 0x008) { 3753d500078SThomas-Henning von Kamptz DBG_DUMP_CG(&sblock, dbg_line, &acg); 3763d500078SThomas-Henning von Kamptz } 3773d500078SThomas-Henning von Kamptz if(cfg_lv & 0x010) { 3783d500078SThomas-Henning von Kamptz DBG_DUMP_INMAP(&sblock, dbg_line, &acg); 3793d500078SThomas-Henning von Kamptz } 3803d500078SThomas-Henning von Kamptz if(cfg_lv & 0x020) { 3813d500078SThomas-Henning von Kamptz DBG_DUMP_FRMAP(&sblock, dbg_line, &acg); 3823d500078SThomas-Henning von Kamptz } 3833d500078SThomas-Henning von Kamptz if(cfg_lv & 0x040) { 3843d500078SThomas-Henning von Kamptz DBG_DUMP_CLMAP(&sblock, dbg_line, &acg); 3853d500078SThomas-Henning von Kamptz DBG_DUMP_CLSUM(&sblock, dbg_line, &acg); 3863d500078SThomas-Henning von Kamptz } 3873d500078SThomas-Henning von Kamptz if(cfg_lv & 0x080) { 3883d500078SThomas-Henning von Kamptz DBG_DUMP_SPTBL(&sblock, dbg_line, &acg); 3893d500078SThomas-Henning von Kamptz } 3903d500078SThomas-Henning von Kamptz } 3913d500078SThomas-Henning von Kamptz /* 3923d500078SThomas-Henning von Kamptz * Dump the requested inode(s). 3933d500078SThomas-Henning von Kamptz */ 3943d500078SThomas-Henning von Kamptz if(cfg_in != -2) { 3953d500078SThomas-Henning von Kamptz dump_whole_inode((ino_t)cfg_in, fsi, cfg_lv); 3963d500078SThomas-Henning von Kamptz } else { 3973d500078SThomas-Henning von Kamptz for(in=cg_start*sblock.fs_ipg; in<(ino_t)cg_stop*sblock.fs_ipg; 3983d500078SThomas-Henning von Kamptz in++) { 3993d500078SThomas-Henning von Kamptz dump_whole_inode(in, fsi, cfg_lv); 4003d500078SThomas-Henning von Kamptz } 4013d500078SThomas-Henning von Kamptz } 4023d500078SThomas-Henning von Kamptz 4033d500078SThomas-Henning von Kamptz DBG_CLOSE; 4043d500078SThomas-Henning von Kamptz 4053d500078SThomas-Henning von Kamptz close(fsi); 4063d500078SThomas-Henning von Kamptz 4073d500078SThomas-Henning von Kamptz DBG_LEAVE; 4083d500078SThomas-Henning von Kamptz return 0; 4093d500078SThomas-Henning von Kamptz } 4103d500078SThomas-Henning von Kamptz 4113d500078SThomas-Henning von Kamptz /* ************************************************** dump_whole_inode ***** */ 4123d500078SThomas-Henning von Kamptz /* 4133d500078SThomas-Henning von Kamptz * Here we dump a list of all blocks allocated by this inode. We follow 4143d500078SThomas-Henning von Kamptz * all indirect blocks. 4153d500078SThomas-Henning von Kamptz */ 4163d500078SThomas-Henning von Kamptz void 4173d500078SThomas-Henning von Kamptz dump_whole_inode(ino_t inode, int fsi, int level) 4183d500078SThomas-Henning von Kamptz { 4193d500078SThomas-Henning von Kamptz DBG_FUNC("dump_whole_inode") 4203d500078SThomas-Henning von Kamptz struct dinode *ino; 4213d500078SThomas-Henning von Kamptz int rb; 4223d500078SThomas-Henning von Kamptz unsigned int ind2ctr, ind3ctr; 4233d500078SThomas-Henning von Kamptz ufs_daddr_t *ind2ptr, *ind3ptr; 4243d500078SThomas-Henning von Kamptz char comment[80]; 4253d500078SThomas-Henning von Kamptz 4263d500078SThomas-Henning von Kamptz DBG_ENTER; 4273d500078SThomas-Henning von Kamptz 4283d500078SThomas-Henning von Kamptz /* 4293d500078SThomas-Henning von Kamptz * Read the inode from disk/cache. 4303d500078SThomas-Henning von Kamptz */ 4313d500078SThomas-Henning von Kamptz ino=ginode(inode, fsi); 4323d500078SThomas-Henning von Kamptz 4333d500078SThomas-Henning von Kamptz if(ino->di_nlink==0) { 4343d500078SThomas-Henning von Kamptz DBG_LEAVE; 4353d500078SThomas-Henning von Kamptz return; /* inode not in use */ 4363d500078SThomas-Henning von Kamptz } 4373d500078SThomas-Henning von Kamptz 4383d500078SThomas-Henning von Kamptz /* 4393d500078SThomas-Henning von Kamptz * Dump the main inode structure. 4403d500078SThomas-Henning von Kamptz */ 4413d500078SThomas-Henning von Kamptz snprintf(comment, 80, "Inode 0x%08x", inode); 4423d500078SThomas-Henning von Kamptz if (level & 0x100) { 4433d500078SThomas-Henning von Kamptz DBG_DUMP_INO(&sblock, comment, ino); 4443d500078SThomas-Henning von Kamptz } 4453d500078SThomas-Henning von Kamptz 4463d500078SThomas-Henning von Kamptz if (!(level & 0x200)) { 4473d500078SThomas-Henning von Kamptz DBG_LEAVE; 4483d500078SThomas-Henning von Kamptz return; 4493d500078SThomas-Henning von Kamptz } 4503d500078SThomas-Henning von Kamptz 4513d500078SThomas-Henning von Kamptz /* 4523d500078SThomas-Henning von Kamptz * Ok, now prepare for dumping all direct and indirect pointers. 4533d500078SThomas-Henning von Kamptz */ 4543d500078SThomas-Henning von Kamptz rb=howmany(ino->di_size, sblock.fs_bsize)-NDADDR; 4553d500078SThomas-Henning von Kamptz if(rb>0) { 4563d500078SThomas-Henning von Kamptz /* 4573d500078SThomas-Henning von Kamptz * Dump single indirect block. 4583d500078SThomas-Henning von Kamptz */ 4593d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, ino->di_ib[0]), sblock.fs_bsize, i1blk, 4603d500078SThomas-Henning von Kamptz fsi); 4613d500078SThomas-Henning von Kamptz snprintf(comment, 80, "Inode 0x%08x: indirect 0", inode); 4623d500078SThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); 4633d500078SThomas-Henning von Kamptz rb-=howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)); 4643d500078SThomas-Henning von Kamptz } 4653d500078SThomas-Henning von Kamptz if(rb>0) { 4663d500078SThomas-Henning von Kamptz /* 4673d500078SThomas-Henning von Kamptz * Dump double indirect blocks. 4683d500078SThomas-Henning von Kamptz */ 4693d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, ino->di_ib[1]), sblock.fs_bsize, i2blk, 4703d500078SThomas-Henning von Kamptz fsi); 4713d500078SThomas-Henning von Kamptz snprintf(comment, 80, "Inode 0x%08x: indirect 1", inode); 4723d500078SThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, comment, i2blk, howmany(rb, 4733d500078SThomas-Henning von Kamptz howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))); 4743d500078SThomas-Henning von Kamptz for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize, 4753d500078SThomas-Henning von Kamptz sizeof(ufs_daddr_t)))&&(rb>0)); ind2ctr++) { 4763d500078SThomas-Henning von Kamptz ind2ptr=&((ufs_daddr_t *)&i2blk)[ind2ctr]; 4773d500078SThomas-Henning von Kamptz 4783d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, *ind2ptr), sblock.fs_bsize, 4793d500078SThomas-Henning von Kamptz i1blk, fsi); 4803d500078SThomas-Henning von Kamptz snprintf(comment, 80, "Inode 0x%08x: indirect 1->%d", 4813d500078SThomas-Henning von Kamptz inode, ind2ctr); 4823d500078SThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); 4833d500078SThomas-Henning von Kamptz rb-=howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)); 4843d500078SThomas-Henning von Kamptz } 4853d500078SThomas-Henning von Kamptz } 4863d500078SThomas-Henning von Kamptz if(rb>0) { 4873d500078SThomas-Henning von Kamptz /* 4883d500078SThomas-Henning von Kamptz * Dump triple indirect blocks. 4893d500078SThomas-Henning von Kamptz */ 4903d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, ino->di_ib[2]), sblock.fs_bsize, i3blk, 4913d500078SThomas-Henning von Kamptz fsi); 4923d500078SThomas-Henning von Kamptz snprintf(comment, 80, "Inode 0x%08x: indirect 2", inode); 4933d500078SThomas-Henning von Kamptz #define SQUARE(a) ((a)*(a)) 4943d500078SThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, comment, i3blk, howmany(rb, 4953d500078SThomas-Henning von Kamptz SQUARE(howmany(sblock.fs_bsize, sizeof(ufs_daddr_t))))); 4963d500078SThomas-Henning von Kamptz #undef SQUARE 4973d500078SThomas-Henning von Kamptz for(ind3ctr=0; ((ind3ctr < howmany(sblock.fs_bsize, 4983d500078SThomas-Henning von Kamptz sizeof(ufs_daddr_t)))&&(rb>0)); ind3ctr ++) { 4993d500078SThomas-Henning von Kamptz ind3ptr=&((ufs_daddr_t *)&i3blk)[ind3ctr]; 5003d500078SThomas-Henning von Kamptz 5013d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, *ind3ptr), sblock.fs_bsize, 5023d500078SThomas-Henning von Kamptz i2blk, fsi); 5033d500078SThomas-Henning von Kamptz snprintf(comment, 80, "Inode 0x%08x: indirect 2->%d", 5043d500078SThomas-Henning von Kamptz inode, ind3ctr); 5053d500078SThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, comment, i2blk, howmany(rb, 5063d500078SThomas-Henning von Kamptz howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)))); 5073d500078SThomas-Henning von Kamptz for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize, 5083d500078SThomas-Henning von Kamptz sizeof(ufs_daddr_t)))&&(rb>0)); ind2ctr ++) { 5093d500078SThomas-Henning von Kamptz ind2ptr=&((ufs_daddr_t *)&i2blk)[ind2ctr]; 5103d500078SThomas-Henning von Kamptz 5113d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, *ind2ptr), 5123d500078SThomas-Henning von Kamptz sblock.fs_bsize, i1blk, fsi); 5133d500078SThomas-Henning von Kamptz snprintf(comment, 80, 5143d500078SThomas-Henning von Kamptz "Inode 0x%08x: indirect 2->%d->%d", inode, 5153d500078SThomas-Henning von Kamptz ind3ctr, ind3ctr); 5163d500078SThomas-Henning von Kamptz DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); 5173d500078SThomas-Henning von Kamptz rb-=howmany(sblock.fs_bsize, 5183d500078SThomas-Henning von Kamptz sizeof(ufs_daddr_t)); 5193d500078SThomas-Henning von Kamptz } 5203d500078SThomas-Henning von Kamptz } 5213d500078SThomas-Henning von Kamptz } 5223d500078SThomas-Henning von Kamptz 5233d500078SThomas-Henning von Kamptz DBG_LEAVE; 5243d500078SThomas-Henning von Kamptz return; 5253d500078SThomas-Henning von Kamptz } 5263d500078SThomas-Henning von Kamptz 5273d500078SThomas-Henning von Kamptz /* ***************************************************** get_disklabel ***** */ 5283d500078SThomas-Henning von Kamptz /* 5293d500078SThomas-Henning von Kamptz * Read the disklabel from disk. 5303d500078SThomas-Henning von Kamptz */ 5313d500078SThomas-Henning von Kamptz struct disklabel * 5323d500078SThomas-Henning von Kamptz get_disklabel(int fd) 5333d500078SThomas-Henning von Kamptz { 5343d500078SThomas-Henning von Kamptz DBG_FUNC("get_disklabel") 5353d500078SThomas-Henning von Kamptz static struct disklabel *lab; 5363d500078SThomas-Henning von Kamptz 5373d500078SThomas-Henning von Kamptz DBG_ENTER; 5383d500078SThomas-Henning von Kamptz 5393d500078SThomas-Henning von Kamptz lab=(struct disklabel *)malloc(sizeof(struct disklabel)); 5403d500078SThomas-Henning von Kamptz if (!lab) { 5413d500078SThomas-Henning von Kamptz fprintf(stderr, "malloc failed\n"); 5423d500078SThomas-Henning von Kamptz exit(-1); 5433d500078SThomas-Henning von Kamptz } 5443d500078SThomas-Henning von Kamptz if (ioctl(fd, DIOCGDINFO, (char *)lab) < 0) { 5453d500078SThomas-Henning von Kamptz fprintf(stderr, "DIOCGDINFO failed\n"); 5463d500078SThomas-Henning von Kamptz exit(-1); 5473d500078SThomas-Henning von Kamptz } 5483d500078SThomas-Henning von Kamptz 5493d500078SThomas-Henning von Kamptz DBG_LEAVE; 5503d500078SThomas-Henning von Kamptz return (lab); 5513d500078SThomas-Henning von Kamptz } 5523d500078SThomas-Henning von Kamptz 5533d500078SThomas-Henning von Kamptz 5543d500078SThomas-Henning von Kamptz /* ************************************************************* usage ***** */ 5553d500078SThomas-Henning von Kamptz /* 5563d500078SThomas-Henning von Kamptz * Dump a line of usage. 5573d500078SThomas-Henning von Kamptz */ 5583d500078SThomas-Henning von Kamptz void 5593d500078SThomas-Henning von Kamptz usage(char *name) 5603d500078SThomas-Henning von Kamptz { 5613d500078SThomas-Henning von Kamptz DBG_FUNC("usage") 5623d500078SThomas-Henning von Kamptz char *basename; 5633d500078SThomas-Henning von Kamptz 5643d500078SThomas-Henning von Kamptz DBG_ENTER; 5653d500078SThomas-Henning von Kamptz 5663d500078SThomas-Henning von Kamptz basename=strrchr(name, '/'); 5673d500078SThomas-Henning von Kamptz if(!basename) { 5683d500078SThomas-Henning von Kamptz basename=name; 5693d500078SThomas-Henning von Kamptz } else { 5703d500078SThomas-Henning von Kamptz basename++; 5713d500078SThomas-Henning von Kamptz } 5723d500078SThomas-Henning von Kamptz fprintf(stderr, 5733d500078SThomas-Henning von Kamptz "usage:\t%s\t[-L] [-g cylgrp] [-i inode] [-l level] [-o outfile]\n" 5743d500078SThomas-Henning von Kamptz "\t\t< special | file >\n", 5753d500078SThomas-Henning von Kamptz basename); 5763d500078SThomas-Henning von Kamptz 5773d500078SThomas-Henning von Kamptz DBG_LEAVE; 5783d500078SThomas-Henning von Kamptz exit(-1); 5793d500078SThomas-Henning von Kamptz } 5803d500078SThomas-Henning von Kamptz 5813d500078SThomas-Henning von Kamptz /* ************************************************************ ginode ***** */ 5823d500078SThomas-Henning von Kamptz /* 5833d500078SThomas-Henning von Kamptz * This function provides access to an individual inode. We find out in which 5843d500078SThomas-Henning von Kamptz * block the requested inode is located, read it from disk if needed, and 5853d500078SThomas-Henning von Kamptz * return the pointer into that block. We maintain a cache of one block to 5863d500078SThomas-Henning von Kamptz * not read the same block again and again if we iterate lineary over all 5873d500078SThomas-Henning von Kamptz * inodes. 5883d500078SThomas-Henning von Kamptz */ 5893d500078SThomas-Henning von Kamptz struct dinode * 5903d500078SThomas-Henning von Kamptz ginode(ino_t inumber, int fsi) 5913d500078SThomas-Henning von Kamptz { 5923d500078SThomas-Henning von Kamptz DBG_FUNC("ginode") 5933d500078SThomas-Henning von Kamptz ufs_daddr_t iblk; 5943d500078SThomas-Henning von Kamptz static ino_t startinum=0; /* first inode in cached block */ 5953d500078SThomas-Henning von Kamptz struct dinode *pi; 5963d500078SThomas-Henning von Kamptz 5973d500078SThomas-Henning von Kamptz DBG_ENTER; 5983d500078SThomas-Henning von Kamptz 5993d500078SThomas-Henning von Kamptz pi=(struct dinode *)ablk; 6003d500078SThomas-Henning von Kamptz if (startinum == 0 || inumber < startinum || 6013d500078SThomas-Henning von Kamptz inumber >= startinum + INOPB(&sblock)) { 6023d500078SThomas-Henning von Kamptz /* 6033d500078SThomas-Henning von Kamptz * The block needed is not cached, so we have to read it from 6043d500078SThomas-Henning von Kamptz * disk now. 6053d500078SThomas-Henning von Kamptz */ 6063d500078SThomas-Henning von Kamptz iblk = ino_to_fsba(&sblock, inumber); 6073d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, iblk), sblock.fs_bsize, (char *)&ablk, 6083d500078SThomas-Henning von Kamptz fsi); 6093d500078SThomas-Henning von Kamptz startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 6103d500078SThomas-Henning von Kamptz } 6113d500078SThomas-Henning von Kamptz 6123d500078SThomas-Henning von Kamptz DBG_LEAVE; 6133d500078SThomas-Henning von Kamptz return (&(pi[inumber % INOPB(&sblock)])); 6143d500078SThomas-Henning von Kamptz } 6153d500078SThomas-Henning von Kamptz 616