[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Please allow ext3grep in lenny (freeze unblock or via t-p-u)



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


Reply to: