diff options
author | Christophe Grenier <[email protected]> | 2010-11-05 09:00:22 +0100 |
---|---|---|
committer | Christophe Grenier <[email protected]> | 2010-11-05 09:00:22 +0100 |
commit | 377144c3a7062b44cdd607c91e86c24cd7fc0f61 (patch) | |
tree | f7d7db52476407e8592e046f49763bde31bc2b34 /src | |
parent | 173e66e1bc9e04d171097eb57d42692fd4440126 (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
Diffstat (limited to 'src')
-rw-r--r-- | src/analyse.c | 184 | ||||
-rw-r--r-- | src/common.h | 1 | ||||
-rw-r--r-- | src/ewf.c | 9 | ||||
-rw-r--r-- | src/godmode.c | 28 | ||||
-rw-r--r-- | src/hdaccess.c | 9 | ||||
-rw-r--r-- | src/hdcache.c | 32 | ||||
-rw-r--r-- | src/io_redir.c | 9 | ||||
-rw-r--r-- | src/msdos.c | 25 | ||||
-rw-r--r-- | src/win32.c | 19 |
9 files changed, 203 insertions, 113 deletions
diff --git a/src/analyse.c b/src/analyse.c index fe8f9624..3036f1dc 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 0e60b47c..f2bcb042 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); @@ -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 6da0446b..2c12865e 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 1f1df3b3..93b2a06d 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 87648f73..e28e7a1a 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 a8f85ca7..449a3e85 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 16d1e634..955f1607 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 6ad7696f..82543025 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; |