| -rw-r--r-- | doc_src/testdisk.8.in | 10 | ||||
| -rw-r--r-- | src/Makefile.am | 1 | ||||
| -rw-r--r-- | src/common.h | 1 | ||||
| -rw-r--r-- | src/dir.c | 4 | ||||
| -rw-r--r-- | src/ewf.c | 7 | ||||
| -rw-r--r-- | src/file_dbn.c | 1 | ||||
| -rw-r--r-- | src/file_doc.c | 4 | ||||
| -rw-r--r-- | src/file_http.c | 66 | ||||
| -rw-r--r-- | src/file_jpg.c | 7 | ||||
| -rw-r--r-- | src/file_list.c | 2 | ||||
| -rw-r--r-- | src/file_prc.c | 2 | ||||
| -rw-r--r-- | src/file_ps.c | 2 | ||||
| -rw-r--r-- | src/file_tiff.c | 182 | ||||
| -rw-r--r-- | src/file_tiff.h | 2 | ||||
| -rw-r--r-- | src/file_vdi.c | 106 | ||||
| -rw-r--r-- | src/godmode.c | 2 | ||||
| -rw-r--r-- | src/hdaccess.c | 9 | ||||
| -rw-r--r-- | src/msdos.c | 2 | ||||
| -rw-r--r-- | src/parthumax.c | 2 | ||||
| -rw-r--r-- | src/parti386.c | 14 |
20 files changed, 316 insertions, 110 deletions
diff --git a/doc_src/testdisk.8.in b/doc_src/testdisk.8.in index bdc3aba..39d9add 100644 --- a/doc_src/testdisk.8.in +++ b/doc_src/testdisk.8.in @@ -17,7 +17,7 @@ testdisk \- Scan and repair disk partitions - DOS/Windows FAT12, FAT16 and FAT32 - HFS and HFS+, Hierarchical File System - JFS, IBM's Journaled File System - - Linux Ext2 and Ext3 + - Linux ext2/ext3/ext4 - Linux Raid RAID 1: mirroring RAID 4: striped array with parity device @@ -27,11 +27,17 @@ testdisk \- Scan and repair disk partitions - LVM and LVM2, Linux Logical Volume Manager - Mac partition map - Novell Storage Services NSS - - NTFS (Windows NT/2K/XP/2003/Vista) + - NTFS (Windows NT/2K/XP/2003/Vista/...) - ReiserFS 3.5, 3.6 and 4 - Sun Solaris i386 disklabel - Unix File System UFS and UFS2 (Sun/BSD/...) - XFS, SGI's Journaled File System + + It can undelete files from + - DOS/Windows FAT12, FAT16 and FAT32 + - Linux ext2 + - NTFS (Windows NT/2K/XP/2003/Vista/...) + .SH OPTIONS .TP .B /log diff --git a/src/Makefile.am b/src/Makefile.am index 68e6fc1..325722a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -213,6 +213,7 @@ file_C = filegen.c \ file_ttf.c \ file_txt.c \ file_tz.c \ + file_vdi.c \ file_veg.c \ file_vfb.c \ file_vmdk.c \ diff --git a/src/common.h b/src/common.h index ac605df..0e60b47 100644 --- a/src/common.h +++ b/src/common.h @@ -44,7 +44,6 @@ struct efi_guid_s #define DISKNAME_MAX 64 #define DISKDESCRIPTION_MAX 128 -#define TAB_PART 0x1BE /* PARTITION TYPE */ #define P_NO_OS 0x00 #define P_12FAT 0x01 @@ -613,7 +613,6 @@ char *mkdir_local(const char *localroot, const char *pathname) while(*src!='\0') { unsigned int n=0; - unsigned int l; const char *src_org=src; char *dst_org=dst; for(n=0; @@ -624,6 +623,7 @@ char *mkdir_local(const char *localroot, const char *pathname) #ifdef __MINGW32__ if(mkdir(localdir)<0 && errno==EINVAL) { + unsigned int l; l=filename_convert(dst_org, src_org, n); dst=dst_org+l; mkdir(localdir); @@ -632,6 +632,7 @@ char *mkdir_local(const char *localroot, const char *pathname) if(memcmp(&localdir[1],":/cygdrive",11)!=0 && mkdir(localdir, 0775)<0 && errno==EINVAL) { + unsigned int l; l=filename_convert(dst_org, src_org, n); dst=dst_org+l; mkdir(localdir, 0775); @@ -639,6 +640,7 @@ char *mkdir_local(const char *localroot, const char *pathname) #else if(mkdir(localdir, 0775)<0 && errno==EINVAL) { + unsigned int l; l=filename_convert(dst_org, src_org, n); dst=dst_org+l; mkdir(localdir, 0775); @@ -199,11 +199,8 @@ static int fewf_clean(disk_t *disk) { struct info_fewf_struct *data=(struct info_fewf_struct *)disk->data; libewf_close(data->handle); - if(data->buffer!=NULL) - { - free(data->buffer); - data->buffer=NULL; - } + free(data->buffer); + data->buffer=NULL; free(disk->data); disk->data=NULL; } diff --git a/src/file_dbn.c b/src/file_dbn.c index f8dbdb1..8b233ba 100644 --- a/src/file_dbn.c +++ b/src/file_dbn.c @@ -33,7 +33,6 @@ static void register_header_check_dbn(file_stat_t *file_stat); static int header_check_dbn(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 void file_check_dbn(file_recovery_t *file_recovery); const file_hint_t file_hint_dbn= { .extension="dbn", diff --git a/src/file_doc.c b/src/file_doc.c index 88167e2..96c2e77 100644 --- a/src/file_doc.c +++ b/src/file_doc.c @@ -825,7 +825,7 @@ static void file_rename_doc(const char *old_filename) } if(memcmp(dir_entry->name, SummaryInformation, sizeof(SummaryInformation))==0) { - OLE_parse_summary(file, fat, fat_entries, header, ministream_block, ministream_block, + OLE_parse_summary(file, fat, fat_entries, header, ministream_block, ministream_size, le32(dir_entry->start_block), le32(dir_entry->size), &ext, &title, &file_time); } @@ -883,7 +883,7 @@ static void file_rename_doc(const char *old_filename) else if(memcmp(dir_entry->name, "N\0a\0t\0i\0v\0e\0C\0o\0n\0t\0e\0n\0t\0_\0M\0A\0I\0N\0", 36)==0) ext="qpw"; if(sid==1 && memcmp(dir_entry->name, "D\0g\0n", 6)==0) - return "dgn"; + ext="dgn"; } } } diff --git a/src/file_http.c b/src/file_http.c new file mode 100644 index 0000000..57a3ea0 --- a/dev/null +++ b/src/file_http.c @@ -0,0 +1,66 @@ +/* + + File: file_http.c + + Copyright (C) 2010 Christophe GRENIER <grenier@cgsecurity.org> + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#include <stdio.h> +#include "types.h" +#include "filegen.h" + +static void register_header_check_http(file_stat_t *file_stat); +static int header_check_http(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_http= { + .extension="http", + .description="HTTP Cache", + .min_header_distance=0, + .max_filesize=PHOTOREC_MAX_FILE_SIZE, + .recover=1, + .enable_by_default=1, + .register_header_check=®ister_header_check_http +}; + +static const unsigned char http_header[22]= { + 'H', 'T', 'T', 'P', '/', '1', '.', '1', + ' ', '2', '0', '0', ' ', 'O', 'K', '\r', + '\n', 'D', 'a', 't', 'e', ':' +}; + +static void register_header_check_http(file_stat_t *file_stat) +{ + register_header_check(0, http_header, sizeof(http_header), &header_check_http, file_stat); +} + +static int header_check_http(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) +{ + if(memcmp(buffer, http_header, sizeof(http_header))==0) + { + reset_file_recovery(file_recovery_new); + file_recovery_new->extension=file_hint_http.extension; + return 1; + } + return 0; +} diff --git a/src/file_jpg.c b/src/file_jpg.c index 771d6cc..fedf2d6 100644 --- a/src/file_jpg.c +++ b/src/file_jpg.c @@ -1020,18 +1020,21 @@ static uint64_t jpg_check_structure(file_recovery_t *file_recovery, const unsign #if 1 if(i+0x0A < nbytes && 2+size > 0x0A) { + const char *potential_error=NULL; const TIFFHeader *tiff=(const TIFFHeader*)&buffer[i+0x0A]; unsigned int tiff_size=2+size-0x0A; const char *thumb_data=NULL; const char *ifbytecount=NULL; if(nbytes - (i+0x0A) < tiff_size) tiff_size=nbytes - (i+0x0A); - thumb_data=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFOFFSET); + thumb_data=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFOFFSET, &potential_error); if(thumb_data!=NULL) { thumb_offset=thumb_data-(const char*)buffer; - ifbytecount=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFBYTECOUNT); + ifbytecount=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFBYTECOUNT, &potential_error); } + if(potential_error!=NULL) + file_recovery->offset_error=potential_error-(const char*)buffer; if(file_recovery->offset_ok<i) file_recovery->offset_ok=i; if(thumb_data!=NULL && ifbytecount!=NULL) diff --git a/src/file_list.c b/src/file_list.c index 4f8e856..9582c54 100644 --- a/src/file_list.c +++ b/src/file_list.c @@ -215,6 +215,7 @@ extern const file_hint_t file_hint_tph; extern const file_hint_t file_hint_ttf; extern const file_hint_t file_hint_txt; extern const file_hint_t file_hint_tz; +extern const file_hint_t file_hint_vdi; extern const file_hint_t file_hint_veg; extern const file_hint_t file_hint_vfb; extern const file_hint_t file_hint_vmdk; @@ -425,6 +426,7 @@ file_enable_t list_file_enable[]= { .enable=0, .file_hint=&file_hint_tz }, { .enable=0, .file_hint=&file_hint_vfb }, { .enable=0, .file_hint=&file_hint_vmdk }, + { .enable=0, .file_hint=&file_hint_vdi }, { .enable=0, .file_hint=&file_hint_veg }, { .enable=0, .file_hint=&file_hint_wdp }, { .enable=0, .file_hint=&file_hint_win }, diff --git a/src/file_prc.c b/src/file_prc.c index bd383f9..3177ce1 100644 --- a/src/file_prc.c +++ b/src/file_prc.c @@ -51,7 +51,7 @@ static void register_header_check_prc(file_stat_t *file_stat) register_header_check(0x30, prc_header,sizeof(prc_header), &header_check_prc, file_stat); } -typedef struct DatabaseHdrType_s { +struct DatabaseHdrType_s { unsigned char name[32]; uint16_t attributes; /* 0x20 */ uint32_t creationDate; /* 0x22 */ diff --git a/src/file_ps.c b/src/file_ps.c index 91d84fe..28830ec 100644 --- a/src/file_ps.c +++ b/src/file_ps.c @@ -89,9 +89,9 @@ static int header_check_ps(const unsigned char *buffer, const unsigned int buffe static int data_check_ps(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery) { - unsigned int i; if(buffer_size>8) { + unsigned int i; for(i=(buffer_size/2)-4;i+4<buffer_size;i++) { if(buffer[i]=='%' && buffer[i+1]=='%' && buffer[i+2]=='E' && buffer[i+3]=='O' && buffer[i+4]=='F') diff --git a/src/file_tiff.c b/src/file_tiff.c index a7b5d8f..45b5184 100644 --- a/src/file_tiff.c +++ b/src/file_tiff.c @@ -57,7 +57,83 @@ const file_hint_t file_hint_tiff= { static const unsigned char tiff_header_be[4]= { 'M','M',0x00, 0x2a}; static const unsigned char tiff_header_le[4]= { 'I','I',0x2a, 0x00}; -static const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag) +static unsigned int type2size(const unsigned int type) +{ + switch(type) + { + case 1: /* TIFF_BYTE */ + case 2: /* TIFF_ASCII */ + case 6: /* TIFF_SBYTE */ + case 7: /* TIFF_UNDEFINED */ + return 1; + case 3: /* TIFF_SHORT */ + case 8: /* TIFF_SSHORT */ + return 2; + case 4: /* TIFF_LONG */ + case 9: /* TIFF_SLONG */ + case 11: /* TIFF_FLOAT */ + case 13: /* TIFF_IFD */ + return 4; + case 5: /* TIFF_RATIONAL */ + case 10: /* TIFF_SRATIONAL */ + case 12: /* TIFF_DOUBLE */ + case 16: /* TIFF_LONG8 */ + case 17: /* TIFF_SLONG8 */ + case 18: /* TIFF_IFD8 */ + return 8; + default: +// case 14: /* TIFF_UNICODE */ +// case 15: /* TIFF_COMPLEX */ + return 1; + } +} + +#ifdef DEBUG_TIFF +static const char *tag_name(unsigned int tag) +{ + switch(tag) + { + case TIFFTAG_IMAGEDESCRIPTION: + return "IMAGEDESCRIPTION"; + case TIFFTAG_MAKE: + return "MAKE"; + case TIFFTAG_MODEL: + return "TIFFTAG_MODEL"; + case TIFFTAG_SUBIFD: + return "SUBIFD"; + case TIFFTAG_EXIFIFD: + return "EXIFIFD"; + case TIFFTAG_STRIPOFFSETS: + return "STRIPOFFSETS"; + case TIFFTAG_STRIPBYTECOUNTS: + return "STRIPBYTECOUNTS"; + case TIFFTAG_KODAKIFD: + return "KODAKIFD"; + case TIFFTAG_JPEGIFOFFSET: + return "JPEGIFOFFSET"; + case TIFFTAG_JPEGIFBYTECOUNT: + return "JPEGIFBYTECOUNT"; + case TIFFTAG_DNGPRIVATEDATA: + return "DNGPRIVATEDATA"; + case EXIFTAG_MAKERNOTE: + return "EXIFTAG_MAKERNOTE"; + case TIFFTAG_PRINTIM: + return "PrintIM"; + case TIFFTAG_IMAGEOFFSET: + return "IMAGEOFFSET"; + case TIFFTAG_IMAGEBYTECOUNT: + return "IMAGEBYTECOUNT"; + case TIFFTAG_ALPHAOFFSET: + return "ALPHAOFFSET"; + case TIFFTAG_ALPHABYTECOUNT: + return "ALPHABYTECOUNT"; + default: + return ""; + } +} +#endif + +static const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag, const char**potential_error) { const struct ifd_header *ifd0=(const struct ifd_header *)((const char*)tiff + be32(tiff->tiff_diroff)); const struct ifd_header *exififd=NULL; @@ -72,6 +148,8 @@ static const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const un (const char*)(ifd+1) <= (const char*)tiff+tiff_size && j<be16(ifd0->nbr_fields); j++, ifd++) { + if(be16(ifd->tdir_type) > 18 && (*potential_error==NULL || *potential_error > (const char*)&ifd->tdir_type+1)) + *potential_error = (const char*)&ifd->tdir_type+1; if(be16(ifd->tdir_tag)==tag) return (const char*)tiff+be32(ifd->tdir_offset); else if(be16(ifd->tdir_tag)==TIFFTAG_EXIFIFD) /* Exif IFD Pointer */ @@ -86,6 +164,8 @@ static const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const un (const char*)(ifd+1) <= (const char*)tiff+tiff_size && j<be16(exififd->nbr_fields); j++, ifd++) { + if(be16(ifd->tdir_type) > 18 && (*potential_error==NULL || *potential_error > (const char*)&ifd->tdir_type+1)) + *potential_error = (const char*)&ifd->tdir_type+1; if(be16(ifd->tdir_tag)==tag) return (const char*)tiff+be32(ifd->tdir_offset); } @@ -101,6 +181,8 @@ static const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const un (const char*)(ifd+1) <= (const char*)tiff+tiff_size && j<be16(ifd1->nbr_fields); j++, ifd++) { + if(be16(ifd->tdir_type) > 18 && (*potential_error==NULL || *potential_error > (const char*)&ifd->tdir_type+1)) + *potential_error = (const char*)&ifd->tdir_type+1; if(be16(ifd->tdir_tag)==tag) return (const char*)tiff+be32(ifd->tdir_offset); } @@ -108,7 +190,7 @@ static const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const un return NULL; } -static const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag) +static const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag, const char**potential_error) { const struct ifd_header *ifd0=(const struct ifd_header *)((const char*)tiff + le32(tiff->tiff_diroff)); const struct ifd_header *exififd=NULL; @@ -123,6 +205,8 @@ static const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const un (const char*)(ifd+1) <= (const char*)tiff+tiff_size && j<le16(ifd0->nbr_fields); j++, ifd++) { + if(le16(ifd->tdir_type) > 18 && (*potential_error==NULL || *potential_error > (const char*)&ifd->tdir_type+1)) + *potential_error = (const char*)&ifd->tdir_type+1; if(le16(ifd->tdir_tag)==tag) return (const char*)tiff+le32(ifd->tdir_offset); else if(le16(ifd->tdir_tag)==TIFFTAG_EXIFIFD) /* Exif IFD Pointer */ @@ -137,6 +221,8 @@ static const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const un (const char*)(ifd+1) <= (const char*)tiff+tiff_size && j<le16(exififd->nbr_fields); j++, ifd++) { + if(le16(ifd->tdir_type) > 18 && (*potential_error==NULL || *potential_error > (const char*)&ifd->tdir_type+1)) + *potential_error = (const char*)&ifd->tdir_type+1; if(le16(ifd->tdir_tag)==tag) /* DateTimeOriginal */ return (const char*)tiff+le32(ifd->tdir_offset); } @@ -153,6 +239,8 @@ static const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const un (const char*)(ifd+1) <= (const char*)tiff+tiff_size && j<le16(ifd1->nbr_fields); j++, ifd++) { + if(le16(ifd->tdir_type) > 18 && (*potential_error==NULL || *potential_error > (const char*)&ifd->tdir_type+1)) + *potential_error = (const char*)&ifd->tdir_type+1; if(le16(ifd->tdir_tag)==tag) return (const char*)tiff+le32(ifd->tdir_offset); } @@ -160,7 +248,7 @@ static const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const un return NULL; } -const char *find_tag_from_tiff_header(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag) +const char *find_tag_from_tiff_header(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag, const char **potential_error) { if(tiff_size < sizeof(TIFFHeader)) return NULL; @@ -168,28 +256,29 @@ const char *find_tag_from_tiff_header(const TIFFHeader *tiff, const unsigned int { if(tiff_size < be32(tiff->tiff_diroff)+sizeof(TIFFDirEntry)) return NULL; - return find_tag_from_tiff_header_be(tiff, tiff_size, tag); + return find_tag_from_tiff_header_be(tiff, tiff_size, tag, potential_error); } else if(tiff->tiff_magic==TIFF_LITTLEENDIAN) { if(tiff_size < le32(tiff->tiff_diroff)+sizeof(TIFFDirEntry)) return NULL; - return find_tag_from_tiff_header_le(tiff, tiff_size, tag); + return find_tag_from_tiff_header_le(tiff, tiff_size, tag, potential_error); } return NULL; } time_t get_date_from_tiff_header(const TIFFHeader *tiff, const unsigned int tiff_size) { + const char *potential_error=NULL; const char *date_asc; struct tm tm_time; /* DateTimeOriginal */ - date_asc=find_tag_from_tiff_header(tiff, tiff_size, 0x9003); + date_asc=find_tag_from_tiff_header(tiff, tiff_size, 0x9003, &potential_error); /* DateTimeDigitalized*/ if(date_asc==NULL || date_asc < (const char *)tiff || &date_asc[18] >= (const char *)tiff + tiff_size) - date_asc=find_tag_from_tiff_header(tiff, tiff_size, 0x9004); + date_asc=find_tag_from_tiff_header(tiff, tiff_size, 0x9004, &potential_error); if(date_asc==NULL || date_asc < (const char *)tiff || &date_asc[18] >= (const char *)tiff + tiff_size) - date_asc=find_tag_from_tiff_header(tiff, tiff_size, 0x132); + date_asc=find_tag_from_tiff_header(tiff, tiff_size, 0x132, &potential_error); if(date_asc==NULL || date_asc < (const char *)tiff || &date_asc[18] >= (const char *)tiff + tiff_size) return (time_t)0; memset(&tm_time, 0, sizeof(tm_time)); @@ -215,12 +304,13 @@ static int header_check_tiff(const unsigned char *buffer, const unsigned int buf if(memcmp(buffer,tiff_header_be,sizeof(tiff_header_be))==0 || memcmp(buffer,tiff_header_le,sizeof(tiff_header_le))==0) { + const char *potential_error=NULL; reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_tiff.extension; /* Canon RAW */ if(buffer[8]=='C' && buffer[9]=='R' && buffer[10]==2) file_recovery_new->extension="cr2"; - else if(find_tag_from_tiff_header((const TIFFHeader *)buffer, buffer_size, TIFFTAG_DNGVERSION)!=NULL) + else if(find_tag_from_tiff_header((const TIFFHeader *)buffer, buffer_size, TIFFTAG_DNGVERSION, &potential_error)!=NULL) { /* Adobe Digital Negative */ file_recovery_new->extension="dng"; @@ -228,7 +318,7 @@ static int header_check_tiff(const unsigned char *buffer, const unsigned int buf else { const char *tag_make; - tag_make=find_tag_from_tiff_header((const TIFFHeader *)buffer, buffer_size, TIFFTAG_MAKE); + tag_make=find_tag_from_tiff_header((const TIFFHeader *)buffer, buffer_size, TIFFTAG_MAKE, &potential_error); if(tag_make!=NULL && tag_make >= (const char *)buffer && tag_make < (const char *)buffer + buffer_size - 20) { if(strcmp(tag_make, "PENTAX Corporation ")==0 || @@ -251,75 +341,6 @@ static int header_check_tiff(const unsigned char *buffer, const unsigned int buf return 0; } -static unsigned int type2size(const unsigned int type) -{ - switch(type) - { - case 1: - case 2: - case 6: - case 7: - return 1; - case 3: - case 8: - return 2; - case 4: - case 9: - case 11: - return 4; - case 5: - case 10: - case 12: - return 8; - default: - return 1; - } -} - -#ifdef DEBUG_TIFF -static const char *tag_name(unsigned int tag) -{ - switch(tag) - { - case TIFFTAG_IMAGEDESCRIPTION: - return "IMAGEDESCRIPTION"; - case TIFFTAG_MAKE: - return "MAKE"; - case TIFFTAG_MODEL: - return "TIFFTAG_MODEL"; - case TIFFTAG_SUBIFD: - return "SUBIFD"; - case TIFFTAG_EXIFIFD: - return "EXIFIFD"; - case TIFFTAG_STRIPOFFSETS: - return "STRIPOFFSETS"; - case TIFFTAG_STRIPBYTECOUNTS: - return "STRIPBYTECOUNTS"; - case TIFFTAG_KODAKIFD: - return "KODAKIFD"; - case TIFFTAG_JPEGIFOFFSET: - return "JPEGIFOFFSET"; - case TIFFTAG_JPEGIFBYTECOUNT: - return "JPEGIFBYTECOUNT"; - case TIFFTAG_DNGPRIVATEDATA: - return "DNGPRIVATEDATA"; - case EXIFTAG_MAKERNOTE: - return "EXIFTAG_MAKERNOTE"; - case TIFFTAG_PRINTIM: - return "PrintIM"; - case TIFFTAG_IMAGEOFFSET: - return "IMAGEOFFSET"; - case TIFFTAG_IMAGEBYTECOUNT: - return "IMAGEBYTECOUNT"; - case TIFFTAG_ALPHAOFFSET: - return "ALPHAOFFSET"; - case TIFFTAG_ALPHABYTECOUNT: - return "ALPHABYTECOUNT"; - default: - return ""; - } -} -#endif #ifdef ENABLE_TIFF_MAKERNOTE static uint64_t tiff_le_makernote(FILE *in, const uint32_t tiff_diroff, const char *tag_make) @@ -911,7 +932,8 @@ void file_check_tiff(file_recovery_t *fr) { const TIFFHeader *header=(const TIFFHeader *)buffer; const char *tag_make; - tag_make=find_tag_from_tiff_header(header, data_read, TIFFTAG_MAKE); + const char *potential_error=NULL; + tag_make=find_tag_from_tiff_header(header, data_read, TIFFTAG_MAKE, &potential_error); if(tag_make < (const char *)buffer || tag_make >= (const char *)buffer + data_read - 20) tag_make=NULL; if(header->tiff_magic==TIFF_LITTLEENDIAN) diff --git a/src/file_tiff.h b/src/file_tiff.h index 2f88e4e..009a2dc 100644 --- a/src/file_tiff.h +++ b/src/file_tiff.h @@ -63,7 +63,7 @@ struct ifd_header { } __attribute__ ((__packed__)); time_t get_date_from_tiff_header(const TIFFHeader *tiff, const unsigned int tiff_size); -const char *find_tag_from_tiff_header(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag); +const char *find_tag_from_tiff_header(const TIFFHeader *tiff, const unsigned int tiff_size, const unsigned int tag, const char **potential_error); void file_check_tiff(file_recovery_t *file_recovery); #ifdef __cplusplus diff --git a/src/file_vdi.c b/src/file_vdi.c new file mode 100644 index 0000000..06ad421 --- a/dev/null +++ b/src/file_vdi.c @@ -0,0 +1,106 @@ +/* + + File: file_vdi.c + + Copyright (C) 2010 Christophe GRENIER <grenier@cgsecurity.org> + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#include <stdio.h> +#include "types.h" +#include "filegen.h" +#include "common.h" + +static void register_header_check_vdi(file_stat_t *file_stat); +static int header_check_vdi(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_vdi= { + .extension="vdi", + .description="Virtual desktop infrastructure 1.1", + .min_header_distance=0, + .max_filesize=PHOTOREC_MAX_FILE_SIZE, + .recover=1, + .enable_by_default=1, + .register_header_check=®ister_header_check_vdi +}; + +static const unsigned char vdi_header[4]= {0x7f, 0x10, 0xda, 0xbe}; + +static void register_header_check_vdi(file_stat_t *file_stat) +{ + register_header_check(0x40, vdi_header,sizeof(vdi_header), &header_check_vdi, file_stat); +} + +/* Image version. */ +#define VDI_VERSION_1_1 0x00010001 + +/* Image type. */ +#define VDI_TYPE_DYNAMIC 1 +#define VDI_TYPE_STATIC 2 + +typedef unsigned char uuid_t[16]; + +typedef struct { + char text[0x40]; + uint32_t signature; + uint32_t version; + uint32_t header_size; + uint32_t image_type; + uint32_t image_flags; + char description[256]; + uint32_t offset_bmap; + uint32_t offset_data; + uint32_t cylinders; /* disk geometry, unused here */ + uint32_t heads; /* disk geometry, unused here */ + uint32_t sectors; /* disk geometry, unused here */ + uint32_t sector_size; + uint32_t unused1; + uint64_t disk_size; + uint32_t block_size; + uint32_t block_extra; /* unused here */ + uint32_t blocks_in_image; + uint32_t blocks_allocated; + uuid_t uuid_image; + uuid_t uuid_last_snap; + uuid_t uuid_link; + uuid_t uuid_parent; + uint64_t unused2[7]; +} VdiHeader; + +static int header_check_vdi(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 VdiHeader *header=(const VdiHeader *)buffer; + if(memcmp(&buffer[0x40], vdi_header, sizeof(vdi_header))==0 && le32(header->version) == VDI_VERSION_1_1) + { + reset_file_recovery(file_recovery_new); + file_recovery_new->extension=file_hint_vdi.extension; + if(le32(header->image_type) == VDI_TYPE_STATIC) + { + file_recovery_new->calculated_file_size=(uint64_t) le32(header->offset_data) + le32(header->blocks_in_image) * le32(header->block_size); + file_recovery_new->data_check=&data_check_size; + file_recovery_new->file_check=&file_check_size; + } + return 1; + } + return 0; +} diff --git a/src/godmode.c b/src/godmode.c index 834261d..28ae96c 100644 --- a/src/godmode.c +++ b/src/godmode.c @@ -471,7 +471,6 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o /* Scan the disk */ while(ind_stop==0 && search_location < search_location_max) { - unsigned int sector_inc=0; static CHS_t start; offset2CHS_inline(disk_car,search_location,&start); #ifdef HAVE_NCURSES @@ -489,6 +488,7 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o } #endif { + unsigned int sector_inc=0; int test_nbr=0; int search_now=0; int search_now_raid=0; diff --git a/src/hdaccess.c b/src/hdaccess.c index 1cbf29a..e1d2538 100644 --- a/src/hdaccess.c +++ b/src/hdaccess.c @@ -392,6 +392,7 @@ list_disk_t *hd_parse(list_disk_t *list_disk, const int verbose, const arch_fnct char device_ide_hd[]="/dev/ad0"; char device_scsi_hd[]="/dev/da0"; char device_cd[]="/dev/acd0"; + char device_vnd[]="/dev/rsvnd0c"; /* virtual node driver, interface to a disk image file */ /* wd da */ /* Disk IDE */ for(i=0;i<8;i++) @@ -447,6 +448,12 @@ list_disk_t *hd_parse(list_disk_t *list_disk, const int verbose, const arch_fnct device_cd[strlen(device_cd)-1]='0'+i; list_disk=insert_new_disk(list_disk,file_test_availability(device_cd,verbose,arch,testdisk_mode)); } + /* VND */ + for(i=0;i<4;i++) + { + device_vnd[strlen(device_vnd)-2]='0'+i; + list_disk=insert_new_disk(list_disk,file_test_availability(device_vnd,verbose,arch,testdisk_mode)); + } } #endif return list_disk; @@ -1221,8 +1228,8 @@ static int file_nopwrite(disk_t *disk_car, const void *buf, const unsigned int c static int file_sync(disk_t *disk_car) { - struct info_file_struct *data=(struct info_file_struct *)disk_car->data; #ifdef HAVE_FSYNC + struct info_file_struct *data=(struct info_file_struct *)disk_car->data; return fsync(data->handle); #else errno=EINVAL; diff --git a/src/msdos.c b/src/msdos.c index 7d53f93..06cca88 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -491,7 +491,6 @@ static int disk_pread(disk_t *disk_car, void *buf, const unsigned int count, con static int disk_pwrite_aux(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t hd_offset) { - struct info_disk_struct*data=disk_car->data; int i=0; int rc; disk_car->write_used=1; @@ -542,7 +541,6 @@ static int disk_clean(disk_t *disk_car) static int hd_report_error(disk_t *disk_car, const uint64_t hd_offset, const unsigned int count, const int rc) { - struct info_disk_struct*data=disk_car->data; log_error(" lba=%lu(%u/%u/%u) nbr_sector=%u, rc=%d\n",(long unsigned int)(hd_offset/disk_car->sector_size), offset2cylinder(disk_car,hd_offset),offset2head(disk_car,hd_offset),offset2sector(disk_car,hd_offset), count/disk_car->sector_size,rc); diff --git a/src/parthumax.c b/src/parthumax.c index dd2afc9..4fefd51 100644 --- a/src/parthumax.c +++ b/src/parthumax.c @@ -154,9 +154,7 @@ static int write_part_humax(disk_t *disk_car, const list_part_t *list_part, cons static list_part_t *init_part_order_humax(const disk_t *disk_car, list_part_t *list_part) { - int insert_error=0; int nbr_prim=0; - partition_t *new_partition; list_part_t *element; for(element=list_part;element!=NULL;element=element->next) { diff --git a/src/parti386.c b/src/parti386.c index fdf3cad..f39b9ad 100644 --- a/src/parti386.c +++ b/src/parti386.c @@ -63,6 +63,7 @@ #include "parti386.h" #include "partgpt.h" +#define TAB_PART 0x1BE static int is_extended(const unsigned int part_type); static int test_structure_i386(list_part_t *list_part); #define pt_offset_const(b, n) ((const struct partition_dos *)((b) + 0x1be + \ @@ -357,7 +358,6 @@ static list_part_t *init_part_order_i386(const disk_t *disk_car, list_part_t *li static list_part_t *read_part_i386(disk_t *disk_car, const int verbose, const int saveheader) { unsigned int i; - int res=0; CHSgeometry_t geometry; list_part_t *new_list_part=NULL; unsigned char *buffer=(unsigned char *)MALLOC(disk_car->sector_size); @@ -401,7 +401,6 @@ static list_part_t *read_part_i386(disk_t *disk_car, const int verbose, const in if(new_partition->errcode!=BAD_NOERR) { screen_buffer_add("%s\n",errmsg_i386_entry2partition(new_partition->errcode)); - res|=1; } new_list_part=insert_new_partition(new_list_part,new_partition, 0, &insert_error); if(insert_error>0) @@ -938,16 +937,17 @@ static int write_MBR_code_i386_aux(unsigned char *buffer) 0xbb, 0x00, 0x7c, 0x50, 0xc6, 0x06, 0x8f, 0x07, 0x01, 0xcd, 0x13, 0x58, 0x5e, 0x73, 0x05, 0x4f, 0x75, 0xb4, 0xeb, 0x93, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0xf6, 0xea, 0x00, 0x7c, 0x00, 0x00, 0xbe, 0x83, 0x07, 0xb9, 0x0a, 0x00, 0x50, 0xb4, 0x0e, 0x31, 0xdb, 0xac, 0xcd, 0x10, 0xe2, - 0xfb, 0x58, 0xc3, 0x54, 0x65, 0x73, 0x74, 0x44, 0x69, 0x73, 0x6b, 0x0d, 0x0a, 0x10, 0x00, 0x01, - 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, - 0x34, 0x46, 0x00, 0x00, 0x41, 0x4e, 0x44, 0x54, 0x6d, 0x62, 0x72, 0x00, 0x02, 0x02, 0x02, 0x1f, + 0xfb, 0x58, 0xc3, 'T', 'e', 's', 't', 'D', 'i', 's', 'k', 0x0d, 0x0a, 0x10, 0x00, 0x01, + 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '1', '2', '3', + '4', 'F', 0x00, 0x00, 0x41, 'N', 'D', 'T', 'm', 'b', 'r', 0x00, 0x02, 0x02, 0x02, 0x1f, 0xc7, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa }; - memcpy(buffer,&mbr_code_testdisk,TAB_PART); + /* don't overwrite the disk signature at 0x1b8 */ + memcpy(buffer, &mbr_code_testdisk, 0x1b8); buffer[0x1FE]=(unsigned char)0x55; buffer[0x1FF]=(unsigned char)0xAA; return 0; |
