mirror of https://github.com/vitalif/e2fsprogs
144 lines
2.6 KiB
C
144 lines
2.6 KiB
C
/*
|
|
* dump.c --- dump the contents of an inode out to a file
|
|
*
|
|
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
|
|
* under the terms of the GNU Public License.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <getopt.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "debugfs.h"
|
|
|
|
struct dump_block_struct {
|
|
int fd;
|
|
char *buf;
|
|
errcode_t errcode;
|
|
};
|
|
|
|
int dump_block(ext2_filsys fs, blk_t *blocknr, int blockcnt, void
|
|
*private)
|
|
{
|
|
ssize_t nbytes;
|
|
|
|
struct dump_block_struct *rec = (struct dump_block_struct *) private;
|
|
|
|
if (blockcnt < 0)
|
|
return 0;
|
|
|
|
if (*blocknr) {
|
|
rec->errcode = io_channel_read_blk(fs->io, *blocknr,
|
|
1, rec->buf);
|
|
if (rec->errcode)
|
|
return BLOCK_ABORT;
|
|
} else
|
|
memset(rec->buf, 0, fs->blocksize);
|
|
|
|
retry_write:
|
|
nbytes = write(rec->fd, rec->buf, fs->blocksize);
|
|
if (nbytes == -1) {
|
|
if (errno == EINTR)
|
|
goto retry_write;
|
|
rec->errcode = errno;
|
|
return BLOCK_ABORT;
|
|
}
|
|
if (nbytes != fs->blocksize) {
|
|
/* XXX not quite right, but good enough */
|
|
rec->errcode = EXT2_ET_SHORT_WRITE;
|
|
return BLOCK_ABORT;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void dump_file(char *cmdname, ino_t inode, int fd, char *outname)
|
|
{
|
|
errcode_t retval;
|
|
struct dump_block_struct rec;
|
|
|
|
rec.fd = fd;
|
|
rec.errcode = 0;
|
|
rec.buf = malloc(fs->blocksize);
|
|
|
|
if (rec.buf == 0) {
|
|
com_err(cmdname, ENOMEM, "while allocating block buffer for dump_inode");
|
|
return;
|
|
}
|
|
|
|
retval = ext2fs_block_iterate(fs, inode, 0, NULL,
|
|
dump_block, &rec);
|
|
if (retval) {
|
|
com_err(cmdname, retval, "while iterating over blocks in %s",
|
|
outname);
|
|
goto cleanup;
|
|
}
|
|
if (rec.errcode) {
|
|
com_err(cmdname, retval, "in dump_block while dumping %s",
|
|
outname);
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
free(rec.buf);
|
|
return;
|
|
}
|
|
|
|
void do_dump(int argc, char **argv)
|
|
{
|
|
ino_t inode;
|
|
int fd;
|
|
|
|
if (argc != 3) {
|
|
com_err(argv[0], 0, "Usage: dump_inode <file> <output_file>");
|
|
return;
|
|
}
|
|
|
|
if (check_fs_open(argv[0]))
|
|
return;
|
|
|
|
inode = string_to_inode(argv[1]);
|
|
if (!inode)
|
|
return;
|
|
|
|
fd = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC, 0666);
|
|
if (fd < 0) {
|
|
com_err(argv[0], errno, "while opening %s for dump_inode",
|
|
argv[2]);
|
|
return;
|
|
}
|
|
|
|
dump_file(argv[0], inode, fd, argv[2]);
|
|
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
void do_cat(int argc, char **argv)
|
|
{
|
|
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)
|
|
return;
|
|
|
|
dump_file(argv[0], inode, 0, argv[2]);
|
|
|
|
return;
|
|
}
|
|
|