]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Add new debugfs commands and arguments which make it easier to
authorTheodore Ts'o <tytso@mit.edu>
Thu, 3 Jan 2002 09:55:25 +0000 (04:55 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 3 Jan 2002 09:55:25 +0000 (04:55 -0500)
recover deleted files.  The lsdel command now takes an optional
argument which allows the user to only see the most recently
deleted files.  Also added a new command, undel, which automates
undeleting a deleted inode and linking it back to a directory.
Also added an optional count argument to the testb, freeb, setb,
and find_free_block commands.  The ls command now takes a new
option, -d, which lists deleted directory entries.

Factored out out commonly used code into utility subroutines
for ease of maintenance and to make the executable size smaller.

12 files changed:
debugfs/ChangeLog
debugfs/debug_cmds.ct
debugfs/debugfs.8.in
debugfs/debugfs.c
debugfs/debugfs.h
debugfs/dump.c
debugfs/icheck.c
debugfs/logdump.c
debugfs/ls.c
debugfs/lsdel.c
debugfs/setsuper.c
debugfs/util.c

index 8cdee8260ce348fec0e085f3459e7d197f8c1b8f..82149ea78d99e0244d804140ef519a0c63d7c8aa 100644 (file)
@@ -1,3 +1,29 @@
+2002-01-03  Theodore Tso  <tytso@valinux.com>
+
+       * lsdel.c (do_lsdel): New optional argument which allows the user
+               to only see the most recently deleted files.
+
+       * debugfs.c (do_undel, do_testb, do_freeb, do_setb, do_ffb): Add
+               new command, undelete, which automates undeleting a
+               deleted inode and linking it back to a directory.  Add a
+               count argument to the testb, freeb, setb, and ffb commands.
+
+       * ls.c (list_dir_proc, do_list_dir): Add support for -d option
+               which lists deleted directory entries.
+
+       * debug_cmds.ct: Add new command, undelete.
+
+       * dump.c, icheck.c, logdump.c, ls.c, lsdel.c, setsuper.c,
+               debugfs.c: Use new utility functions which factor out
+               commonly used code.
+
+       * util.c (debugfs_read_inode, debugfs_write_inode,
+               common_block_args_process, common_inode_args_process,
+               common_args_process, strtoblk, parse_ulong): New
+               functions which factor out commonly used code into
+               subroutines for ease of maintenance and to make the
+               executable size smaller.
+
 2001-12-23  Theodore Tso  <tytso@valinux.com>
 
        * Makefile.in, jfs_user.h: Move linux/jbd.h to
index 4cd034f8825d72b6fb168095facb6e09f3f51d3b..63f9c0a09065b35f35fea609693416866f90ffd7 100644 (file)
@@ -103,6 +103,9 @@ request do_mknod, "Create a special file",
 request do_lsdel, "List deleted inodes",
        list_deleted_inodes, lsdel;
 
+request do_undel, "Undelete file",
+       undelete, undel;
+
 request do_write, "Copy a file from your native filesystem",
        write;
 
index 77a893a1452c7d4d7a749b2e6d842ad00d7b2e13..231a3e31c34b94df2a2107d4a10888429ff598ae 100644 (file)
@@ -185,8 +185,10 @@ Set or clear various filesystem features in the superblock.  After setting
 or clearing any filesystem features that were requested, print the current
 state of the filesystem feature set.
 .TP
-.I find_free_block [goal]
-Find the first free block, starting from
+.I find_free_block [count [goal]]
+Find the first 
+.I count
+free blocks, starting from
 .I goal
 and allocate it.
 .TP
@@ -200,10 +202,17 @@ optional argument
 specifies the permissions of the new inode.  (If the directory bit is set
 on the mode, the allocation routine will function differently.)
 .TP
-.I freeb block
+.I freeb block [count]
 Mark the block number
 .I block
 as not allocated.
+If the optional argument 
+.I count 
+is present, then 
+.I count
+blocks starting at block number
+.I block
+will be marked as not allocated.
 .TP
 .I freei filespec
 Free the inode specified by 
@@ -253,9 +262,15 @@ Note this does not adjust the inode reference counts.
 .I logdump [-ac] [-b<block>] [-i<inode>] [-f<journal_file>] [output_file]
 Dump the contents of the ext3 journal.
 .TP
-.I ls [-l] filespec
+.I ls [-l] [-d] filespec
 Print a listing of the files in the directory
 .IR filespec .
+The 
+.I \-l
+flag will list files using a more verbose format.
+The
+.I \-d
+flag will list deleted entries in the directory.
 .TP
 .I modify_inode filespec
 Modify the contents of the inode structure in the inode
@@ -318,10 +333,17 @@ Remove the directory
 .IR filespec .
 This function is currently not implemented.
 .TP
-.I setb block
+.I setb block [count]
 Mark the block number
 .I block
 as allocated.
+If the optional argument 
+.I count 
+is present, then 
+.I count
+blocks starting at block number
+.I block
+will be marked as allocated.
 .TP
 .I seti filespec
 Mark inode 
@@ -346,10 +368,17 @@ flag is given, only print out the superblock contents.
 Display the contents of the inode structure of the inode
 .IR filespec .
 .TP
-.I testb block
+.I testb block [count]
 Test if the block number
 .I block
 is marked as allocated in the block bitmap.
+If the optional argument 
+.I count 
+is present, then 
+.I count
+blocks starting at block number
+.I block
+will be tested.
 .TP
 .I testi filespec
 Test if the inode 
index ebd02f272cf1db0f4692214b48dab71e58558541..df08610260aa71f2257188585cc5825ed9728bc8 100644 (file)
@@ -95,11 +95,10 @@ errout:
 void do_open_filesys(int argc, char **argv)
 {
        const char *usage = "Usage: open [-s superblock] [-b blocksize] [-c] [-w] <device>";
-       int     c;
+       int     c, err;
        int     catastrophic = 0;
        blk_t   superblock = 0;
        blk_t   blocksize = 0;
-       char    *tmp;
        int open_flags = 0;
        
        optind = 0;
@@ -121,20 +120,16 @@ void do_open_filesys(int argc, char **argv)
                        catastrophic = 1;
                        break;
                case 'b':
-                       blocksize = strtoul(optarg, &tmp, 0);
-                       if (*tmp) {
-                               com_err(argv[0], 0,
-                                       "Bad block size - %s", optarg);
+                       blocksize = parse_ulong(optarg, argv[0],
+                                               "block size", &err);
+                       if (err)
                                return;
-                       }
                        break;
                case 's':
-                       superblock = strtoul(optarg, &tmp, 0);
-                       if (*tmp) {
-                               com_err(argv[0], 0,
-                                       "Bad superblock number - %s", optarg);
+                       superblock = parse_ulong(optarg, argv[0],
+                                                "superblock number", &err);
+                       if (err)
                                return;
-                       }
                        break;
                default:
                        com_err(argv[0], 0, usage);
@@ -153,12 +148,9 @@ void do_open_filesys(int argc, char **argv)
 
 void do_lcd(int argc, char **argv)
 {
-       const char *usage = "Usage: lcd <native dir>";
-
-       if (argc != 2) {
-               com_err(argv[0], 0, usage);
+       if (common_args_process(argc, argv, 2, 2, "lcd",
+                               "<native dir>", 0))
                return;
-       }
 
        if (chdir(argv[1]) == -1) {
                com_err(argv[0], errno,
@@ -191,35 +183,26 @@ static void close_filesystem(NOARGS)
 
 void do_close_filesys(int argc, char **argv)
 {
-       if (argc > 1) {
-               com_err(argv[0], 0, "Usage: close_filesys");
-               return;
-       }
-       if (check_fs_open(argv[0]))
+       if (common_args_process(argc, argv, 1, 1, "close_filesys", "", 0))
                return;
        close_filesystem();
 }
 
 void do_init_filesys(int argc, char **argv)
 {
-       const char      *usage = "Usage: initialize <device> <blocksize>";
        struct ext2_super_block param;
        errcode_t       retval;
-       char            *tmp;
+       int             err;
        
-       if (argc != 3) {
-               com_err(argv[0], 0, usage);
-               return;
-       }
-       if (check_fs_not_open(argv[0]))
+       if (common_args_process(argc, argv, 3, 3, "initialize",
+                               "<device> <blocksize>", CHECK_FS_NOTOPEN))
                return;
 
        memset(&param, 0, sizeof(struct ext2_super_block));
-       param.s_blocks_count = strtoul(argv[2], &tmp, 0);
-       if (*tmp) {
-               com_err(argv[0], 0, "Bad blocks count - %s", argv[2]);
+       param.s_blocks_count = parse_ulong(argv[0], argv[2],
+                                          "blocks count", &err);
+       if (err)
                return;
-       }
        retval = ext2fs_initialize(argv[1], 0, &param,
                                   unix_io_manager, &current_fs);
        if (retval) {
@@ -491,29 +474,17 @@ static void dump_inode(ext2_ino_t inode_num, struct ext2_inode inode)
        close_pager(out);
 }
 
-
 void do_stat(int argc, char *argv[])
 {
        ext2_ino_t      inode;
        struct ext2_inode inode_buf;
        int             retval;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: stat <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode, 0))
                return;
 
-       retval = ext2fs_read_inode(current_fs, inode, &inode_buf);
-       if (retval) 
-         {
-           com_err(argv[0], retval, "while trying to read inode %d", inode);
-           return;
-         }
+       if (debugfs_read_inode(inode, &inode_buf, argv[0]))
+               return;
 
        dump_inode(inode,inode_buf);
        return;
@@ -524,14 +495,7 @@ void do_chroot(int argc, char *argv[])
        ext2_ino_t inode;
        int retval;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: chroot <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode, 0))
                return;
 
        retval = ext2fs_check_directory(current_fs, inode);
@@ -548,47 +512,22 @@ void do_clri(int argc, char *argv[])
        int retval;
        struct ext2_inode inode_buf;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: clri <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       if (check_fs_read_write(argv[0]))
-               return;
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode, CHECK_FS_RW))
                return;
 
-       retval = ext2fs_read_inode(current_fs, inode, &inode_buf);
-       if (retval) {
-               com_err(argv[0], retval, "while trying to read inode %d", 
-                       inode);
+       if (debugfs_read_inode(inode, &inode_buf, argv[0]))
                return;
-       }
        memset(&inode_buf, 0, sizeof(inode_buf));
-       retval = ext2fs_write_inode(current_fs, inode, &inode_buf);
-       if (retval) {
-               com_err(argv[0], retval, "while trying to write inode %d",
-                       inode);
+       if (debugfs_write_inode(inode, &inode_buf, argv[0]))
                return;
-       }
 }
 
 void do_freei(int argc, char *argv[])
 {
        ext2_ino_t inode;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: freei <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       if (check_fs_read_write(argv[0]))
-               return;
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode,
+                                     CHECK_FS_RW | CHECK_FS_BITMAPS))
                return;
 
        if (!ext2fs_test_inode_bitmap(current_fs->inode_map,inode))
@@ -601,16 +540,8 @@ void do_seti(int argc, char *argv[])
 {
        ext2_ino_t inode;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: seti <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       if (check_fs_read_write(argv[0]))
-               return;
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode,
+                                     CHECK_FS_RW | CHECK_FS_BITMAPS))
                return;
 
        if (ext2fs_test_inode_bitmap(current_fs->inode_map,inode))
@@ -623,16 +554,7 @@ void do_testi(int argc, char *argv[])
 {
        ext2_ino_t inode;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: testi <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       if (check_fs_bitmaps(argv[0]))
-               return;
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode, CHECK_FS_BITMAPS))
                return;
 
        if (ext2fs_test_inode_bitmap(current_fs->inode_map,inode))
@@ -641,76 +563,58 @@ void do_testi(int argc, char *argv[])
                printf("Inode %u is not in use\n", inode);
 }
 
-
 void do_freeb(int argc, char *argv[])
 {
        blk_t block;
-       char *tmp;
+       int count = 1;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: freeb <block>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
+       if (common_block_args_process(argc, argv, &block, &count))
                return;
        if (check_fs_read_write(argv[0]))
                return;
-       block = strtoul(argv[1], &tmp, 0);
-       if (!block || *tmp) {
-               com_err(argv[0], 0, "No block 0");
-               return;
-       } 
-       if (!ext2fs_test_block_bitmap(current_fs->block_map,block))
-               com_err(argv[0], 0, "Warning: block already clear");
-       ext2fs_unmark_block_bitmap(current_fs->block_map,block);
+       while (count-- > 0) {
+               if (!ext2fs_test_block_bitmap(current_fs->block_map,block))
+                       com_err(argv[0], 0, "Warning: block %d already clear",
+                               block);
+               ext2fs_unmark_block_bitmap(current_fs->block_map,block);
+               block++;
+       }
        ext2fs_mark_bb_dirty(current_fs);
 }
 
 void do_setb(int argc, char *argv[])
 {
        blk_t block;
-       char *tmp;
+       int count = 1;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: setb <block>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
+       if (common_block_args_process(argc, argv, &block, &count))
                return;
        if (check_fs_read_write(argv[0]))
                return;
-       block = strtoul(argv[1], &tmp, 0);
-       if (!block || *tmp) {
-               com_err(argv[0], 0, "No block 0");
-               return;
-       } 
-       if (ext2fs_test_block_bitmap(current_fs->block_map,block))
-               com_err(argv[0], 0, "Warning: block already set");
-       ext2fs_mark_block_bitmap(current_fs->block_map,block);
+       while (count-- > 0) {
+               if (ext2fs_test_block_bitmap(current_fs->block_map,block))
+                       com_err(argv[0], 0, "Warning: block %d already set",
+                               block);
+               ext2fs_mark_block_bitmap(current_fs->block_map,block);
+               block++;
+       }
        ext2fs_mark_bb_dirty(current_fs);
 }
 
 void do_testb(int argc, char *argv[])
 {
        blk_t block;
-       char *tmp;
+       int count = 1;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: testb <block>");
+       if (common_block_args_process(argc, argv, &block, &count))
                return;
+       while (count-- > 0) {
+               if (ext2fs_test_block_bitmap(current_fs->block_map,block))
+                       printf("Block %d marked in use\n", block);
+               else
+                       printf("Block %d not in use\n", block);
+               block++;
        }
-       if (check_fs_open(argv[0]))
-               return;
-       if (check_fs_bitmaps(argv[0]))
-               return;
-       block = strtoul(argv[1], &tmp, 0);
-       if (!block || *tmp) {
-               com_err(argv[0], 0, "No block 0");
-               return;
-       } 
-       if (ext2fs_test_block_bitmap(current_fs->block_map,block))
-               printf("Block %d marked in use\n", block);
-       else printf("Block %d not in use\n", block);
 }
 
 static void modify_u8(char *com, const char *prompt,
@@ -790,25 +694,11 @@ void do_modify_inode(int argc, char *argv[])
        const char      *octal_format = "0%o";
        const char      *decimal_format = "%d";
        
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: modify_inode <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       if (check_fs_read_write(argv[0]))
-               return;
-
-       inode_num = string_to_inode(argv[1]);
-       if (!inode_num) 
+       if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW))
                return;
 
