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