Thread: [Extundelete-users] extundelete truncates files over 2GB
Status: Beta
Brought to you by:
necase
From: <ext...@li...> - 2014-07-19 14:57:32
|
Hello, Firstly, extundelete was very helpful in undeleting some of my files! Great work. However, I discovered it seems to have a problem restoring files over 2GB in size. The block extraction works fine, but then it calls truncate() with entirely the wrong file size. Here's a quick test. This creates an ext4 (32-bit) filesystem, with one deleted file on it, just over 2GB in size. dd if=/dev/zero of=img bs=1024 count=10485760 losetup /dev/loop0 img mkfs -t ext4 /dev/loop0 mkdir fs mount img fs dd if=/dev/zero of=fs/undelete-me bs=1024 count=2097152 echo >>fs/undelete-me 'and just a few more bytes over 2GB'; sync rm fs/undelete-me; sync umount fs losetup -d /dev/loop0 rmdir fs The correct size of undelete-me is 2147483683 bytes. parse_inode_block() writes 713031680 into i_size instead. It doesn't even attempt to read i_size_high, it's presumed to be the old i_dir_acl, although I'm not sure i_size_high would be needed for a file under 4GB. Once the file (all 2GB of it) is restored, it immediately truncates it to 680MB. $ extundelete --restore-file undelete-me img & while true; do ls -l RECOVERED_FILES/undelete-me; sleep 1; done [1] 31128 ls: cannot access RECOVERED_FILES/undelete-me: No such file or directory WARNING: Extended attributes are not restored. Loading filesystem metadata ... 80 groups loaded. Loading journal descriptors ... 64 descriptors loaded. Writing output to directory RECOVERED_FILES/ -rw-r--r-- 1 root root 93118464 Jul 19 14:13 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 193581056 Jul 19 14:13 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 318885888 Jul 19 14:13 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 424448000 Jul 19 14:13 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 528601088 Jul 19 14:13 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 635232256 Jul 19 14:13 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 760991744 Jul 19 14:13 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 849346560 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 972148736 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1064300544 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1182126080 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1280122880 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1391329280 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1496858624 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1601818624 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1709273088 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1812582400 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 1922551808 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 2021249024 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 2136420352 Jul 19 14:14 RECOVERED_FILES/undelete-me Restored inode 12 to file RECOVERED_FILES/undelete-me [1]+ Done extundelete --restore-file undelete-me img -rw-r--r-- 1 root root 713031680 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 713031680 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 713031680 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 713031680 Jul 19 14:14 RECOVERED_FILES/undelete-me -rw-r--r-- 1 root root 713031680 Jul 19 14:14 RECOVERED_FILES/undelete-me While I don't claim to know the right way to get the true file size, I made this patch just to get my large files restored without truncation. --- extundelete-0.2.0/src/extundelete.cc.orig 2014-07-12 17:43:22.315234887 +0100 +++ extundelete-0.2.0/src/extundelete.cc 2014-07-19 15:27:25.485146941 +0100 @@ -2547,18 +2547,29 @@ ext2fs_file_close(infile); */ + file.seekp(0, std::ios::end); + const blk64_t real_size = file.tellp(); file.close(); if(!flag) { - if (truncate( (outputdir + fname2).c_str(), EXT2_I_SIZE(inode)) == 0) { + const blk64_t alledged_size = EXT2_I_SIZE(inode); + if (real_size < alledged_size + block_size_) { + if (truncate( (outputdir + fname2).c_str(), EXT2_I_SIZE(inode)) == 0) { + std::cout << "Restored inode " << ino << " to file "; + std::cout << (outputdir + fname2) << std::endl; + retval = 0; + } else { + std::cout << "Failed to restore inode " << ino << " to file "; + std::cout << (outputdir + fname2) << ":"; + std::cout << "Unable to set proper file size." << std::endl; + retval = EU_RESTORE_FAIL; + } + } + else { std::cout << "Restored inode " << ino << " to file "; - std::cout << (outputdir + fname2) << std::endl; - retval = 0; - } else { - std::cout << "Failed to restore inode " << ino << " to file "; - std::cout << (outputdir + fname2) << ":"; - std::cout << "Unable to set proper file size." << std::endl; - retval = EU_RESTORE_FAIL; + std::cout << (outputdir + fname2) << " but size may be wrong. "; + std::cout << "Size in inode is " << alledged_size; + std::cout << " bytes but recovered " << real_size << " bytes." << std::endl; } } else { What's causing extundelete to read the incorrect file size from the deleted inode? Regards Stuart |