-       retval = ext2fs_read_inode(current_fs, inode_num, &inode);
-       if (retval) {
-               com_err(argv[1], retval, "while trying to read inode %d",
-                       inode_num);
+       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);
@@ -867,12 +757,8 @@ void do_modify_inode(int argc, char *argv[])
                    &inode.i_block[EXT2_DIND_BLOCK]);
        modify_u32(argv[0], "Triple Indirect Block", decimal_format,
                    &inode.i_block[EXT2_TIND_BLOCK]);
-       retval = ext2fs_write_inode(current_fs, inode_num, &inode);
-       if (retval) {
-               com_err(argv[1], retval, "while trying to write inode %d",
-                       inode_num);
+       if (debugfs_write_inode(inode_num, &inode, argv[1]))
                return;
-       }
 }
 
 void do_change_working_dir(int argc, char *argv[])
@@ -880,15 +766,7 @@ void do_change_working_dir(int argc, char *argv[])
        ext2_ino_t      inode;
        int             retval;
        
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: cd <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode, 0))
                return;
 
        retval = ext2fs_check_directory(current_fs, inode);
@@ -905,11 +783,8 @@ void do_print_working_directory(int argc, char *argv[])
        int     retval;
        char    *pathname = NULL;
        
-       if (argc > 1) {
-               com_err(argv[0], 0, "Usage: print_working_directory");
-               return;
-       }
-       if (check_fs_open(argv[0]))
+       if (common_args_process(argc, argv, 1, 1,
+                               "print_working_directory", "", 0))
                return;
 
        retval = ext2fs_get_pathname(current_fs, cwd, 0, &pathname);
