dump.c revision 544349270e4c74a6feb971123884a8cf5052a7ee
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 27f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 28f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include "debugfs.h" 29f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 30819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o#ifndef O_LARGEFILE 31819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o#define O_LARGEFILE 0 32819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o#endif 33819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o 34fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o/* 35fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o * The mode_xlate function translates a linux mode into a native-OS mode_t. 36fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o */ 37fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'ostatic struct { 38fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o __u16 lmask; 39fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o mode_t mask; 40fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o} mode_table[] = { 41fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IRUSR, S_IRUSR }, 42fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IWUSR, S_IWUSR }, 43fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IXUSR, S_IXUSR }, 44fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IRGRP, S_IRGRP }, 45fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IWGRP, S_IWGRP }, 46fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IXGRP, S_IXGRP }, 47fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IROTH, S_IROTH }, 48fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IWOTH, S_IWOTH }, 49fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { LINUX_S_IXOTH, S_IXOTH }, 50fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o { 0, 0 } 51fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o}; 52fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o 53fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'ostatic mode_t mode_xlate(__u16 lmode) 54fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o{ 55fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o mode_t mode = 0; 56fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o int i; 57fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o 58fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o for (i=0; mode_table[i].lmask; i++) { 59fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o if (lmode & mode_table[i].lmask) 60fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o mode |= mode_table[i].mask; 61fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o } 62fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o return mode; 63fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o} 64fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o 652e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'ostatic void fix_perms(const char *cmd, const struct ext2_inode *inode, 662e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o int fd, const char *name) 672e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o{ 682e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o struct utimbuf ut; 692e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o int i; 702e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 712e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (fd != -1) 722e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o i = fchmod(fd, mode_xlate(inode->i_mode)); 732e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o else 742e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o i = chmod(name, mode_xlate(inode->i_mode)); 752e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (i == -1) 762e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err(cmd, errno, "while setting permissions of %s", name); 772e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 782e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o#ifndef HAVE_FCHOWN 79c5de1d4a0d1a45e3068247192d2297f94d70340fTheodore Ts'o i = chown(name, inode->i_uid, inode->i_gid); 802e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o#else 812e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (fd != -1) 822e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o i = fchown(fd, inode->i_uid, inode->i_gid); 832e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o else 842e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o i = chown(name, inode->i_uid, inode->i_gid); 852e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o#endif 862e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (i == -1) 872e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err(cmd, errno, "while changing ownership of %s", name); 882e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 892e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (fd != -1) 902e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o close(fd); 912e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 922e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o ut.actime = inode->i_atime; 932e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o ut.modtime = inode->i_mtime; 942e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (utime(name, &ut) == -1) 952e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err(cmd, errno, "while setting times of %s", name); 962e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o} 972e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 98b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'ostatic void dump_file(const char *cmdname, ext2_ino_t ino, int fd, 99b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o int preserve, char *outname) 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 101f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o errcode_t retval; 102fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o struct ext2_inode inode; 1035a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o char buf[8192]; 1045a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o ext2_file_t e2_file; 1054a31c48b827f378f386b28461fd14b41d709e4ebTheodore Ts'o int nbytes; 1064a31c48b827f378f386b28461fd14b41d709e4ebTheodore Ts'o unsigned int got; 1075a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o 108e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (debugfs_read_inode(ino, &inode, cmdname)) 109fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o return; 110f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1115a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o retval = ext2fs_file_open(current_fs, ino, 0, &e2_file); 1125a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o if (retval) { 1135a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o com_err(cmdname, retval, "while opening ext2 file"); 114f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 115f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1165a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o while (1) { 1175a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o retval = ext2fs_file_read(e2_file, buf, sizeof(buf), &got); 1185a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o if (retval) 1195a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o com_err(cmdname, retval, "while reading ext2 file"); 1205a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o if (got == 0) 1215a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o break; 1225a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o nbytes = write(fd, buf, got); 123544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if ((unsigned) nbytes != got) 1245a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o com_err(cmdname, errno, "while writing file"); 125f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1265a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o retval = ext2fs_file_close(e2_file); 1275a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o if (retval) { 1285a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o com_err(cmdname, retval, "while closing ext2 file"); 1295a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o return; 130f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1315a51384ef2cdcb2d49965c841ff558afc1f4ee01Theodore Ts'o 1322e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (preserve) 1332e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o fix_perms("dump_file", &inode, fd, outname); 1342e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o else if (fd != 1) 135fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o close(fd); 136fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o 137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 138f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 139f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 140f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ovoid do_dump(int argc, char **argv) 141f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 142b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t inode; 143b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o int fd; 144b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o int c; 145b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o int preserve = 0; 146fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o const char *dump_usage = "Usage: dump_inode [-p] <file> <output_file>"; 147b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o char *in_fn, *out_fn; 148fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o 14988494bb6d440f703db98b6cc4452f63d7aa392b9Theodore Ts'o reset_getopt(); 150fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o while ((c = getopt (argc, argv, "p")) != EOF) { 151fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o switch (c) { 152fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o case 'p': 153fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o preserve++; 154fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o break; 155fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o default: 156fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o com_err(argv[0], 0, dump_usage); 157fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o return; 158fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o } 159fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o } 160fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o if (optind != argc-2) { 161fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o com_err(argv[0], 0, dump_usage); 162f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 163f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 164f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 165f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (check_fs_open(argv[0])) 166f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 167f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 168fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o in_fn = argv[optind]; 169fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o out_fn = argv[optind+1]; 170fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o 171fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o inode = string_to_inode(in_fn); 172f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!inode) 173f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 174f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 175819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o fd = open(out_fn, O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE, 0666); 176f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (fd < 0) { 177f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err(argv[0], errno, "while opening %s for dump_inode", 178fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o out_fn); 179f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 180f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 181f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 182fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o dump_file(argv[0], inode, fd, preserve, out_fn); 183f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 184f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 185f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 186f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 187b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'ostatic void rdump_symlink(ext2_ino_t ino, struct ext2_inode *inode, 1882e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o const char *fullname) 1892e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o{ 1902e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o ext2_file_t e2_file; 1912e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o char *buf; 1922e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o errcode_t retval; 1932e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 1942e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o buf = malloc(inode->i_size + 1); 1952e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (!buf) { 1962e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", errno, "while allocating for symlink"); 1972e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o goto errout; 1982e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 1992e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2002e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o /* Apparently, this is the right way to detect and handle fast 2012e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o * symlinks; see do_stat() in debugfs.c. */ 2022e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (inode->i_blocks == 0) 2032e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o strcpy(buf, (char *) inode->i_block); 2042e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o else { 2052e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o unsigned bytes = inode->i_size; 2062e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o char *p = buf; 2072e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o retval = ext2fs_file_open(current_fs, ino, 0, &e2_file); 2082e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (retval) { 2092e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", retval, "while opening symlink"); 2102e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o goto errout; 2112e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2122e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o for (;;) { 2132e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o unsigned int got; 2142e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o retval = ext2fs_file_read(e2_file, p, bytes, &got); 2152e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (retval) { 2162e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", retval, "while reading symlink"); 2172e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o goto errout; 2182e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2192e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o bytes -= got; 2202e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o p += got; 2212e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (got == 0 || bytes == 0) 2222e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o break; 2232e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2242e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o buf[inode->i_size] = 0; 2252e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o retval = ext2fs_file_close(e2_file); 2262e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (retval) 2272e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", retval, "while closing symlink"); 2282e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2292e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2302e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (symlink(buf, fullname) == -1) { 2312e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", errno, "while creating symlink %s -> %s", buf, fullname); 2322e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o goto errout; 2332e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2342e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2352e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'oerrout: 2362e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o free(buf); 2372e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o} 2382e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2392e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'ostatic int rdump_dirent(struct ext2_dir_entry *, int, int, char *, void *); 2402e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 241b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'ostatic void rdump_inode(ext2_ino_t ino, struct ext2_inode *inode, 2422e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o const char *name, const char *dumproot) 2432e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o{ 2442e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o char *fullname; 2452e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2462e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o /* There are more efficient ways to do this, but this method 2472e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o * requires only minimal debugging. */ 2482e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o fullname = malloc(strlen(dumproot) + strlen(name) + 2); 2492e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (!fullname) { 2502e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", errno, "while allocating memory"); 2512e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return; 2522e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2532e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o sprintf(fullname, "%s/%s", dumproot, name); 2542e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2552e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (LINUX_S_ISLNK(inode->i_mode)) 2562e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o rdump_symlink(ino, inode, fullname); 2572e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o else if (LINUX_S_ISREG(inode->i_mode)) { 2582e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o int fd; 2592e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o fd = open(fullname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); 2602e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (fd == -1) { 2612e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", errno, "while dumping %s", fullname); 2622e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o goto errout; 2632e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2642e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o dump_file("rdump", ino, fd, 1, fullname); 2652e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2662e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o else if (LINUX_S_ISDIR(inode->i_mode) && strcmp(name, ".") && strcmp(name, "..")) { 2672e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o errcode_t retval; 2682e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2692e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o /* Create the directory with 0700 permissions, because we 2702e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o * expect to have to create entries it. Then fix its perms 2712e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o * once we've done the traversal. */ 2722e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (mkdir(fullname, S_IRWXU) == -1) { 2732e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", errno, "while making directory %s", fullname); 2742e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o goto errout; 2752e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2762e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2772e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o retval = ext2fs_dir_iterate(current_fs, ino, 0, 0, 2782e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o rdump_dirent, (void *) fullname); 2792e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (retval) 2802e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", retval, "while dumping %s", fullname); 2812e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2822e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o fix_perms("rdump", inode, -1, fullname); 2832e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 2842e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o /* else do nothing (don't dump device files, sockets, fifos, etc.) */ 2852e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 2862e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'oerrout: 2872e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o free(fullname); 2882e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o} 2892e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 290544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int rdump_dirent(struct ext2_dir_entry *dirent, 291544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int offset EXT2FS_ATTR((unused)), 292544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int blocksize EXT2FS_ATTR((unused)), 293544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o char *buf EXT2FS_ATTR((unused)), void *private) 2942e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o{ 2952e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o char name[EXT2_NAME_LEN]; 2962e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o int thislen; 2972e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o const char *dumproot = private; 2982e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o struct ext2_inode inode; 2992e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3002e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN 3012e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o ? (dirent->name_len & 0xFF) : EXT2_NAME_LEN); 3022e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o strncpy(name, dirent->name, thislen); 3032e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o name[thislen] = 0; 3042e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 305e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (debugfs_read_inode(dirent->inode, &inode, name)) 3062e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return 0; 3072e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3082e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o rdump_inode(dirent->inode, &inode, name, dumproot); 3092e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3102e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return 0; 3112e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o} 3122e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3132e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'ovoid do_rdump(int argc, char **argv) 3142e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o{ 315b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t ino; 3162e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o struct ext2_inode inode; 3172e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o struct stat st; 3182e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o int i; 3192e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o char *p; 3202e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 321e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (common_args_process(argc, argv, 3, 3, "rdump", 322e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o "<directory> <native directory>", 0)) 3232e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return; 3242e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3252e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o ino = string_to_inode(argv[1]); 3262e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (!ino) 3272e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return; 3282e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3292e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o /* Ensure ARGV[2] is a directory. */ 3302e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o i = stat(argv[2], &st); 3312e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (i == -1) { 3322e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", errno, "while statting %s", argv[2]); 3332e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return; 3342e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 3352e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (!S_ISDIR(st.st_mode)) { 3362e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o com_err("rdump", 0, "%s is not a directory", argv[2]); 3372e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return; 3382e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o } 3392e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 340e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (debugfs_read_inode(ino, &inode, argv[1])) 3412e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o return; 3422e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3432e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o p = strrchr(argv[1], '/'); 3442e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o if (p) 3452e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o p++; 3462e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o else 3472e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o p = argv[1]; 3482e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 3492e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o rdump_inode(ino, &inode, p, argv[2]); 3502e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o} 3512e8d40d562ec93d68505800a46c5b9dcc229264eTheodore Ts'o 352f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ovoid do_cat(int argc, char **argv) 353f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 354b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t inode; 355f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 356e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (common_inode_args_process(argc, argv, &inode, 0)) 357f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 358f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 359fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o fflush(stdout); 360fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o fflush(stderr); 361fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o dump_file(argv[0], inode, 1, 0, argv[2]); 362f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 363f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 364f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 365f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 366