/* * 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 #include #include #include #include #include #include #include #include #include #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 "); 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 "); 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; }