@@ -980,13 +855,63 @@ static void make_link(char *sourcename, char *destname)
 
 void do_link(int argc, char *argv[])
 {
-       if (argc != 3) {
-               com_err(argv[0], 0, "Usage: link <source_file> <dest_name>");
+       if (common_args_process(argc, argv, 3, 3, "link",
+                               "<source file> <dest_name>", CHECK_FS_RW))
+               return;
+
+       make_link(argv[1], argv[2]);
+}
+
+static int mark_blocks_proc(ext2_filsys fs, blk_t *blocknr,
+                           int blockcnt, void *private)
+{
+       blk_t   block;
+       dgrp_t  group;
+
+       block = *blocknr;
+       ext2fs_block_alloc_stats(fs, block, +1);
+       return 0;
+}
+
+void do_undel(int argc, char *argv[])
+{
+       ext2_ino_t      ino;
+       struct ext2_inode inode;
+       int             retval;
+       dgrp_t group;
+
+       if (common_args_process(argc, argv, 3, 3, "undelete",
+                               "<inode_num> <dest_name>",
+                               CHECK_FS_RW | CHECK_FS_BITMAPS))
+               return;
+
+       ino = string_to_inode(argv[1]);
+       if (!ino)
+               return;
+
+       if (debugfs_read_inode(ino, &inode, argv[1]))
+               return;
+
+       if (ext2fs_test_inode_bitmap(current_fs->inode_map, ino)) {
+               com_err(argv[1], 0, "Inode is not marked as deleted");
                return;
        }
-       if (check_fs_open(argv[0]))
+
+       /*
+        * XXX this function doesn't handle changing the links count on the
+        * parent directory when undeleting a directory.  
+        */
+       inode.i_links_count = LINUX_S_ISDIR(inode.i_mode) ? 2 : 1;
+       inode.i_dtime = 0;
+
+       if (debugfs_write_inode(ino, &inode, argv[0]))
                return;
 
+       ext2fs_block_iterate(current_fs, ino, 0, NULL,
+                            mark_blocks_proc, NULL);
+
+       ext2fs_inode_alloc_stats(current_fs, ino, +1);
+
        make_link(argv[1], argv[2]);
 }
 
@@ -1014,11 +939,8 @@ static void unlink_file_by_name(char *filename)
 
 void do_unlink(int argc, char *argv[])
 {
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: unlink <pathname>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
+       if (common_args_process(argc, argv, 2, 2, "link",
+                               "<pathname>", CHECK_FS_RW))
                return;
 
        unlink_file_by_name(argv[1]);
@@ -1027,18 +949,28 @@ void do_unlink(int argc, char *argv[])
 void do_find_free_block(int argc, char *argv[])
 {
        blk_t   free_blk, goal;
+       int             count;
        errcode_t       retval;
        char            *tmp;
        
-       if ((argc > 2) || (argc==2 && *argv[1] == '?')) {
-               com_err(argv[0], 0, "Usage: find_free_block [goal]");
+       if ((argc > 3) || (argc==2 && *argv[1] == '?')) {
+               com_err(argv[0], 0, "Usage: find_free_block [count [goal]]");
                return;
        }
        if (check_fs_open(argv[0]))
                return;
 
        if (argc > 1) {
-               goal = strtol(argv[1], &tmp, 0);
+               count = strtol(argv[1],&tmp,0);
+               if (*tmp) {
+                       com_err(argv[0], 0, "Bad count - %s", argv[1]);
+                       return;
+               }
+       } else
+               count = 1;
+
+       if (argc > 2) {
+               goal = strtol(argv[2], &tmp, 0);
                if (*tmp) {
                        com_err(argv[0], 0, "Bad goal - %s", argv[1]);
                        return;
@@ -1047,12 +979,18 @@ void do_find_free_block(int argc, char *argv[])
        else
                goal = current_fs->super->s_first_data_block;
 
-       retval = ext2fs_new_block(current_fs, goal, 0, &free_blk);
-       if (retval)
-               com_err("ext2fs_new_block", retval, "");
-       else
-               printf("Free block found: %d\n", free_blk);
-
+       printf("Free blocks found: ");
+       free_blk = goal - 1;    
+       while (count-- > 0) {
+               retval = ext2fs_new_block(current_fs, free_blk + 1, 0,
+                                         &free_blk);
+               if (retval) {
+                       com_err("ext2fs_new_block", retval, "");
+                       return;
+               } else
+                       printf("%d ", free_blk);
+       }
+       printf("\n");
 }
 
 void do_find_free_inode(int argc, char *argv[])
@@ -1128,7 +1066,6 @@ static errcode_t copy_file(int fd, ext2_ino_t newfile)
                }
        }
        retval = ext2fs_file_close(e2_file);
-
        return retval;
 
 fail:
@@ -1146,17 +1083,13 @@ void do_write(int argc, char *argv[])
        struct ext2_inode inode;
        dgrp_t          group;
 
-       if (check_fs_open(argv[0]))
-               return;
-       if (argc != 3) {
-               com_err(argv[0], 0, "Usage: write <nativefile> <newfile>");
-               return;
-       }
-       if (check_fs_read_write(argv[0]))
+       if (common_args_process(argc, argv, 3, 3, "write",
+                               "<native file> <new file>", CHECK_FS_RW))
                return;
+
        fd = open(argv[1], O_RDONLY);
        if (fd < 0) {
-               com_err(argv[1], fd, "");
+               com_err(argv[1], errno, "");
                return;
        }
        if (fstat(fd, &statbuf) < 0) {
@@ -1171,10 +1104,6 @@ void do_write(int argc, char *argv[])
                close(fd);
                return;
        }
-       group = ext2fs_group_of_ino(current_fs, newfile);
-       current_fs->group_desc[group].bg_free_inodes_count--;
-       current_fs->super->s_free_inodes_count--;
-       ext2fs_mark_super_dirty(current_fs);
        printf("Allocated inode: %u\n", newfile);
        retval = ext2fs_link(current_fs, cwd, argv[2], newfile,
                             EXT2_FT_REG_FILE);
@@ -1185,17 +1114,13 @@ void do_write(int argc, char *argv[])
        }
         if (ext2fs_test_inode_bitmap(current_fs->inode_map,newfile))
                com_err(argv[0], 0, "Warning: inode already set");
-       ext2fs_mark_inode_bitmap(current_fs->inode_map,newfile);
-       ext2fs_mark_ib_dirty(current_fs);
+       ext2fs_inode_alloc_stats(current_fs, newfile, +1);
        memset(&inode, 0, sizeof(inode));
        inode.i_mode = statbuf.st_mode;
        inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
        inode.i_links_count = 1;
        inode.i_size = statbuf.st_size;
-       retval = ext2fs_write_inode(current_fs, newfile, &inode);
-       if (retval) {
-               com_err(argv[0], retval, "while trying to write inode %d", 
-                       inode);
+       if (debugfs_write_inode(newfile, &inode, argv[0])) {
                close(fd);
                return;
        }
@@ -1218,6 +1143,7 @@ void do_mknod(int argc, char *argv[])
        if (check_fs_open(argv[0]))
                return;
        if (argc < 3 || argv[2][1]) {
+       usage:
                com_err(argv[0], 0, "Usage: mknod <name> [p| [c|b] <major> <minor>]");
                return;
        }
@@ -1248,10 +1174,8 @@ void do_mknod(int argc, char *argv[])
                if (major > 255 || minor > 255 || argv[3][0] || argv[4][0])
                        nr = 0;
        }
-       if (argc != nr) {
-               com_err(argv[0], 0, "Usage: mknod <name> [p| [c|b] <major> <minor>]");
-               return;
-       }
+       if (argc != nr)
+               goto usage;
        if (check_fs_read_write(argv[0]))
                return;
        retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile);
@@ -1283,11 +1207,8 @@ void do_mknod(int argc, char *argv[])
        inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
        inode.i_block[0] = major*256+minor;
        inode.i_links_count = 1;
-       retval = ext2fs_write_inode(current_fs, newfile, &inode);
-       if (retval) {
-               com_err(argv[0], retval, "while trying to write inode %d", inode);
+       if (debugfs_write_inode(newfile, &inode, argv[0]))
                return;
-       }
 }
 
 void do_mkdir(int argc, char *argv[])
@@ -1297,15 +1218,8 @@ void do_mkdir(int argc, char *argv[])
        char    *name;
        errcode_t retval;
 
-       if (check_fs_open(argv[0]))
-               return;
-
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: mkdir <file>");
-               return;
-       }
-
-       if (check_fs_read_write(argv[0]))
+       if (common_args_process(argc, argv, 2, 2, "mkdir",
+                               "<filename>", CHECK_FS_RW))
                return;
 
        cp = strrchr(argv[1], '/');
@@ -1341,14 +1255,10 @@ static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr,
                               int blockcnt, void *private)
 {
        blk_t   block;
-       int     group;
+       dgrp_t  group;
 
        block = *blocknr;
-       printf("%d ", block);
-       ext2fs_unmark_block_bitmap(fs->block_map,block);
-       group = ext2fs_group_of_blk(fs, block);
-       fs->group_desc[group].bg_free_blocks_count++;
-       fs->super->s_free_blocks_count++;
+       ext2fs_block_alloc_stats(fs, block, -1);
        return 0;
 }
 
