Whamcloud - gitweb
ChangeLog, configure, configure.in:
[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 #endif
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include <linux/ext2_fs.h>
33
34 #include "ext2fs/ext2fs.h"
35 #include "e2p/e2p.h"
36
37 #include "../version.h"
38 #include "nls-enable.h"
39
40 #define in_use(m, x)    (ext2fs_test_bit ((x), (m)))
41
42 const char * program_name = "dumpe2fs";
43 char * device_name = NULL;
44
45 static void usage(void)
46 {
47         fprintf (stderr, _("Usage: %s [-bV] [-ob superblock] "
48                  "[-oB blocksize] device\n"), program_name);
49         exit (1);
50 }
51
52 static void print_free (unsigned long group, char * bitmap,
53                         unsigned long nbytes, unsigned long offset)
54 {
55         int p = 0;
56         unsigned long i;
57         unsigned long j;
58
59         for (i = 0; i < nbytes; i++)
60                 if (!in_use (bitmap, i))
61                 {
62                         if (p)
63                                 printf (", ");
64                         if (i == nbytes - 1 || in_use (bitmap, i + 1))
65                                 printf ("%lu", group * nbytes + i + offset);
66                         else
67                         {
68                                 for (j = i; j < nbytes && !in_use (bitmap, j);
69                                      j++)
70                                         ;
71                                 printf ("%lu-%lu", group * nbytes + i + offset,
72                                         group * nbytes + (j - 1) + offset);
73                                 i = j - 1;
74                         }
75                         p = 1;
76                 }
77 }
78
79 static void list_desc (ext2_filsys fs)
80 {
81         unsigned long i;
82         blk_t   group_blk, next_blk;
83         char * block_bitmap = fs->block_map->bitmap;
84         char * inode_bitmap = fs->inode_map->bitmap;
85
86         printf ("\n");
87         group_blk = fs->super->s_first_data_block;
88         for (i = 0; i < fs->group_desc_count; i++) {
89                 next_blk = group_blk + fs->super->s_blocks_per_group;
90                 if (next_blk > fs->super->s_blocks_count)
91                         next_blk = fs->super->s_blocks_count;
92                 printf (_("Group %lu: (Blocks %u -- %u)\n"), i,
93                         group_blk, next_blk -1 );
94                 printf (_("  Block bitmap at %u (+%d), "
95                         "Inode bitmap at %u (+%d)\n  "
96                         "Inode table at %u (+%d)\n"),
97                         fs->group_desc[i].bg_block_bitmap,
98                         fs->group_desc[i].bg_block_bitmap - group_blk,
99                         fs->group_desc[i].bg_inode_bitmap,
100                         fs->group_desc[i].bg_inode_bitmap - group_blk,
101                         fs->group_desc[i].bg_inode_table,
102                         fs->group_desc[i].bg_inode_table - group_blk);
103                 printf (_("  %d free blocks, %d free inodes, %d directories\n"),
104                         fs->group_desc[i].bg_free_blocks_count,
105                         fs->group_desc[i].bg_free_inodes_count,
106                         fs->group_desc[i].bg_used_dirs_count);
107                 printf (_("  Free blocks: "));
108                 print_free (i, block_bitmap, fs->super->s_blocks_per_group,
109                             fs->super->s_first_data_block);
110                 block_bitmap += fs->super->s_blocks_per_group / 8;
111                 printf ("\n");
112                 printf (_("  Free inodes: "));
113                 print_free (i, inode_bitmap, fs->super->s_inodes_per_group, 1);
114                 inode_bitmap += fs->super->s_inodes_per_group / 8;
115                 printf ("\n");
116                 group_blk = next_blk;
117         }
118 }
119
120 static void list_bad_blocks(ext2_filsys fs)
121 {
122         badblocks_list          bb_list = 0;
123         badblocks_iterate       bb_iter;
124         blk_t                   blk;
125         errcode_t               retval;
126
127         retval = ext2fs_read_bb_inode(fs, &bb_list);
128         if (retval) {
129                 com_err("ext2fs_read_bb_inode", retval, "");
130                 exit(1);
131         }
132         retval = badblocks_list_iterate_begin(bb_list, &bb_iter);
133         if (retval) {
134                 com_err("badblocks_list_iterate_begin", retval,
135                         _("while printing bad block list"));
136                 exit(1);
137         }
138         if (badblocks_list_iterate(bb_iter, &blk))
139                 printf(_("Bad blocks: %d"), blk);
140         while (badblocks_list_iterate(bb_iter, &blk))
141                 printf(", %d", blk);
142         badblocks_list_iterate_end(bb_iter);
143         printf("\n");
144 }
145
146 static void dump_bad_blocks(ext2_filsys fs)
147 {
148         badblocks_list          bb_list = 0;
149         badblocks_iterate       bb_iter;
150         blk_t                   blk;
151         errcode_t               retval;
152
153         retval = ext2fs_read_bb_inode(fs, &bb_list);
154         if (retval) {
155                 com_err("ext2fs_read_bb_inode", retval, "");
156                 exit(1);
157         }
158         retval = badblocks_list_iterate_begin(bb_list, &bb_iter);
159         if (retval) {
160                 com_err("badblocks_list_iterate_begin", retval,
161                         _("while printing bad block list"));
162                 exit(1);
163         }
164         while (badblocks_list_iterate(bb_iter, &blk))
165                 printf("%d\n", blk);
166         badblocks_list_iterate_end(bb_iter);
167 }
168
169 static int i386_byteorder(void)
170 {
171         int one = 1;
172         char *cp = (char *) &one;
173
174         return (*cp == 1);
175 }
176
177 int main (int argc, char ** argv)
178 {
179         errcode_t       retval;
180         ext2_filsys     fs;
181         int             print_badblocks = 0;
182         int             use_superblock = 0;
183         int             use_blocksize = 0;
184         int             force = 0;
185         int             header_only = 0;
186         int             big_endian;
187         int             c;
188
189 #ifdef ENABLE_NLS
190         setlocale(LC_MESSAGES, "");
191         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
192         textdomain(NLS_CAT_NAME);
193 #endif
194         initialize_ext2_error_table();
195         fprintf (stderr, _("dumpe2fs %s, %s for EXT2 FS %s, %s\n"),
196                  E2FSPROGS_VERSION, E2FSPROGS_DATE,
197                  EXT2FS_VERSION, EXT2FS_DATE);
198         if (argc && *argv)
199                 program_name = *argv;
200         
201         while ((c = getopt (argc, argv, "bfhVo:")) != EOF) {
202                 switch (c) {
203                 case 'b':
204                         print_badblocks++;
205                         break;
206                 case 'f':
207                         force++;
208                         break;
209                 case 'h':
210                         header_only++;
211                         break;
212                 case 'o':
213                         if (optarg[0] == 'b')
214                                 use_superblock = atoi(optarg+1);
215                         else if (optarg[0] == 'B')
216                                 use_blocksize = atoi(optarg+1);
217                         else
218                                 usage();
219                         break;
220                 case 'V':
221                         /* Print version number and exit */
222                         fprintf(stderr, _("\tUsing %s\n"),
223                                 error_message(EXT2_ET_BASE));
224                         exit(0);
225                 default:
226                         usage();
227                 }
228         }
229         if (optind > argc - 1)
230                 usage();
231         device_name = argv[optind++];
232         if (use_superblock && !use_blocksize)
233                 use_blocksize = 1024;
234         retval = ext2fs_open (device_name, force ? EXT2_FLAG_FORCE : 0,
235                               use_superblock, use_blocksize,
236                               unix_io_manager, &fs);
237         if (retval) {
238                 com_err (program_name, retval, _("while trying to open %s"),
239                          device_name);
240                 printf (_("Couldn't find valid filesystem superblock.\n"));
241                 exit (1);
242         }
243         if (print_badblocks) {
244                 dump_bad_blocks(fs);
245         } else {
246                 big_endian = ((fs->flags & EXT2_FLAG_SWAP_BYTES) != 0);
247                 if (!i386_byteorder())
248                         big_endian = !big_endian;
249                 if (big_endian)
250                         printf(_("Note: This is a byte-swapped filesystem\n"));
251                 list_super (fs->super);
252                 list_bad_blocks (fs);
253                 if (header_only) {
254                         ext2fs_close (fs);
255                         exit (0);
256                 }
257                 retval = ext2fs_read_bitmaps (fs);
258                 if (retval) {
259                         com_err (program_name, retval,
260                                  _("while trying to read the bitmaps"),
261                                  device_name);
262                         ext2fs_close (fs);
263                         exit (1);
264                 }
265                 list_desc (fs);
266         }
267         ext2fs_close (fs);
268         exit (0);
269 }