X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=debugfs%2Fdebugfs.c;h=8b0965ecd6e3e9ebcd68e77b3ba43b7f53e2b270;hb=711d3846a03d97a340b261f7524b83ec09c7cbe3;hp=a92933d2012fead7dbf0c1297f69062a4994d145;hpb=5aae7c292fe0e10ec4e36d664da86939d15aca31;p=tools%2Fe2fsprogs.git diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index a92933d..8b0965e 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -4,7 +4,7 @@ * * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed * under the terms of the GNU Public License. - * + * * Modifications by Robert Sanders */ @@ -16,7 +16,7 @@ #include #ifdef HAVE_GETOPT_H #include -#else +#else extern int optind; extern char *optarg; #endif @@ -36,14 +36,17 @@ extern char *optarg; #include #include "../version.h" +#include "jfs_user.h" extern ss_request_table debug_cmds; +ss_request_table *extra_cmds; +const char *debug_prog_name; ext2_filsys current_fs = NULL; ext2_ino_t root, cwd; static void open_filesystem(char *device, int open_flags, blk_t superblock, - blk_t blocksize, int catastrophic, + blk_t blocksize, int catastrophic, char *data_filename) { int retval; @@ -57,7 +60,7 @@ static void open_filesystem(char *device, int open_flags, blk_t superblock, if (data_filename) { if ((open_flags & EXT2_FLAG_IMAGE_FILE) == 0) { - com_err(device, 0, + com_err(device, 0, "The -d option is only valid when reading an e2image file"); current_fs = NULL; return; @@ -75,7 +78,7 @@ static void open_filesystem(char *device, int open_flags, blk_t superblock, "opening read-only because of catastrophic mode"); open_flags &= ~EXT2_FLAG_RW; } - + retval = ext2fs_open(device, open_flags, superblock, blocksize, unix_io_manager, ¤t_fs); if (retval) { @@ -102,7 +105,7 @@ static void open_filesystem(char *device, int open_flags, blk_t superblock, if (data_io) { retval = ext2fs_set_data_io(current_fs, data_io); if (retval) { - com_err(device, retval, + com_err(device, retval, "while setting data source"); goto errout; } @@ -126,7 +129,7 @@ void do_open_filesys(int argc, char **argv) blk_t blocksize = 0; int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES; char *data_filename = 0; - + reset_getopt(); while ((c = getopt (argc, argv, "iwfecb:s:d:")) != EOF) { switch (c) { @@ -170,7 +173,7 @@ void do_open_filesys(int argc, char **argv) if (check_fs_not_open(argv[0])) return; open_filesystem(argv[optind], open_flags, - superblock, blocksize, catastrophic, + superblock, blocksize, catastrophic, data_filename); return; @@ -197,7 +200,7 @@ void do_lcd(int argc, char **argv) static void close_filesystem(NOARGS) { int retval; - + if (current_fs->flags & EXT2_FLAG_IB_DIRTY) { retval = ext2fs_write_inode_bitmap(current_fs); if (retval) @@ -227,7 +230,7 @@ void do_init_filesys(int argc, char **argv) struct ext2_super_block param; errcode_t retval; int err; - + if (common_args_process(argc, argv, 3, 3, "initialize", " ", CHECK_FS_NOTOPEN)) return; @@ -286,7 +289,10 @@ void do_show_super_stats(int argc, char *argv[]) FILE *out; struct ext2_group_desc *gdp; int c, header_only = 0; - int numdirs = 0, first; + int numdirs = 0, first, gdt_csum; + + gdt_csum = EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super, + EXT4_FEATURE_RO_COMPAT_GDT_CSUM); reset_getopt(); while ((c = getopt (argc, argv, "h")) != EOF) { @@ -309,12 +315,12 @@ void do_show_super_stats(int argc, char *argv[]) for (i=0; i < current_fs->group_desc_count; i++) numdirs += current_fs->group_desc[i].bg_used_dirs_count; fprintf(out, "Directories: %d\n", numdirs); - + if (header_only) { close_pager(out); return; } - + gdp = ¤t_fs->group_desc[0]; for (i = 0; i < current_fs->group_desc_count; i++, gdp++) { fprintf(out, " Group %2d: block bitmap at %u, " @@ -322,7 +328,7 @@ void do_show_super_stats(int argc, char *argv[]) "inode table at %u\n" " %d free %s, " "%d free %s, " - "%d used %s\n", + "%d used %s%s", i, gdp->bg_block_bitmap, gdp->bg_inode_bitmap, gdp->bg_inode_table, gdp->bg_free_blocks_count, @@ -331,12 +337,21 @@ void do_show_super_stats(int argc, char *argv[]) gdp->bg_free_inodes_count != 1 ? "inodes" : "inode", gdp->bg_used_dirs_count, gdp->bg_used_dirs_count != 1 ? "directories" - : "directory"); + : "directory", gdt_csum ? ", " : "\n"); + if (gdt_csum) + fprintf(out, "%d unused %s\n", + gdp->bg_itable_unused, + gdp->bg_itable_unused != 1 ? "inodes":"inode"); first = 1; print_bg_opts(gdp, EXT2_BG_INODE_UNINIT, "Inode not init", &first, out); print_bg_opts(gdp, EXT2_BG_BLOCK_UNINIT, "Block not init", &first, out); + if (gdt_csum) { + fprintf(out, "%sChecksum 0x%04x", + first ? " [":", ", gdp->bg_checksum); + first = 0; + } if (!first) fputs("]\n", out); } @@ -346,7 +361,7 @@ print_usage: fprintf(stderr, "%s: Usage: show_super [-h]\n", argv[0]); } -void do_dirty_filesys(int argc EXT2FS_ATTR((unused)), +void do_dirty_filesys(int argc EXT2FS_ATTR((unused)), char **argv EXT2FS_ATTR((unused))) { if (check_fs_open(argv[0])) @@ -387,10 +402,10 @@ static void finish_range(struct list_blocks_struct *lb) lb->first_block = 0; } -static int list_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)), - blk_t *blocknr, e2_blkcnt_t blockcnt, +static int list_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)), + blk_t *blocknr, e2_blkcnt_t blockcnt, blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), void *private) { struct list_blocks_struct *lb = (struct list_blocks_struct *) private; @@ -436,7 +451,7 @@ static void dump_xattr_string(FILE *out, const char *str, int len) { int printable = 0; int i; - + /* check: is string "printable enough?" */ for (i = 0; i < len; i++) if (isprint(str[i])) @@ -453,9 +468,9 @@ static void dump_xattr_string(FILE *out, const char *str, int len) fprintf(out, "%02x ", (unsigned char)str[i]); } -static void internal_dump_inode_extra(FILE *out, +static void internal_dump_inode_extra(FILE *out, const char *prefix EXT2FS_ATTR((unused)), - ext2_ino_t inode_num EXT2FS_ATTR((unused)), + ext2_ino_t inode_num EXT2FS_ATTR((unused)), struct ext2_inode_large *inode) { struct ext2_ext_attr_entry *entry; @@ -489,7 +504,7 @@ static void internal_dump_inode_extra(FILE *out, return; } fprintf(out, " "); - dump_xattr_string(out, EXT2_EXT_ATTR_NAME(entry), + dump_xattr_string(out, EXT2_EXT_ATTR_NAME(entry), entry->e_name_len); fprintf(out, " = \""); dump_xattr_string(out, start + entry->e_value_offs, @@ -509,7 +524,7 @@ static void dump_blocks(FILE *f, const char *prefix, ext2_ino_t inode) lb.first_block = 0; lb.f = f; lb.first = 1; - ext2fs_block_iterate2(current_fs, inode, 0, NULL, + ext2fs_block_iterate2(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL, list_blocks_proc, (void *)&lb); finish_range(&lb); if (lb.total) @@ -525,7 +540,13 @@ void internal_dump_inode(FILE *out, const char *prefix, const char *i_type; char frag, fsize; int os = current_fs->super->s_creator_os; - + struct ext2_inode_large *large_inode; + int is_large_inode = 0; + + if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE) + is_large_inode = 1; + large_inode = (struct ext2_inode_large *) inode; + if (LINUX_S_ISDIR(inode->i_mode)) i_type = "directory"; else if (LINUX_S_ISREG(inode->i_mode)) i_type = "regular"; else if (LINUX_S_ISLNK(inode->i_mode)) i_type = "symlink"; @@ -535,9 +556,16 @@ void internal_dump_inode(FILE *out, const char *prefix, else if (LINUX_S_ISSOCK(inode->i_mode)) i_type = "socket"; else i_type = "bad type"; fprintf(out, "%sInode: %u Type: %s ", prefix, inode_num, i_type); - fprintf(out, "%sMode: %04o Flags: 0x%x Generation: %u\n", - prefix, - inode->i_mode & 0777, inode->i_flags, inode->i_generation); + fprintf(out, "%sMode: %04o Flags: 0x%x\n", + prefix, inode->i_mode & 0777, inode->i_flags); + if (is_large_inode && large_inode->i_extra_isize >= 24) { + fprintf(out, "%sGeneration: %u Version: 0x%08x:%08x\n", + prefix, inode->i_generation, large_inode->i_version_hi, + inode->osd1.linux1.l_i_version); + } else { + fprintf(out, "%sGeneration: %u Version: 0x%08x\n", prefix, + inode->i_generation, inode->osd1.linux1.l_i_version); + } fprintf(out, "%sUser: %5d Group: %5d Size: ", prefix, inode_uid(*inode), inode_gid(*inode)); if (LINUX_S_ISREG(inode->i_mode)) { @@ -557,11 +585,11 @@ void internal_dump_inode(FILE *out, const char *prefix, fprintf(out, "%sFile ACL: %d Directory ACL: %d\n", prefix, inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0); - if (os == EXT2_OS_LINUX) + if (os == EXT2_OS_LINUX) fprintf(out, "%sLinks: %d Blockcount: %llu\n", - prefix, inode->i_links_count, - (((unsigned long long) - inode->osd2.linux2.l_i_blocks_hi << 32)) + + prefix, inode->i_links_count, + (((unsigned long long) + inode->osd2.linux2.l_i_blocks_hi << 32)) + inode->i_blocks); else fprintf(out, "%sLinks: %d Blockcount: %u\n", @@ -571,22 +599,33 @@ void internal_dump_inode(FILE *out, const char *prefix, frag = inode->osd2.hurd2.h_i_frag; fsize = inode->osd2.hurd2.h_i_fsize; break; - case EXT2_OS_MASIX: - frag = inode->osd2.masix2.m_i_frag; - fsize = inode->osd2.masix2.m_i_fsize; - break; default: frag = fsize = 0; } fprintf(out, "%sFragment: Address: %d Number: %d Size: %d\n", prefix, inode->i_faddr, frag, fsize); - fprintf(out, "%sctime: 0x%08x -- %s", prefix, inode->i_ctime, - time_to_string(inode->i_ctime)); - fprintf(out, "%satime: 0x%08x -- %s", prefix, inode->i_atime, - time_to_string(inode->i_atime)); - fprintf(out, "%smtime: 0x%08x -- %s", prefix, inode->i_mtime, - time_to_string(inode->i_mtime)); - if (inode->i_dtime) + if (is_large_inode && large_inode->i_extra_isize >= 24) { + fprintf(out, "%s ctime: 0x%08x:%08x -- %s", prefix, + inode->i_ctime, large_inode->i_ctime_extra, + time_to_string(inode->i_ctime)); + fprintf(out, "%s atime: 0x%08x:%08x -- %s", prefix, + inode->i_atime, large_inode->i_atime_extra, + time_to_string(inode->i_atime)); + fprintf(out, "%s mtime: 0x%08x:%08x -- %s", prefix, + inode->i_mtime, large_inode->i_mtime_extra, + time_to_string(inode->i_mtime)); + fprintf(out, "%scrtime: 0x%08x:%08x -- %s", prefix, + large_inode->i_crtime, large_inode->i_crtime_extra, + time_to_string(large_inode->i_crtime)); + } else { + fprintf(out, "%sctime: 0x%08x -- %s", prefix, inode->i_ctime, + time_to_string(inode->i_ctime)); + fprintf(out, "%satime: 0x%08x -- %s", prefix, inode->i_atime, + time_to_string(inode->i_atime)); + fprintf(out, "%smtime: 0x%08x -- %s", prefix, inode->i_mtime, + time_to_string(inode->i_mtime)); + } + if (inode->i_dtime) fprintf(out, "%sdtime: 0x%08x -- %s", prefix, inode->i_dtime, time_to_string(inode->i_dtime)); if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE) @@ -605,11 +644,11 @@ void internal_dump_inode(FILE *out, const char *prefix, devnote = ""; } else { major = (inode->i_block[1] & 0xfff00) >> 8; - minor = ((inode->i_block[1] & 0xff) | + minor = ((inode->i_block[1] & 0xff) | ((inode->i_block[1] >> 12) & 0xfff00)); devnote = "(New-style) "; } - fprintf(out, "%sDevice major/minor number: %02d:%02d (hex %02x:%02x)\n", + fprintf(out, "%sDevice major/minor number: %02d:%02d (hex %02x:%02x)\n", devnote, major, minor, major, minor); } else if (do_dump_blocks) @@ -619,7 +658,7 @@ void internal_dump_inode(FILE *out, const char *prefix, static void dump_inode(ext2_ino_t inode_num, struct ext2_inode *inode) { FILE *out; - + out = open_pager(); internal_dump_inode(out, "", inode_num, inode, 1); close_pager(out); @@ -791,7 +830,8 @@ static void modify_u8(char *com, const char *prompt, sprintf(buf, format, *val); printf("%30s [%s] ", prompt, buf); - fgets(buf, sizeof(buf), stdin); + if (!fgets(buf, sizeof(buf), stdin)) + return; if (buf[strlen (buf) - 1] == '\n') buf[strlen (buf) - 1] = '\0'; if (!buf[0]) @@ -812,7 +852,8 @@ static void modify_u16(char *com, const char *prompt, sprintf(buf, format, *val); printf("%30s [%s] ", prompt, buf); - fgets(buf, sizeof(buf), stdin); + if (!fgets(buf, sizeof(buf), stdin)) + return; if (buf[strlen (buf) - 1] == '\n') buf[strlen (buf) - 1] = '\0'; if (!buf[0]) @@ -833,7 +874,8 @@ static void modify_u32(char *com, const char *prompt, sprintf(buf, format, *val); printf("%30s [%s] ", prompt, buf); - fgets(buf, sizeof(buf), stdin); + if (!fgets(buf, sizeof(buf), stdin)) + return; if (buf[strlen (buf) - 1] == '\n') buf[strlen (buf) - 1] = '\0'; if (!buf[0]) @@ -858,7 +900,7 @@ void do_modify_inode(int argc, char *argv[]) const char *octal_format = "0%o"; const char *decimal_format = "%d"; const char *unsignedlong_format = "%lu"; - + if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW)) return; @@ -866,7 +908,7 @@ void do_modify_inode(int argc, char *argv[]) if (debugfs_read_inode(inode_num, &inode, argv[1])) return; - + modify_u16(argv[0], "Mode", octal_format, &inode.i_mode); modify_u16(argv[0], "User ID", decimal_format, &inode.i_uid); modify_u16(argv[0], "Group ID", decimal_format, &inode.i_gid); @@ -877,7 +919,7 @@ void do_modify_inode(int argc, char *argv[]) modify_u32(argv[0], "Deletion time", decimal_format, &inode.i_dtime); modify_u16(argv[0], "Link count", decimal_format, &inode.i_links_count); if (os == EXT2_OS_LINUX) - modify_u16(argv[0], "Block count high", unsignedlong_format, + modify_u16(argv[0], "Block count high", unsignedlong_format, &inode.osd2.linux2.l_i_blocks_hi); modify_u32(argv[0], "Block count", unsignedlong_format, &inode.i_blocks); modify_u32(argv[0], "File flags", hex_format, &inode.i_flags); @@ -894,17 +936,13 @@ void do_modify_inode(int argc, char *argv[]) if (os == EXT2_OS_HURD) modify_u32(argv[0], "Translator Block", decimal_format, &inode.osd1.hurd1.h_i_translator); - + modify_u32(argv[0], "Fragment address", decimal_format, &inode.i_faddr); switch (os) { case EXT2_OS_HURD: frag = &inode.osd2.hurd2.h_i_frag; fsize = &inode.osd2.hurd2.h_i_fsize; break; - case EXT2_OS_MASIX: - frag = &inode.osd2.masix2.m_i_frag; - fsize = &inode.osd2.masix2.m_i_fsize; - break; default: frag = fsize = 0; } @@ -918,7 +956,7 @@ void do_modify_inode(int argc, char *argv[]) modify_u32(argv[0], buf, decimal_format, &inode.i_block[i]); } modify_u32(argv[0], "Indirect Block", decimal_format, - &inode.i_block[EXT2_IND_BLOCK]); + &inode.i_block[EXT2_IND_BLOCK]); modify_u32(argv[0], "Double Indirect Block", decimal_format, &inode.i_block[EXT2_DIND_BLOCK]); modify_u32(argv[0], "Triple Indirect Block", decimal_format, @@ -931,7 +969,7 @@ void do_change_working_dir(int argc, char *argv[]) { ext2_ino_t inode; int retval; - + if (common_inode_args_process(argc, argv, &inode, 0)) return; @@ -948,7 +986,7 @@ void do_print_working_directory(int argc, char *argv[]) { int retval; char *pathname = NULL; - + if (common_args_process(argc, argv, 1, 1, "print_working_directory", "", 0)) return; @@ -988,22 +1026,22 @@ static int ext2_file_type(unsigned int mode) if (LINUX_S_ISDIR(mode)) return EXT2_FT_DIR; - + if (LINUX_S_ISCHR(mode)) return EXT2_FT_CHRDEV; - + if (LINUX_S_ISBLK(mode)) return EXT2_FT_BLKDEV; - + if (LINUX_S_ISLNK(mode)) return EXT2_FT_SYMLINK; if (LINUX_S_ISFIFO(mode)) return EXT2_FT_FIFO; - + if (LINUX_S_ISSOCK(mode)) return EXT2_FT_SOCK; - + return 0; } @@ -1013,7 +1051,7 @@ static void make_link(char *sourcename, char *destname) struct ext2_inode inode; int retval; ext2_ino_t dir; - char *dest, *cp, *basename; + char *dest, *cp, *base_name; /* * Get the source inode @@ -1021,17 +1059,17 @@ static void make_link(char *sourcename, char *destname) ino = string_to_inode(sourcename); if (!ino) return; - basename = strrchr(sourcename, '/'); - if (basename) - basename++; + base_name = strrchr(sourcename, '/'); + if (base_name) + base_name++; else - basename = sourcename; + base_name = sourcename; /* * Figure out the destination. First see if it exists and is - * a directory. + * a directory. */ if (! (retval=ext2fs_namei(current_fs, root, cwd, destname, &dir))) - dest = basename; + dest = base_name; else { /* * OK, it doesn't exist. See if it is @@ -1052,8 +1090,8 @@ static void make_link(char *sourcename, char *destname) if (debugfs_read_inode(ino, &inode, sourcename)) return; - - retval = ext2fs_link(current_fs, dir, dest, ino, + + retval = ext2fs_link(current_fs, dir, dest, ino, ext2_file_type(inode.i_mode)); if (retval) com_err("make_link", retval, 0); @@ -1071,7 +1109,7 @@ void do_link(int argc, char *argv[]) } static int mark_blocks_proc(ext2_filsys fs, blk_t *blocknr, - int blockcnt EXT2FS_ATTR((unused)), + int blockcnt EXT2FS_ATTR((unused)), void *private EXT2FS_ATTR((unused))) { blk_t block; @@ -1105,7 +1143,7 @@ void do_undel(int argc, char *argv[]) /* * XXX this function doesn't handle changing the links count on the - * parent directory when undeleting a directory. + * parent directory when undeleting a directory. */ inode.i_links_count = LINUX_S_ISDIR(inode.i_mode) ? 2 : 1; inode.i_dtime = 0; @@ -1113,7 +1151,7 @@ void do_undel(int argc, char *argv[]) if (debugfs_write_inode(ino, &inode, argv[0])) return; - ext2fs_block_iterate(current_fs, ino, 0, NULL, + ext2fs_block_iterate(current_fs, ino, BLOCK_FLAG_READ_ONLY, NULL, mark_blocks_proc, NULL); ext2fs_inode_alloc_stats2(current_fs, ino, +1, 0); @@ -1126,19 +1164,19 @@ static void unlink_file_by_name(char *filename) { int retval; ext2_ino_t dir; - char *basename; - - basename = strrchr(filename, '/'); - if (basename) { - *basename++ = '\0'; + char *base_name; + + base_name = strrchr(filename, '/'); + if (base_name) { + *base_name++ = '\0'; dir = string_to_inode(filename); if (!dir) return; } else { dir = cwd; - basename = filename; + base_name = filename; } - retval = ext2fs_unlink(current_fs, dir, basename, 0, 0); + retval = ext2fs_unlink(current_fs, dir, base_name, 0, 0); if (retval) com_err("unlink_file_by_name", retval, 0); return; @@ -1159,7 +1197,7 @@ void do_find_free_block(int argc, char *argv[]) int count; errcode_t retval; char *tmp; - + if ((argc > 3) || (argc==2 && *argv[1] == '?')) { com_err(argv[0], 0, "Usage: find_free_block [count [goal]]"); return; @@ -1187,7 +1225,7 @@ void do_find_free_block(int argc, char *argv[]) goal = current_fs->super->s_first_data_block; printf("Free blocks found: "); - free_blk = goal - 1; + free_blk = goal - 1; while (count-- > 0) { retval = ext2fs_new_block(current_fs, free_blk + 1, 0, &free_blk); @@ -1211,7 +1249,7 @@ void do_find_free_inode(int argc, char *argv[]) int mode; int retval; char *tmp; - + if (argc > 3 || (argc>1 && *argv[1] == '?')) { com_err(argv[0], 0, "Usage: find_free_inode [dir] [mode]"); return; @@ -1329,6 +1367,7 @@ void do_write(int argc, char *argv[]) retval = ext2fs_expand_dir(current_fs, cwd); if (retval) { com_err(argv[0], retval, "while expanding directory"); + close(fd); return; } retval = ext2fs_link(current_fs, cwd, argv[2], newfile, @@ -1344,10 +1383,13 @@ void do_write(int argc, char *argv[]) ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); memset(&inode, 0, sizeof(inode)); inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; - inode.i_atime = inode.i_ctime = inode.i_mtime = + inode.i_atime = inode.i_ctime = inode.i_mtime = current_fs->now ? current_fs->now : time(0); inode.i_links_count = 1; inode.i_size = statbuf.st_size; + if (current_fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_EXTENTS) + inode.i_flags |= EXT4_EXTENTS_FL; if (debugfs_write_new_inode(newfile, &inode, argv[0])) { close(fd); return; @@ -1432,7 +1474,7 @@ void do_mknod(int argc, char *argv[]) ext2fs_mark_ib_dirty(current_fs); memset(&inode, 0, sizeof(inode)); inode.i_mode = mode; - inode.i_atime = inode.i_ctime = inode.i_mtime = + inode.i_atime = inode.i_ctime = inode.i_mtime = current_fs->now ? current_fs->now : time(0); if ((major < 256) && (minor < 256)) { inode.i_block[0] = major*256+minor; @@ -1476,7 +1518,7 @@ try_again: if (retval == EXT2_ET_DIR_NO_SPACE) { retval = ext2fs_expand_dir(current_fs, parent); if (retval) { - com_err("argv[0]", retval, "while expanding directory"); + com_err(argv[0], retval, "while expanding directory"); return; } goto try_again; @@ -1489,7 +1531,7 @@ try_again: } static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr, - int blockcnt EXT2FS_ATTR((unused)), + int blockcnt EXT2FS_ATTR((unused)), void *private EXT2FS_ATTR((unused))) { blk_t block; @@ -1511,7 +1553,7 @@ static void kill_file_by_inode(ext2_ino_t inode) if (!ext2fs_inode_has_valid_blocks(&inode_buf)) return; - ext2fs_block_iterate(current_fs, inode, 0, NULL, + ext2fs_block_iterate(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL, release_blocks_proc, NULL); printf("\n"); ext2fs_inode_alloc_stats2(current_fs, inode, -1, @@ -1589,7 +1631,7 @@ static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), rds->empty = 0; return 0; } - + void do_rmdir(int argc, char *argv[]) { int retval; @@ -1646,7 +1688,7 @@ void do_rmdir(int argc, char *argv[]) } } -void do_show_debugfs_params(int argc EXT2FS_ATTR((unused)), +void do_show_debugfs_params(int argc EXT2FS_ATTR((unused)), char *argv[] EXT2FS_ATTR((unused))) { FILE *out = stdout; @@ -1675,7 +1717,7 @@ void do_expand_dir(int argc, char *argv[]) void do_features(int argc, char *argv[]) { int i; - + if (check_fs_open(argv[0])) return; @@ -1698,7 +1740,7 @@ void do_bmap(int argc, char *argv[]) blk_t blk, pblk; int err; errcode_t errcode; - + if (common_args_process(argc, argv, 3, 3, argv[0], " logical_blk", 0)) return; @@ -1738,7 +1780,7 @@ void do_imap(int argc, char *argv[]) group); return; } - block_nr = current_fs->group_desc[(unsigned)group].bg_inode_table + + block_nr = current_fs->group_desc[(unsigned)group].bg_inode_table + block; offset &= (EXT2_BLOCK_SIZE(current_fs->super) - 1); @@ -1768,6 +1810,71 @@ void do_set_current_time(int argc, char *argv[]) } } +static int find_supp_feature(__u32 *supp, int feature_type, char *name) +{ + int compat, bit, ret; + unsigned int feature_mask; + + if (name) { + if (feature_type == E2P_FS_FEATURE) + ret = e2p_string2feature(name, &compat, &feature_mask); + else + ret = e2p_jrnl_string2feature(name, &compat, + &feature_mask); + if (ret) + return ret; + + if (!(supp[compat] & feature_mask)) + return 1; + } else { + for (compat = 0; compat < 3; compat++) { + for (bit = 0, feature_mask = 1; bit < 32; + bit++, feature_mask <<= 1) { + if (supp[compat] & feature_mask) { + if (feature_type == E2P_FS_FEATURE) + fprintf(stdout, " %s", + e2p_feature2string(compat, + feature_mask)); + else + fprintf(stdout, " %s", + e2p_jrnl_feature2string(compat, + feature_mask)); + } + } + } + fprintf(stdout, "\n"); + } + + return 0; +} + +void do_supported_features(int argc, char *argv[]) +{ + int i, j, ret; + __u32 supp[3] = { EXT2_LIB_FEATURE_COMPAT_SUPP, + EXT2_LIB_FEATURE_INCOMPAT_SUPP, + EXT2_LIB_FEATURE_RO_COMPAT_SUPP }; + __u32 jrnl_supp[3] = { JFS_KNOWN_COMPAT_FEATURES, + JFS_KNOWN_INCOMPAT_FEATURES, + JFS_KNOWN_ROCOMPAT_FEATURES }; + + if (argc > 1) { + ret = find_supp_feature(supp, E2P_FS_FEATURE, argv[1]); + if (ret) { + ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE, + argv[1]); + } + if (ret) + com_err(argv[0], 0, "Unknown feature: %s\n", argv[1]); + else + fprintf(stdout, "Supported feature: %s\n", argv[1]); + } else { + fprintf(stdout, "Supported features:"); + ret = find_supp_feature(supp, E2P_FS_FEATURE, NULL); + ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE, NULL); + } +} + static int source_file(const char *cmd_file, int sci_idx) { FILE *f; @@ -1785,6 +1892,8 @@ static int source_file(const char *cmd_file, int sci_idx) exit(1); } } + fflush(stdout); + fflush(stderr); setbuf(stdout, NULL); setbuf(stderr, NULL); while (!feof(f)) { @@ -1810,7 +1919,7 @@ int main(int argc, char **argv) { int retval; int sci_idx; - const char *usage = "Usage: debugfs [-b blocksize] [-s superblock] [-f cmd_file] [-R request] [-V] [[-w] [-c] device]"; + const char *usage = "Usage: %s [-b blocksize] [-s superblock] [-f cmd_file] [-R request] [-V] [[-w] [-c] device]"; int c; int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES; char *request = 0; @@ -1820,10 +1929,13 @@ int main(int argc, char **argv) blk_t blocksize = 0; int catastrophic = 0; char *data_filename = 0; - + + if (debug_prog_name == 0) + debug_prog_name = "debugfs"; + add_error_table(&et_ext2_error_table); - fprintf (stderr, "debugfs %s (%s)\n", E2FSPROGS_VERSION, - E2FSPROGS_DATE); + fprintf (stderr, "%s %s (%s)\n", debug_prog_name, + E2FSPROGS_VERSION, E2FSPROGS_DATE); while ((c = getopt (argc, argv, "iwcR:f:b:s:Vd:")) != EOF) { switch (c) { @@ -1843,11 +1955,11 @@ int main(int argc, char **argv) open_flags |= EXT2_FLAG_RW; break; case 'b': - blocksize = parse_ulong(optarg, argv[0], + blocksize = parse_ulong(optarg, argv[0], "block size", 0); break; case 's': - superblock = parse_ulong(optarg, argv[0], + superblock = parse_ulong(optarg, argv[0], "superblock number", 0); break; case 'c': @@ -1859,7 +1971,7 @@ int main(int argc, char **argv) error_message(EXT2_ET_BASE)); exit(0); default: - com_err(argv[0], 0, usage); + com_err(argv[0], 0, usage, debug_prog_name); return 1; } } @@ -1867,8 +1979,8 @@ int main(int argc, char **argv) open_filesystem(argv[optind], open_flags, superblock, blocksize, catastrophic, data_filename); - - sci_idx = ss_create_invocation("debugfs", "0.0", (char *) NULL, + + sci_idx = ss_create_invocation(debug_prog_name, "0.0", (char *) NULL, &debug_cmds, &retval); if (retval) { ss_perror(sci_idx, retval, "creating invocation"); @@ -1881,6 +1993,12 @@ int main(int argc, char **argv) ss_perror(sci_idx, retval, "adding standard requests"); exit (1); } + if (extra_cmds) + ss_add_request_table (sci_idx, extra_cmds, 1, &retval); + if (retval) { + ss_perror(sci_idx, retval, "adding extra requests"); + exit (1); + } if (request) { retval = 0; retval = ss_execute_line(sci_idx, request); @@ -1896,7 +2014,7 @@ int main(int argc, char **argv) if (current_fs) close_filesystem(); - + remove_error_table(&et_ext2_error_table); return exit_status; }