diff options
author | Christophe Grenier <[email protected]> | 2011-02-07 09:17:12 +0100 |
---|---|---|
committer | Christophe Grenier <[email protected]> | 2011-02-07 09:17:12 +0100 |
commit | 237b0d53ac0d638ccbd8671293b6695436bad32c (patch) | |
tree | ad4178e092a225fe05d9cf69aa312b0db41367e2 | |
parent | 2d02984cbcde496a462304bb2bdcdfe5550c8e43 (diff) |
Minimal support to list and copy files from exFAT for TestDisk.
PhotoRec:Can carve files from exFAT free space only
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/adv.c | 15 | ||||
-rw-r--r-- | src/dirpart.c | 8 | ||||
-rw-r--r-- | src/exfat.c | 17 | ||||
-rw-r--r-- | src/exfat.h | 51 | ||||
-rw-r--r-- | src/exfatp.c | 121 | ||||
-rw-r--r-- | src/exfatp.h | 30 | ||||
-rw-r--r-- | src/intrface.c | 1 | ||||
-rw-r--r-- | src/pfree_whole.c | 13 | ||||
-rw-r--r-- | src/photorec.c | 4 | ||||
-rw-r--r-- | src/texfat.c | 240 | ||||
-rw-r--r-- | src/texfat.h | 30 |
12 files changed, 527 insertions, 13 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0dbe9b8b..38da0f5c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,10 +19,10 @@ base_H = alignio.h autoset.h common.h crc.h ewf.h fnctdsk.h hdaccess.h hdwin32 fs_C = analyse.c bfs.c bsd.c cramfs.c exfat.c fat.c fatx.c ext2.c jfs.c hfs.c hfsp.c hpfs.c luks.c lvm.c md.c netware.c ntfs.c rfs.c savehdr.c sun.c swap.c sysv.c ufs.c xfs.c zfs.c fs_H = analyse.h bfs.h bsd.h cramfs.h exfat.h fat.h fatx.h ext2.h jfs_superblock.h jfs.h hfs.h hfsp.h hpfs.h luks.h lvm.h md.h netware.h ntfs.h rfs.h savehdr.h sun.h swap.h sysv.h ufs.h xfs.h zfs.h -testdisk_ncurses_C = addpart.c adv.c askloc.c chgtype.c chgtypen.c dimage.c dirn.c dirpart.c diskacc.c diskcapa.c edit.c ext2_sb.c ext2_sbn.c fat1x.c fat32.c fat_adv.c fat_cluster.c fatn.c geometry.c godmode.c hiddenn.c intrface.c intrfn.c nodisk.c ntfs_adv.c ntfs_fix.c ntfs_udl.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c tanalyse.c tbanner.c tdelete.c tdiskop.c tdisksel.c testdisk.c thfs.c tload.c tlog.c tmbrcode.c tntfs.c toptions.c tpartwr.c -testdisk_ncurses_H = addpart.h adv.h askloc.h chgtype.h chgtypen.h dimage.h dirn.h dirpart.h diskacc.h diskcapa.h edit.h ext2_sb.h ext2_sbn.h fat1x.h fat32.h fat_adv.h fat_cluster.h fatn.h geometry.h godmode.h hiddenn.h intrface.h intrfn.h nodisk.h ntfs_udl.h partgptn.h parti386n.h partmacn.h partsunn.h partxboxn.h tanalyse.h tdelete.h tdiskop.h tdisksel.h thfs.h tload.h tlog.h tmbrcode.h tntfs.h toptions.h tpartwr.h +testdisk_ncurses_C = addpart.c adv.c askloc.c chgtype.c chgtypen.c dimage.c dirn.c dirpart.c diskacc.c diskcapa.c edit.c ext2_sb.c ext2_sbn.c fat1x.c fat32.c fat_adv.c fat_cluster.c fatn.c geometry.c godmode.c hiddenn.c intrface.c intrfn.c nodisk.c ntfs_adv.c ntfs_fix.c ntfs_udl.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c tanalyse.c tbanner.c tdelete.c tdiskop.c tdisksel.c testdisk.c texfat.c thfs.c tload.c tlog.c tmbrcode.c tntfs.c toptions.c tpartwr.c +testdisk_ncurses_H = addpart.h adv.h askloc.h chgtype.h chgtypen.h dimage.h dirn.h dirpart.h diskacc.h diskcapa.h edit.h ext2_sb.h ext2_sbn.h fat1x.h fat32.h fat_adv.h fat_cluster.h fatn.h geometry.h godmode.h hiddenn.h intrface.h intrfn.h nodisk.h ntfs_udl.h partgptn.h parti386n.h partmacn.h partsunn.h partxboxn.h tanalyse.h tdelete.h tdiskop.h tdisksel.h texfat.h thfs.h tload.h tlog.h tmbrcode.h tntfs.h toptions.h tpartwr.h -testdisk_SOURCES = $(base_C) $(base_H) $(fs_C) $(fs_H) $(testdisk_ncurses_C) $(testdisk_ncurses_H) dir.c dir.h ext2_dir.c ext2_dir.h ext2_inc.h fat_dir.c fat_dir.h ntfs_dir.c ntfs_dir.h ntfs_inc.h partgptw.c rfs_dir.c rfs_dir.h setdate.c setdate.h $(ICON_TESTDISK) next.c next.h +testdisk_SOURCES = $(base_C) $(base_H) $(fs_C) $(fs_H) $(testdisk_ncurses_C) $(testdisk_ncurses_H) dir.c dir.h exfat_dir.c exfat_dir.h ext2_dir.c ext2_dir.h ext2_inc.h fat_dir.c fat_dir.h ntfs_dir.c ntfs_dir.h ntfs_inc.h partgptw.c rfs_dir.c rfs_dir.h setdate.c setdate.h $(ICON_TESTDISK) next.c next.h file_C = filegen.c \ file_list.c \ @@ -242,9 +242,9 @@ file_C = filegen.c \ file_H = ext2.h filegen.h file_jpg.h file_sp3.h file_tar.h file_tiff.h file_txt.h list.h ole.h pe.h suspend.h -photorec_C = photorec.c phcfg.c dir.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c list.c ntfs_dir.c ntfsp.c sessionp.c setdate.c +photorec_C = photorec.c phcfg.c dir.c exfatp.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c list.c ntfs_dir.c ntfsp.c sessionp.c setdate.c -photorec_H = photorec.h phcfg.h dir.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h fat_dir.h fatp.h file_found.h memmem.h ntfs_dir.h ntfsp.h ntfs_inc.h sessionp.h setdate.h +photorec_H = photorec.h phcfg.h dir.h exfatp.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h fat_dir.h fatp.h file_found.h memmem.h ntfs_dir.h ntfsp.h ntfs_inc.h sessionp.h setdate.h photorec_ncurses_C = addpart.c askloc.c chgtype.c chgtypen.c fat_cluster.c fat_unformat.c geometry.c hiddenn.c intrfn.c nodisk.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c pbanner.c pblocksize.c pdisksel.c pfree_whole.c phbf.c phbs.c phnc.c phrecn.c ppartsel.c photorec_ncurses_H = addpart.h askloc.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometry.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdisksel.h pfree_whole.h pnext.h phbf.h phbs.h phnc.h phrecn.h ppartsel.h @@ -54,6 +54,7 @@ #include "ext2_sbn.h" #include "fat1x.h" #include "fat32.h" +#include "texfat.h" #include "tntfs.h" #include "thfs.h" #include "askloc.h" @@ -75,12 +76,18 @@ extern const arch_fnct_t arch_xbox; #define DEFAULT_IMAGE_NAME "image.dd" +static int is_exfat(const partition_t *partition); static int is_hfs(const partition_t *partition); static int is_hfsp(const partition_t *partition); static int is_linux(const partition_t *partition); static int is_part_hfs(const partition_t *partition); static int is_part_hfsp(const partition_t *partition); +static int is_exfat(const partition_t *partition) +{ + return (is_part_ntfs(partition) || partition->upart_type==UP_EXFAT); +} + static int is_hfs(const partition_t *partition) { return (is_part_hfs(partition) || partition->upart_type==UP_HFS); @@ -291,6 +298,8 @@ void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const options="tubcq"; else if(is_ntfs(partition)) options="tlubcq"; + else if(is_exfat(partition)) + options="tlbcq"; else if(is_linux(partition)) { if(partition->upart_type==UP_EXT2) @@ -440,6 +449,7 @@ void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const else if(is_part_ntfs(partition)) { ntfs_boot_sector(disk_car, partition, verbose, expert, current_cmd); +// exFAT_boot_sector(disk_car, partition, verbose, current_cmd); rewrite=1; } else if(partition->upart_type==UP_FAT32) @@ -457,6 +467,11 @@ void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const ntfs_boot_sector(disk_car, partition, verbose, expert, current_cmd); rewrite=1; } + else if(partition->upart_type==UP_EXFAT) + { + exFAT_boot_sector(disk_car, partition, verbose, current_cmd); + rewrite=1; + } } break; case 'c': diff --git a/src/dirpart.c b/src/dirpart.c index 9d596be7..949019d8 100644 --- a/src/dirpart.c +++ b/src/dirpart.c @@ -39,6 +39,7 @@ #endif #include "dir.h" #include "dirn.h" +#include "exfat_dir.h" #include "ext2_dir.h" #include "fat_dir.h" #include "ntfs_dir.h" @@ -61,7 +62,11 @@ int dir_partition(disk_t *disk_car, const partition_t *partition, const int verb if(is_part_fat(partition)) res=dir_partition_fat_init(disk_car,partition,&dir_data,verbose); else if(is_part_ntfs(partition)) + { res=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); + if(res!=0) + res=dir_partition_exfat_init(disk_car, partition, &dir_data, verbose); + } else if(is_part_linux(partition)) { res=dir_partition_ext2_init(disk_car,partition,&dir_data,verbose); @@ -90,6 +95,9 @@ int dir_partition(disk_t *disk_car, const partition_t *partition, const int verb case UP_NTFS: res=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); break; + case UP_EXFAT: + res=dir_partition_exfat_init(disk_car, partition, &dir_data, verbose); + break; default: return res; } diff --git a/src/exfat.c b/src/exfat.c index f0611c93..a2b38e62 100644 --- a/src/exfat.c +++ b/src/exfat.c @@ -34,6 +34,19 @@ #include "common.h" #include "exfat.h" +uint64_t exfat_cluster_to_offset(const struct exfat_super_block *exfat_header, const unsigned int cluster) +{ + return ((uint64_t)(((cluster-2) << exfat_header->block_per_clus_bits) + le32(exfat_header->clus_blocknr))) << exfat_header->blocksize_bits; +} + +int exfat_read_cluster(disk_t *disk, const partition_t *partition, const struct exfat_super_block*exfat_header, void *buffer, const unsigned int cluster) +{ + return disk->pread(disk, + buffer, + 1 << (exfat_header->block_per_clus_bits + exfat_header->blocksize_bits), + partition->part_offset + exfat_cluster_to_offset(exfat_header, cluster)); +} + static int set_EXFAT_info(partition_t *partition) { partition->fsname[0]='\0'; @@ -44,10 +57,10 @@ static int set_EXFAT_info(partition_t *partition) return 0; } -int check_EXFAT(disk_t *disk_car, partition_t *partition) +int check_EXFAT(disk_t *disk, partition_t *partition) { unsigned char *buffer=(unsigned char*)MALLOC(EXFAT_BS_SIZE); - if(disk_car->pread(disk_car, buffer, EXFAT_BS_SIZE, partition->part_offset) != EXFAT_BS_SIZE) + if(disk->pread(disk, buffer, EXFAT_BS_SIZE, partition->part_offset) != EXFAT_BS_SIZE) { free(buffer); return 1; diff --git a/src/exfat.h b/src/exfat.h index 1753c5a1..9152f53e 100644 --- a/src/exfat.h +++ b/src/exfat.h @@ -1,8 +1,8 @@ /* - file: swap.h + file: exfat.h - Copyright (C) 2009 Christophe GRENIER <[email protected]> + Copyright (C) 2010-2011 Christophe GRENIER <[email protected]> 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 @@ -49,7 +49,52 @@ struct exfat_super_block { uint16_t signature; /* 0xaa55 */ } __attribute__ ((__packed__)); -int check_EXFAT(disk_t *disk_car, partition_t *partition); +struct exfat_file_entry +{ + uint8_t type; + uint8_t sec_count; + uint16_t checksum; + uint16_t attr; + uint16_t reserved1; + uint16_t ctime; + uint16_t cdate; + uint16_t mtime; + uint16_t mdate; + uint16_t atime; + uint16_t adate; + uint8_t cms; + uint8_t mms; + uint8_t ctz; + uint8_t mtz; + uint8_t reserved2[7]; +} __attribute__ ((__packed__)); + +struct exfat_stream_ext_entry +{ + uint8_t type; + uint8_t sec_flags; + uint8_t reserved1; + uint8_t name_length; + uint16_t name_hash; + uint16_t reserved2; + uint64_t valid_data_length; + uint32_t reserved3; + uint32_t first_cluster; + uint64_t data_length; +} __attribute__ ((__packed__)); + +struct exfat_alloc_bitmap_entry +{ + uint8_t type; + uint8_t bitmap_flags; + uint8_t reserved[18]; + uint32_t first_cluster; + uint64_t data_length; +} __attribute__ ((__packed__)); + +uint64_t exfat_cluster_to_offset(const struct exfat_super_block *exfat_header, const unsigned int cluster); +int exfat_read_cluster(disk_t *disk, const partition_t *partition, const struct exfat_super_block*exfat_header, void *buffer, const unsigned int cluster); +int check_EXFAT(disk_t *disk, partition_t *partition); int recover_EXFAT(const disk_t *disk, const struct exfat_super_block *exfat_header, partition_t *partition); int test_EXFAT(const struct exfat_super_block *exfat_header, partition_t *partition); diff --git a/src/exfatp.c b/src/exfatp.c new file mode 100644 index 00000000..d20fac7b --- /dev/null +++ b/src/exfatp.c @@ -0,0 +1,121 @@ +/* + + File: fatp.c + + Copyright (C) 2010 Christophe GRENIER <[email protected]> + + 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 +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include "types.h" +#include "common.h" +#include "list.h" +#include "filegen.h" +#include "exfatp.h" +#include "exfat.h" +#include "log.h" +#include "fat.h" + +static struct exfat_alloc_bitmap_entry *exfat_get_bitmap(unsigned char*buffer, const unsigned int size) +{ + unsigned int i; + for(i=0; i<size; i+=0x20) + if(buffer[i]==0x81) + return (struct exfat_alloc_bitmap_entry *)&buffer[i]; + return NULL; +} + +unsigned int exfat_remove_used_space(disk_t *disk, const partition_t *partition, alloc_data_t *list_search_space) +{ + struct exfat_super_block *exfat_header; + struct exfat_alloc_bitmap_entry *bitmap; + unsigned int cluster_shift; + /* Load boot sector */ + exfat_header=(struct exfat_super_block *)MALLOC(0x200); + if(disk->pread(disk, exfat_header, 0x200, partition->part_offset) != 0x200) + { + log_error("Can't read exFAT boot sector.\n"); + free(exfat_header); + return 0; + } + cluster_shift=exfat_header->block_per_clus_bits + exfat_header->blocksize_bits; + /* Load bitmap information */ + { + const uint64_t start=partition->part_offset + + exfat_cluster_to_offset(exfat_header, le32(exfat_header->rootdir_clusnr)); + unsigned char *buffer_rootdir=(unsigned char *)MALLOC(1<<cluster_shift); + unsigned char *buffer; + unsigned int i; + unsigned int cluster_bitmap; + const uint64_t start_exfat1=le32(exfat_header->fat_blocknr) << exfat_header->blocksize_bits; + uint64_t start_free=0; + uint64_t end_free=0; + if(disk->pread(disk, buffer_rootdir, 1 << cluster_shift, start) != (1<<cluster_shift)) + { + log_error("exFAT: Can't root directory cluster.\n"); + free(buffer_rootdir); + free(exfat_header); + return 0; + } + bitmap=exfat_get_bitmap(buffer_rootdir, 1<<cluster_shift); + if(bitmap==NULL) + { + log_error("exFAT: Can't find bitmap.\n"); + free(buffer_rootdir); + free(exfat_header); + return 0; + } + cluster_bitmap=le32(bitmap->first_cluster); + log_trace("exfat_remove_used_space\n"); + buffer=(unsigned char *)MALLOC(1<<cluster_shift); + for(i=2; i<le32(exfat_header->total_clusters)+2; i++) + { + unsigned int offset_o; + offset_o=(i-2)%(8<<cluster_shift); + if(offset_o==0) + { + exfat_read_cluster(disk, partition, exfat_header, buffer, cluster_bitmap); + cluster_bitmap=get_next_cluster(disk, partition, UP_FAT32, start_exfat1, cluster_bitmap); + } + if(((buffer[offset_o/8]>>(offset_o%8))&1) != 0) + { + /* Not free */ + if(end_free+1==partition->part_offset + exfat_cluster_to_offset(exfat_header, i)) + end_free+=(1<<cluster_shift); + else + { + if(start_free != end_free) + del_search_space(list_search_space, start_free, end_free); + start_free=partition->part_offset + exfat_cluster_to_offset(exfat_header, i); + end_free=start_free + (1<<cluster_shift) - 1; + } + } + } + free(buffer); + if(start_free != end_free) + del_search_space(list_search_space, start_free, end_free); + free(buffer_rootdir); + free(exfat_header); + } + return (1<<cluster_shift); +} diff --git a/src/exfatp.h b/src/exfatp.h new file mode 100644 index 00000000..142b3399 --- /dev/null +++ b/src/exfatp.h @@ -0,0 +1,30 @@ +/* + + File: exfatp.h + + Copyright (C) 2011 Christophe GRENIER <[email protected]> + + 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 __cplusplus +extern "C" { +#endif + +unsigned int exfat_remove_used_space(disk_t *disk, const partition_t *partition, alloc_data_t *list_search_space); + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif diff --git a/src/intrface.c b/src/intrface.c index d593b9cc..043e8e9d 100644 --- a/src/intrface.c +++ b/src/intrface.c @@ -235,6 +235,7 @@ static list_part_t *ask_structure_ncurses(disk_t *disk_car,list_part_t *list_par } switch(pos->part->upart_type) { + case UP_EXFAT: case UP_EXT2: case UP_EXT3: case UP_EXT4: diff --git a/src/pfree_whole.c b/src/pfree_whole.c index 76c8fd43..6a208c5c 100644 --- a/src/pfree_whole.c +++ b/src/pfree_whole.c @@ -43,6 +43,12 @@ int ask_mode_ext2(const disk_t *disk_car, const partition_t *partition, unsigned {'O',"Other","FAT/NTFS/HFS+/ReiserFS/..."}, {0,NULL,NULL} }; + static const struct MenuItem menuexFAT[]= + { + {'F',"Free", "Scan for files from exFAT unallocated space only"}, + {'W',"Whole","Extract files from whole partition"}, + {0,NULL,NULL} + }; static const struct MenuItem menuFAT12[]= { {'F',"Free", "Scan for files from FAT12 unallocated space only"}, @@ -110,8 +116,11 @@ int ask_mode_ext2(const disk_t *disk_car, const partition_t *partition, unsigned wmove(window,7,0); wclrtoeol(window); waddstr(window,"Please choose if all space need to be analysed:"); - if(partition->upart_type==UP_FAT12) - command = wmenuSelect_ext(window, 23, 8, 0, menuFAT16, 11, + if(partition->upart_type==UP_EXFAT) + command = wmenuSelect_ext(window, 23, 8, 0, menuexFAT, 11, + options, MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); + else if(partition->upart_type==UP_FAT12) + command = wmenuSelect_ext(window, 23, 8, 0, menuFAT12, 11, options, MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); else if(partition->upart_type==UP_FAT16) command = wmenuSelect_ext(window, 23, 8, 0, menuFAT16, 11, diff --git a/src/photorec.c b/src/photorec.c index 475c7d7a..73b310c8 100644 --- a/src/photorec.c +++ b/src/photorec.c @@ -41,6 +41,7 @@ #include "dir.h" #include "filegen.h" #include "photorec.h" +#include "exfatp.h" #include "ext2p.h" #include "fatp.h" #include "ntfsp.h" @@ -390,6 +391,8 @@ unsigned int remove_used_space(disk_t *disk_car, const partition_t *partition, a partition->upart_type==UP_FAT16 || partition->upart_type==UP_FAT32) return fat_remove_used_space(disk_car, partition, list_search_space); + else if(partition->upart_type==UP_EXFAT) + return exfat_remove_used_space(disk_car, partition, list_search_space); #ifdef HAVE_LIBNTFS else if(partition->upart_type==UP_NTFS) return ntfs_remove_used_space(disk_car, partition, list_search_space); @@ -708,7 +711,6 @@ alloc_data_t *file_finish2(file_recovery_t *file_recovery, const char *recup_dir } fclose(file_recovery->handle); file_recovery->handle=NULL; - // log_debug("%s %llu\n",file_recovery->filename,(long long unsigned)file_recovery->file_size); if(file_recovery->file_size>0) { if(file_recovery->time!=0 && file_recovery->time!=(time_t)-1) diff --git a/src/texfat.c b/src/texfat.c new file mode 100644 index 00000000..a2f4b0e9 --- /dev/null +++ b/src/texfat.c @@ -0,0 +1,240 @@ +/* + + File: texFAT.c + + Copyright (C) 2011 Christophe GRENIER <[email protected]> + + 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 + +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#include <ctype.h> +#include "types.h" +#include "common.h" +#include "lang.h" +#include "intrf.h" +#include "intrfn.h" +#include "exfat.h" +#include "log.h" +#include "log_part.h" +#include "texfat.h" + +#ifdef HAVE_NCURSES +static void exFAT_dump_ncurses(disk_t *disk, const partition_t *partition, const unsigned char *buffer_bs, const unsigned char *buffer_backup_bs) +{ + WINDOW *window=newwin(0,0,0,0); /* full screen */ + keypad(window, TRUE); /* Need it to get arrow key */ + aff_copy(window); + wmove(window,4,0); + wprintw(window,"%s",disk->description(disk)); + wmove(window,5,0); + aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); + mvwaddstr(window,6,0, "Boot sector Backup boot record"); + dump2(window, buffer_bs, buffer_backup_bs, 12 * disk->sector_size); + delwin(window); + (void) clearok(stdscr, TRUE); +#ifdef HAVE_TOUCHWIN + touchwin(stdscr); +#endif +} +#endif + +static void exFAT_dump(disk_t *disk, const partition_t *partition, const unsigned char *buffer_bs, const unsigned char *buffer_backup_bs) +{ + log_info("Superblock Backup superblock\n"); + dump2_log(buffer_bs, buffer_backup_bs, 12 * disk->sector_size); +#ifdef HAVE_NCURSES + exFAT_dump_ncurses(disk, partition, buffer_bs, buffer_backup_bs); +#endif +} + +int exFAT_boot_sector(disk_t *disk, partition_t *partition, const int verbose, char **current_cmd) +{ + unsigned char *buffer_bs; + unsigned char *buffer_backup_bs; + const char *options=""; + int rescan=1; +#ifdef HAVE_NCURSES + struct MenuItem menu_exFAT[]= + { + { 'P', "Previous",""}, + { 'N', "Next","" }, + { 'Q', "Quit","Return to Advanced menu"}, + { 'O', "Org. BS","Copy superblock over backup sector"}, + { 'B', "Backup BS","Copy backup superblock over superblock"}, + { 'D', "Dump","Dump superblock and backup superblock"}, + { 0, NULL, NULL } + }; +#endif + buffer_bs=(unsigned char*)MALLOC(12 * disk->sector_size); + buffer_backup_bs=(unsigned char*)MALLOC(12 * disk->sector_size); + + while(1) + { +#ifdef HAVE_NCURSES + unsigned int menu=0; +#endif + int command; + screen_buffer_reset(); + if(rescan==1) + { + int opt_over=0; + int opt_B=0; + int opt_O=0; + options="D"; +#ifdef HAVE_NCURSES + aff_copy(stdscr); + wmove(stdscr,4,0); + wprintw(stdscr,"%s",disk->description(disk)); + mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); + wmove(stdscr,6,0); + aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); +#endif + log_info("\nexFAT_boot_sector\n"); + log_partition(disk,partition); + screen_buffer_add("Boot sector\n"); + if(disk->pread(disk, buffer_bs, 12 * disk->sector_size, partition->part_offset) != 12 * disk->sector_size) + { + screen_buffer_add("Bad: can't read exFAT boot record.\n"); + memset(buffer_bs,0,12 * disk->sector_size); + } + else if(test_EXFAT((const struct exfat_super_block*)buffer_bs, partition)==0) + { + screen_buffer_add("exFAT OK\n"); + opt_O=1; + opt_over=1; + } + else + screen_buffer_add("Bad\n"); + screen_buffer_add("\nBackup boot record\n"); + if(disk->pread(disk, buffer_backup_bs, 12 * disk->sector_size, partition->part_offset + 12 * disk->sector_size) != 12 * disk->sector_size) + { + screen_buffer_add("Bad: can't read exFAT backup boot record.\n"); + memset(buffer_backup_bs,0,12 * disk->sector_size); + } + else if(test_EXFAT((const struct exfat_super_block*)buffer_backup_bs, partition)==0) + { + screen_buffer_add("exFAT OK\n"); + opt_B=1; + opt_over=1; + } + else + screen_buffer_add("Bad\n"); + screen_buffer_add("\n"); + if(memcmp(buffer_bs,buffer_backup_bs,12 * disk->sector_size)==0) + { + screen_buffer_add("Sectors are identical.\n"); + opt_over=0; + } + else + { + screen_buffer_add("Sectors are not identical.\n"); + } + if(opt_over!=0) + { + if(opt_B!=0 && opt_O!=0) + options="DOB"; + else if(opt_B!=0) + options="DB"; + else if(opt_O!=0) + options="DO"; + } + rescan=0; + } + screen_buffer_to_log(); + if(*current_cmd!=NULL) + { + command=0; + while(*current_cmd[0]==',') + (*current_cmd)++; + if(strncmp(*current_cmd,"dump",4)==0) + { + (*current_cmd)+=4; + command='D'; + } + else if(strncmp(*current_cmd,"originalexFAT",11)==0) + { + (*current_cmd)+=11; + if(strchr(options,'O')!=NULL) + command='O'; + } + else if(strncmp(*current_cmd,"backupexFAT",9)==0) + { + (*current_cmd)+=9; + if(strchr(options,'B')!=NULL) + command='B'; + } + } + else + { + log_flush(); +#ifdef HAVE_NCURSES + command=screen_buffer_display_ext(stdscr, options, menu_exFAT, &menu); +#else + command=0; +#endif + } + switch(command) + { + case 0: + free(buffer_bs); + free(buffer_backup_bs); + return 0; + case 'O': /* O : copy original superblock over backup boot */ +#ifdef HAVE_NCURSES + if(ask_confirmation("Copy original exFAT boot record over backup, confirm ? (Y/N)")!=0) + { + log_info("copy original superblock over backup boot\n"); + if(disk->pwrite(disk, buffer_bs, 12 * disk->sector_size, partition->part_offset + 12 * disk->sector_size) != 12 * disk->sector_size) + { + display_message("Write error: Can't overwrite exFAT backup boot record\n"); + } + disk->sync(disk); + rescan=1; + } +#endif + break; + case 'B': /* B : copy backup superblock over main superblock */ +#ifdef HAVE_NCURSES + if(ask_confirmation("Copy backup exFAT boot record over main boot record, confirm ? (Y/N)")!=0) + { + log_info("copy backup superblock over main superblock\n"); + /* Reset information about backup boot record */ + partition->sb_offset=0; + if(disk->pwrite(disk, buffer_backup_bs, 12 * disk->sector_size, partition->part_offset) != 12 * disk->sector_size) + { + display_message("Write error: Can't overwrite exFAT main boot record\n"); + } + disk->sync(disk); + rescan=1; + } +#endif + break; + case 'D': + exFAT_dump(disk, partition, buffer_bs, buffer_backup_bs); + break; + } + } +} diff --git a/src/texfat.h b/src/texfat.h new file mode 100644 index 00000000..c939ac70 --- /dev/null +++ b/src/texfat.h @@ -0,0 +1,30 @@ +/* + + File: texfat.h + + Copyright (C) 2011 Christophe GRENIER <[email protected]> + + 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 __cplusplus +extern "C" { +#endif + +int exFAT_boot_sector(disk_t *disk, partition_t *partition, const int verbose, char **current_cmd); + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif |