Hi, currently ext3grep isn't part of lenny, mainly because of bad timing between me and the other co-maintainer; it was also blocked by RC bug #491621. Version 0.8.0-1 has now been in sid for almost two weeks without a bug, so I'm primarily asking here if the release team would concede a freeze unblock for it. I'm anyway aware that the team rightly doesn't like unblock for new upstream version, so I have already backported the fix for #491621 in a t-p-u revision (0.6.0-1+lenny1, whose debdiff to 0.6.0-1 is attached here) as a fallback option to have it in lenny. Patch was picked from upstream svn, it only contains inode_size adjustments and due changes to related groups/blocks management. I'm anyway more confident with 0.8.0-1, as it fixed a bunch of other possible issues, and is mainly the sane evolution of initial ext3grep draft into a more mature project. Both changelog mention BE-arch drop, but this non-issue has already been sorted out as per #495880. I hope you would allow ext3grep in lenny, as it will be quite a loss if we release without it. Please let me know how to proceed now. Ciao, Luca -- .''`. ** Debian GNU/Linux ** | Luca Bruno (kaeso) : :' : The Universal O.S. | lucab (AT) debian.org `. `'` | GPG Key ID: 3BFB9FB3 `- http://www.debian.org | Debian GNU/Linux Developer
diff -u ext3grep-0.6.0/debian/changelog ext3grep-0.6.0/debian/changelog --- ext3grep-0.6.0/debian/changelog +++ ext3grep-0.6.0/debian/changelog @@ -1,3 +1,12 @@ +ext3grep (0.6.0-1+lenny1) testing-proposed-updates; urgency=medium + + * Allow inode_size_ to be larger than sizeof(Inode) (backported from + upstream SVN r97, closes: #491621) + * Removed all big-endian arch, as ext3grep won't work there + * Urgency medium, fixes RC bug. + + -- Luca Bruno <lucab@debian.org> Wed, 27 Aug 2008 13:29:49 +0200 + ext3grep (0.6.0-1) unstable; urgency=low * Initial release (Closes: #470813) diff -u ext3grep-0.6.0/debian/rules ext3grep-0.6.0/debian/rules --- ext3grep-0.6.0/debian/rules +++ ext3grep-0.6.0/debian/rules @@ -3,6 +3,8 @@ # richer debug information. # DEB_BUILD_OPTIONS += nostrip noopt +include /usr/share/quilt/quilt.make + DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) @@ -16,7 +18,7 @@ EXTRA += --enable-debug --disable-optimization endif -clean: +clean: unpatch dh_testdir dh_testroot rm -f build-stamp @@ -25,7 +27,7 @@ dh_clean -config.status: configure +config.status: patch configure dh_testdir ifneq "$(wildcard /usr/share/misc/config.sub)" "" diff -u ext3grep-0.6.0/debian/control ext3grep-0.6.0/debian/control --- ext3grep-0.6.0/debian/control +++ ext3grep-0.6.0/debian/control @@ -3,14 +3,14 @@ Priority: extra Maintainer: Debian Forensics <forensics-devel@lists.alioth.debian.org> Uploaders: Luca Bruno <lucab@debian.org>, Rich Ercolani <rercola@acm.jhu.edu> -Build-Depends: debhelper (>= 7), autotools-dev, e2fslibs-dev, libncurses5 | libncurses-dev, pkg-config +Build-Depends: debhelper (>= 7), autotools-dev, e2fslibs-dev, libncurses5 | libncurses-dev, pkg-config, quilt Standards-Version: 3.8.0 Homepage: http://code.google.com/p/ext3grep/ Vcs-Browser: http://git.debian.org/?p=forensics/ext3grep.git Vcs-Git: git://git.debian.org/git/forensics/ext3grep.git Package: ext3grep -Architecture: any +Architecture: alpha amd64 arm armel i386 ia64 mipsel Depends: ${shlibs:Depends}, ${misc:Depends} Description: Tool to help recover deleted files on ext3 filesystems ext3grep is a simple tool intended to aid anyone who accidentally deletes a only in patch2: unchanged: --- ext3grep-0.6.0.orig/debian/patches/series +++ ext3grep-0.6.0/debian/patches/series @@ -0,0 +1 @@ +inode_size.diff only in patch2: unchanged: --- ext3grep-0.6.0.orig/debian/patches/inode_size.diff +++ ext3grep-0.6.0/debian/patches/inode_size.diff @@ -0,0 +1,231 @@ +--- ext3grep.orig/src/ext3grep.cc 2008-08-27 13:12:31.000000000 +0200 ++++ ext3grep/src/ext3grep.cc 2008-08-27 13:24:20.000000000 +0200 +@@ -367,10 +367,14 @@ void init_consts() + assert(block_size_ == fragment_size(super_block)); + // The inode bitmap has to fit in a single block. + assert(inodes_per_group(super_block) <= 8 * block_size_); +- // inode_size is expected to be (at least) 128. +- assert(inode_size_ >= 128); +- // But theoretically sizeof(Inode) can be more (not at the moment). +- assert((size_t)inode_size_ <= sizeof(Inode)); ++ // The rest of the code assumes that sizeof(Inode) is a power of 2. ++ assert(sizeof(Inode) == 128); ++ // inode_size is expected to be (at least) the size of Inode. ++ assert(inode_size_ >= sizeof(Inode)); ++ // Each inode must fit within one block. ++ assert(inode_size_ <= block_size_); ++ // inode_size must be a power of 2. ++ assert(!((inode_size_ - 1) & inode_size_)); + // There should fit exactly an integer number of inodes in one block. + assert((block_size_ / inode_size_) * inode_size_ == block_size_); + // Space needed for the inode table should match the returned value of the number of blocks they need. +@@ -417,7 +421,6 @@ void init_consts() + // We use this array to know of which groups we loaded the metadata. Therefore zero it out. + std::memset(block_bitmap, 0, sizeof(bitmap_t*) * groups_); + inode_bitmap = new bitmap_t* [groups_]; +- assert((size_t)inode_size_ == sizeof(Inode)); // This fails if kernel headers are used. + + // Initialize group_descriptor_table. + +@@ -568,10 +571,25 @@ class InodePointer { + + Inode InodePointer::S_fake_inode; // This will be filled with zeroes. + ++inline unsigned int bit_to_all_inodes_group_index(unsigned int bit) ++{ ++#if USE_MMAP ++ // If bit is incremented by one, we need to skip inode_size_ bytes in the (mmap-ed) inode table. ++ // Since the type of the table is Inode* the index needs to be incremented with the number of Inode structs that we need to skip. ++ // Because both inode_size_ and sizeof(Inode) are a power of 2 and inode_size_ >= sizeof(Inode), this amounts to inode_size_ / sizeof(Inode) ++ // index incrementation per bit. ++ return bit * (inode_size_ / sizeof(Inode)); ++#else ++ // If no mmap is used, the table only contains the first 128 bytes of each inode. ++ return bit; ++#endif ++} ++ + inline InodePointer get_inode(uint32_t inode) + { + int group = (inode - 1) / inodes_per_group_; + unsigned int bit = inode - 1 - group * inodes_per_group_; ++ // The bit in the bit mask must fit inside a single block. + ASSERT(bit < 8U * block_size_); + #if USE_MMAP + if (all_inodes[group] == NULL) +@@ -580,7 +598,7 @@ inline InodePointer get_inode(uint32_t i + if (block_bitmap[group] == NULL) + load_meta_data(group); + #endif +- return InodePointer(all_inodes[group][bit], group); ++ return InodePointer(all_inodes[group][bit_to_all_inodes_group_index(bit)], group); + } + + static void print_inode_to(std::ostream& os, InodePointer inoderef) +@@ -1310,17 +1328,25 @@ void load_inodes(int group) + load_meta_data(group); + // The start block of the inode table. + int block_number = group_descriptor_table[group].bg_inode_table; +- // Load all inodes into memory. +- all_inodes[group] = new Inode[inodes_per_group_]; // sizeof(Inode) == inode_size_ ++ // Load all inodes of this group into memory. ++ char* inode_table = new char[inodes_per_group_ * inode_size_]; + device.seekg(block_to_offset(block_number)); + ASSERT(device.good()); +- device.read(reinterpret_cast<char*>(const_cast<Inode*>(all_inodes[group])), inodes_per_group_ * inode_size_); ++ device.read(inode_table, inodes_per_group_ * inode_size_); + ASSERT(device.good()); ++ all_inodes[group] = new Inode[inodes_per_group_]; ++ // Copy the first 128 bytes of each inode into all_inodes[group]. ++ for (int i = 0; i < inodes_per_group_; ++i) ++ std::memcpy(all_inodes[group][i], inode_table + i * inode_size_, sizeof(Inode)); ++ // Free temporary table again. ++ delete [] inode_table; + #ifdef DEBUG + // We set this, so that we can find back where an inode struct came from + // during debugging of this program in gdb. It is not used anywhere. +- for (int ino = 0; ino < inodes_per_group_; ++ino) +- const_cast<Inode*>(all_inodes[group])[ino].set_reserved2(ino + 1 + group * inodes_per_group_); ++ // Note that THIS is the only reason that !USE_MMAP exists: we can't write to a mmapped area. ++ // Another solution would be to just allocate a seperate array for just this number, of course. ++ for (int i = 0; i < inodes_per_group_; ++i) ++ const_cast<Inode*>(all_inodes[group])[i].set_reserved2(i + 1 + group * inodes_per_group_); + #endif + } + #endif +@@ -1377,7 +1403,7 @@ void run_program(void) + feature_incompat_filetype = super_block.s_feature_incompat & EXT3_FEATURE_INCOMPAT_FILETYPE; + + // Do we have a journal? +- if (super_block.s_journal_dev == 0) ++ if (super_block.s_journal_inum != 0) + { + InodePointer journal_inode = get_inode(super_block.s_journal_inum); + int first_block = journal_inode->block()[0]; +@@ -1401,15 +1427,15 @@ void run_program(void) + } + + // Check commandline options against superblock contents. +- if (commandline_journal && super_block.s_journal_dev) ++ if (commandline_journal && !super_block.s_journal_inum) + { + std::cout << std::flush; +- std::cerr << progname << ": --journal: The journal appears to be external." << std::endl; ++ std::cerr << progname << ": --journal: The journal is on an external device. Please add support for it." << std::endl; + exit(EXIT_FAILURE); + } + if (commandline_inode != -1) + { +- if ((uint32_t)commandline_inode >= inode_count_) ++ if ((uint32_t)commandline_inode > inode_count_) + { + std::cout << std::flush; + std::cerr << progname << ": --inode: inode " << commandline_inode << " is out of range. There are only " << inode_count_ << " inodes." << std::endl; +@@ -1440,7 +1466,7 @@ void run_program(void) + } + if (commandline_show_journal_inodes != -1) + { +- if ((uint32_t)commandline_show_journal_inodes >= inode_count_) ++ if ((uint32_t)commandline_show_journal_inodes > inode_count_) + { + std::cout << std::flush; + std::cerr << progname << ": --show-journal-inodes: inode " << commandline_show_journal_inodes << +@@ -1942,6 +1968,12 @@ void run_program(void) + // Handle --inode-to-block + if (commandline_inode_to_block != -1) + { ++ if ((uint32_t)commandline_inode_to_block > inode_count_) ++ { ++ std::cout << std::flush; ++ std::cerr << progname << ": --inode-to-block: inode " << commandline_inode_to_block << " is out of range. There are only " << inode_count_ << " inodes." << std::endl; ++ exit(EXIT_FAILURE); ++ } + int block = inode_to_block(super_block, commandline_inode_to_block); + std::cout << "Inode " << commandline_inode_to_block << " resides in block " << block << + " at offset 0x" << std::hex << ((commandline_inode_to_block - block_to_inode(block)) * inode_size_) << std::dec << ".\n"; +@@ -4169,7 +4201,7 @@ static void init_journal(void) + int inode_number = block_to_inode(block_nr); + // Run over all inodes in the journal block. + get_block(tag->Descriptor::block(), block_buf); +- for (unsigned int i = 0; i < block_size_ / sizeof(Inode); ++i, ++inode_number) ++ for (unsigned int i = 0; i < block_size_ / sizeof(Inode); i += inode_size_ / sizeof(Inode), ++inode_number) + { + // Skip non-directories. + if (!is_directory(inode[i])) +@@ -4213,7 +4245,7 @@ static bool is_in_journal(int blocknr) + + static bool is_journal(int blocknr) + { +- if (super_block.s_journal_dev) ++ if (!super_block.s_journal_inum) + { + ASSERT(!commandline_journal); + return false; +@@ -4878,6 +4910,7 @@ void init_dir_inode_to_block_cache(void) + // sequence number. + #if INCLUDE_JOURNAL + uint32_t highest_sequence = 0; ++ int min_block = std::numeric_limits<int>::max(); + int journal_block_count = 0; + int total_block_count = 0; + iter = dirs.begin(); +@@ -4888,19 +4921,13 @@ void init_dir_inode_to_block_cache(void) + { + ++journal_block_count; + block_in_journal_to_descriptors_map_type::iterator iter2 = block_in_journal_to_descriptors_map.find(iter->block()); +- if (iter2 == block_in_journal_to_descriptors_map.end()) ++ if (iter2 != block_in_journal_to_descriptors_map.end()) + { +- std::cout << "Cannot find block " << iter->block() << " (in journal) in block_in_journal_to_descriptors_map!\n"; +- std::cout << "Dump of block_in_journal_to_descriptors_map:\n"; +- for (block_in_journal_to_descriptors_map_type::iterator iter3 = block_in_journal_to_descriptors_map.begin(); iter3 != block_in_journal_to_descriptors_map.end(); ++iter3) +- { +- std::cout << iter3->first << ", {" << iter3->second->sequence() << ", " << iter3->second->block() << "}\n"; +- } +- std::cout << std::flush; ++ uint32_t sequence = iter2->second->sequence(); ++ highest_sequence = std::max(highest_sequence, sequence); + } +- ASSERT(iter2 != block_in_journal_to_descriptors_map.end()); +- uint32_t sequence = iter2->second->sequence(); +- highest_sequence = std::max(highest_sequence, sequence); ++ else ++ min_block = std::min(min_block, iter->block()); + } + else + break; // No need to continue. +@@ -4919,7 +4946,16 @@ void init_dir_inode_to_block_cache(void) + if (need_keep_one_journal) + { + block_in_journal_to_descriptors_map_type::iterator iter2 = block_in_journal_to_descriptors_map.find(iter->block()); +- if (iter2->second->sequence() == highest_sequence) ++ if (highest_sequence == 0 && iter->block() == min_block) ++ { ++ std::cout << std::flush; ++ std::cerr << "WARNING: More than one directory block references inode " << i << ++ " but all of them are in the journal and none of them have a descriptor block (the start of the transaction was probably overwritten)." ++ " The mostly likely correct directory block would be block " << min_block << ++ " but we're disregarding it because ext3grep can't deal with journal blocks without a descriptor block."; ++ std::cerr << std::endl; ++ } ++ if (iter2 != block_in_journal_to_descriptors_map.end() && iter2->second->sequence() == highest_sequence) + { + ++iter; + continue; +@@ -5815,7 +5851,15 @@ void init_files(void) + continue; + ASSERT(is_journal(directory_block.block())); + block_in_journal_to_descriptors_map_type::iterator descriptors_iter = block_in_journal_to_descriptors_map.find(directory_block.block()); +- ASSERT(descriptors_iter != block_in_journal_to_descriptors_map.end()); ++ if (descriptors_iter == block_in_journal_to_descriptors_map.end()) ++ { ++ std::cout << std::flush; ++ std::cerr << "WARNING: Disregarding directory block " << directory_block.block() << " from the journal, " ++ " that appears to belong to a directory with inode number " << directory.inode_number() << ++ ", because it doesn't have a descriptor block (the start of the transaction was probably overwritten)." ++ " We're disregarding it because ext3grep can't deal with journal blocks without a descriptor block." << std::endl; ++ continue; ++ } + Descriptor& descriptor(*descriptors_iter->second); + ASSERT(descriptor.descriptor_type() == dt_tag); + //DescriptorTag& descriptor_tag(static_cast<DescriptorTag&>(descriptor));
Attachment:
pgpRqiGPUdVWd.pgp
Description: PGP signature