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