Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / misc / dumpe2fs.c
1 /*
2  * dumpe2fs.c           - List the control structures of a second
3  *                        extended filesystem
4  *
5  * Copyright (C) 1992, 1993, 1994  Remy Card <card@masi.ibp.fr>
6  *                                 Laboratoire MASI, Institut Blaise Pascal
7  *                                 Universite Pierre et Marie Curie (Paris VI)
8  *
9  * Copyright 1995, 1996, 1997 by Theodore Ts'o.
10  *
11  * %Begin-Header%
12  * This file may be redistributed under the terms of the GNU Public
13  * License.
14  * %End-Header%
15  */
16
17 /*
18  * History:
19  * 94/01/09     - Creation
20  * 94/02/27     - Ported to use the ext2fs library
21  */
22
23 #ifdef HAVE_GETOPT_H
24 #include <getopt.h>
25 #else
26 extern char *optarg;
27 extern int optind;
28 #endif
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include <linux/ext2_fs.h>
36
37 #include "ext2fs/ext2fs.h"
38 #include "e2p/e2p.h"
39
40 #include "../version.h"
41 #include "nls-enable.h"
42
43 #define in_use(m, x)    (ext2fs_test_bit ((x), (m)))
44
45 const char * program_name = "dumpe2fs";
46 char * device_name = NULL;
47 int opt_hex = 0;
48
49 static void usage(void)
50 {
51         fprintf (stderr, _("Usage: %s [-bfhxV] [-ob superblock] "
52                  "[-oB blocksize] device\n"), program_name);
53         exit (1);
54 }
55
56 static void print_free (unsigned long group, char * bitmap,
57                         unsigned long nbytes, unsigned long offset)
58 {
59         int p = 0;
60         unsigned long i;
61         unsigned long j;
62
63         for (i = 0; i < nbytes; i++)
64                 if (!in_use (bitmap, i))
65                 {
66                         if (p)
67                                 printf (", ");
68                         if (i == nbytes - 1 || in_use (bitmap, i + 1))
69                                 printf (opt_hex ? "0x%04x" : "%lu",
70                                         group * nbytes + i + offset);
71                         else
72                         {
73                                 for (j = i; j < nbytes && !in_use (bitmap, j);
74                                      j++)
75                                         ;
76                                 printf (opt_hex ? "0x%04lx-0x%04lx" :
77                                         "%lu-%lu", group * nbytes + i + offset,
78                                         group * nbytes + (j - 1) + offset);
79                                 i = j - 1;
80                         }
81                         p = 1;
82                 }
83 }
84
85 static void list_desc (ext2_filsys fs)
86 {
87         unsigned long i;
88         blk_t   group_blk, next_blk;
89         char * block_bitmap = fs->block_map->bitmap;
90         char * inode_bitmap = fs->inode_map->bitmap;
91         int inode_blocks_per_group;
92         int group_desc_blocks;
93
94         inode_blocks_per_group = ((fs->super->s_inodes_per_group *
95                                    EXT2_INODE_SIZE(fs->super)) +
96                                   EXT2_BLOCK_SIZE(fs->super) - 1) /
97                                  EXT2_BLOCK_SIZE(fs->super);
98         group_desc_blocks = ((fs->super->s_blocks_count -
99                               fs->super->s_first_data_block +
100                               EXT2_BLOCKS_PER_GROUP(fs->super) - 1) /
101                              EXT2_BLOCKS_PER_GROUP(fs->super) +
102                              EXT2_DESC_PER_BLOCK(fs->super) - 1) /
103                             EXT2_DESC_PER_BLOCK(fs->super);
104
105         printf ("\n");
106         group_blk = fs->super->s_first_data_block;
107         for (i = 0; i < fs->group_desc_count; i++) {
108                 next_blk = group_blk + fs->super->s_blocks_per_group;
109                 if (next_blk > fs->super->s_blocks_count)
110                         next_blk = fs->super->s_blocks_count;
111                 printf (opt_hex ? _("Group %lu: (Blocks %04x -- %04x)\n"):
112                          _("Group %lu: (Blocks %u -- %u)\n"), i,
113                         group_blk, next_blk -1 );
114                 if (ext2fs_bg_has_super (fs, i))
115                         printf (opt_hex ? _("  %s Superblock at 0x%04x,"
116                                 "  Group Descriptors at 0x%04x-0x%04x\n"):
117                                 _("  %s Superblock at %u,"
118                                 "  Group Descriptors at %u-%u\n"),
119                                 i == 0 ? _("Primary") : _("Backup"),
120                                 group_blk, group_blk + 1,
121                                 group_blk + group_desc_blocks);
122                 printf (opt_hex ? _("  Block bitmap at %04x (+%d), "
123                         "Inode bitmap at %04x (+%d)\n  "
124                         "Inode table at %04x-%04x (+%d)\n"):
125                         _("  Block bitmap at %u (+%d), "
126                         "Inode bitmap at %u (+%d)\n  "
127                         "Inode table at %u-%u (+%d)\n"),
128                         fs->group_desc[i].bg_block_bitmap,
129                         fs->group_desc[i].bg_block_bitmap - group_blk,
130                         fs->group_desc[i].bg_inode_bitmap,
131                         fs->group_desc[i].bg_inode_bitmap - group_blk,
132                         fs->group_desc[i].bg_inode_table,
133                         fs->group_desc[i].bg_inode_table +
134                                 inode_blocks_per_group,
135                         fs->group_desc[i].bg_inode_table - group_blk);
136                 printf (_("  %d free blocks, %d free inodes, %d directories\n"),
137                         fs->group_desc[i].bg_free_blocks_count,
138                         fs->group_desc[i].bg_free_inodes_count,
139                         fs->group_desc[i].bg_used_dirs_count);
140                 printf (_("  Free blocks: "));
141                 print_free (i, block_bitmap, fs->super->s_blocks_per_group,
142                             fs->super->s_first_data_block);
143                 block_bitmap += fs->super->s_blocks_per_group / 8;
144                 printf ("\n");
145                 printf (_("  Free inodes: "));
146                 print_free (i, inode_bitmap, fs->super->s_inodes_per_group, 1);
147                 inode_bitmap += fs->super->s_inodes_per_group / 8;
148                 printf ("\n");
149                 group_blk = next_blk;
150         }
151 }
152
153 static void list_bad_blocks(ext2_filsys fs)
154 {
155         badblocks_list          bb_list = 0;
156         badblocks_iterate       bb_iter;
157         blk_t                   blk;
158         errcode_t               retval;
159
160         retval = ext2fs_read_bb_inode(fs, &bb_list);
161         if (retval) {
162                 com_err("ext2fs_read_bb_inode", retval, "");
163                 exit(1);
164         }
165         retval = badblocks_list_iterate_begin(bb_list, &bb_iter);
166         if (retval) {
167                 com_err("badblocks_list_iterate_begin", retval,
168                         _("while printing bad block list"));
169                 exit(1);
170         }
171         if (badblocks_list_iterate(bb_iter, &blk))
172                 printf(_("Bad blocks: %d"), blk);
173         while (badblocks_list_iterate(bb_iter, &blk))
174                 printf(", %d", blk);
175         badblocks_list_iterate_end(bb_iter);
176         printf("\n");
177 }
178
179 static void dump_bad_blocks(ext2_filsys fs)
180 {
181         badblocks_list          bb_list = 0;
182         badblocks_iterate       bb_iter;
183         blk_t                   blk;
184         errcode_t               retval;
185
186         retval = ext2fs_read_bb_inode(fs, &bb_list);
187         if (retval) {
188                 com_err("ext2fs_read_bb_inode", retval, "");
189                 exit(1);
190         }
191         retval = badblocks_list_iterate_begin(bb_list, &bb_iter);
192         if (retval) {
193                 com_err("badblocks_list_iterate_begin", retval,
194                         _("while printing bad block list"));
195                 exit(1);
196         }
197         while (badblocks_list_iterate(bb_iter, &blk))
198                 printf("%d\n", blk);
199         badblocks_list_iterate_end(bb_iter);
200 }
201
202 static int i386_byteorder(void)
203 {
204         int one = 1;
205         char *cp = (char *) &one;
206
207         return (*cp == 1);
208 }
209
210 int main (int argc, char ** argv)
211 {
212         errcode_t       retval;
213         ext2_filsys     fs;
214         int             print_badblocks = 0;
215         int             use_superblock = 0;
216         int             use_blocksize = 0;
217         int             force = 0;
218         int             header_only = 0;
219         int             big_endian;
220         int             c;
221
222 #ifdef ENABLE_NLS
223         setlocale(LC_MESSAGES, "");
224         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
225         textdomain(NLS_CAT_NAME);
226 #endif
227         initialize_ext2_error_table();
228         fprintf (stderr, _("dumpe2fs %s, %s for EXT2 FS %s, %s\n"),
229                  E2FSPROGS_VERSION, E2FSPROGS_DATE,
230                  EXT2FS_VERSION, EXT2FS_DATE);
231         if (argc && *argv)
232                 program_name = *argv;
233         
234         while ((c = getopt (argc, argv, "bfhxVo:")) != EOF) {
235                 switch (c) {
236                 case 'b':
237                         print_badblocks++;
238                         break;
239                 case 'f':
240                         force++;
241                         break;
242                 case 'h':
243                         header_only++;
244                         break;
245                 case 'o':
246                         if (optarg[0] == 'b')
247                                 use_superblock = atoi(optarg+1);
248                         else if (optarg[0] == 'B')
249                                 use_blocksize = atoi(optarg+1);
250                         else
251                                 usage();
252                         break;
253                 case 'V':
254                         /* Print version number and exit */
255                         fprintf(stderr, _("\tUsing %s\n"),
256                                 error_message(EXT2_ET_BASE));
257                         exit(0);
258                 case 'x':
259                         opt_hex=1;
260                         break;
261                 default:
262                         usage();
263                 }
264         }
265         if (optind > argc - 1)
266                 usage();
267         device_name = argv[optind++];
268         if (use_superblock && !use_blocksize)
269                 use_blocksize = 1024;
270         retval = ext2fs_open (device_name, force ? EXT2_FLAG_FORCE : 0,
271                               use_superblock, use_blocksize,
272                               unix_io_manager, &fs);
273         if (retval) {
274                 com_err (program_name, retval, _("while trying to open %s"),
275                          device_name);
276                 printf (_("Couldn't find valid filesystem superblock.\n"));
277                 exit (1);
278         }
279         if (print_badblocks) {
280                 dump_bad_blocks(fs);
281         } else {
282                 big_endian = ((fs->flags & EXT2_FLAG_SWAP_BYTES) != 0);
283                 if (!i386_byteorder())
284                         big_endian = !big_endian;
285                 if (big_endian)
286                         printf(_("Note: This is a byte-swapped filesystem\n"));
287                 list_super (fs->super);
288                 list_bad_blocks (fs);
289                 if (header_only) {
290                         ext2fs_close (fs);
291                         exit (0);
292                 }
293                 retval = ext2fs_read_bitmaps (fs);
294                 if (retval) {
295                         com_err (program_name, retval,
296                                  _("while trying to read the bitmaps"),
297                                  device_name);
298                         ext2fs_close (fs);
299                         exit (1);
300                 }
301                 list_desc (fs);
302         }
303         ext2fs_close (fs);
304         exit (0);
305 }