@@ -1357,22 +1267,17 @@ static void kill_file_by_inode(ext2_ino_t inode)
        struct ext2_inode inode_buf;
        int     group;
 
-       ext2fs_read_inode(current_fs, inode, &inode_buf);
+       if (debugfs_read_inode(inode, &inode_buf, 0))
+               return;
        inode_buf.i_dtime = time(NULL);
-       ext2fs_write_inode(current_fs, inode, &inode_buf);
+       if (debugfs_write_inode(inode, &inode_buf, 0))
+               return;
 
        printf("Kill file by inode %u\n", inode);
        ext2fs_block_iterate(current_fs, inode, 0, NULL,
                             release_blocks_proc, NULL);
        printf("\n");
-       ext2fs_unmark_inode_bitmap(current_fs->inode_map, inode);
-       group = ext2fs_group_of_ino(current_fs, inode);
-       current_fs->group_desc[group].bg_free_inodes_count++;
-       current_fs->super->s_free_inodes_count++;
-       
-       ext2fs_mark_super_dirty(current_fs);
-       ext2fs_mark_bb_dirty(current_fs);
-       ext2fs_mark_ib_dirty(current_fs);
+       ext2fs_inode_alloc_stats(current_fs, inode, -1);
 }
 
 
@@ -1380,21 +1285,9 @@ void do_kill_file(int argc, char *argv[])
 {
        ext2_ino_t inode_num;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: kill_file <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
+       if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW))
                return;
 
-       if (check_fs_read_write(argv[0]))
-               return;
-
-       inode_num = string_to_inode(argv[1]);
-       if (!inode_num) {
-               com_err(argv[0], 0, "Cannot find file");
-               return;
-       }
        kill_file_by_inode(inode_num);
 }
 
@@ -1404,14 +1297,8 @@ void do_rm(int argc, char *argv[])
        ext2_ino_t inode_num;
        struct ext2_inode inode;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: rm <filename>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-
-       if (check_fs_read_write(argv[0]))
+       if (common_args_process(argc, argv, 2, 2, "rm",
+                               "<filename>", CHECK_FS_RW))
                return;
 
        retval = ext2fs_namei(current_fs, root, cwd, argv[1], &inode_num);
@@ -1420,11 +1307,8 @@ void do_rm(int argc, char *argv[])
                return;
        }
 
-       retval = ext2fs_read_inode(current_fs,inode_num,&inode);
-       if (retval) {
-               com_err(argv[0], retval, "while reading file's inode");
+       if (debugfs_read_inode(inode_num, &inode, argv[0]))
                return;
-       }
 
        if (LINUX_S_ISDIR(inode.i_mode)) {
                com_err(argv[0], 0, "file is a directory");
@@ -1432,11 +1316,8 @@ void do_rm(int argc, char *argv[])
        }
 
        --inode.i_links_count;
-       retval = ext2fs_write_inode(current_fs,inode_num,&inode);
-       if (retval) {
-               com_err(argv[0], retval, "while writing inode");
+       if (debugfs_write_inode(inode_num, &inode, argv[0]))
                return;
-       }
 
        unlink_file_by_name(argv[1]);
        if (inode.i_links_count == 0)
@@ -1459,14 +1340,7 @@ void do_expand_dir(int argc, char *argv[])
        ext2_ino_t inode;
        int retval;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: expand_dir <file>");
-               return;
-       }
-       if (check_fs_open(argv[0]))
-               return;
-       inode = string_to_inode(argv[1]);
-       if (!inode)
+       if (common_inode_args_process(argc, argv, &inode, CHECK_FS_RW))
                return;
 
        retval = ext2fs_expand_dir(current_fs, inode);
@@ -1546,7 +1420,6 @@ int main(int argc, char **argv)
        blk_t           superblock = 0;
        blk_t           blocksize = 0;
        int             catastrophic = 0;
-       char            *tmp;
        
        initialize_ext2_error_table();
        fprintf (stderr, "debugfs %s (%s)\n", E2FSPROGS_VERSION,
@@ -1567,20 +1440,12 @@ int main(int argc, char **argv)
                        open_flags |= EXT2_FLAG_RW;
                        break;
                case 'b':
-                       blocksize = strtoul(optarg, &tmp, 0);
-                       if (*tmp) {
-                               com_err(argv[0], 0,
-                                       "Bad block size - %s", optarg);
-                               return 1;
-                       }
+                       blocksize = parse_ulong(argv[0], optarg,
+                                               "block size", 0);
                        break;
                case 's':
-                       superblock = strtoul(optarg, &tmp, 0);
-                       if (*tmp) {
-                               com_err(argv[0], 0,
-                                       "Bad superblock number - %s", optarg);
-                               return 1;
-                       }
+                       superblock = parse_ulong(argv[0], optarg,
+                                                "superblock number", 0);
                        break;
                case 'c':
                        catastrophic = 1;
index 1cc308adf88de73376e1f83521c6e32791a0d8c3..1634875c227c374e5ab13fc530a74d3a72c95e97 100644 (file)
 #define const
 #endif
 
+/*
+ * Flags used by the common argument processing functions
+ */
+#define CHECK_FS_RW            0x0001
+#define CHECK_FS_BITMAPS       0x0002
+#define CHECK_FS_NOTOPEN       0x0004
+
 extern ext2_filsys current_fs;
 extern ext2_ino_t      root, cwd;
 
@@ -23,6 +30,20 @@ extern int check_fs_read_write(char *name);
 extern int check_fs_bitmaps(char *name);
 extern ext2_ino_t string_to_inode(char *str);
 extern char *time_to_string(__u32);
+extern unsigned long parse_ulong(const char *str, const char *cmd,
+                                const char *descr, int *err);
+extern int strtoblk(const char *cmd, const char *str, blk_t *ret);
+extern int common_args_process(int argc, char *argv[], int min_argc,
+                              int max_argc, const char *cmd,
+                              const char *usage, int flags);
+extern int common_inode_args_process(int argc, char *argv[],
+                                    ext2_ino_t *inode, int flags);
+extern int common_block_args_process(int argc, char *argv[],
+                                    blk_t *block, int *count);
+extern int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode,
+                             const char *cmd);
+extern int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode,
+                              const char *cmd);
 
 /* ss command functions */
 
