Whamcloud - gitweb
ChangeLog, dumpe2fs.c, mke2fs.c:
[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 "ext2fs/ext2_fs.h"
36
37 #include "ext2fs/ext2fs.h"
38 #include "e2p/e2p.h"
39 #include "jfs_user.h"
40
41 #include "../version.h"
42 #include "nls-enable.h"
43
44 #define in_use(m, x)    (ext2fs_test_bit ((x), (m)))
45
46 const char * program_name = "dumpe2fs";
47 char * device_name = NULL;
48 int opt_hex = 0;
49
50 static void usage(void)
51 {
52         fprintf (stderr, _("Usage: %s [-bfhixV] [-ob superblock] "
53                  "[-oB blocksize] device\n"), program_name);
54         exit (1);
55 }
56
57 static void print_free (unsigned long group, char * bitmap,
58                         unsigned long nbytes, unsigned long offset)
59 {
60         int p = 0;
61         unsigned long i;
62         unsigned long j;
63
64         for (i = 0; i < nbytes; i++)
65                 if (!in_use (bitmap, i))
66                 {
67                         if (p)
68                                 printf (", ");
69                         if (i == nbytes - 1 || in_use (bitmap, i + 1))
70                                 printf (opt_hex ? "0x%04x" : "%lu",
71                                         group * nbytes + i + offset);
72                         else
73                         {
74                                 for (j = i; j < nbytes && !in_use (bitmap, j);
75                                      j++)
76                                         ;
77                                 printf (opt_hex ? "0x%04lx-0x%04lx" :
78                                         "%lu-%lu", group * nbytes + i + offset,
79                                         group * nbytes + (j - 1) + offset);
80                                 i = j - 1;
81                         }
82                         p = 1;
83                 }
84 }
85
86 static void list_desc (ext2_filsys fs)
87 {
88         unsigned long i;
89         blk_t   group_blk, next_blk;
90         char * block_bitmap = fs->block_map->bitmap;
91         char * inode_bitmap = fs->inode_map->bitmap;
92         int inode_blocks_per_group;
93         int group_desc_blocks;
94
95         inode_blocks_per_group = ((fs->super->s_inodes_per_group *
96                                    EXT2_INODE_SIZE(fs->super)) +
97                                   EXT2_BLOCK_SIZE(fs->super) - 1) /
98                                  EXT2_BLOCK_SIZE(fs->super);
99         group_desc_blocks = ((fs->super->s_blocks_count -
100                               fs->super->s_first_data_block +
101                               EXT2_BLOCKS_PER_GROUP(fs->super) - 1) /
102                              EXT2_BLOCKS_PER_GROUP(fs->super) +
103                              EXT2_DESC_PER_BLOCK(fs->super) - 1) /
104                             EXT2_DESC_PER_BLOCK(fs->super);
105
106         printf ("\n");
107         group_blk = fs->super->s_first_data_block;
108         for (i = 0; i < fs->group_desc_count; i++) {
109                 next_blk = group_blk + fs->super->s_blocks_per_group;
110                 if (next_blk > fs->super->s_blocks_count)
111                         next_blk = fs->super->s_blocks_count;
112                 printf (opt_hex ? _("Group %lu: (Blocks 0x%04x -- 0x%04x)\n"):
113                          _("Group %lu: (Blocks %u -- %u)\n"), i,
114                         group_blk, next_blk -1 );
115                 if (ext2fs_bg_has_super (fs, i))
116                         printf (opt_hex ? _("  %s Superblock at 0x%04x,"
117                                 "  Group Descriptors at 0x%04x-0x%04x\n"):
118                                 _("  %s Superblock at %u,"
119                                 "  Group Descriptors at %u-%u\n"),
120                                 i == 0 ? _("Primary") : _("Backup"),
121                                 group_blk, group_blk + 1,
122                                 group_blk + group_desc_blocks);
123                 printf (opt_hex ? _("  Block bitmap at 0x%04x (+%d), "
124                         "Inode bitmap at 0x%04x (+%d)\n  "
125                         "Inode table at 0x%04x-0x%04x (+%d)\n"):
126                         _("  Block bitmap at %u (+%d), "
127                         "Inode bitmap at %u (+%d)\n  "
128                         "Inode table at %u-%u (+%d)\n"),
129                         fs->group_desc[i].bg_block_bitmap,
130                         fs->group_desc[i].bg_block_bitmap - group_blk,
131                         fs->group_desc[i].bg_inode_bitmap,
132                         fs->group_desc[i].bg_inode_bitmap - group_blk,
133                         fs->group_desc[i].bg_inode_table,
134                         fs->group_desc[i].bg_inode_table +
135                                 inode_blocks_per_group - 1,
136                         fs->group_desc[i].bg_inode_table - group_blk);
137                 printf (_("  %d free blocks, %d free inodes, %d directories\n"),
138                         fs->group_desc[i].bg_free_blocks_count,
139                         fs->group_desc[i].bg_free_inodes_count,
140                         fs->group_desc[i].bg_used_dirs_count);
141                 printf (_("  Free blocks: "));
142                 print_free (i, block_bitmap, fs->super->s_blocks_per_group,
143                             fs->super->s_first_data_block);
144                 block_bitmap += fs->super->s_blocks_per_group / 8;
145                 printf ("\n");
146                 printf (_("  Free inodes: "));
147                 print_free (i, inode_bitmap, fs->super->s_inodes_per_group, 1);
148                 inode_bitmap += fs->super->s_inodes_per_group / 8;
149                 printf ("\n");
150                 group_blk = next_blk;
151         }
152 }
153
154 static void list_bad_blocks(ext2_filsys fs)
155 {
156         badblocks_list          bb_list = 0;
157         badblocks_iterate       bb_iter;
158         blk_t                   blk;
159         errcode_t               retval;
160
161         retval = ext2fs_read_bb_inode(fs, &bb_list);
162         if (retval) {
163                 com_err("ext2fs_read_bb_inode", retval, "");
164                 exit(1);
165         }
166         retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
167         if (retval) {
168                 com_err("ext2fs_badblocks_list_iterate_begin", retval,
169                         _("while printing bad block list"));
170                 exit(1);
171         }
172         if (ext2fs_badblocks_list_iterate(bb_iter, &blk))
173                 printf(_("Bad blocks: %d"), blk);
174         while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
175                 printf(", %d", blk);
176         ext2fs_badblocks_list_iterate_end(bb_iter);
177         printf("\n");
178 }
179
180 static void dump_bad_blocks(ext2_filsys fs)
181 {
182         badblocks_list          bb_list = 0;
183         badblocks_iterate       bb_iter;
184         blk_t                   blk;
185         errcode_t               retval;
186
187         retval = ext2fs_read_bb_inode(fs, &bb_list);
188         if (retval) {
189                 com_err("ext2fs_read_bb_inode", retval, "");
190                 exit(1);
191         }
192         retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
193         if (retval) {
194                 com_err("ext2fs_badblocks_list_iterate_begin", retval,
195                         _("while printing bad block list"));
196                 exit(1);
197         }
198         while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
199                 printf("%d\n", blk);
200         ext2fs_badblocks_list_iterate_end(bb_iter);
201 }
202
203 static void print_journal_information(ext2_filsys fs)
204 {
205         errcode_t       retval;
206         char            buf[1024];
207         char            str[80];
208         int             i;
209         journal_superblock_t    *jsb;
210
211         /* Get the journal superblock */
212         if ((retval = io_channel_read_blk(fs->io, fs->super->s_first_data_block+1, -1024, buf))) {
213                 com_err(program_name, retval,
214                         _("while reading journal superblock"));
215                 exit(1);
216         }
217         jsb = (journal_superblock_t *) buf;
218         if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
219             (jsb->s_header.h_blocktype !=
220              (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
221                 com_err(program_name, 0,
222                         _("Couldn't find journal superblock magic numbers"));
223                 exit(1);
224         }
225
226         fputs("\n", stdout);
227         printf("Journal block size:       %d\n", ntohl(jsb->s_blocksize));
228         printf("Journal length:           %d\n", ntohl(jsb->s_maxlen));
229         printf("Journal first block:      %d\n", ntohl(jsb->s_first));
230         printf("Journal sequence:         0x%08x\n", ntohl(jsb->s_sequence));
231         printf("Journal start:            %d\n", ntohl(jsb->s_start));
232         printf("Journal number of users:  %d\n", ntohl(jsb->s_nr_users));
233         for (i=0; i < ntohl(jsb->s_nr_users); i++) {
234                 if (i)
235                         printf("                          ");
236                 else
237                         printf("Journal users:            ");
238                 uuid_unparse(&jsb->s_users[i*16], str);
239                 printf("%s\n", str);
240         }
241 }
242
243 int main (int argc, char ** argv)
244 {
245         errcode_t       retval;
246         ext2_filsys     fs;
247         int             print_badblocks = 0;
248         int             use_superblock = 0;
249         int             use_blocksize = 0;
250         int             image_dump = 0;
251         int             force = 0;
252         int             flags;
253         int             header_only = 0;
254         int             big_endian;
255         int             c;
256
257 #ifdef ENABLE_NLS
258         setlocale(LC_MESSAGES, "");
259         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
260         textdomain(NLS_CAT_NAME);
261 #endif
262         initialize_ext2_error_table();
263         fprintf (stderr, _("dumpe2fs %s, %s for EXT2 FS %s, %s\n"),
264                  E2FSPROGS_VERSION, E2FSPROGS_DATE,
265                  EXT2FS_VERSION, EXT2FS_DATE);
266         if (argc && *argv)
267                 program_name = *argv;
268         
269         while ((c = getopt (argc, argv, "bfhixVo:")) != EOF) {
270                 switch (c) {
271                 case 'b':
272                         print_badblocks++;
273                         break;
274                 case 'f':
275                         force++;
276                         break;
277                 case 'h':
278                         header_only++;
279                         break;
280                 case 'i':
281                         image_dump++;
282                         break;
283                 case 'o':
284                         if (optarg[0] == 'b')
285                                 use_superblock = atoi(optarg+1);
286                         else if (optarg[0] == 'B')
287                                 use_blocksize = atoi(optarg+1);
288                         else
289                                 usage();
290                         break;
291                 case 'V':
292                         /* Print version number and exit */
293                         fprintf(stderr, _("\tUsing %s\n"),
294                                 error_message(EXT2_ET_BASE));
295                         exit(0);
296                 case 'x':
297                         opt_hex=1;
298                         break;
299                 default:
300                         usage();
301                 }
302         }
303         if (optind > argc - 1)
304                 usage();
305         device_name = argv[optind++];
306         if (use_superblock && !use_blocksize)
307                 use_blocksize = 1024;
308         flags = EXT2_FLAG_JOURNAL_DEV_OK;
309         if (force)
310                 flags |= EXT2_FLAG_FORCE;
311         if (image_dump)
312                 flags |= EXT2_FLAG_IMAGE_FILE;
313         
314         retval = ext2fs_open (device_name, flags, use_superblock,
315                               use_blocksize, unix_io_manager, &fs);
316         if (retval) {
317                 com_err (program_name, retval, _("while trying to open %s"),
318                          device_name);
319                 printf (_("Couldn't find valid filesystem superblock.\n"));
320                 exit (1);
321         }
322         if (print_badblocks) {
323                 dump_bad_blocks(fs);
324         } else {
325                 big_endian = ((fs->flags & EXT2_FLAG_SWAP_BYTES) != 0);
326 #ifdef WORDS_BIGENDIAN
327                 big_endian = !big_endian;
328 #endif
329                 if (big_endian)
330                         printf(_("Note: This is a byte-swapped filesystem\n"));
331                 list_super (fs->super);
332                 if (fs->super->s_feature_incompat &
333                       EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
334                         print_journal_information(fs);
335                         ext2fs_close(fs);
336                         exit(0);
337                 }
338                 list_bad_blocks (fs);
339                 if (header_only) {
340                         ext2fs_close (fs);
341                         exit (0);
342                 }
343                 retval = ext2fs_read_bitmaps (fs);
344                 if (retval) {
345                         com_err (program_name, retval,
346                                  _("while trying to read the bitmaps"),
347                                  device_name);
348                         ext2fs_close (fs);
349                         exit (1);
350                 }
351                 list_desc (fs);
352         }
353         ext2fs_close (fs);
354         exit (0);
355 }