2 * dump.c --- dump the contents of an inode out to a file
4 * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
5 * under the terms of the GNU Public License.
17 #include <sys/types.h>
28 extern int optreset; /* defined by BSD, but not others */
34 * The mode_xlate function translates a linux mode into a native-OS mode_t.
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 },
52 static mode_t mode_xlate(__u16 lmode)
57 for (i=0; mode_table[i].lmask; i++) {
58 if (lmode & mode_table[i].lmask)
59 mode |= mode_table[i].mask;
64 struct dump_block_struct {
71 static int dump_block(ext2_filsys fs, blk_t *blocknr, int blockcnt,
77 struct dump_block_struct *rec = (struct dump_block_struct *) private;
83 rec->errcode = io_channel_read_blk(fs->io, *blocknr,
89 * OK, the file has a hole. Let's try to seek past
90 * the hole in the destination file, so that the
91 * destination file has a hole too.
93 ret_off = lseek(rec->fd, fs->blocksize, SEEK_CUR);
96 memset(rec->buf, 0, fs->blocksize);
99 left = (rec->left > fs->blocksize) ? fs->blocksize : rec->left;
103 nbytes = write(rec->fd, rec->buf, left);
107 rec->errcode = errno;
117 static void dump_file(char *cmdname, ino_t ino, int fd, int preserve,
121 struct dump_block_struct rec;
122 struct ext2_inode inode;
125 retval = ext2fs_read_inode(current_fs, ino, &inode);
127 com_err(cmdname, retval,
128 "while reading inode %u in dump_file", ino);
134 rec.buf = malloc(current_fs->blocksize);
135 rec.left = inode.i_size;
138 com_err(cmdname, ENOMEM,
139 "while allocating block buffer for dump_inode");
143 retval = ext2fs_block_iterate(current_fs, ino,
144 BLOCK_FLAG_HOLE|BLOCK_FLAG_DATA_ONLY,
145 NULL, dump_block, &rec);
147 com_err(cmdname, retval, "while iterating over blocks in %s",
152 com_err(cmdname, retval, "in dump_block while dumping %s",
160 if (fchown(fd, inode.i_uid, inode.i_gid) < 0)
161 com_err("dump_file", errno,
162 "while changing ownership of %s", outname);
164 if (chown(outname, inode.i_uid, inode.i_gid) < 0)
165 com_err("dump_file", errno,
166 "while changing ownership of %s", outname);
169 if (fchmod(fd, mode_xlate(inode.i_mode)) < 0)
170 com_err("dump_file", errno,
171 "while setting permissions of %s", outname);
172 ut.actime = inode.i_atime;
173 ut.modtime = inode.i_mtime;
175 if (utime(outname, &ut) < 0)
176 com_err("dump_file", errno,
177 "while setting times on %s", outname);
185 void do_dump(int argc, char **argv)
191 const char *dump_usage = "Usage: dump_inode [-p] <file> <output_file>";
192 char *in_fn, *out_fn;
196 optreset = 1; /* Makes BSD getopt happy */
198 while ((c = getopt (argc, argv, "p")) != EOF) {
204 com_err(argv[0], 0, dump_usage);
208 if (optind != argc-2) {
209 com_err(argv[0], 0, dump_usage);
213 if (check_fs_open(argv[0]))
216 in_fn = argv[optind];
217 out_fn = argv[optind+1];
219 inode = string_to_inode(in_fn);
223 fd = open(out_fn, O_CREAT | O_WRONLY | O_TRUNC, 0666);
225 com_err(argv[0], errno, "while opening %s for dump_inode",
230 dump_file(argv[0], inode, fd, preserve, out_fn);
235 void do_cat(int argc, char **argv)
240 com_err(argv[0], 0, "Usage: cat <file>");
244 if (check_fs_open(argv[0]))
247 inode = string_to_inode(argv[1]);
253 dump_file(argv[0], inode, 1, 0, argv[2]);