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