diff options
Diffstat (limited to 'src/file_ext.c')
-rw-r--r-- | src/file_ext.c | 71 |
1 files changed, 65 insertions, 6 deletions
diff --git a/src/file_ext.c b/src/file_ext.c index 3f9502c..d7ad79a 100644 --- a/src/file_ext.c +++ b/src/file_ext.c @@ -33,23 +33,41 @@ #include "filegen.h" static void register_header_check_ext2_sb(file_stat_t *file_stat); -static int header_check_ext2_sb(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new); const file_hint_t file_hint_ext2_sb= { - .extension="", + .extension="ext", .description="ext2/ext3/ext4 Superblock", .min_header_distance=0, - .max_filesize=1, + .max_filesize=PHOTOREC_MAX_FILE_SIZE, .recover=0, .enable_by_default=1, .register_header_check=®ister_header_check_ext2_sb }; -static const unsigned char ext2_sb_header[2]= {0x53, 0xEF}; +static void file_rename_ext(const char *old_filename) +{ + unsigned char buffer[512]; + unsigned char buffer_cluster[32]; + FILE *file; + const struct ext2_super_block *sb=(const struct ext2_super_block *)&buffer; + int buffer_size; + unsigned long int block_nr; + if((file=fopen(old_filename, "rb"))==NULL) + return; + buffer_size=fread(buffer, 1, sizeof(buffer), file); + fclose(file); + if(buffer_size!=sizeof(buffer)) + return; + block_nr=(le32(sb->s_first_data_block)+le16(sb->s_block_group_nr)*le32(sb->s_blocks_per_group)); + sprintf(buffer_cluster, "sb_%lu", block_nr); + file_rename(old_filename, buffer_cluster, strlen(buffer_cluster), 0, NULL, 1); +} -static void register_header_check_ext2_sb(file_stat_t *file_stat) +static int data_check_ext(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery) { - register_header_check(0x38, ext2_sb_header,sizeof(ext2_sb_header), &header_check_ext2_sb, file_stat); + /* Save only one block */ + file_recovery->calculated_file_size=buffer_size/2; + return 2; } static int header_check_ext2_sb(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) @@ -74,5 +92,46 @@ static int header_check_ext2_sb(const unsigned char *buffer, const unsigned int return 0; reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_ext2_sb.extension; + file_recovery_new->data_check=&data_check_ext; + file_recovery_new->file_check=&file_check_size; + file_recovery_new->file_rename=&file_rename_ext; return 1; } + +static void file_rename_extdir(const char *old_filename) +{ + unsigned char buffer[512]; + unsigned char buffer_cluster[32]; + FILE *file; + int buffer_size; + const uint32_t *inode=(const uint32_t *)&buffer[0]; + if((file=fopen(old_filename, "rb"))==NULL) + return; + buffer_size=fread(buffer, 1, sizeof(buffer), file); + fclose(file); + if(buffer_size!=sizeof(buffer)) + return; + sprintf(buffer_cluster, "inode_%u", (unsigned int)le32(*inode)); + file_rename(old_filename, buffer_cluster, strlen(buffer_cluster), 0, NULL, 1); +} + +static int header_check_ext2_dir(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) +{ + static const unsigned char ext2_ll_dir2[6]= { 0x02, 0x02, '.', '.', 0x00, 0x00}; + if(memcmp(&buffer[0x12], ext2_ll_dir2, sizeof(ext2_ll_dir2))!=0) + return 0; + reset_file_recovery(file_recovery_new); + file_recovery_new->extension=file_hint_ext2_sb.extension; + file_recovery_new->data_check=&data_check_ext; + file_recovery_new->file_check=&file_check_size; + file_recovery_new->file_rename=&file_rename_extdir; + return 1; +} + +static void register_header_check_ext2_sb(file_stat_t *file_stat) +{ + static const unsigned char ext2_sb_header[2]= {0x53, 0xEF}; + static const unsigned char ext2_ll_dir1[8]= {0x0c, 0x00, 0x01, 0x02, '.', 0x00, 0x00, 0x00}; + register_header_check(0x38, ext2_sb_header, sizeof(ext2_sb_header), &header_check_ext2_sb, file_stat); + register_header_check(0x4, ext2_ll_dir1, sizeof(ext2_ll_dir1), &header_check_ext2_dir, file_stat); +} |