summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2010-11-05 09:00:22 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2010-11-05 09:00:22 +0100
commit377144c3a7062b44cdd607c91e86c24cd7fc0f61 (patch)
treef7d7db52476407e8592e046f49763bde31bc2b34
parent173e66e1bc9e04d171097eb57d42692fd4440126 (diff)
Introduce pread_fast(), a function that can return a pointer to the data in cache
instead of using memcpy to fill the buffer with a copy of the data
-rw-r--r--src/analyse.c184
-rw-r--r--src/common.h1
-rw-r--r--src/ewf.c9
-rw-r--r--src/godmode.c28
-rw-r--r--src/hdaccess.c9
-rw-r--r--src/hdcache.c32
-rw-r--r--src/io_redir.c9
-rw-r--r--src/msdos.c25
-rw-r--r--src/win32.c19
9 files changed, 203 insertions, 113 deletions
diff --git a/src/analyse.c b/src/analyse.c
index fe8f962..3036f1d 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -58,70 +58,78 @@
int search_NTFS_backup(unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
{
- const struct ntfs_boot_sector*ntfs_header=(const struct ntfs_boot_sector*)buffer;
-// assert(sizeof(struct ntfs_boot_sector)<=DEFAULT_SECTOR_SIZE);
- if(disk->pread(disk, buffer, DEFAULT_SECTOR_SIZE, partition->part_offset) != DEFAULT_SECTOR_SIZE)
- return -1;
- /* NTFS recovery using backup sector */
- if(le16(ntfs_header->marker)==0xAA55 &&
- recover_NTFS(disk, ntfs_header, partition, verbose, dump_ind, 1)==0)
- return 1;
+ void *data=disk->pread_fast(disk, buffer, DEFAULT_SECTOR_SIZE, partition->part_offset);
+ if(data==NULL)
+ return -1;
+ {
+ const struct ntfs_boot_sector*ntfs_header=(const struct ntfs_boot_sector*)data;
+ /* NTFS recovery using backup sector */
+ if(le16(ntfs_header->marker)==0xAA55 &&
+ recover_NTFS(disk, ntfs_header, partition, verbose, dump_ind, 1)==0)
+ return 1;
+ }
return 0;
}
int search_HFS_backup(unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
{
- const hfs_mdb_t *hfs_mdb=(const hfs_mdb_t *)buffer;
- const struct hfsp_vh *vh=(const struct hfsp_vh *)buffer;
-// assert(sizeof(hfs_mdb_t)<=0x400);
-// assert(sizeof(struct hfsp_vh)==0x200);
- if(disk->pread(disk, buffer, 0x400, partition->part_offset) != 0x400)
+ void *data=disk->pread_fast(disk, buffer, 0x400, partition->part_offset);
+ if(data==NULL)
return -1;
- /* HFS recovery using backup sector */
- if(hfs_mdb->drSigWord==be16(HFS_SUPER_MAGIC) &&
- recover_HFS(disk, hfs_mdb, partition, verbose, dump_ind, 1)==0)
- {
- strncpy(partition->info,"HFS found using backup sector!",sizeof(partition->info));
- return 1;
- }
- if((be16(vh->version)==4 || be16(vh->version)==5) &&
- recover_HFSP(disk, vh, partition, verbose, dump_ind, 1)==0)
{
- strncpy(partition->info,"HFS+ found using backup sector!",sizeof(partition->info));
- return 1;
+ const hfs_mdb_t *hfs_mdb=(const hfs_mdb_t *)data;
+ const struct hfsp_vh *vh=(const struct hfsp_vh *)data;
+ /* HFS recovery using backup sector */
+ if(hfs_mdb->drSigWord==be16(HFS_SUPER_MAGIC) &&
+ recover_HFS(disk, hfs_mdb, partition, verbose, dump_ind, 1)==0)
+ {
+ strncpy(partition->info,"HFS found using backup sector!",sizeof(partition->info));
+ return 1;
+ }
+ if((be16(vh->version)==4 || be16(vh->version)==5) &&
+ recover_HFSP(disk, vh, partition, verbose, dump_ind, 1)==0)
+ {
+ strncpy(partition->info,"HFS+ found using backup sector!",sizeof(partition->info));
+ return 1;
+ }
}
return 0;
}
int search_EXFAT_backup(unsigned char *buffer, disk_t *disk, partition_t *partition)
{
- const struct exfat_super_block *exfat_header=(const struct exfat_super_block *)buffer;
- if(disk->pread(disk, buffer, DEFAULT_SECTOR_SIZE, partition->part_offset) != DEFAULT_SECTOR_SIZE)
+ void *data=disk->pread_fast(disk, buffer, DEFAULT_SECTOR_SIZE, partition->part_offset);
+ if(data==NULL)
return -1;
- /* EXFAT recovery using backup sector */
- if(le16(exfat_header->signature)==0xAA55 &&
- recover_EXFAT(disk, exfat_header, partition)==0)
{
- strncpy(partition->info,"EXFAT found using backup sector!",sizeof(partition->info));
- partition->sb_offset=6*512;
- partition->part_offset-=partition->sb_offset; /* backup sector */
- return 1;
+ const struct exfat_super_block *exfat_header=(const struct exfat_super_block *)data;
+ /* EXFAT recovery using backup sector */
+ if(le16(exfat_header->signature)==0xAA55 &&
+ recover_EXFAT(disk, exfat_header, partition)==0)
+ {
+ strncpy(partition->info,"EXFAT found using backup sector!",sizeof(partition->info));
+ partition->sb_offset=6*512;
+ partition->part_offset-=partition->sb_offset; /* backup sector */
+ return 1;
+ }
}
return 0;
}
int search_FAT_backup(unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
{
- const struct fat_boot_sector *fat_header=(const struct fat_boot_sector *)buffer;
-// assert(sizeof(struct fat_boot_sector)==DEFAULT_SECTOR_SIZE);
- if(disk->pread(disk, buffer, DEFAULT_SECTOR_SIZE, partition->part_offset) != DEFAULT_SECTOR_SIZE)
+ void *data=disk->pread_fast(disk, buffer, DEFAULT_SECTOR_SIZE, partition->part_offset);
+ if(data==NULL)
return -1;
- /* FAT32 recovery using backup sector */
- if(le16(fat_header->marker)==0xAA55 &&
- recover_FAT(disk, fat_header, partition, verbose, dump_ind, 1)==0)
{
- strncpy(partition->info,"FAT found using backup sector!",sizeof(partition->info));
- return 1;
+ const struct fat_boot_sector *fat_header=(const struct fat_boot_sector *)data;
+ /* FAT32 recovery using backup sector */
+ if(le16(fat_header->marker)==0xAA55 &&
+ recover_FAT(disk, fat_header, partition, verbose, dump_ind, 1)==0)
+ {
+ strncpy(partition->info,"FAT found using backup sector!",sizeof(partition->info));
+ return 1;
+ }
}
return 0;
}
@@ -260,17 +268,19 @@ int search_type_2(const unsigned char *buffer, disk_t *disk, partition_t *partit
int search_type_8(unsigned char *buffer, disk_t *disk,partition_t *partition,const int verbose, const int dump_ind)
{
+ void *data;
if(verbose>2)
{
log_trace("search_type_8 lba=%lu\n",
(long unsigned)(partition->part_offset/disk->sector_size));
}
- if(disk->pread(disk, buffer, 4096, partition->part_offset + 4096) != 4096)
+ data=disk->pread_fast(disk, buffer, 4096, partition->part_offset + 4096);
+ if(data==NULL)
return -1;
{ /* MD 1.2 */
- const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer;
+ const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)data;
if(le32(sb1->major_version)==1 &&
- recover_MD(disk,(const struct mdp_superblock_s*)buffer,partition,verbose,dump_ind)==0)
+ recover_MD(disk, (const struct mdp_superblock_s*)data, partition, verbose, dump_ind)==0)
{
partition->part_offset-=(uint64_t)le64(sb1->super_offset)*512-4096;
return 1;
@@ -281,74 +291,82 @@ int search_type_8(unsigned char *buffer, disk_t *disk,partition_t *partition,con
int search_type_16(unsigned char *buffer, disk_t *disk,partition_t *partition,const int verbose, const int dump_ind)
{
- const struct ufs_super_block *ufs=(const struct ufs_super_block *)buffer;
- const struct vdev_boot_header *zfs=(const struct vdev_boot_header*)buffer;
-// assert(sizeof(struct ufs_super_block)<=3*DEFAULT_SECTOR_SIZE);
+ void *data;
if(verbose>2)
{
log_trace("search_type_16 lba=%lu\n",
(long unsigned)(partition->part_offset/disk->sector_size));
}
/* 8k offset */
- if(disk->pread(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 16 * 512) != 3 * DEFAULT_SECTOR_SIZE)
+ data=disk->pread_fast(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 16 * 512);
+ if(data==NULL)
return -1;
- /* Test UFS */
- if((le32(ufs->fs_magic)==UFS_MAGIC || be32(ufs->fs_magic)==UFS_MAGIC ||
- le32(ufs->fs_magic)==UFS2_MAGIC || be32(ufs->fs_magic)==UFS2_MAGIC) &&
- recover_ufs(disk, ufs, partition, verbose, dump_ind)==0)
- return 1;
- if(le64(zfs->vb_magic)==VDEV_BOOT_MAGIC &&
- recover_ZFS(disk, zfs, partition, verbose, dump_ind)==0)
- return 1;
+ {
+ const struct ufs_super_block *ufs=(const struct ufs_super_block *)data;
+ const struct vdev_boot_header *zfs=(const struct vdev_boot_header*)data;
+ /* Test UFS */
+ if((le32(ufs->fs_magic)==UFS_MAGIC || be32(ufs->fs_magic)==UFS_MAGIC ||
+ le32(ufs->fs_magic)==UFS2_MAGIC || be32(ufs->fs_magic)==UFS2_MAGIC) &&
+ recover_ufs(disk, ufs, partition, verbose, dump_ind)==0)
+ return 1;
+ if(le64(zfs->vb_magic)==VDEV_BOOT_MAGIC &&
+ recover_ZFS(disk, zfs, partition, verbose, dump_ind)==0)
+ return 1;
+ }
return 0;
}
int search_type_64(unsigned char *buffer, disk_t *disk,partition_t *partition,const int verbose, const int dump_ind)
{
-// assert(sizeof(struct jfs_superblock)<=2*DEFAULT_SECTOR_SIZE);
- const struct jfs_superblock* jfs=(const struct jfs_superblock*)(buffer+0x200);
+ void *data;
if(verbose>2)
{
log_trace("search_type_64 lba=%lu\n",
(long unsigned)(partition->part_offset/disk->sector_size));
}
/* 32k offset */
- if(disk->pread(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 63 * 512) != 3 * DEFAULT_SECTOR_SIZE)
+ data=disk->pread_fast(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 63 * 512);
+ if(data==NULL)
return -1;
- /* Test JFS */
- if(memcmp(jfs->s_magic,"JFS1",4)==0 &&
- recover_JFS(disk, jfs, partition, verbose, dump_ind)==0)
- return 1;
+ data=(char*)data+0x200;
+ {
+ const struct jfs_superblock* jfs=(const struct jfs_superblock*)data;
+ /* Test JFS */
+ if(memcmp(jfs->s_magic,"JFS1",4)==0 &&
+ recover_JFS(disk, jfs, partition, verbose, dump_ind)==0)
+ return 1;
+ }
return 0;
}
int search_type_128(unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
{
- const struct reiserfs_super_block *rfs=(const struct reiserfs_super_block *)(buffer+0x400);
- const struct reiser4_master_sb *rfs4=(const struct reiser4_master_sb *)(buffer+0x400);
- const struct ufs_super_block *ufs=(const struct ufs_super_block *)(buffer+0x400);
- /* Reiserfs4 need to read the master superblock and the format40 superblock => 4096 */
-// assert(sizeof(struct reiserfs_super_block)<=9*DEFAULT_SECTOR_SIZE);
-// assert(4096+sizeof(struct format40_super)<=9*DEFAULT_SECTOR_SIZE);
-// assert(sizeof(struct ufs_super_block)<=9*DEFAULT_SECTOR_SIZE);
+ void *data;
if(verbose>2)
{
log_trace("search_type_128 lba=%lu\n",
(long unsigned)(partition->part_offset/disk->sector_size));
}
- /* 64k offset */
- if(disk->pread(disk, buffer, 11 * DEFAULT_SECTOR_SIZE, partition->part_offset + 126 * 512) != 11 * DEFAULT_SECTOR_SIZE)
+ data=disk->pread_fast(disk, buffer, 11 * DEFAULT_SECTOR_SIZE, partition->part_offset + 126 * 512);
+ if(data==NULL)
return -1;
- /* Test ReiserFS */
- if((memcmp(rfs->s_magic,"ReIs",4) == 0 ||
- memcmp(rfs4->magic,REISERFS4_SUPER_MAGIC,sizeof(REISERFS4_SUPER_MAGIC)) == 0) &&
- recover_rfs(disk, rfs, partition, verbose, dump_ind)==0)
- return 1;
- /* Test UFS2 */
- if((le32(ufs->fs_magic)==UFS_MAGIC || be32(ufs->fs_magic)==UFS_MAGIC ||
- le32(ufs->fs_magic)==UFS2_MAGIC || be32(ufs->fs_magic)==UFS2_MAGIC) &&
- recover_ufs(disk, ufs, partition, verbose, dump_ind)==0)
- return 1;
-// if(recover_gfs2(disk,(buffer+0x400),partition,verbose,dump_ind)==0) return 1;
+ data=(char*)data+0x400;
+ {
+ const struct reiserfs_super_block *rfs=(const struct reiserfs_super_block *)data;
+ const struct reiser4_master_sb *rfs4=(const struct reiser4_master_sb *)data;
+ const struct ufs_super_block *ufs=(const struct ufs_super_block *)data;
+ /* 64k offset */
+ /* Test ReiserFS */
+ if((memcmp(rfs->s_magic,"ReIs",4) == 0 ||
+ memcmp(rfs4->magic,REISERFS4_SUPER_MAGIC,sizeof(REISERFS4_SUPER_MAGIC)) == 0) &&
+ recover_rfs(disk, rfs, partition, verbose, dump_ind)==0)
+ return 1;
+ /* Test UFS2 */
+ if((le32(ufs->fs_magic)==UFS_MAGIC || be32(ufs->fs_magic)==UFS_MAGIC ||
+ le32(ufs->fs_magic)==UFS2_MAGIC || be32(ufs->fs_magic)==UFS2_MAGIC) &&
+ recover_ufs(disk, ufs, partition, verbose, dump_ind)==0)
+ return 1;
+ // if(recover_gfs2(disk,(buffer+0x400),partition,verbose,dump_ind)==0) return 1;
+ }
return 0;
}
diff --git a/src/common.h b/src/common.h
index 0e60b47..f2bcb04 100644
--- a/src/common.h
+++ b/src/common.h
@@ -312,6 +312,7 @@ struct param_disk_struct
char *model;
const char *(*description)(disk_t *disk_car);
const char *(*description_short)(disk_t *disk_car);
+ void *(*pread_fast)(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset);
int (*pread)(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset);
int (*pwrite)(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset);
int (*sync)(disk_t *disk_car);
diff --git a/src/ewf.c b/src/ewf.c
index 2424f9f..cdf7136 100644
--- a/src/ewf.c
+++ b/src/ewf.c
@@ -58,6 +58,7 @@
static const char *fewf_description(disk_t *disk);
static const char *fewf_description_short(disk_t *disk);
static int fewf_clean(disk_t *disk);
+static void *fewf_pread_fast(disk_t *disk, void *buffer, const unsigned int count, const uint64_t offset);
static int fewf_pread(disk_t *disk, void *buffer, const unsigned int count, const uint64_t offset);
static int fewf_nopwrite(disk_t *disk, const void *buffer, const unsigned int count, const uint64_t offset);
static int fewf_sync(disk_t *disk);
@@ -129,6 +130,7 @@ disk_t *fewf_init(const char *device, const arch_fnct_t *arch, const int mode)
disk->data=data;
disk->description=fewf_description;
disk->description_short=fewf_description_short;
+ disk->pread_fast=fewf_pread_fast;
disk->pread=fewf_pread;
disk->pwrite=fewf_nopwrite;
disk->sync=fewf_sync;
@@ -237,6 +239,13 @@ static int fewf_pread(disk_t *disk, void *buffer, const unsigned int count, cons
return taille;
}
+static void *fewf_pread_fast(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset)
+{
+ if(fewf_pread(disk, buf, count, offset)==offset)
+ return buf;
+ return NULL;
+}
+
static int fewf_nopwrite(disk_t *disk, const void *buffer, const unsigned int count, const uint64_t offset)
{
log_error("fewf_nopwrite(xx,%u,buffer,%lu(%u/%u/%u)) write refused\n",
diff --git a/src/godmode.c b/src/godmode.c
index 6da0446..2c12865 100644
--- a/src/godmode.c
+++ b/src/godmode.c
@@ -532,15 +532,12 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o
{
if(search_now_raid>0 || fast_mode>1)
{ /* Search Linux software RAID */
- if(disk_car->pread(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE, search_location) != 8 * DEFAULT_SECTOR_SIZE)
+ void *data=disk_car->pread_fast(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE, search_location);
+ if(data!=NULL)
{
- res = -1;
- }
- else
- {
- if(recover_MD(disk_car,(const struct mdp_superblock_s*)buffer_disk,partition,verbose,dump_ind)==0)
+ if(recover_MD(disk_car, (const struct mdp_superblock_s*)data, partition, verbose, dump_ind)==0)
{
- const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer_disk;
+ const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)data;
if(le32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC)
{
if(le32(sb1->major_version)==0)
@@ -628,9 +625,10 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o
if((disk_car->arch==&arch_i386 && start_ext2.sector==1 && (start_ext2.head<=2 || fast_mode>1)) ||
(disk_car->arch!=&arch_i386 && search_location%location_boundary==0))
{
- if(disk_car->pread(disk_car, buffer_disk, 1024, search_location) == 1024)
+ void *data=disk_car->pread_fast(disk_car, buffer_disk, 1024, search_location);
+ if(data!=NULL)
{
- const struct ext2_super_block *sb=(const struct ext2_super_block*)buffer_disk;
+ const struct ext2_super_block *sb=(const struct ext2_super_block*)data;
if(le16(sb->s_block_group_nr)>0)
{
if(le16(sb->s_magic)==EXT2_SUPER_MAGIC &&
@@ -638,10 +636,6 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o
res=1;
}
}
- else
- {
- res = -1;
- }
}
}
}
@@ -691,7 +685,7 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o
if(res<=0 && test_nbr==12)
{
/* read to fill the cache */
- disk_car->pread(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE,
+ disk_car->pread_fast(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE,
partition->part_offset + (63 + 16) * 512);
/* Try to catch disklabel before BSD FFS partition */
res=search_type_128(buffer_disk,disk_car,partition,verbose,dump_ind);
@@ -858,11 +852,13 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o
unsigned int i;
for(i=32;i>0;i--)
{
+ void *data;
partition->part_size=(uint64_t)0;
partition->part_offset=element->part->part_offset - i * disk_car->sector_size;
- if(disk_car->pread(disk_car, buffer_disk, DEFAULT_SECTOR_SIZE, partition->part_offset) == DEFAULT_SECTOR_SIZE)
+ data=disk_car->pread_fast(disk_car, buffer_disk, DEFAULT_SECTOR_SIZE, partition->part_offset);
+ if(data!=NULL)
{
- if(recover_NTFS(disk_car,(const struct ntfs_boot_sector*)buffer_disk,partition,verbose,dump_ind,0)==0)
+ if(recover_NTFS(disk_car, (const struct ntfs_boot_sector*)data, partition, verbose, dump_ind, 0)==0)
{
partition->status=STATUS_DELETED;
if(disk_car->arch->is_part_known(partition)!=0 && partition->part_size>1 &&
diff --git a/src/hdaccess.c b/src/hdaccess.c
index 1f1df3b..93b2a06 100644
--- a/src/hdaccess.c
+++ b/src/hdaccess.c
@@ -144,6 +144,7 @@ static const char *file_description(disk_t *disk_car);
static const char *file_description_short(disk_t *disk_car);
static int file_clean(disk_t *disk_car);
static int file_pread(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset);
+static void *file_pread_fast(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset);
static int file_pwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset);
static int file_nopwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset);
static int file_sync(disk_t *disk_car);
@@ -1176,6 +1177,13 @@ static int file_pread(disk_t *disk_car, void *buf, const unsigned int count, con
return align_pread(&file_pread_aux, disk_car, buf, count, offset);
}
+static void *file_pread_fast(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset)
+{
+ if(file_pread(disk, buf, count, offset)==offset)
+ return buf;
+ return NULL;
+}
+
static int file_pwrite_aux(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset)
{
int fd=((struct info_file_struct *)disk_car->data)->handle;
@@ -1395,6 +1403,7 @@ disk_t *file_test_availability(const char *device, const int verbose, const arch
disk_car->data=data;
disk_car->description=file_description;
disk_car->description_short=file_description_short;
+ disk_car->pread_fast=file_pread_fast;
disk_car->pread=file_pread;
disk_car->pwrite=((mode&O_RDWR)==O_RDWR?file_pwrite:file_nopwrite);
disk_car->sync=file_sync;
diff --git a/src/hdcache.c b/src/hdcache.c
index 87648f7..e28e7a1 100644
--- a/src/hdcache.c
+++ b/src/hdcache.c
@@ -34,7 +34,7 @@
#include "hdcache.h"
#include "log.h"
-#define CACHE_BUFFER_NBR 128
+#define CACHE_BUFFER_NBR 16
#define CACHE_DEFAULT_SIZE 64*512
//#define DEBUG_CACHE 1
@@ -64,12 +64,41 @@ struct cache_struct
static int cache_pread_aux(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset, const unsigned int read_ahead);
static int cache_pread(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset);
+static void *cache_pread_fast(disk_t *disk, void *buffer, const unsigned int count, const uint64_t offset);
static int cache_pwrite(disk_t *disk_car, const void *buffer, const unsigned int count, const uint64_t offset);
static int cache_sync(disk_t *clean);
static int cache_clean(disk_t *clean);
static const char *cache_description(disk_t *disk_car);
static const char *cache_description_short(disk_t *disk_car);
+static void *cache_get_data_p(disk_t *disk, const unsigned int count, const uint64_t offset)
+{
+ struct cache_struct *data=(struct cache_struct *)disk->data;
+ unsigned int i;
+ unsigned int cache_buffer_nbr;
+ for(i=0, cache_buffer_nbr=data->cache_buffer_nbr;
+ i<CACHE_BUFFER_NBR;
+ i++, cache_buffer_nbr=(cache_buffer_nbr+CACHE_BUFFER_NBR-1)%CACHE_BUFFER_NBR)
+ {
+ const struct cache_buffer_struct *cache=&data->cache[cache_buffer_nbr];
+ if(cache->buffer!=NULL && cache->cache_size>0 &&
+ cache->cache_offset <= offset &&
+ offset + count < cache->cache_offset + cache->cache_size)
+ return cache->buffer + offset - cache->cache_offset;
+ }
+ return NULL;
+}
+
+static void* cache_pread_fast(disk_t *disk, void *buffer, const unsigned int count, const uint64_t offset)
+{
+ void*data=cache_get_data_p(disk, count, offset);
+ if(data!=NULL)
+ return data;
+ if(cache_pread(disk, buffer, count, offset) == count)
+ return buffer;
+ return NULL;
+}
+
static int cache_pread(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset)
{
const struct cache_struct *data=(const struct cache_struct *)disk_car->data;
@@ -265,6 +294,7 @@ disk_t *new_diskcache(disk_t *disk_car, const unsigned int testdisk_mode)
new_disk_car->disk_real_size=disk_car->disk_real_size;
new_disk_car->write_used=0;
new_disk_car->data=data;
+ new_disk_car->pread_fast=cache_pread_fast;
new_disk_car->pread=cache_pread;
new_disk_car->pwrite=cache_pwrite;
new_disk_car->sync=cache_sync;
diff --git a/src/io_redir.c b/src/io_redir.c
index a8f85ca..449a3e8 100644
--- a/src/io_redir.c
+++ b/src/io_redir.c
@@ -55,6 +55,7 @@ struct info_io_redir
list_redir_t *list_redir;
};
+static void *io_redir_pread_fast(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset);
static int io_redir_pread(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset);
static int io_redir_clean(disk_t *clean);
@@ -78,6 +79,7 @@ int io_redir_add_redir(disk_t *disk_car, const uint64_t org_offset, const unsign
disk_car->data=data;
disk_car->description=old_disk_car->description;
disk_car->pwrite=old_disk_car->pwrite;
+ disk_car->pread_fast=io_redir_pread_fast;
disk_car->pread=io_redir_pread;
disk_car->clean=io_redir_clean;
}
@@ -217,6 +219,13 @@ static int io_redir_pread(disk_t *disk_car, void *buffer, const unsigned int cou
return count;
}
+static void *io_redir_pread_fast(disk_t *disk, void *buffer, const unsigned int count, const uint64_t offset)
+{
+ if(io_redir_pread(disk, buffer, count, offset)==count)
+ return buffer;
+ return NULL;
+}
+
static int io_redir_clean(disk_t *disk_car)
{
if(disk_car->data)
diff --git a/src/msdos.c b/src/msdos.c
index 16d1e63..955f160 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -52,6 +52,7 @@ static int hd_identify_enh_bios(disk_t *param_disk,const int verbose);
static int check_enh_bios(const unsigned int disk, const int verbose);
static int hd_report_error(disk_t *disk_car, const uint64_t hd_offset, const unsigned int count, const int rc);
static const char *disk_description_short(disk_t *disk_car);
+static void *disk_pread_fast(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset);
static int disk_pread(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t hd_offset);
static int disk_pwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t hd_offset);
static int disk_nopwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset);
@@ -84,7 +85,7 @@ static int alloc_cmd_dos_buffer(void)
static void disk_reset_error(disk_t *disk_car)
{
- struct info_disk_struct*data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
biosdisk(0, data->disk, 0, 0, 1, 1, NULL);
}
@@ -95,7 +96,7 @@ static int hd_pread(disk_t *disk_car, void *buf, const unsigned int count, const
int xfer_dos_segment, xfer_dos_selector;
int nsects;
unsigned long int hd_offset;
- struct info_disk_struct*data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
nsects=count/disk_car->sector_size;
hd_offset=offset/disk_car->sector_size;
if(data->mode_enh==0)
@@ -146,7 +147,7 @@ static int hd_pwrite(disk_t *disk_car, const void *buf, const unsigned int count
int xfer_dos_segment, xfer_dos_selector;
int nsects;
unsigned long int hd_offset;
- struct info_disk_struct*data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
nsects=count/disk_car->sector_size;
hd_offset=offset/disk_car->sector_size;
@@ -240,7 +241,7 @@ static int hd_identify_enh_bios(disk_t *disk_car,const int verbose)
int compute_LBA=0;
__dpmi_regs r;
unsigned char buf[0x200]; /* Don't change it! */
- struct info_disk_struct*data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
if(cmd_dos_segment==0)
if(alloc_cmd_dos_buffer())
return 1;
@@ -376,6 +377,7 @@ disk_t *hd_identify(const int verbose, const unsigned int disk, const arch_fnct_
disk_car->sector_size=DEFAULT_SECTOR_SIZE;
disk_car->description=disk_description;
disk_car->description_short=disk_description_short;
+ disk_car->pread_fast=disk_pread_fast;
disk_car->pread=disk_pread;
disk_car->pwrite=((testdisk_mode&TESTDISK_O_RDWR)==TESTDISK_O_RDWR?disk_pwrite:disk_nopwrite);
disk_car->sync=disk_sync;
@@ -430,7 +432,7 @@ disk_t *hd_identify(const int verbose, const unsigned int disk, const arch_fnct_
const char *disk_description(disk_t *disk_car)
{
- struct info_disk_struct*data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
char buffer_disk_size[100];
size_to_unit(disk_car->disk_size, buffer_disk_size),
snprintf(disk_car->description_txt, sizeof(disk_car->description_txt),"Disk %2x - %s - CHS %lu %u %u%s",
@@ -442,7 +444,7 @@ const char *disk_description(disk_t *disk_car)
static const char *disk_description_short(disk_t *disk_car)
{
- struct info_disk_struct*data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
char buffer_disk_size[100];
size_to_unit(disk_car->disk_size, buffer_disk_size);
snprintf(disk_car->description_short_txt, sizeof(disk_car->description_txt),"Disk %2x - %s",
@@ -452,7 +454,7 @@ static const char *disk_description_short(disk_t *disk_car)
static int disk_pread_aux(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset)
{
- struct info_disk_struct*data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
if(data->geo_phys.cylinders>0 && offset+count>disk_car->disk_size)
{
log_error("disk_pread_aux: Don't read after the end of the disk\n");
@@ -491,6 +493,13 @@ static int disk_pread(disk_t *disk_car, void *buf, const unsigned int count, con
return align_pread(&disk_pread_aux, disk_car, buf, count, offset);
}
+static void *disk_pread_fast(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset)
+{
+ if(disk_pread(disk, buf, count, offset)==offset)
+ return buf;
+ return NULL;
+}
+
static int disk_pwrite_aux(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t hd_offset)
{
int i=0;
@@ -517,7 +526,7 @@ static int disk_pwrite(disk_t *disk_car, const void *buf, const unsigned int cou
static int disk_nopwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset)
{
- struct info_disk_struct *data=disk_car->data;
+ struct info_disk_struct *data=(struct info_disk_struct *)disk_car->data;
log_warning("disk_nopwrite(%d,%u,buffer,%lu(%u/%u/%u)) write refused\n", data->disk,
(unsigned)(count/disk_car->sector_size),(long unsigned)(offset/disk_car->sector_size),
offset2cylinder(disk_car,offset),offset2head(disk_car,offset),offset2sector(disk_car,offset));
diff --git a/src/win32.c b/src/win32.c
index 6ad7696..8254302 100644
--- a/src/win32.c
+++ b/src/win32.c
@@ -58,6 +58,7 @@ static uint64_t filewin32_getfilesize(HANDLE handle, const char *device);
static const char *file_win32_description(disk_t *disk_car);
static const char *file_win32_description_short(disk_t *disk_car);
static int file_win32_clean(disk_t *disk_car);
+static void *file_win32_pread_fast(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset);
static int file_win32_pread(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset);
static int file_win32_pwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset);
static int file_win32_nopwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset);
@@ -319,6 +320,7 @@ disk_t *file_test_availability_win32(const char *device, const int verbose, cons
disk_car->data=data;
disk_car->description=file_win32_description;
disk_car->description_short=file_win32_description_short;
+ disk_car->pread_fast=file_win32_pread_fast;
disk_car->pread=file_win32_pread;
disk_car->pwrite=((data->mode&FILE_WRITE_DATA)==FILE_WRITE_DATA?file_win32_pwrite:file_win32_nopwrite);
disk_car->sync=file_win32_sync;
@@ -343,7 +345,7 @@ disk_t *file_test_availability_win32(const char *device, const int verbose, cons
static const char *file_win32_description(disk_t *disk_car)
{
- struct info_file_win32_struct *data=disk_car->data;
+ struct info_file_win32_struct *data=(struct info_file_win32_struct *)disk_car->data;
char buffer_disk_size[100];
size_to_unit(disk_car->disk_size, buffer_disk_size);
if(disk_car->device[0]=='\\' && disk_car->device[1]=='\\' && disk_car->device[2]=='.' && disk_car->device[3]=='\\' && disk_car->device[5]==':')
@@ -361,7 +363,7 @@ static const char *file_win32_description(disk_t *disk_car)
static const char *file_win32_description_short(disk_t *disk_car)
{
- struct info_file_win32_struct *data=disk_car->data;
+ struct info_file_win32_struct *data=(struct info_file_win32_struct *)disk_car->data;
char buffer_disk_size[100];
size_to_unit(disk_car->disk_size, buffer_disk_size);
if(disk_car->device[0]=='\\' && disk_car->device[1]=='\\' && disk_car->device[2]=='.' && disk_car->device[3]=='\\' && disk_car->device[5]==':')
@@ -399,7 +401,7 @@ static int file_win32_clean(disk_t *disk_car)
{
if(disk_car->data!=NULL)
{
- struct info_file_win32_struct *data=disk_car->data;
+ struct info_file_win32_struct *data=(struct info_file_win32_struct *)disk_car->data;
CloseHandle(data->handle);
}
return generic_clean(disk_car);
@@ -494,6 +496,13 @@ static int file_win32_pread(disk_t *disk_car, void *buf, const unsigned int coun
return align_pread(&file_win32_pread_aux, disk_car, buf, count, offset);
}
+static void *file_win32_pread_fast(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset)
+{
+ if(file_win32_pread(disk, buf, count, offset)==offset)
+ return buf;
+ return NULL;
+}
+
static int file_win32_pwrite_aux(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset)
{
long int ret;
@@ -543,7 +552,7 @@ static int file_win32_pwrite(disk_t *disk_car, const void *buf, const unsigned i
static int file_win32_nopwrite(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset)
{
- const struct info_file_win32_struct *data=disk_car->data;
+ const struct info_file_win32_struct *data=(const struct info_file_win32_struct *)disk_car->data;
log_warning("file_win32_nopwrite(%d,%u,buffer,%lu(%u/%u/%u)) write refused\n", (unsigned int)data->handle,
(unsigned)(count/disk_car->sector_size),(long unsigned)(offset/disk_car->sector_size),
offset2cylinder(disk_car,offset),offset2head(disk_car,offset),offset2sector(disk_car,offset));
@@ -552,7 +561,7 @@ static int file_win32_nopwrite(disk_t *disk_car, const void *buf, const unsigned
static int file_win32_sync(disk_t *disk_car)
{
- const struct info_file_win32_struct *data=disk_car->data;
+ const struct info_file_win32_struct *data=(const struct info_file_win32_struct *)disk_car->data;
if(FlushFileBuffers(data->handle)==0)
{
errno=EINVAL;