summaryrefslogtreecommitdiff
Diffstat
-rw-r--r--doc_src/testdisk.8.in10
-rw-r--r--src/Makefile.am1
-rw-r--r--src/common.h1
-rw-r--r--src/dir.c4
-rw-r--r--src/ewf.c7
-rw-r--r--src/file_dbn.c1
-rw-r--r--src/file_doc.c4
-rw-r--r--src/file_http.c66
-rw-r--r--src/file_jpg.c7
-rw-r--r--src/file_list.c2
-rw-r--r--src/file_prc.c2
-rw-r--r--src/file_ps.c2
-rw-r--r--src/file_tiff.c182
-rw-r--r--src/file_tiff.h2
-rw-r--r--src/file_vdi.c106
-rw-r--r--src/godmode.c2
-rw-r--r--src/hdaccess.c9
-rw-r--r--src/msdos.c2
-rw-r--r--src/parthumax.c2
-rw-r--r--src/parti386.c14
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
diff --git a/src/dir.c b/src/dir.c
index cbbef9d..c17d8eb 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -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);
diff --git a/src/ewf.c b/src/ewf.c
index ed06841..6174b0a 100644
--- a/src/ewf.c
+++ b/src/ewf.c
@@ -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=&register_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=&register_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;