X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=debugfs%2Fdebugfs.c;h=9b6321dc4262aba21ecf7efe17e8f1291fbe336b;hb=74571d9430da149fa46a0f7ef171920ebe9a7b8c;hp=db85028f472f3ab8841720228dae81c4cba5628d;hpb=c8b20b40ebf0278b2d100a964a32d8e13046f437;p=tools%2Fe2fsprogs.git diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index db85028..9b6321d 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef HAVE_GETOPT_H #include #else @@ -25,6 +26,9 @@ extern char *optarg; #include #endif #include +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif #include "debugfs.h" #include "uuid/uuid.h" @@ -34,26 +38,113 @@ extern char *optarg; #include "../version.h" #include "jfs_user.h" -#include "../misc/plausible.h" +#include "support/plausible.h" #ifndef BUFSIZ #define BUFSIZ 8192 #endif +#ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */ +int journal_enable_debug = -1; +#endif + +/* + * There must be only one definition if we're hooking in extra commands or + * changing default prompt. Use -DSKIP_GLOBDEF for that. + */ +#ifndef SKIP_GLOBDEFS ss_request_table *extra_cmds; const char *debug_prog_name; -int sci_idx; +#endif +int ss_sci_idx; ext2_filsys current_fs; quota_ctx_t current_qctx; ext2_ino_t root, cwd; +int no_copy_xattrs; + +static int debugfs_setup_tdb(const char *device_name, char *undo_file, + io_manager *io_ptr) +{ + errcode_t retval = ENOMEM; + const char *tdb_dir = NULL; + char *tdb_file = NULL; + char *dev_name, *tmp_name; + + /* (re)open a specific undo file */ + if (undo_file && undo_file[0] != 0) { + retval = set_undo_io_backing_manager(*io_ptr); + if (retval) + goto err; + *io_ptr = undo_io_manager; + retval = set_undo_io_backup_file(undo_file); + if (retval) + goto err; + printf("Overwriting existing filesystem; this can be undone " + "using the command:\n" + " e2undo %s %s\n\n", + undo_file, device_name); + return retval; + } + + /* + * Configuration via a conf file would be + * nice + */ + tdb_dir = ss_safe_getenv("E2FSPROGS_UNDO_DIR"); + if (!tdb_dir) + tdb_dir = "/var/lib/e2fsprogs"; + + if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) || + access(tdb_dir, W_OK)) + return 0; + + tmp_name = strdup(device_name); + if (!tmp_name) + goto errout; + dev_name = basename(tmp_name); + tdb_file = malloc(strlen(tdb_dir) + 9 + strlen(dev_name) + 7 + 1); + if (!tdb_file) { + free(tmp_name); + goto errout; + } + sprintf(tdb_file, "%s/debugfs-%s.e2undo", tdb_dir, dev_name); + free(tmp_name); + + if ((unlink(tdb_file) < 0) && (errno != ENOENT)) { + retval = errno; + com_err("debugfs", retval, + "while trying to delete %s", tdb_file); + goto errout; + } + + retval = set_undo_io_backing_manager(*io_ptr); + if (retval) + goto errout; + *io_ptr = undo_io_manager; + retval = set_undo_io_backup_file(tdb_file); + if (retval) + goto errout; + printf("Overwriting existing filesystem; this can be undone " + "using the command:\n" + " e2undo %s %s\n\n", tdb_file, device_name); + + free(tdb_file); + return 0; +errout: + free(tdb_file); +err: + com_err("debugfs", retval, "while trying to setup undo file\n"); + return retval; +} static void open_filesystem(char *device, int open_flags, blk64_t superblock, blk64_t blocksize, int catastrophic, - char *data_filename) + char *data_filename, char *undo_file) { int retval; io_channel data_io = 0; + io_manager io_ptr = unix_io_manager; if (superblock != 0 && blocksize == 0) { com_err(device, 0, "if you specify the superblock, you must also specify the block size"); @@ -76,18 +167,27 @@ static void open_filesystem(char *device, int open_flags, blk64_t superblock, } } - if (catastrophic && (open_flags & EXT2_FLAG_RW)) { - com_err(device, 0, - "opening read-only because of catastrophic mode"); - open_flags &= ~EXT2_FLAG_RW; - } if (catastrophic) - open_flags |= EXT2_FLAG_SKIP_MMP; + open_flags |= EXT2_FLAG_SKIP_MMP | EXT2_FLAG_IGNORE_SB_ERRORS; + if (undo_file) { + retval = debugfs_setup_tdb(device, undo_file, &io_ptr); + if (retval) + exit(1); + } + +try_open_again: retval = ext2fs_open(device, open_flags, superblock, blocksize, - unix_io_manager, ¤t_fs); + io_ptr, ¤t_fs); + if (retval && (retval == EXT2_ET_SB_CSUM_INVALID) && + !(open_flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)) { + open_flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS; + printf("Checksum errors in superblock! Retrying...\n"); + goto try_open_again; + } if (retval) { - com_err(device, retval, "while opening filesystem"); + com_err(debug_prog_name, retval, + "while trying to open %s", device); if (retval == EXT2_ET_BAD_MAGIC) check_plausibility(device, CHECK_FS_EXIST, NULL); current_fs = NULL; @@ -95,17 +195,11 @@ static void open_filesystem(char *device, int open_flags, blk64_t superblock, } current_fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; - if (catastrophic) - com_err(device, 0, "catastrophic mode - not reading inode or group bitmaps"); - else { - retval = ext2fs_read_inode_bitmap(current_fs); - if (retval) { - com_err(device, retval, "while reading inode bitmap"); - goto errout; - } - retval = ext2fs_read_block_bitmap(current_fs); + if (!catastrophic) { + retval = ext2fs_read_bitmaps(current_fs); if (retval) { - com_err(device, retval, "while reading block bitmap"); + com_err(device, retval, + "while reading allocation bitmaps"); goto errout; } } @@ -128,17 +222,20 @@ errout: com_err(device, retval, "while trying to close filesystem"); } -void do_open_filesys(int argc, char **argv) +void do_open_filesys(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { int c, err; int catastrophic = 0; blk64_t superblock = 0; blk64_t blocksize = 0; - int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS; + int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS | + EXT2_FLAG_THREADS; char *data_filename = 0; + char *undo_file = NULL; reset_getopt(); - while ((c = getopt (argc, argv, "iwfecb:s:d:D")) != EOF) { + while ((c = getopt(argc, argv, "iwfecb:s:d:Dz:")) != EOF) { switch (c) { case 'i': open_flags |= EXT2_FLAG_IMAGE_FILE; @@ -177,6 +274,13 @@ void do_open_filesys(int argc, char **argv) if (err) return; break; + case 'z': +#ifdef READ_ONLY + goto print_usage; +#else + undo_file = optarg; +#endif + break; default: goto print_usage; } @@ -188,19 +292,21 @@ void do_open_filesys(int argc, char **argv) return; open_filesystem(argv[optind], open_flags, superblock, blocksize, catastrophic, - data_filename); + data_filename, undo_file); return; print_usage: fprintf(stderr, "%s: Usage: open [-s superblock] [-b blocksize] " - "[-d image_filename] [-c] [-i] [-f] [-e] [-D] " -#ifndef READ_ONLY - "[-w] " +#ifdef READ_ONLY + "[-d image_filename] [-z undo_file] [-c] [-i] [-f] [-e] [-D] " +#else + "[-d image_filename] [-c] [-i] [-f] [-e] [-D] [-w] " #endif "\n", argv[0]); } -void do_lcd(int argc, char **argv) +void do_lcd(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { if (argc != 2) { com_err(argv[0], 0, "Usage: %s %s", argv[0], ""); @@ -237,7 +343,8 @@ static void close_filesystem(NOARGS) return; } -void do_close_filesys(int argc, char **argv) +void do_close_filesys(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { int c; @@ -265,7 +372,8 @@ void do_close_filesys(int argc, char **argv) } #ifndef READ_ONLY -void do_init_filesys(int argc, char **argv) +void do_init_filesys(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { struct ext2_super_block param; errcode_t retval; @@ -325,7 +433,9 @@ static void print_bg_opts(ext2_filsys fs, dgrp_t group, int mask, } } -void do_show_super_stats(int argc, char *argv[]) +void do_show_super_stats(int argc, char *argv[], + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { const char *units ="block"; dgrp_t i; @@ -350,14 +460,24 @@ void do_show_super_stats(int argc, char *argv[]) return; out = open_pager(); - if (EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super, - EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + if (ext2fs_has_feature_bigalloc(current_fs->super)) units = "cluster"; list_super2(current_fs->super, out); + if (ext2fs_has_feature_metadata_csum(current_fs->super) && + !ext2fs_superblock_csum_verify(current_fs, + current_fs->super)) { + __u32 orig_csum = current_fs->super->s_checksum; + + ext2fs_superblock_csum_set(current_fs, + current_fs->super); + fprintf(out, "Expected Checksum: 0x%08x\n", + current_fs->super->s_checksum); + current_fs->super->s_checksum = orig_csum; + } for (i=0; i < current_fs->group_desc_count; i++) numdirs += ext2fs_bg_used_dirs_count(current_fs, i); - fprintf(out, "Directories: %d\n", numdirs); + fprintf(out, "Directories: %u\n", numdirs); if (header_only) { close_pager(out); @@ -371,11 +491,12 @@ void do_show_super_stats(int argc, char *argv[]) "inode table at %llu\n" " %u free %s%s, " "%u free %s, " - "%u used %s%s", - i, ext2fs_block_bitmap_loc(current_fs, i), - ext2fs_inode_bitmap_loc(current_fs, i), - ext2fs_inode_table_loc(current_fs, i), - ext2fs_bg_free_blocks_count(current_fs, i), units, + "%u used %s%s", i, + (unsigned long long) ext2fs_block_bitmap_loc(current_fs, i), + (unsigned long long) ext2fs_inode_bitmap_loc(current_fs, i), + (unsigned long long) ext2fs_inode_table_loc(current_fs, i), + ext2fs_bg_free_blocks_count(current_fs, i), + units, ext2fs_bg_free_blocks_count(current_fs, i) != 1 ? "s" : "", ext2fs_bg_free_inodes_count(current_fs, i), @@ -405,12 +526,14 @@ void do_show_super_stats(int argc, char *argv[]) close_pager(out); return; print_usage: - fprintf(stderr, "%s: Usage: show_super [-h]\n", argv[0]); + fprintf(stderr, "%s: Usage: show_super_stats [-h]\n", argv[0]); } #ifndef READ_ONLY void do_dirty_filesys(int argc EXT2FS_ATTR((unused)), - char **argv EXT2FS_ATTR((unused))) + char **argv EXT2FS_ATTR((unused)), + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { if (check_fs_open(argv[0])) return; @@ -443,11 +566,13 @@ static void finish_range(struct list_blocks_struct *lb) fprintf(lb->f, ", "); if (lb->first_block == lb->last_block) fprintf(lb->f, "(%lld):%llu", - (long long)lb->first_bcnt, lb->first_block); + (long long)lb->first_bcnt, + (unsigned long long) lb->first_block); else fprintf(lb->f, "(%lld-%lld):%llu-%llu", (long long)lb->first_bcnt, (long long)lb->last_bcnt, - lb->first_block, lb->last_block); + (unsigned long long) lb->first_block, + (unsigned long long) lb->last_block); lb->first_block = 0; } @@ -597,18 +722,18 @@ static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino, info.curr_level, info.max_depth, info.curr_entry, info.num_entries, logical_width, - extent.e_lblk, + (unsigned long long) extent.e_lblk, logical_width, - extent.e_lblk + (extent.e_len - 1), + (unsigned long long) extent.e_lblk + (extent.e_len - 1), physical_width, - extent.e_pblk, + (unsigned long long) extent.e_pblk, physical_width+3, "", extent.e_len); continue; } - fprintf(f, "%s(ETB%d):%lld", + fprintf(f, "%s(ETB%d):%llu", printed ? ", " : "", info.curr_level, - extent.e_pblk); + (unsigned long long) extent.e_pblk); printed = 1; continue; } @@ -619,13 +744,13 @@ static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino, info.curr_level, info.max_depth, info.curr_entry, info.num_entries, logical_width, - extent.e_lblk, + (unsigned long long) extent.e_lblk, logical_width, - extent.e_lblk + (extent.e_len - 1), + (unsigned long long) extent.e_lblk + (extent.e_len - 1), physical_width, - extent.e_pblk, + (unsigned long long) extent.e_pblk, physical_width, - extent.e_pblk + (extent.e_len - 1), + (unsigned long long) extent.e_pblk + (extent.e_len - 1), extent.e_len, extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? "Uninit" : ""); @@ -638,20 +763,20 @@ static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino, fprintf(f, "%s(%lld%s):%lld", printed ? ", " : "", - extent.e_lblk, + (unsigned long long) extent.e_lblk, extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? "[u]" : "", - extent.e_pblk); + (unsigned long long) extent.e_pblk); else fprintf(f, "%s(%lld-%lld%s):%lld-%lld", printed ? ", " : "", - extent.e_lblk, - extent.e_lblk + (extent.e_len - 1), + (unsigned long long) extent.e_lblk, + (unsigned long long) extent.e_lblk + (extent.e_len - 1), extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? "[u]" : "", - extent.e_pblk, - extent.e_pblk + (extent.e_len - 1)); + (unsigned long long) extent.e_pblk, + (unsigned long long) extent.e_pblk + (extent.e_len - 1)); printed = 1; } if (printed) @@ -669,41 +794,31 @@ static void dump_inline_data(FILE *out, const char *prefix, ext2_ino_t inode_num fprintf(out, "%sSize of inline data: %zu\n", prefix, size); } -static void dump_fast_link(FILE *out, ext2_ino_t inode_num, - struct ext2_inode *inode, const char *prefix) +static void dump_inline_symlink(FILE *out, ext2_ino_t inode_num, + struct ext2_inode *inode, const char *prefix) { - errcode_t retval = 0; - char *buf; + errcode_t retval; + char *buf = NULL; size_t size; - if (inode->i_flags & EXT4_INLINE_DATA_FL) { - retval = ext2fs_inline_data_size(current_fs, inode_num, &size); - if (retval) - goto out; - - retval = ext2fs_get_memzero(size + 1, &buf); - if (retval) - goto out; + retval = ext2fs_inline_data_size(current_fs, inode_num, &size); + if (retval) + goto out; - retval = ext2fs_inline_data_get(current_fs, inode_num, - inode, buf, &size); - if (retval) - goto out; - fprintf(out, "%sFast link dest: \"%.*s\"\n", prefix, - (int)size, buf); + retval = ext2fs_get_memzero(size + 1, &buf); + if (retval) + goto out; - retval = ext2fs_free_mem(&buf); - if (retval) - goto out; - } else { - int sz = EXT2_I_SIZE(inode); + retval = ext2fs_inline_data_get(current_fs, inode_num, + inode, buf, &size); + if (retval) + goto out; - if (sz > sizeof(inode->i_block)) - sz = sizeof(inode->i_block); - fprintf(out, "%sFast link dest: \"%.*s\"\n", prefix, sz, - (char *)inode->i_block); - } + fprintf(out, "%sFast link dest: \"%.*s\"\n", prefix, + (int)size, buf); out: + if (buf) + ext2fs_free_mem(&buf); if (retval) com_err(__func__, retval, "while dumping link destination"); } @@ -731,8 +846,8 @@ 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\n", - prefix, inode->i_mode & 0777, inode->i_flags); + fprintf(out, "%sMode: 0%03o Flags: 0x%x\n", + prefix, inode->i_mode & 07777, 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, @@ -741,32 +856,34 @@ void internal_dump_inode(FILE *out, const char *prefix, 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: ", + fprintf(out, "%sUser: %5d Group: %5d", prefix, inode_uid(*inode), inode_gid(*inode)); - if (LINUX_S_ISREG(inode->i_mode)) - fprintf(out, "%llu\n", EXT2_I_SIZE(inode)); + if (is_large_inode && large_inode->i_extra_isize >= 32) + fprintf(out, " Project: %5d", large_inode->i_projid); + fputs(" Size: ", out); + if (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode)) + fprintf(out, "%llu\n", (unsigned long long) EXT2_I_SIZE(inode)); else - fprintf(out, "%d\n", inode->i_size); + fprintf(out, "%u\n", inode->i_size); if (os == EXT2_OS_HURD) fprintf(out, - "%sFile ACL: %d Directory ACL: %d Translator: %d\n", + "%sFile ACL: %u Translator: %u\n", prefix, - inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0, + inode->i_file_acl, inode->osd1.hurd1.h_i_translator); else - fprintf(out, "%sFile ACL: %llu Directory ACL: %d\n", + fprintf(out, "%sFile ACL: %llu\n", prefix, inode->i_file_acl | ((long long) - (inode->osd2.linux2.l_i_file_acl_high) << 32), - LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0); - if (os == EXT2_OS_LINUX) - fprintf(out, "%sLinks: %d Blockcount: %llu\n", + (inode->osd2.linux2.l_i_file_acl_high) << 32)); + if (os != EXT2_OS_HURD) + fprintf(out, "%sLinks: %u Blockcount: %llu\n", 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", + fprintf(out, "%sLinks: %u Blockcount: %u\n", prefix, inode->i_links_count, inode->i_blocks); switch (os) { case EXT2_OS_HURD: @@ -776,39 +893,47 @@ void internal_dump_inode(FILE *out, const char *prefix, default: frag = fsize = 0; } - fprintf(out, "%sFragment: Address: %d Number: %d Size: %d\n", + fprintf(out, "%sFragment: Address: %u Number: %u Size: %u\n", prefix, inode->i_faddr, frag, fsize); 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)); + inode_time_to_string(inode->i_ctime, + large_inode->i_ctime_extra)); fprintf(out, "%s atime: 0x%08x:%08x -- %s", prefix, inode->i_atime, large_inode->i_atime_extra, - time_to_string(inode->i_atime)); + inode_time_to_string(inode->i_atime, + large_inode->i_atime_extra)); fprintf(out, "%s mtime: 0x%08x:%08x -- %s", prefix, inode->i_mtime, large_inode->i_mtime_extra, - time_to_string(inode->i_mtime)); + inode_time_to_string(inode->i_mtime, + large_inode->i_mtime_extra)); fprintf(out, "%scrtime: 0x%08x:%08x -- %s", prefix, large_inode->i_crtime, large_inode->i_crtime_extra, - time_to_string(large_inode->i_crtime)); + inode_time_to_string(large_inode->i_crtime, + large_inode->i_crtime_extra)); + if (inode->i_dtime) + fprintf(out, "%s dtime: 0x%08x:(%08x) -- %s", prefix, + large_inode->i_dtime, large_inode->i_ctime_extra, + inode_time_to_string(inode->i_dtime, + large_inode->i_ctime_extra)); } else { fprintf(out, "%sctime: 0x%08x -- %s", prefix, inode->i_ctime, - time_to_string(inode->i_ctime)); + time_to_string((__s32) inode->i_ctime)); fprintf(out, "%satime: 0x%08x -- %s", prefix, inode->i_atime, - time_to_string(inode->i_atime)); + time_to_string((__s32) inode->i_atime)); fprintf(out, "%smtime: 0x%08x -- %s", prefix, inode->i_mtime, - time_to_string(inode->i_mtime)); + time_to_string((__s32) inode->i_mtime)); + if (inode->i_dtime) + fprintf(out, "%sdtime: 0x%08x -- %s", prefix, + inode->i_dtime, + time_to_string((__s32) inode->i_dtime)); } - 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) internal_dump_inode_extra(out, prefix, inode_num, (struct ext2_inode_large *) inode); dump_inode_attributes(out, inode_num); - if (current_fs->super->s_creator_os == EXT2_OS_LINUX && - current_fs->super->s_feature_ro_compat & - EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) { + if (ext2fs_has_feature_metadata_csum(current_fs->super)) { __u32 crc = inode->i_checksum_lo; if (is_large_inode && large_inode->i_extra_isize >= @@ -819,9 +944,12 @@ void internal_dump_inode(FILE *out, const char *prefix, fprintf(out, "Inode checksum: 0x%08x\n", crc); } - if (LINUX_S_ISLNK(inode->i_mode) && - ext2fs_inode_data_blocks(current_fs, inode) == 0) - dump_fast_link(out, inode_num, inode, prefix); + if (LINUX_S_ISLNK(inode->i_mode) && ext2fs_is_fast_symlink(inode)) + fprintf(out, "%sFast link dest: \"%.*s\"\n", prefix, + (int)EXT2_I_SIZE(inode), (char *)inode->i_block); + else if (LINUX_S_ISLNK(inode->i_mode) && + (inode->i_flags & EXT4_INLINE_DATA_FL)) + dump_inline_symlink(out, inode_num, inode, prefix); else if (LINUX_S_ISBLK(inode->i_mode) || LINUX_S_ISCHR(inode->i_mode)) { int major, minor; const char *devnote; @@ -858,7 +986,8 @@ static void dump_inode(ext2_ino_t inode_num, struct ext2_inode *inode) close_pager(out); } -void do_stat(int argc, char *argv[]) +void do_stat(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode; struct ext2_inode * inode_buf; @@ -878,8 +1007,8 @@ void do_stat(int argc, char *argv[]) return; } - if (debugfs_read_inode_full(inode, inode_buf, argv[0], - EXT2_INODE_SIZE(current_fs->super))) { + if (debugfs_read_inode2(inode, inode_buf, argv[0], + EXT2_INODE_SIZE(current_fs->super), 0)) { free(inode_buf); return; } @@ -889,7 +1018,8 @@ void do_stat(int argc, char *argv[]) return; } -void do_dump_extents(int argc, char **argv) +void do_dump_extents(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { struct ext2_inode inode; ext2_ino_t ino; @@ -956,11 +1086,12 @@ static int print_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)), int ref_offset EXT2FS_ATTR((unused)), void *private EXT2FS_ATTR((unused))) { - printf("%llu ", *blocknr); + printf("%llu ", (unsigned long long) *blocknr); return 0; } -void do_blocks(int argc, char *argv[]) +void do_blocks(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode; @@ -977,7 +1108,8 @@ void do_blocks(int argc, char *argv[]) return; } -void do_chroot(int argc, char *argv[]) +void do_chroot(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode; int retval; @@ -994,7 +1126,8 @@ void do_chroot(int argc, char *argv[]) } #ifndef READ_ONLY -void do_clri(int argc, char *argv[]) +void do_clri(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode; struct ext2_inode inode_buf; @@ -1009,7 +1142,8 @@ void do_clri(int argc, char *argv[]) return; } -void do_freei(int argc, char *argv[]) +void do_freei(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { unsigned int len = 1; int err = 0; @@ -1039,7 +1173,8 @@ void do_freei(int argc, char *argv[]) ext2fs_mark_ib_dirty(current_fs); } -void do_seti(int argc, char *argv[]) +void do_seti(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { unsigned int len = 1; int err = 0; @@ -1070,7 +1205,8 @@ void do_seti(int argc, char *argv[]) } #endif /* READ_ONLY */ -void do_testi(int argc, char *argv[]) +void do_testi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode; @@ -1084,7 +1220,8 @@ void do_testi(int argc, char *argv[]) } #ifndef READ_ONLY -void do_freeb(int argc, char *argv[]) +void do_freeb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { blk64_t block; blk64_t count = 1; @@ -1096,14 +1233,15 @@ void do_freeb(int argc, char *argv[]) while (count-- > 0) { if (!ext2fs_test_block_bitmap2(current_fs->block_map,block)) com_err(argv[0], 0, "Warning: block %llu already clear", - block); + (unsigned long long) block); ext2fs_unmark_block_bitmap2(current_fs->block_map,block); block++; } ext2fs_mark_bb_dirty(current_fs); } -void do_setb(int argc, char *argv[]) +void do_setb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { blk64_t block; blk64_t count = 1; @@ -1115,7 +1253,7 @@ void do_setb(int argc, char *argv[]) while (count-- > 0) { if (ext2fs_test_block_bitmap2(current_fs->block_map,block)) com_err(argv[0], 0, "Warning: block %llu already set", - block); + (unsigned long long) block); ext2fs_mark_block_bitmap2(current_fs->block_map,block); block++; } @@ -1123,7 +1261,8 @@ void do_setb(int argc, char *argv[]) } #endif /* READ_ONLY */ -void do_testb(int argc, char *argv[]) +void do_testb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { blk64_t block; blk64_t count = 1; @@ -1132,9 +1271,11 @@ void do_testb(int argc, char *argv[]) return; while (count-- > 0) { if (ext2fs_test_block_bitmap2(current_fs->block_map,block)) - printf("Block %llu marked in use\n", block); + printf("Block %llu marked in use\n", + (unsigned long long) block); else - printf("Block %llu not in use\n", block); + printf("Block %llu not in use\n", + (unsigned long long) block); block++; } } @@ -1207,7 +1348,8 @@ static void modify_u32(char *com, const char *prompt, } -void do_modify_inode(int argc, char *argv[]) +void do_modify_inode(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { struct ext2_inode inode; ext2_ino_t inode_num; @@ -1247,10 +1389,9 @@ void do_modify_inode(int argc, char *argv[]) modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1); #endif modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl); - if (LINUX_S_ISDIR(inode.i_mode)) - modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl); - else - modify_u32(argv[0], "High 32bits of size", decimal_format, &inode.i_size_high); + + modify_u32(argv[0], "High 32bits of size", decimal_format, + &inode.i_size_high); if (os == EXT2_OS_HURD) modify_u32(argv[0], "Translator Block", @@ -1271,7 +1412,7 @@ void do_modify_inode(int argc, char *argv[]) modify_u8(argv[0], "Fragment size", decimal_format, fsize); for (i=0; i < EXT2_NDIR_BLOCKS; i++) { - sprintf(buf, "Direct Block #%d", i); + sprintf(buf, "Direct Block #%u", i); modify_u32(argv[0], buf, decimal_format, &inode.i_block[i]); } modify_u32(argv[0], "Indirect Block", decimal_format, @@ -1285,7 +1426,9 @@ void do_modify_inode(int argc, char *argv[]) } #endif /* READ_ONLY */ -void do_change_working_dir(int argc, char *argv[]) +void do_change_working_dir(int argc, char *argv[], + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode; int retval; @@ -1302,7 +1445,9 @@ void do_change_working_dir(int argc, char *argv[]) return; } -void do_print_working_directory(int argc, char *argv[]) +void do_print_working_directory(int argc, char *argv[], + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { int retval; char *pathname = NULL; @@ -1391,7 +1536,8 @@ static void make_link(char *sourcename, char *destname) } -void do_link(int argc, char *argv[]) +void do_link(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { if (common_args_process(argc, argv, 3, 3, "link", " ", CHECK_FS_RW)) @@ -1413,7 +1559,8 @@ static int mark_blocks_proc(ext2_filsys fs, blk64_t *blocknr, return 0; } -void do_undel(int argc, char *argv[]) +void do_undel(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t ino; struct ext2_inode inode; @@ -1476,7 +1623,8 @@ static void unlink_file_by_name(char *filename) return; } -void do_unlink(int argc, char *argv[]) +void do_unlink(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { if (common_args_process(argc, argv, 2, 2, "link", "", CHECK_FS_RW)) @@ -1484,9 +1632,39 @@ void do_unlink(int argc, char *argv[]) unlink_file_by_name(argv[1]); } + +void do_copy_inode(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) +{ + ext2_ino_t src_ino, dest_ino; + unsigned char buf[4096]; + + if (common_args_process(argc, argv, 3, 3, "copy_inode", + " ", CHECK_FS_RW)) + return; + + src_ino = string_to_inode(argv[1]); + if (!src_ino) + return; + + dest_ino = string_to_inode(argv[2]); + if (!dest_ino) + return; + + if (debugfs_read_inode2(src_ino, (struct ext2_inode *) buf, + argv[0], sizeof(buf), 0)) + return; + + if (debugfs_write_inode2(dest_ino, (struct ext2_inode *) buf, + argv[0], sizeof(buf), 0)) + return; +} + #endif /* READ_ONLY */ -void do_find_free_block(int argc, char *argv[]) +void do_find_free_block(int argc, char *argv[], + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { blk64_t free_blk, goal, first_free = 0; int count; @@ -1533,12 +1711,14 @@ void do_find_free_block(int argc, char *argv[]) com_err("ext2fs_new_block", retval, 0); return; } else - printf("%llu ", free_blk); + printf("%llu ", (unsigned long long) free_blk); } printf("\n"); } -void do_find_free_inode(int argc, char *argv[]) +void do_find_free_inode(int argc, char *argv[], + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t free_inode, dir; int mode; @@ -1546,7 +1726,7 @@ void do_find_free_inode(int argc, char *argv[]) char *tmp; if (argc > 3 || (argc>1 && *argv[1] == '?')) { - com_err(argv[0], 0, "Usage: find_free_inode [dir] [mode]"); + com_err(argv[0], 0, "Usage: find_free_inode [dir [mode]]"); return; } if (check_fs_open(argv[0])) @@ -1578,7 +1758,8 @@ void do_find_free_inode(int argc, char *argv[]) } #ifndef READ_ONLY -void do_write(int argc, char *argv[]) +void do_write(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { errcode_t retval; @@ -1591,7 +1772,8 @@ void do_write(int argc, char *argv[]) com_err(argv[0], retval, 0); } -void do_mknod(int argc, char *argv[]) +void do_mknod(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { unsigned long major, minor; errcode_t retval; @@ -1635,12 +1817,14 @@ void do_mknod(int argc, char *argv[]) goto usage; st.st_rdev = makedev(major, minor); - retval = do_mknod_internal(current_fs, cwd, argv[1], &st); + retval = do_mknod_internal(current_fs, cwd, argv[1], + st.st_mode, st.st_rdev); if (retval) com_err(argv[0], retval, 0); } -void do_mkdir(int argc, char *argv[]) +void do_mkdir(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { errcode_t retval; @@ -1648,7 +1832,7 @@ void do_mkdir(int argc, char *argv[]) "", CHECK_FS_RW)) return; - retval = do_mkdir_internal(current_fs, cwd, argv[1], NULL, root); + retval = do_mkdir_internal(current_fs, cwd, argv[1], root); if (retval) com_err(argv[0], retval, 0); @@ -1658,11 +1842,17 @@ static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), blk64_t ref_block EXT2FS_ATTR((unused)), int ref_offset EXT2FS_ATTR((unused)), - void *private EXT2FS_ATTR((unused))) + void *private) { - blk64_t block; + blk64_t block = *blocknr; + blk64_t *last_cluster = (blk64_t *)private; + blk64_t cluster = EXT2FS_B2C(fs, block); + + if (cluster == *last_cluster) + return 0; + + *last_cluster = cluster; - block = *blocknr; ext2fs_block_alloc_stats2(fs, block, -1); return 0; } @@ -1677,8 +1867,9 @@ static void kill_file_by_inode(ext2_ino_t inode) if (debugfs_write_inode(inode, &inode_buf, 0)) return; if (ext2fs_inode_has_valid_blocks2(current_fs, &inode_buf)) { + blk64_t last_cluster = 0; ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, - NULL, release_blocks_proc, NULL); + NULL, release_blocks_proc, &last_cluster); } printf("\n"); ext2fs_inode_alloc_stats2(current_fs, inode, -1, @@ -1686,7 +1877,8 @@ static void kill_file_by_inode(ext2_ino_t inode) } -void do_kill_file(int argc, char *argv[]) +void do_kill_file(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode_num; @@ -1696,7 +1888,8 @@ void do_kill_file(int argc, char *argv[]) kill_file_by_inode(inode_num); } -void do_rm(int argc, char *argv[]) +void do_rm(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { int retval; ext2_ino_t inode_num; @@ -1757,7 +1950,8 @@ static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), return 0; } -void do_rmdir(int argc, char *argv[]) +void do_rmdir(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { int retval; ext2_ino_t inode_num; @@ -1815,7 +2009,9 @@ void do_rmdir(int argc, char *argv[]) #endif /* READ_ONLY */ void do_show_debugfs_params(int argc EXT2FS_ATTR((unused)), - char *argv[] EXT2FS_ATTR((unused))) + char *argv[] EXT2FS_ATTR((unused)), + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { if (current_fs) printf("Open mode: read-%s\n", @@ -1825,7 +2021,8 @@ void do_show_debugfs_params(int argc EXT2FS_ATTR((unused)), } #ifndef READ_ONLY -void do_expand_dir(int argc, char *argv[]) +void do_expand_dir(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t inode; int retval; @@ -1839,7 +2036,8 @@ void do_expand_dir(int argc, char *argv[]) return; } -void do_features(int argc, char *argv[]) +void do_features(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { int i; @@ -1860,34 +2058,73 @@ void do_features(int argc, char *argv[]) } #endif /* READ_ONLY */ -void do_bmap(int argc, char *argv[]) +void do_bmap(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t ino; - blk64_t blk, pblk; - int err; + blk64_t blk, pblk = 0; + int c, err, flags = 0, ret_flags = 0; errcode_t errcode; - if (common_args_process(argc, argv, 3, 3, argv[0], - " logical_blk", 0)) + if (check_fs_open(argv[0])) return; - ino = string_to_inode(argv[1]); + reset_getopt(); + while ((c = getopt (argc, argv, "a")) != EOF) { + switch (c) { + case 'a': + flags |= BMAP_ALLOC; + break; + default: + goto print_usage; + } + } + + if (argc <= optind+1) { + print_usage: + com_err(0, 0, + "Usage: bmap [-a] logical_blk [physical_blk]"); + return; + } + + ino = string_to_inode(argv[optind++]); if (!ino) return; - err = strtoblk(argv[0], argv[2], "logical block", &blk); + err = strtoblk(argv[0], argv[optind++], "logical block", &blk); if (err) return; - errcode = ext2fs_bmap2(current_fs, ino, 0, 0, 0, blk, 0, &pblk); + if (argc > optind+1) + goto print_usage; + + if (argc == optind+1) { + err = strtoblk(argv[0], argv[optind++], + "physical block", &pblk); + if (err) + return; + if (flags & BMAP_ALLOC) { + com_err(0, 0, "Can't set and allocate a block"); + return; + } + flags |= BMAP_SET; + } + + errcode = ext2fs_bmap2(current_fs, ino, 0, 0, flags, blk, + &ret_flags, &pblk); if (errcode) { com_err(argv[0], errcode, - "while mapping logical block %llu\n", blk); + "while mapping logical block %llu\n", + (unsigned long long) blk); return; } - printf("%llu\n", pblk); + printf("%llu", (unsigned long long) pblk); + if (ret_flags & BMAP_RET_UNINIT) + fputs(" (uninit)", stdout); + fputc('\n', stdout); } -void do_imap(int argc, char *argv[]) +void do_imap(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { ext2_ino_t ino; unsigned long group, block, block_nr, offset; @@ -1912,23 +2149,38 @@ void do_imap(int argc, char *argv[]) block; offset &= (EXT2_BLOCK_SIZE(current_fs->super) - 1); - printf("Inode %d is part of block group %lu\n" + printf("Inode %u is part of block group %lu\n" "\tlocated at block %lu, offset 0x%04lx\n", ino, group, block_nr, offset); } -void do_idump(int argc, char *argv[]) +void do_idump(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { + struct ext2_inode_large *inode; ext2_ino_t ino; unsigned char *buf; errcode_t err; - int isize; + unsigned int isize, size, offset = 0; + int c, mode = 0; - if (common_args_process(argc, argv, 2, 2, argv[0], - "", 0)) + reset_getopt(); + while ((c = getopt (argc, argv, "bex")) != EOF) { + if (mode || c == '?') { + com_err(argv[0], 0, + "Usage: inode_dump [-b]|[-e] "); + return; + } + mode = c; + } + if (optind != argc-1) return; - ino = string_to_inode(argv[1]); + + if (check_fs_open(argv[0])) + return; + + ino = string_to_inode(argv[optind]); if (!ino) return; @@ -1942,26 +2194,50 @@ void do_idump(int argc, char *argv[]) err = ext2fs_read_inode_full(current_fs, ino, (struct ext2_inode *)buf, isize); if (err) { - com_err(argv[0], err, "while reading inode %d", ino); + com_err(argv[0], err, "while reading inode %u", ino); goto err; } - do_byte_hexdump(stdout, buf, isize); + inode = (struct ext2_inode_large *) buf; + size = isize; + switch (mode) { + case 'b': + offset = ((char *) (&inode->i_block)) - ((char *) buf); + size = sizeof(inode->i_block); + break; + case 'x': + case 'e': + if (size <= EXT2_GOOD_OLD_INODE_SIZE) { + com_err(argv[0], 0, "No extra space in inode"); + goto err; + } + offset = EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize; + if (offset > size) + goto err; + size -= offset; + break; + } + if (mode == 'x') + raw_inode_xattr_dump(stdout, buf + offset, size); + else + do_byte_hexdump(stdout, buf + offset, size); err: ext2fs_free_mem(&buf); } #ifndef READ_ONLY -void do_set_current_time(int argc, char *argv[]) +void do_set_current_time(int argc, char *argv[], + int sci_idx EXT2FS_ATTR((unused)), + void *infop EXT2FS_ATTR((unused))) { - time_t now; + __s64 now; if (common_args_process(argc, argv, 2, 2, argv[0], "