dump.c revision 4a31c48b827f378f386b28461fd14b41d709e4eb
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>
1450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_ERRNO_H
1550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h>
1650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
17f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h>
18f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/stat.h>
19f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <fcntl.h>
20fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#include <utime.h>
21fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#ifdef HAVE_GETOPT_H
22fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#include <getopt.h>
23fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#else
24fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'oextern int optind;
25fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'oextern char *optarg;
26fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#endif
27fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#ifdef HAVE_OPTRESET
28fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'oextern int optreset;		/* defined by BSD, but not others */
29fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#endif
30f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
31f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include "debugfs.h"
32f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
33fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o/*
34fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o * The mode_xlate function translates a linux mode into a native-OS mode_t.
35fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o */
36fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'ostatic struct {
37fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	__u16 lmask;
38fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	mode_t mask;
39fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o} mode_table[] = {
40fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IRUSR, S_IRUSR },
41fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IWUSR, S_IWUSR },
42fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IXUSR, S_IXUSR },
43fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IRGRP, S_IRGRP },
44fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IWGRP, S_IWGRP },
45fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IXGRP, S_IXGRP },
46fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IROTH, S_IROTH },
47fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IWOTH, S_IWOTH },
48fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ LINUX_S_IXOTH, S_IXOTH },
49fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	{ 0, 0 }
50fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o};
51fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o
52fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'ostatic mode_t mode_xlate(__u16 lmode)
53fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o{
54fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	mode_t	mode = 0;
55fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	int	i;
56fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o
57fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	for (i=0; mode_table[i].lmask; i++) {
58fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		if (lmode & mode_table[i].lmask)
59fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			mode |= mode_table[i].mask;
60fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	}
61fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	return mode;
62fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o}
63fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o
64fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'ostatic void dump_file(char *cmdname, ino_t ino, int fd, int preserve,
65fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		      char *outname)
66f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
67f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	errcode_t retval;
68fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	struct ext2_inode	inode;
69fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	struct utimbuf	ut;
705a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o	char 		buf[8192];
715a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o	ext2_file_t	e2_file;
724a31c48b827f378f386b28461fd14b41d709e4ebTheodore Ts'o	int		nbytes;
734a31c48b827f378f386b28461fd14b41d709e4ebTheodore Ts'o	unsigned int	got;
745a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o
75fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	retval = ext2fs_read_inode(current_fs, ino, &inode);
76fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	if (retval) {
77fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		com_err(cmdname, retval,
78fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			"while reading inode %u in dump_file", ino);
79fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		return;
80fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	}
81f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
825a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o	retval = ext2fs_file_open(current_fs, ino, 0, &e2_file);
835a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o	if (retval) {
845a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		com_err(cmdname, retval, "while opening ext2 file");
85f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
86f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
875a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o	while (1) {
885a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		retval = ext2fs_file_read(e2_file, buf, sizeof(buf), &got);
895a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		if (retval)
905a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o			com_err(cmdname, retval, "while reading ext2 file");
915a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		if (got == 0)
925a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o			break;
935a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		nbytes = write(fd, buf, got);
945a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		if (nbytes != got)
955a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o			com_err(cmdname, errno, "while writing file");
96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
975a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o	retval = ext2fs_file_close(e2_file);
985a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o	if (retval) {
995a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		com_err(cmdname, retval, "while closing ext2 file");
1005a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o		return;
101f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
1025a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o
103fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	if (preserve) {
104fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#ifdef HAVE_FCHOWN
105fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		if (fchown(fd, inode.i_uid, inode.i_gid) < 0)
106fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			com_err("dump_file", errno,
107fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o				"while changing ownership of %s", outname);
108fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#else
109fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		if (chown(outname, inode.i_uid, inode.i_gid) < 0)
110fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			com_err("dump_file", errno,
111fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o				"while changing ownership of %s", outname);
112fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o
113fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#endif
114fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		if (fchmod(fd, mode_xlate(inode.i_mode)) < 0)
115fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			com_err("dump_file", errno,
116fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o				"while setting permissions of %s", outname);
117fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		ut.actime = inode.i_atime;
118fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		ut.modtime = inode.i_mtime;
119fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		close(fd);
120fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		if (utime(outname, &ut) < 0)
121fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			com_err("dump_file", errno,
122fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o				"while setting times on %s", outname);
123fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	} else if (fd != 1)
124fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		close(fd);
125fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o
126f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	return;
127f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
128f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
129f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ovoid do_dump(int argc, char **argv)
130f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
131f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	ino_t	inode;
132f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	int	fd;
133f13048113f09def05a024470bfeaf44635bf7e98Theodore Ts'o	int	c;
134fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	int	preserve = 0;
135fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	const char *dump_usage = "Usage: dump_inode [-p] <file> <output_file>";
136fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	char	*in_fn, *out_fn;
137fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o
138fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	optind = 0;
139fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#ifdef HAVE_OPTRESET
140fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	optreset = 1;		/* Makes BSD getopt happy */
141fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o#endif
142fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	while ((c = getopt (argc, argv, "p")) != EOF) {
143fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		switch (c) {
144fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		case 'p':
145fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			preserve++;
146fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			break;
147fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		default:
148fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			com_err(argv[0], 0, dump_usage);
149fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			return;
150fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		}
151fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	}
152fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	if (optind != argc-2) {
153fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o		com_err(argv[0], 0, dump_usage);
154f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
155f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
156f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
157f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (check_fs_open(argv[0]))
158f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
159f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
160fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	in_fn = argv[optind];
161fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	out_fn = argv[optind+1];
162fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o
163fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	inode = string_to_inode(in_fn);
164f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (!inode)
165f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
166f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
167fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	fd = open(out_fn, O_CREAT | O_WRONLY | O_TRUNC, 0666);
168f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (fd < 0) {
169f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		com_err(argv[0], errno, "while opening %s for dump_inode",
170fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o			out_fn);
171f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
172f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
173f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
174fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	dump_file(argv[0], inode, fd, preserve, out_fn);
175f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
176f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	return;
177f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
178f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
179f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ovoid do_cat(int argc, char **argv)
180f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
181f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	ino_t	inode;
182f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
183f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (argc != 2) {
184f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		com_err(argv[0], 0, "Usage: cat <file>");
185f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
186f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
187f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
188f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (check_fs_open(argv[0]))
189f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
190f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
191f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	inode = string_to_inode(argv[1]);
192f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (!inode)
193f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return;
194f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
195fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	fflush(stdout);
196fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	fflush(stderr);
197fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o	dump_file(argv[0], inode, 1, 0, argv[2]);
198f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
199f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	return;
200f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
201f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
202