index e290c14e22f1214f0e3ea82b0ef039da77b2c18e..abe8ea6fb75b9b51522ee8eb6ea68d142c9f8cd8 100644 (file)
@@ -104,12 +104,8 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd,
        int             nbytes;
        unsigned int    got;
        
-       retval = ext2fs_read_inode(current_fs, ino, &inode);
-       if (retval) {
-               com_err(cmdname, retval,
-                       "while reading inode %u in dump_file", ino);
+       if (debugfs_read_inode(ino, &inode, cmdname))
                return;
-       }
 
        retval = ext2fs_file_open(current_fs, ino, 0, &e2_file);
        if (retval) {
@@ -307,11 +303,8 @@ static int rdump_dirent(struct ext2_dir_entry *dirent, int offset,
        strncpy(name, dirent->name, thislen);
        name[thislen] = 0;
 
-       retval = ext2fs_read_inode(current_fs, dirent->inode, &inode);
-       if (retval) {
-               com_err("rdump", retval, "while dumping %s/%s", dumproot, name);
+       if (debugfs_read_inode(dirent->inode, &inode, name))
                return 0;
-       }
 
        rdump_inode(dirent->inode, &inode, name, dumproot);
 
@@ -327,12 +320,8 @@ void do_rdump(int argc, char **argv)
        int i;
        char *p;
 
-       if (argc != 3) {
-               com_err(argv[0], 0, "Usage: rdump <directory> <native directory>");
-               return;
-       }
-
-       if (check_fs_open(argv[0]))
+       if (common_args_process(argc, argv, 3, 3, "rdump",
+                               "<directory> <native directory>", 0))
                return;
 
        ino = string_to_inode(argv[1]);
@@ -350,11 +339,8 @@ void do_rdump(int argc, char **argv)
                return;
        }
 
-       retval = ext2fs_read_inode(current_fs, ino, &inode);
-       if (retval) {
-               com_err("rdump", retval, "while dumping %s", argv[1]);
+       if (debugfs_read_inode(ino, &inode, argv[1]))
                return;
-       }
 
        p = strrchr(argv[1], '/');
        if (p)
@@ -369,16 +355,7 @@ void do_cat(int argc, char **argv)
 {
        ext2_ino_t      inode;
 
-       if (argc != 2) {
-               com_err(argv[0], 0, "Usage: cat <file>");
-               return;
-       }
-
-       if (check_fs_open(argv[0]))
-               return;
-
-       inode = string_to_inode(argv[1]);
-       if (!inode) 
+       if (common_inode_args_process(argc, argv, &inode, 0))
                return;
 
        fflush(stdout);
index fa065c6fa9ab05f0c29a82432c6d52e18880fefd..941c749df82694d44970be731d84002e75fcc462 100644 (file)
@@ -61,7 +61,6 @@ void do_icheck(int argc, char **argv)
        ext2_ino_t              ino;
        struct ext2_inode       inode;
        errcode_t               retval;
-       char                    *tmp;
        char                    *block_buf;
        
        if (argc < 2) {
@@ -86,11 +85,8 @@ void do_icheck(int argc, char **argv)
        }
 
        for (i=1; i < argc; i++) {
-               bw.barray[i-1].blk = strtoul(argv[i], &tmp, 0);
-               if (*tmp) {
-                       com_err(argv[0], 0, "Bad block - %s", argv[i]);
+               if (strtoblk(argv[0], argv[i], &bw.barray[i-1].blk))
                        return;
-               }
        }
 
        bw.num_blocks = bw.blocks_left = argc-1;
index 34552d01bbe1cb1857b04c7ea2fd9ec9a49e7cf9..c7a5ca944339197c9ce501958322cd16985b482b 100644 (file)
@@ -203,13 +203,8 @@ void do_logdump(int argc, char **argv)
                journal_source.where = JOURNAL_IS_EXTERNAL;
                journal_source.fd = journal_fd;
        } else if ((journal_inum = current_fs->super->s_journal_inum)) {
-               retval = ext2fs_read_inode(current_fs, journal_inum, 
-                                          &journal_inode);
-               if (retval) {
-                       com_err(argv[0], retval,
-                               "while reading inode %u", journal_inum);
+               if (debugfs_read_inode(journal_inum, &journal_inode, argv[0]))
                        return;
-               }
 
                retval = ext2fs_file_open(current_fs, journal_inum,
                                          0, &journal_file);
index e24bdb3586d0d9ea2a9ad249701bd8dc9b6246bb..4459f306cb1253f90cdba34c30819d9c346602dc 100644 (file)
 #include <errno.h>
 #endif
 #include <sys/types.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else 
+extern int optind;
+extern char *optarg;
+#endif
+#ifdef HAVE_OPTRESET
+extern int optreset;           /* defined by BSD, but not others */
+#endif
 
 #include "debugfs.h"
 
@@ -23,6 +32,7 @@
  */
 
 #define LONG_OPT       0x0001
+#define DELETED_OPT    0x0002
 
 struct list_dir_struct {
        FILE    *f;
@@ -33,73 +43,73 @@ struct list_dir_struct {
 static const char *monstr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
                                        
-static void ls_l_file(struct list_dir_struct *ls, char *name, ext2_ino_t ino)
+static int list_dir_proc(ext2_ino_t dir,
+                        int    entry,
+                        struct ext2_dir_entry *dirent,
+                        int    offset,
+                        int    blocksize,
+                        char   *buf,
+                        void   *private)
 {
        struct ext2_inode       inode;
+       ext2_ino_t              ino;
        errcode_t               retval;
        struct tm               *tm_p;
        time_t                  modtime;
+       char                    name[EXT2_NAME_LEN];
+       char                    tmp[EXT2_NAME_LEN + 16];
        char                    datestr[80];
-
-       retval = ext2fs_read_inode(current_fs, ino, &inode);
-       if (retval) {
-               fprintf(ls->f, "%5ld --- error ---  %s\n", retval, name);
-               return;
-       }
-       modtime = inode.i_mtime;
-       tm_p = localtime(&modtime);
-       sprintf(datestr, "%2d-%s-%4d %02d:%02d",
-               tm_p->tm_mday, monstr[tm_p->tm_mon], 1900 + tm_p->tm_year,
-               tm_p->tm_hour, tm_p->tm_min);
-       fprintf(ls->f, "%6u %6o  %5d  %5d   ", ino, inode.i_mode,
-              inode.i_uid, inode.i_gid);
-       if (LINUX_S_ISDIR(inode.i_mode))
-               fprintf(ls->f, "%5d", inode.i_size);
-       else
-               fprintf(ls->f, "%5lld", inode.i_size |
-                       ((__u64)inode.i_size_high << 32));
-       fprintf (ls->f, " %s %s\n", datestr, name);
-}
-
-static void ls_file(struct list_dir_struct *ls, char *name,
-                   ext2_ino_t ino, int rec_len)
-{
-       char    tmp[EXT2_NAME_LEN + 16];
-       int     thislen;
-
-       sprintf(tmp, "%u (%d) %s   ", ino, rec_len, name);
-       thislen = strlen(tmp);
-
-       if (ls->col + thislen > 80) {
-               fprintf(ls->f, "\n");
-               ls->col = 0;
-       }
-       fprintf(ls->f, "%s", tmp);
-       ls->col += thislen;
-}      
-
-
-static int list_dir_proc(struct ext2_dir_entry *dirent,
-                        int    offset,
-                        int    blocksize,
-                        char   *buf,
-                        void   *private)
-{
-       char    name[EXT2_NAME_LEN];
-
+       char                    lbr, rbr;
+       int                     thislen;
        struct list_dir_struct *ls = (struct list_dir_struct *) private;
-       int     thislen;
 
        thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ?
                (dirent->name_len & 0xFF) : EXT2_NAME_LEN;
        strncpy(name, dirent->name, thislen);
        name[thislen] = '\0';
-
-       if (ls->options & LONG_OPT) 
-               ls_l_file(ls, name, dirent->inode);
-       else
-               ls_file(ls, name, dirent->inode, dirent->rec_len);
-       
+       ino = dirent->inode;
+
+       if (entry == DIRENT_DELETED_FILE) {
+               lbr = '<';
+               rbr = '>';
+               ino = 0;
+       } else {
+               lbr = rbr = ' ';
+       }
+       if (ls->options & LONG_OPT) {
+               if (ino) {
+                       if (debugfs_read_inode(ino, &inode, name))
+                               return;
+                       modtime = inode.i_mtime;
+                       tm_p = localtime(&modtime);
+                       sprintf(datestr, "%2d-%s-%4d %02d:%02d",
+                               tm_p->tm_mday, monstr[tm_p->tm_mon],
+                               1900 + tm_p->tm_year, tm_p->tm_hour,
+                               tm_p->tm_min);
+               } else {
+                       strcpy(datestr, "                 ");
+                       memset(&inode, 0, sizeof(struct ext2_inode));
+               }
+               fprintf(ls->f, "%c%6u%c %6o  %5d  %5d   ", lbr, ino, rbr,
+                       inode.i_mode, inode.i_uid, inode.i_gid);
+               if (LINUX_S_ISDIR(inode.i_mode))
+                       fprintf(ls->f, "%5d", inode.i_size);
+               else
+                       fprintf(ls->f, "%5lld", inode.i_size |
+                               ((__u64)inode.i_size_high << 32));
+               fprintf (ls->f, " %s %s\n", datestr, name);
+       } else {
+               sprintf(tmp, "%c%u%c (%d) %s   ", lbr, dirent->inode, rbr,
+                       dirent->rec_len, name);
+               thislen = strlen(tmp);
+
+               if (ls->col + thislen > 80) {
+                       fprintf(ls->f, "\n");
+                       ls->col = 0;
+               }
+               fprintf(ls->f, "%s", tmp);
+               ls->col += thislen;
+       }
        return 0;
 }
 
@@ -107,29 +117,48 @@ void do_list_dir(int argc, char *argv[])
 {
        ext2_ino_t      inode;
        int             retval;
+       int             c;
+       int             flags;
        struct list_dir_struct ls;
-       int             argptr = 1;
        
        ls.options = 0;
        if (check_fs_open(argv[0]))
                return;
 
-       if ((argc > argptr) && (argv[argptr][0] == '-')) {
-               argptr++;
-               ls.options = LONG_OPT;
+       optind = 0;
+#ifdef HAVE_OPTRESET
+       optreset = 1;           /* Makes BSD getopt happy */
+#endif
+       while ((c = getopt (argc, argv, "dl")) != EOF) {
+               switch (c) {
+               case 'l':
+                       ls.options |= LONG_OPT;
+                       break;
+               case 'd':
+                       ls.options |= DELETED_OPT;
+                       break;
+               }
+       }
+
+       if (argc > optind+1) {
+               com_err(0, 0, "Usage: ls [-l] [-d] file");
+               return;
        }
 
-       if (argc <= argptr)
+       if (argc == optind)
                inode = cwd;
        else
-               inode = string_to_inode(argv[argptr]);
+               inode = string_to_inode(argv[optind]);
        if (!inode)
                return;
 
        ls.f = open_pager();
        ls.col = 0;
-       retval = ext2fs_dir_iterate(current_fs, inode,
-                                   DIRENT_FLAG_INCLUDE_EMPTY,
+       flags = DIRENT_FLAG_INCLUDE_EMPTY;
+       if (ls.options & DELETED_OPT)
+               flags |= DIRENT_FLAG_INCLUDE_REMOVED;
+
+       retval = ext2fs_dir_iterate2(current_fs, inode, flags,
                                    0, list_dir_proc, &ls);
        fprintf(ls.f, "\n");
        close_pager(ls.f);
index 6100434033e17c922e5f621d5901587c8536d8ac..251e06ebaadabd4722be59403b6511a929238c00 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * undelete.c --- routines to try to help a user recover a deleted file.
+ * lsdel.c --- routines to try to help a user recover a deleted file.
  * 
- * Copyright (C) 1994 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ * Theodore Ts'o.  This file may be redistributed under the terms of
+ * the GNU Public License.
  */
 
 #include <stdio.h>
@@ -78,13 +79,20 @@ void do_lsdel(int argc, char **argv)
        errcode_t               retval;
        char                    *block_buf;
        int                     i;
+       long                    secs = 0;
+       char                    *tmp;
+       time_t                  now = time(0);
        
-       if (argc > 1) {
-               com_err(argv[0], 0, "Usage: ls_deleted_inodes\n");
+       if (common_args_process(argc, argv, 1, 2, "ls_deleted_inodes",
+                               "[secs]", 0))
                return;
+       if (argc > 1) {
+               secs = strtol(argv[1],&tmp,0);
+               if (*tmp) {
+                       com_err(argv[0], 0, "Bad time - %s",argv[1]);
+                       return;
+               }
        }
-       if (check_fs_open(argv[0]))
-               return;
 
        max_delarray = 100;
        num_delarray = 0;
@@ -118,7 +126,8 @@ void do_lsdel(int argc, char **argv)
        }
        
        while (ino) {
-               if (inode.i_dtime == 0)
+               if ((inode.i_dtime == 0) ||
+                   (secs && ((now - secs) > inode.i_dtime)))
                        goto next;
 
                lsd.inode = ino;
@@ -170,7 +179,6 @@ void do_lsdel(int argc, char **argv)
                }
        }
 
-       printf("%d deleted inodes found.\n", num_delarray);
        printf(" Inode  Owner  Mode    Size    Blocks    Time deleted\n");
        
        qsort(delarray, num_delarray, sizeof(struct deleted_info),
@@ -182,6 +190,7 @@ void do_lsdel(int argc, char **argv)
                       delarray[i].free_blocks, delarray[i].num_blocks, 
                       time_to_string(delarray[i].dtime));
        }
+       printf("%d deleted inodes found.\n", num_delarray);
        
 error_out:
        free(block_buf);
index d48bd048739d8e7008fd26322af056593a6975b2..ce574d0b3e1fc9ac29f07300f3c83af7a2eca0cb 100644 (file)
@@ -169,7 +169,7 @@ static errcode_t parse_string(struct super_set_info *info, char *arg)
        return 0;
 }
 
-static void print_possible_fields()
+static void print_possible_fields(void)
 {
        struct super_set_info *ss;
        const char      *type;
@@ -190,9 +190,9 @@ static void print_possible_fields()
 
 void do_set_super(int argc, char *argv[])
 {
-       const char *usage = "Usage: set_super <field> <value>\n"
-               "\t\"set_super -l\" will list the names of superblock fields "
-               "which\n\tcan be set.";
+       const char *usage = "<field> <value>\n"
+               "\t\"set_super_value -l\" will list the names of "
+               "superblock fields\n\twhich can be set.";
        static struct super_set_info *ss;
        
        if ((argc == 2) && !strcmp(argv[1], "-l")) {
@@ -200,17 +200,10 @@ void do_set_super(int argc, char *argv[])
                return;
        }
 
-       if (check_fs_open(argv[0]))
+       if (common_args_process(argc, argv, 3, 3, "set_super_value",
+                               usage, CHECK_FS_RW))
                return;
 
-       if (argc != 3) {
-               com_err(argv[0], 0, usage);
-               return;
-       }
-
-       if (check_fs_read_write(argv[0]))
-               return;
-       
        if ((ss = find_field(argv[1])) == 0) {
                com_err(argv[0], 0, "invalid field specifier: %s", argv[1]);
                return;
index 6fcbac2207204f18f1dba7cd77d1c54d2df5436f..183a5f6065e022b9997f604840081e91ab3ebc4c 100644 (file)
@@ -132,6 +132,135 @@ char *time_to_string(__u32 cl)
        return ctime(&t);
 }
 
+/*
+ * This function will convert a string to an unsigned long, printing
+ * an error message if it fails, and returning success or failure in err.
+ */
+unsigned long parse_ulong(const char *str, const char *cmd,
+                         const char *descr, int *err)
+{
+       char            *tmp;
+       unsigned long   ret;
+       
+       ret = strtoul(str, &tmp, 0);
+       if (*tmp == 0) {
+               if (*err)
+                       *err = 0;
+               return ret;
+       }
+       com_err(cmd, 0, "Bad %s - %s", descr, str);
+       if (*err)
+               *err = 1;
+       else
+               exit(1);
+       return 0;
+}
+
+/*
+ * This function will convert a string to a block number.  It returns
+ * 0 on success, 1 on failure.
+ */
+int strtoblk(const char *cmd, const char *str, blk_t *ret)
+{
+       blk_t   blk;
+       int     err;
+
+       blk = parse_ulong(str, cmd, "block number", &err);
+       *ret = blk;
+       if (err == 0 && blk == 0) {
+               com_err(cmd, 0, "Invalid block number 0");
+               err = 1;
+       }
+       return err;
+}
+
+/*
+ * This is a common helper function used by the command processing
+ * routines
+ */
+int common_args_process(int argc, char *argv[], int min_argc, int max_argc,
+                       const char *cmd, const char *usage, int flags)
+{
+       if (argc < min_argc || argc > max_argc) {
+               com_err(argv[0], 0, "Usage: %s %s", cmd, usage);
+               return 1;
+       }
+       if (flags & CHECK_FS_NOTOPEN) {
+               if (check_fs_not_open(argv[0]))
+                       return 1;
+       } else {
+               if (check_fs_open(argv[0]))
+                       return 1;
+       }
+       if ((flags & CHECK_FS_RW) && check_fs_read_write(argv[0]))
+               return 1;
+       if ((flags & CHECK_FS_BITMAPS) && check_fs_bitmaps(argv[0]))
+               return 1;
+       return 0;
+}
 
+/*
+ * This is a helper function used by do_stat, do_freei, do_seti, and
+ * do_testi, etc.  Basically, any command which takes a single
+ * argument which is a file/inode number specifier.
+ */
+int common_inode_args_process(int argc, char *argv[],
+                             ext2_ino_t *inode, int flags)
+{
+       if (common_args_process(argc, argv, 2, 2, argv[0], "<file>", flags))
+               return 1;
        
+       *inode = string_to_inode(argv[1]);
+       if (!*inode) 
+               return 1;
+       return 0;
+}
+
+/*
+ * This is a helper function used by do_freeb, do_setb, and do_testb
+ */
+int common_block_args_process(int argc, char *argv[],
+                             blk_t *block, int *count)
+{
+       int     err;
+
+       if (common_args_process(argc, argv, 2, 3, argv[0],
+                               "<block> [count]", CHECK_FS_BITMAPS))
+               return 1;
+
+       if (strtoblk(argv[0], argv[1], block))
+               return 1;
+       if (argc > 2) {
+               *count = parse_ulong(argv[0], argv[2], "count", &err);
+               if (err)
+                       return 1;
+       }
+       return 0;
+}
+
+int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode,
+                       const char *cmd)
+{
+       int retval;
+
+       retval = ext2fs_read_inode(current_fs, ino, inode);
+       if (retval) {
+               com_err(cmd, retval, "while reading inode %u", ino);
+               return 1;
+       }
+       return 0;
+}
+
+int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode,
+                       const char *cmd)
+{
+       int retval;
+
+       retval = ext2fs_write_inode(current_fs, ino, inode);
+       if (retval) {
+               com_err(cmd, retval, "while writing inode %u", ino);
+               return 1;
+       }
+       return 0;
+}