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