Whamcloud - gitweb
debugfs: support encoding when printing the file hash
[tools/e2fsprogs.git] / debugfs / dump.c
index 4cf0752..fdd6619 100644 (file)
@@ -9,6 +9,7 @@
 #define _GNU_SOURCE /* for O_LARGEFILE */
 #endif
 
+#include "config.h"
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -90,9 +91,6 @@ static void fix_perms(const char *cmd, const struct ext2_inode *inode,
        if (i == -1)
                com_err(cmd, errno, "while changing ownership of %s", name);
 
-       if (fd != -1)
-               close(fd);
-
        ut.actime = inode->i_atime;
        ut.modtime = inode->i_mtime;
        if (utime(name, &ut) == -1)
@@ -104,10 +102,10 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd,
 {
        errcode_t retval;
        struct ext2_inode       inode;
-       char            buf[8192];
+       char            *buf = 0;
        ext2_file_t     e2_file;
        int             nbytes;
-       unsigned int    got;
+       unsigned int    got, blocksize = current_fs->blocksize;
 
        if (debugfs_read_inode(ino, &inode, cmdname))
                return;
@@ -117,8 +115,13 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd,
                com_err(cmdname, retval, "while opening ext2 file");
                return;
        }
+       retval = ext2fs_get_mem(blocksize, &buf);
+       if (retval) {
+               com_err(cmdname, retval, "while allocating memory");
+               return;
+       }
        while (1) {
-               retval = ext2fs_file_read(e2_file, buf, sizeof(buf), &got);
+               retval = ext2fs_file_read(e2_file, buf, blocksize, &got);
                if (retval)
                        com_err(cmdname, retval, "while reading ext2 file");
                if (got == 0)
@@ -127,6 +130,8 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd,
                if ((unsigned) nbytes != got)
                        com_err(cmdname, errno, "while writing file");
        }
+       if (buf)
+               ext2fs_free_mem(&buf);
        retval = ext2fs_file_close(e2_file);
        if (retval) {
                com_err(cmdname, retval, "while closing ext2 file");
@@ -135,13 +140,12 @@ static void dump_file(const char *cmdname, ext2_ino_t ino, int fd,
 
        if (preserve)
                fix_perms("dump_file", &inode, fd, outname);
-       else if (fd != 1)
-               close(fd);
 
        return;
 }
 
-void do_dump(int argc, char **argv)
+void do_dump(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
+            void *infop EXT2FS_ATTR((unused)))
 {
        ext2_ino_t      inode;
        int             fd;
@@ -183,6 +187,11 @@ void do_dump(int argc, char **argv)
        }
 
        dump_file(argv[0], inode, fd, preserve, out_fn);
+       if (close(fd) != 0) {
+               com_err(argv[0], errno, "while closing %s for dump_inode",
+                       out_fn);
+               return;
+       }
 
        return;
 }
@@ -200,9 +209,7 @@ static void rdump_symlink(ext2_ino_t ino, struct ext2_inode *inode,
                goto errout;
        }
 
-       /* Apparently, this is the right way to detect and handle fast
-        * symlinks; see do_stat() in debugfs.c. */
-       if (inode->i_blocks == 0)
+       if (ext2fs_is_fast_symlink(inode))
                strcpy(buf, (char *) inode->i_block);
        else {
                unsigned bytes = inode->i_size;
@@ -261,10 +268,14 @@ static void rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
                int fd;
                fd = open(fullname, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRWXU);
                if (fd == -1) {
-                       com_err("rdump", errno, "while dumping %s", fullname);
+                       com_err("rdump", errno, "while opening %s", fullname);
                        goto errout;
                }
                dump_file("rdump", ino, fd, 1, fullname);
+               if (close(fd) != 0) {
+                       com_err("rdump", errno, "while closing %s", fullname);
+                       goto errout;
+               }
        }
        else if (LINUX_S_ISDIR(inode->i_mode) && strcmp(name, ".") && strcmp(name, "..")) {
                errcode_t retval;
@@ -272,7 +283,7 @@ static void rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
                /* Create the directory with 0700 permissions, because we
                 * expect to have to create entries it.  Then fix its perms
                 * once we've done the traversal. */
-               if (mkdir(fullname, S_IRWXU) == -1) {
+               if (name[0] && mkdir(fullname, S_IRWXU) == -1) {
                        com_err("rdump", errno, "while making directory %s", fullname);
                        goto errout;
                }
@@ -300,8 +311,7 @@ static int rdump_dirent(struct ext2_dir_entry *dirent,
        const char *dumproot = private;
        struct ext2_inode inode;
 
-       thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN
-                  ? (dirent->name_len & 0xFF) : EXT2_NAME_LEN);
+       thislen = ext2fs_dirent_name_len(dirent);
        strncpy(name, dirent->name, thislen);
        name[thislen] = 0;
 
@@ -313,46 +323,53 @@ static int rdump_dirent(struct ext2_dir_entry *dirent,
        return 0;
 }
 
-void do_rdump(int argc, char **argv)
+void do_rdump(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
+             void *infop EXT2FS_ATTR((unused)))
 {
-       ext2_ino_t ino;
-       struct ext2_inode inode;
        struct stat st;
+       char *dest_dir;
        int i;
-       char *p;
 
-       if (common_args_process(argc, argv, 3, 3, "rdump",
-                               "<directory> <native directory>", 0))
+       if (common_args_process(argc, argv, 3, INT_MAX, "rdump",
+                               "<directory>... <native directory>", 0))
                return;
 
-       ino = string_to_inode(argv[1]);
-       if (!ino)
-               return;
+       /* Pull out last argument */
+       dest_dir = argv[argc - 1];
+       argc--;
 
-       /* Ensure ARGV[2] is a directory. */
-       i = stat(argv[2], &st);
-       if (i == -1) {
-               com_err("rdump", errno, "while statting %s", argv[2]);
+       /* Ensure last arg is a directory. */
+       if (stat(dest_dir, &st) == -1) {
+               com_err("rdump", errno, "while statting %s", dest_dir);
                return;
        }
        if (!S_ISDIR(st.st_mode)) {
-               com_err("rdump", 0, "%s is not a directory", argv[2]);
+               com_err("rdump", 0, "%s is not a directory", dest_dir);
                return;
        }
 
-       if (debugfs_read_inode(ino, &inode, argv[1]))
-               return;
+       for (i = 1; i < argc; i++) {
+               char *arg = argv[i], *basename;
+               struct ext2_inode inode;
+               ext2_ino_t ino = string_to_inode(arg);
+               if (!ino)
+                       continue;
 
-       p = strrchr(argv[1], '/');
-       if (p)
-               p++;
-       else
-               p = argv[1];
+               if (debugfs_read_inode(ino, &inode, arg))
+                       continue;
 
-       rdump_inode(ino, &inode, p, argv[2]);
+               basename = strrchr(arg, '/');
+               if (basename)
+                       basename++;
+               else
+                       basename = arg;
+
+               rdump_inode(ino, &inode, basename, dest_dir);
+       }
 }
 
-void do_cat(int argc, char **argv)
+void do_cat(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
+           void *infop EXT2FS_ATTR((unused)))
 {
        ext2_ino_t      inode;