summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am10
-rw-r--r--src/adv.c15
-rw-r--r--src/dirpart.c8
-rw-r--r--src/exfat.c17
-rw-r--r--src/exfat.h51
-rw-r--r--src/exfatp.c121
-rw-r--r--src/exfatp.h30
-rw-r--r--src/intrface.c1
-rw-r--r--src/pfree_whole.c13
-rw-r--r--src/photorec.c4
-rw-r--r--src/texfat.c240
-rw-r--r--src/texfat.h30
12 files changed, 527 insertions, 13 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 0dbe9b8..38da0f5 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
diff --git a/src/adv.c b/src/adv.c
index e470bae..45a22ad 100644
--- a/src/adv.c
+++ b/src/adv.c
@@ -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 9d596be..949019d 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 f0611c9..a2b38e6 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 1753c5a..9152f53 100644
--- a/src/exfat.h
+++ b/src/exfat.h
@@ -1,8 +1,8 @@
/*
- file: swap.h
+ file: exfat.h
- Copyright (C) 2009 Christophe GRENIER <grenier@cgsecurity.org>
+ Copyright (C) 2010-2011 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
@@ -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 0000000..d20fac7
--- /dev/null
+++ b/src/exfatp.c
@@ -0,0 +1,121 @@
+/*
+
+ File: fatp.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
+#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 0000000..142b339
--- /dev/null
+++ b/src/exfatp.h
@@ -0,0 +1,30 @@
+/*
+
+ File: exfatp.h
+
+ Copyright (C) 2011 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 __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 d593b9c..043e8e9 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 76c8fd4..6a208c5 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 475c7d7..73b310c 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 0000000..a2f4b0e
--- /dev/null
+++ b/src/texfat.c
@@ -0,0 +1,240 @@
+/*
+
+ File: texFAT.c
+
+ Copyright (C) 2011 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
+
+#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 0000000..c939ac7
--- /dev/null
+++ b/src/texfat.h
@@ -0,0 +1,30 @@
+/*
+
+ File: texfat.h
+
+ Copyright (C) 2011 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 __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