dump.c revision 50e1e10fa0ac12a3e2a9d20a75ee9041873cda96
1/*
2 * dump.c --- dump the contents of an inode out to a file
3 *
4 * Copyright (C) 1994 Theodore Ts'o.  This file may be redistributed
5 * under the terms of the GNU Public License.
6 */
7
8#include <stdio.h>
9#include <unistd.h>
10#include <stdlib.h>
11#include <ctype.h>
12#include <string.h>
13#include <time.h>
14#ifdef HAVE_ERRNO_H
15#include <errno.h>
16#endif
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20
21#include "debugfs.h"
22
23struct dump_block_struct {
24	int		fd;
25	char		*buf;
26	errcode_t	errcode;
27};
28
29static int dump_block(ext2_filsys fs, blk_t *blocknr, int blockcnt,
30		      void *private)
31{
32	ssize_t nbytes;
33
34	struct dump_block_struct *rec = (struct dump_block_struct *) private;
35
36	if (blockcnt < 0)
37		return 0;
38
39	if (*blocknr) {
40		rec->errcode = io_channel_read_blk(fs->io, *blocknr,
41						   1, rec->buf);
42		if (rec->errcode)
43			return BLOCK_ABORT;
44	} else
45		memset(rec->buf, 0, fs->blocksize);
46
47retry_write:
48	nbytes = write(rec->fd, rec->buf, fs->blocksize);
49	if (nbytes == -1) {
50		if (errno == EINTR)
51			goto retry_write;
52		rec->errcode = errno;
53		return BLOCK_ABORT;
54	}
55	if (nbytes != fs->blocksize) {
56		/* XXX not quite right, but good enough */
57		rec->errcode = EXT2_ET_SHORT_WRITE;
58		return BLOCK_ABORT;
59	}
60	return 0;
61}
62
63static void dump_file(char *cmdname, ino_t inode, int fd, char *outname)
64{
65	errcode_t retval;
66	struct dump_block_struct rec;
67
68	rec.fd = fd;
69	rec.errcode = 0;
70	rec.buf = malloc(fs->blocksize);
71
72	if (rec.buf == 0) {
73		com_err(cmdname, ENOMEM, "while allocating block buffer for dump_inode");
74		return;
75	}
76
77	retval = ext2fs_block_iterate(fs, inode, 0, NULL,
78				      dump_block, &rec);
79	if (retval) {
80		com_err(cmdname, retval, "while iterating over blocks in %s",
81			outname);
82		goto cleanup;
83	}
84	if (rec.errcode) {
85		com_err(cmdname, retval, "in dump_block while dumping %s",
86			outname);
87		goto cleanup;
88	}
89
90cleanup:
91	free(rec.buf);
92	return;
93}
94
95void do_dump(int argc, char **argv)
96{
97	ino_t	inode;
98	int	fd;
99
100	if (argc != 3) {
101		com_err(argv[0], 0, "Usage: dump_inode <file> <output_file>");
102		return;
103	}
104
105	if (check_fs_open(argv[0]))
106		return;
107
108	inode = string_to_inode(argv[1]);
109	if (!inode)
110		return;
111
112	fd = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC, 0666);
113	if (fd < 0) {
114		com_err(argv[0], errno, "while opening %s for dump_inode",
115			argv[2]);
116		return;
117	}
118
119	dump_file(argv[0], inode, fd, argv[2]);
120
121	close(fd);
122	return;
123}
124
125void do_cat(int argc, char **argv)
126{
127	ino_t	inode;
128
129	if (argc != 2) {
130		com_err(argv[0], 0, "Usage: cat <file>");
131		return;
132	}
133
134	if (check_fs_open(argv[0]))
135		return;
136
137	inode = string_to_inode(argv[1]);
138	if (!inode)
139		return;
140
141	dump_file(argv[0], inode, 0, argv[2]);
142
143	return;
144}
145
146