source: mainline/uspace/app/ext2info/ext2info.c@ 5352d72

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5352d72 was 5352d72, checked in by Martin Sucha <sucha14@…>, 14 years ago

Added support for reading and displaying inode contents to ext2info

  • Property mode set to 100644
File size: 10.8 KB
RevLine 
[d5e2763]1/*
2 * Copyright (c) 2011 Martin Sucha
3 * Copyright (c) 2010 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup fs
31 * @{
32 */
33
34/**
35 * @file ext2info.c
36 * @brief Tool for displaying information about ext2 filesystem
37 *
38 */
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <libblock.h>
43#include <mem.h>
44#include <devmap.h>
45#include <byteorder.h>
46#include <sys/types.h>
47#include <sys/typefmt.h>
48#include <inttypes.h>
49#include <errno.h>
50#include <libext2.h>
51
52#define NAME "ext2info"
53
54static void syntax_print(void);
[d241aae]55static void print_superblock(ext2_superblock_t *);
56static void print_block_groups(ext2_filesystem_t *);
57static void print_block_group(ext2_block_group_t *);
[5352d72]58static void print_inode_by_number(ext2_filesystem_t *, uint32_t);
59static void print_inode(ext2_inode_t *);
60
61#define ARG_SUPERBLOCK 1
62#define ARG_BLOCK_GROUPS 2
63#define ARG_INODE 4
64#define ARG_STRICT_CHECK 8
65#define ARG_COMMON (ARG_SUPERBLOCK | ARG_BLOCK_GROUPS)
66#define ARG_ALL (ARG_COMMON | ARG_INODE)
67
[d5e2763]68
69int main(int argc, char **argv)
70{
71
72 int rc;
[5352d72]73 char *endptr;
[d5e2763]74 char *dev_path;
75 devmap_handle_t handle;
[8bd5dad]76 ext2_filesystem_t filesystem;
[5352d72]77 int arg_flags;
78 uint32_t inode = 0;
79
80 arg_flags = 0;
[d5e2763]81
82 if (argc < 2) {
83 printf(NAME ": Error, argument missing.\n");
84 syntax_print();
85 return 1;
86 }
[d241aae]87
[5352d72]88 // Skip program name
89 --argc; ++argv;
90
[d241aae]91 if (str_cmp(*argv, "--strict-check") == 0) {
92 --argc; ++argv;
[5352d72]93 arg_flags |= ARG_STRICT_CHECK;
94 }
95
96 if (str_cmp(*argv, "--superblock") == 0) {
97 --argc; ++argv;
98 arg_flags |= ARG_SUPERBLOCK;
99 }
100
101 if (str_cmp(*argv, "--block-groups") == 0) {
102 --argc; ++argv;
103 arg_flags |= ARG_BLOCK_GROUPS;
104 }
105
106 if (str_cmp(*argv, "--inode") == 0) {
107 --argc; ++argv;
108 if (argc == 0) {
109 printf(NAME ": Argument expected for --inode\n");
110 return 2;
111 }
112
113 inode = strtol(*argv, &endptr, 10);
114 if (*endptr != '\0') {
115 printf(NAME ": Error, invalid argument for --inode.\n");
116 syntax_print();
117 return 1;
118 }
119
120 arg_flags |= ARG_INODE;
121 --argc; ++argv;
[d241aae]122 }
[d5e2763]123
124 if (argc != 1) {
125 printf(NAME ": Error, unexpected argument.\n");
126 syntax_print();
127 return 1;
128 }
[5352d72]129
130 // Display common things by default
131 if ((arg_flags & ARG_ALL) == 0) {
132 arg_flags = ARG_COMMON;
133 }
[d5e2763]134
135 dev_path = *argv;
136
137 rc = devmap_device_get_handle(dev_path, &handle, 0);
138 if (rc != EOK) {
139 printf(NAME ": Error resolving device `%s'.\n", dev_path);
140 return 2;
141 }
142
[8bd5dad]143 rc = ext2_filesystem_init(&filesystem, handle);
[d5e2763]144 if (rc != EOK) {
[8bd5dad]145 printf(NAME ": Error initializing libext2.\n");
[d5e2763]146 return 3;
147 }
148
[1d6f507]149 rc = ext2_filesystem_check_sanity(&filesystem);
150 if (rc != EOK) {
151 printf(NAME ": Filesystem did not pass sanity check.\n");
[5352d72]152 if (arg_flags & ARG_STRICT_CHECK) {
[d241aae]153 return 3;
154 }
[1d6f507]155 }
156
[5352d72]157 if (arg_flags & ARG_SUPERBLOCK) {
158 print_superblock(filesystem.superblock);
159 }
160
161 if (arg_flags & ARG_BLOCK_GROUPS) {
162 print_block_groups(&filesystem);
163 }
164
165 if (arg_flags & ARG_INODE) {
166 print_inode_by_number(&filesystem, inode);
167 }
[d5e2763]168
[8bd5dad]169 ext2_filesystem_fini(&filesystem);
[d5e2763]170
171 return 0;
172}
173
174
175static void syntax_print(void)
176{
[5352d72]177 printf("syntax: ext2info --strict-check --superblock --block-groups --inode <i-number> <device_name>\n");
[c00e729]178}
179
180static void print_superblock(ext2_superblock_t *superblock)
181{
182 uint16_t magic;
183 uint32_t first_block;
184 uint32_t block_size;
185 uint32_t fragment_size;
186 uint32_t blocks_per_group;
187 uint32_t fragments_per_group;
188 uint32_t rev_major;
189 uint16_t rev_minor;
190 uint16_t state;
191 uint32_t first_inode;
192 uint16_t inode_size;
[f6fa2c2]193 uint32_t total_blocks;
194 uint32_t reserved_blocks;
195 uint32_t free_blocks;
196 uint32_t total_inodes;
197 uint32_t free_inodes;
198 uint32_t os;
[c00e729]199
200 int pos;
201 unsigned char c;
202
203 magic = ext2_superblock_get_magic(superblock);
204 first_block = ext2_superblock_get_first_block(superblock);
205 block_size = ext2_superblock_get_block_size(superblock);
206 fragment_size = ext2_superblock_get_fragment_size(superblock);
207 blocks_per_group = ext2_superblock_get_blocks_per_group(superblock);
208 fragments_per_group = ext2_superblock_get_fragments_per_group(superblock);
209 rev_major = ext2_superblock_get_rev_major(superblock);
210 rev_minor = ext2_superblock_get_rev_minor(superblock);
211 state = ext2_superblock_get_state(superblock);
212 first_inode = ext2_superblock_get_first_inode(superblock);
213 inode_size = ext2_superblock_get_inode_size(superblock);
[f6fa2c2]214 total_blocks = ext2_superblock_get_total_block_count(superblock);
215 reserved_blocks = ext2_superblock_get_reserved_block_count(superblock);
216 free_blocks = ext2_superblock_get_free_block_count(superblock);
217 total_inodes = ext2_superblock_get_total_inode_count(superblock);
218 free_inodes = ext2_superblock_get_free_inode_count(superblock);
219 os = ext2_superblock_get_os(superblock);
[c00e729]220
221 printf("Superblock:\n");
222
223 if (magic == EXT2_SUPERBLOCK_MAGIC) {
224 printf(" Magic value: %X (correct)\n", magic);
225 }
226 else {
227 printf(" Magic value: %X (incorrect)\n", magic);
228 }
229
230 printf(" Revision: %u.%hu\n", rev_major, rev_minor);
231 printf(" State: %hu\n", state);
[f6fa2c2]232 printf(" Creator OS: %u\n", os);
[c00e729]233 printf(" First block: %u\n", first_block);
234 printf(" Block size: %u bytes (%u KiB)\n", block_size, block_size/1024);
235 printf(" Blocks per group: %u\n", blocks_per_group);
[f6fa2c2]236 printf(" Total blocks: %u\n", total_blocks);
237 printf(" Reserved blocks: %u\n", reserved_blocks);
238 printf(" Free blocks: %u\n", free_blocks);
[c00e729]239 printf(" Fragment size: %u bytes (%u KiB)\n", fragment_size,
240 fragment_size/1024);
241 printf(" Fragments per group: %u\n", fragments_per_group);
242 printf(" First inode: %u\n", first_inode);
243 printf(" Inode size: %hu bytes\n", inode_size);
[f6fa2c2]244 printf(" Total inodes: %u\n", total_inodes);
245 printf(" Free inodes: %u\n", free_inodes);
[c00e729]246
247
[f6fa2c2]248 if (rev_major == 1) {
249 printf(" UUID: ");
250 for (pos = 0; pos < 16; pos++) {
251 printf("%02x", superblock->uuid[pos]);
[c00e729]252 }
[f6fa2c2]253 printf("\n");
254
255 printf(" Volume label: ");
256 for (pos = 0; pos < 16; pos++) {
257 c = superblock->volume_name[pos];
258 if (c >= 32 && c < 128) {
259 putchar(c);
260 }
261 else {
262 putchar(' ');
263 }
[c00e729]264 }
[f6fa2c2]265 printf("\n");
[c00e729]266 }
267
[d5e2763]268}
269
[5352d72]270void print_block_groups(ext2_filesystem_t *filesystem)
271{
[d241aae]272 uint32_t block_group_count;
273 uint32_t i;
274 ext2_block_group_ref_t *block_group_ref;
275 int rc;
276
277 printf("Block groups:\n");
278
279 block_group_count = ext2_superblock_get_block_group_count(
280 filesystem->superblock);
281
282 for (i = 0; i < block_group_count; i++) {
283 printf(" Block group %u\n", i);
284 rc = ext2_filesystem_get_block_group_ref(filesystem, i, &block_group_ref);
285 if (rc != EOK) {
286 printf(" Failed reading block group\n");
287 continue;
288 }
289
290 print_block_group(block_group_ref->block_group);
291
292 rc = ext2_filesystem_put_block_group_ref(block_group_ref);
293 if (rc != EOK) {
294 printf(" Failed freeing block group\n");
295 }
296 }
297
298}
299
[5352d72]300void print_block_group(ext2_block_group_t *bg)
301{
[d241aae]302 uint32_t block_bitmap_block;
303 uint32_t inode_bitmap_block;
304 uint32_t inode_table_first_block;
305 uint16_t free_block_count;
306 uint16_t free_inode_count;
307 uint16_t directory_inode_count;
308
309 block_bitmap_block = ext2_block_group_get_block_bitmap_block(bg);
310 inode_bitmap_block = ext2_block_group_get_inode_bitmap_block(bg);
311 inode_table_first_block = ext2_block_group_get_inode_table_first_block(bg);
312 free_block_count = ext2_block_group_get_free_block_count(bg);
313 free_inode_count = ext2_block_group_get_free_inode_count(bg);
314 directory_inode_count = ext2_block_group_get_directory_inode_count(bg);
315
316 printf(" Block bitmap block: %u\n", block_bitmap_block);
317 printf(" Inode bitmap block: %u\n", inode_bitmap_block);
318 printf(" Inode table's first block: %u\n", inode_table_first_block);
319 printf(" Free blocks: %u\n", free_block_count);
320 printf(" Free inodes: %u\n", free_inode_count);
321 printf(" Directory inodes: %u\n", directory_inode_count);
322}
323
[5352d72]324void print_inode_by_number(ext2_filesystem_t *fs, uint32_t inode)
325{
326 int rc;
327 ext2_inode_ref_t *inode_ref;
328
329 printf("Inode %u\n", inode);
330
331 rc = ext2_filesystem_get_inode_ref(fs, inode, &inode_ref);
332 if (rc != EOK) {
333 printf(" Failed getting inode ref\n");
334 return;
335 }
336
337 print_inode(inode_ref->inode);
338
339 rc = ext2_filesystem_put_inode_ref(inode_ref);
340 if (rc != EOK) {
341 printf(" Failed putting inode ref\n");
342 }
343}
344
345void print_inode(ext2_inode_t *inode)
346{
347 uint16_t mode;
348 uint32_t user_id;
349 uint32_t group_id;
350 uint32_t size;
351 uint16_t usage_count;
352 uint32_t flags;
353 uint16_t access;
354 const char *type;
355 uint32_t block;
356 int i;
357 bool all_blocks = false;
358
359 mode = ext2_inode_get_mode(inode);
360 user_id = ext2_inode_get_user_id(inode);
361 group_id = ext2_inode_get_group_id(inode);
362 size = ext2_inode_get_size(inode);
363 usage_count = ext2_inode_get_usage_count(inode);
364 flags = ext2_inode_get_flags(inode);
365
366 type = "Unknown";
367 if ((mode & EXT2_INODE_MODE_BLOCKDEV) == EXT2_INODE_MODE_BLOCKDEV) {
368 type = "Block device";
369 }
370 else if (mode & EXT2_INODE_MODE_FIFO) {
371 type = "Fifo (pipe)";
372 }
373 else if (mode & EXT2_INODE_MODE_CHARDEV) {
374 type = "Character device";
375 }
376 else if (mode & EXT2_INODE_MODE_DIRECTORY) {
377 type = "Directory";
378 }
379 else if (mode & EXT2_INODE_MODE_FILE) {
380 type = "File";
381 }
382 else if (mode & EXT2_INODE_MODE_SOFTLINK) {
383 type = "Soft link";
384 }
385 else if (mode & EXT2_INODE_MODE_SOCKET) {
386 type = "Socket";
387 }
388
389 access = mode & EXT2_INODE_MODE_ACCESS_MASK;
390
391 printf(" Mode: %04x (Type: %s, Access bits: %04ho)\n", mode, type, access);
392 printf(" User ID: %u\n", user_id);
393 printf(" Group ID: %u\n", group_id);
394 printf(" Size: %u\n", size);
395 printf(" Usage (link) count: %u\n", usage_count);
396 printf(" Flags: %u\n", flags);
397 printf(" Block list: ");
398 for (i = 0; i < 12; i++) {
399 block = ext2_inode_get_direct_block(inode, i);
400 if (block == 0) {
401 all_blocks = true;
402 break;
403 }
404 printf("%u ", block);
405 }
406 if (!all_blocks) {
407 printf(" and more...");
408 }
409 printf("\n");
410}
411
[d5e2763]412/**
413 * @}
414 */
Note: See TracBrowser for help on using the repository browser.