Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F4324613
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
53 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.c b/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.c
index b66b3f6..67c37c7 100644
--- a/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.c
+++ b/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.c
@@ -1,149 +1,374 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program 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 3 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "fat_functions.h"
#include "libxmount_morphing_unallocated_retvalues.h"
+#include <string.h> // For memset
+
#define LOG_DEBUG(...) { \
LIBXMOUNT_LOG_DEBUG(p_fat_handle->debug,__VA_ARGS__); \
}
/*
* ReadFatHeader
*/
int ReadFatHeader(pts_FatHandle p_fat_handle,
pts_LibXmountMorphingInputFunctions p_input_functions,
uint8_t debug)
{
pts_FatVH p_fat_vh;
int ret;
size_t bytes_read;
uint32_t root_dir_sectors;
uint32_t fat_size;
uint32_t total_sectors;
uint32_t data_sectors;
uint32_t cluster_count;
// Init FAT handle
- p_fat_handle->p_fat_vh=NULL;
+ memset(p_fat_handle,0,sizeof(ts_FatHandle));
+ p_fat_handle->fat_type=FatType_Unknown;
p_fat_handle->debug=debug;
LOG_DEBUG("Trying to read FAT volume header\n");
// Alloc buffer for header
p_fat_vh=calloc(1,sizeof(ts_FatVH));
if(p_fat_vh==NULL) return UNALLOCATED_MEMALLOC_FAILED;
// Read VH from input image
ret=p_input_functions->Read(0,
(char*)(p_fat_vh),
0,
sizeof(ts_FatVH),
&bytes_read);
if(ret!=0 || bytes_read!=sizeof(ts_FatVH)) {
free(p_fat_vh);
- p_fat_vh=NULL;
return UNALLOCATED_FAT_CANNOT_READ_HEADER;
}
// Convert values to host endianness (FAT values are always stored in little
// endian)
p_fat_vh->bytes_per_sector=le16toh(p_fat_vh->bytes_per_sector);
p_fat_vh->reserved_sectors=le16toh(p_fat_vh->reserved_sectors);
p_fat_vh->root_entry_count=le16toh(p_fat_vh->root_entry_count);
p_fat_vh->total_sectors_16=le16toh(p_fat_vh->total_sectors_16);
p_fat_vh->fat16_sectors=le16toh(p_fat_vh->fat16_sectors);
p_fat_vh->total_sectors_32=le32toh(p_fat_vh->total_sectors_32);
p_fat_vh->fat32_sectors=le32toh(p_fat_vh->fat32_sectors);
LOG_DEBUG("FAT VH jump instruction 1: 0x%02X\n",p_fat_vh->jump_inst[0]);
LOG_DEBUG("FAT bytes per sector: %" PRIu16 "\n",
p_fat_vh->bytes_per_sector);
LOG_DEBUG("FAT sectors per cluster: %" PRIu8 "\n",
p_fat_vh->sectors_per_cluster);
LOG_DEBUG("FAT reserved sectors: %" PRIu16 "\n",
p_fat_vh->reserved_sectors);
LOG_DEBUG("FAT count: %" PRIu8 "\n",p_fat_vh->fat_count);
LOG_DEBUG("FAT root entry count: %" PRIu16 "\n",
p_fat_vh->root_entry_count);
LOG_DEBUG("FAT media type: %02X\n",p_fat_vh->media_type);
LOG_DEBUG("FAT total sector count (16bit): %" PRIu16 "\n",
p_fat_vh->total_sectors_16);
LOG_DEBUG("FAT sectors per FAT (16bit): %" PRIu16 "\n",
p_fat_vh->fat16_sectors);
LOG_DEBUG("FAT total sector count (32bit): %" PRIu32 "\n",
p_fat_vh->total_sectors_32);
LOG_DEBUG("FAT sectors per FAT (32bit): %" PRIu32 "\n",
p_fat_vh->fat32_sectors);
// Check header values
if((p_fat_vh->jump_inst[0]!=0xEB && p_fat_vh->jump_inst[0]!=0xE9) ||
p_fat_vh->bytes_per_sector==0 ||
p_fat_vh->bytes_per_sector%512!=0 ||
p_fat_vh->sectors_per_cluster==0 ||
p_fat_vh->sectors_per_cluster%2!=0 ||
p_fat_vh->reserved_sectors==0 ||
p_fat_vh->fat_count==0 ||
(p_fat_vh->total_sectors_16==0 && p_fat_vh->total_sectors_32==0) ||
(p_fat_vh->total_sectors_16!=0 && p_fat_vh->total_sectors_32!=0))
{
free(p_fat_vh);
- p_fat_vh=NULL;
return UNALLOCATED_FAT_INVALID_HEADER;
}
LOG_DEBUG("Determining FAT type\n");
// Determine the count of sectors occupied by the root directory
root_dir_sectors=((p_fat_vh->root_entry_count*32)+
(p_fat_vh->bytes_per_sector-1))/p_fat_vh->bytes_per_sector;
// Determine the count of sectors in the data region
if(p_fat_vh->fat16_sectors!=0) fat_size=p_fat_vh->fat16_sectors;
else fat_size=p_fat_vh->fat32_sectors;
if(p_fat_vh->total_sectors_16!=0) total_sectors=p_fat_vh->total_sectors_16;
else total_sectors=p_fat_vh->total_sectors_32;
data_sectors=total_sectors-(p_fat_vh->reserved_sectors+
(p_fat_vh->fat_count*fat_size)+root_dir_sectors);
// Determine the count of clusters
cluster_count=data_sectors/p_fat_vh->sectors_per_cluster;
// Determine FAT type
if(cluster_count<4085) {
- LOG_DEBUG("FAT is of type FAT12\n");
- p_fat_handle->fat_type=FatType_Fat12;
+ LOG_DEBUG("FAT is of unsupported type FAT12\n");
+ free(p_fat_vh);
+ return UNALLOCATED_FAT_UNSUPPORTED_FS_TYPE;
} else if(cluster_count<65525) {
LOG_DEBUG("FAT is of type FAT16\n");
p_fat_handle->fat_type=FatType_Fat16;
} else {
LOG_DEBUG("FAT is of type FAT32\n");
p_fat_handle->fat_type=FatType_Fat32;
}
+ // TODO: What about newer version of FAT like exFAT etc... ??
p_fat_handle->p_fat_vh=p_fat_vh;
return UNALLOCATED_OK;
}
/*
* FreeFatHeader
*/
void FreeFatHeader(pts_FatHandle p_fat_handle) {
if(p_fat_handle==NULL) return;
if(p_fat_handle->p_fat_vh!=NULL) free(p_fat_handle->p_fat_vh);
+ switch(p_fat_handle->fat_type) {
+ case FatType_Fat16: {
+ if(p_fat_handle->p_fat16!=NULL) free(p_fat_handle->p_fat16);
+ break;
+ }
+ case FatType_Fat32: {
+ if(p_fat_handle->p_fat32!=NULL) free(p_fat_handle->p_fat32);
+ break;
+ }
+ case FatType_Unknown:
+ default:
+ break;
+ }
+}
+
+/*
+ * ReadFat
+ */
+int ReadFat(pts_FatHandle p_fat_handle,
+ pts_LibXmountMorphingInputFunctions p_input_functions)
+{
+ pts_FatVH p_fat_vh=p_fat_handle->p_fat_vh;
+ int ret;
+ size_t fat_size;
+ off_t fat_offset;
+ size_t bytes_read;
+
+ LOG_DEBUG("Trying to read FAT\n");
+
+ // Determine FAT size
+ if(p_fat_vh->fat16_sectors!=0) fat_size=p_fat_vh->fat16_sectors;
+ else fat_size=p_fat_vh->fat32_sectors;
+ fat_size*=p_fat_vh->bytes_per_sector;
+
+ // Calculate FAT offset
+ fat_offset=p_fat_vh->reserved_sectors*p_fat_vh->bytes_per_sector;
+
+ LOG_DEBUG("FAT consists of %zu bytes starting at offset %zu\n",
+ fat_size,
+ fat_offset);
+
+ // Alloc buffer and Read FAT
+ if(p_fat_handle->fat_type==FatType_Fat32) {
+ // Alloc buffer
+ p_fat_handle->p_fat32=(uint32_t*)calloc(1,fat_size);
+ if(p_fat_handle->p_fat32==NULL) return UNALLOCATED_MEMALLOC_FAILED;
+
+ // Read FAT
+ ret=p_input_functions->Read(0,
+ (char*)(p_fat_handle->p_fat32),
+ fat_offset,
+ fat_size,
+ &bytes_read);
+ if(ret!=0 || bytes_read!=fat_size) {
+ free(p_fat_handle->p_fat32);
+ p_fat_handle->p_fat32=NULL;
+ return UNALLOCATED_FAT_CANNOT_READ_FAT;
+ }
+
+ // Convert FAT to host endianness
+ for(uint64_t i=0;i<fat_size/sizeof(uint32_t);i++) {
+ p_fat_handle->p_fat32[i]=le32toh(p_fat_handle->p_fat32[i]);
+ }
+ } else {
+ // Alloc buffer
+ p_fat_handle->p_fat16=(uint16_t*)calloc(1,fat_size);
+ if(p_fat_handle->p_fat16==NULL) return UNALLOCATED_MEMALLOC_FAILED;
+
+ // Read FAT
+ ret=p_input_functions->Read(0,
+ (char*)(p_fat_handle->p_fat16),
+ fat_offset,
+ fat_size,
+ &bytes_read);
+ if(ret!=0 || bytes_read!=fat_size) {
+ free(p_fat_handle->p_fat16);
+ p_fat_handle->p_fat16=NULL;
+ return UNALLOCATED_FAT_CANNOT_READ_FAT;
+ }
+
+ // Convert FAT to host endianness
+ for(uint64_t i=0;i<fat_size/sizeof(uint16_t);i++) {
+ p_fat_handle->p_fat16[i]=le16toh(p_fat_handle->p_fat16[i]);
+ }
+ }
+
+ LOG_DEBUG("FAT read successfully\n");
+
+ return UNALLOCATED_OK;
+}
+
+/*
+ * BuildFatBlockMap
+ */
+int BuildFatBlockMap(pts_FatHandle p_fat_handle,
+ uint64_t **pp_free_block_map,
+ uint64_t *p_free_block_map_size,
+ uint64_t *p_block_size)
+{
+ pts_FatVH p_fat_vh=p_fat_handle->p_fat_vh;
+ uint64_t total_clusters;
+ uint64_t *p_free_block_map=NULL;
+ uint64_t free_block_map_size=0;
+
+ LOG_DEBUG("Searching unallocated FAT clusters\n");
+
+ // Calculate total amount of cluster
+ if(p_fat_vh->total_sectors_16!=0) total_clusters=p_fat_vh->total_sectors_16;
+ else total_clusters=p_fat_vh->total_sectors_32;
+ total_clusters/=p_fat_vh->sectors_per_cluster;
+
+ // Save offset of every unallocated cluster in block map
+ if(p_fat_handle->fat_type==FatType_Fat32) {
+ for(uint64_t cur_cluster=0;cur_cluster<total_clusters;cur_cluster++) {
+ if((p_fat_handle->p_fat32[cur_cluster] & 0x0FFFFFFF)==0 ||
+ (p_fat_handle->p_fat32[cur_cluster] & 0x0FFFFFFF)==0x0FFFFFF7)
+ {
+ LOG_DEBUG("Cluster %" PRIu64 " is unallocated (FAT value 0x%08X)\n",
+ cur_cluster,
+ p_fat_handle->p_fat32[cur_cluster]);
+ p_free_block_map=realloc(p_free_block_map,
+ (free_block_map_size+1)*sizeof(uint64_t));
+ if(p_free_block_map==NULL) return UNALLOCATED_MEMALLOC_FAILED;
+ p_free_block_map[free_block_map_size]=
+ cur_cluster*p_fat_vh->bytes_per_sector*p_fat_vh->sectors_per_cluster;
+ free_block_map_size++;
+ } else {
+ LOG_DEBUG("Cluster %" PRIu64 " is allocated (FAT value 0x%08X)\n",
+ cur_cluster,
+ p_fat_handle->p_fat32[cur_cluster]);
+ }
+ }
+ } else {
+ for(uint64_t cur_cluster=0;cur_cluster<total_clusters;cur_cluster++) {
+ if((p_fat_handle->p_fat16[cur_cluster] & 0x0FFF)==0 ||
+ (p_fat_handle->p_fat16[cur_cluster] & 0x0FFF)==0x0FF7)
+ {
+ LOG_DEBUG("Cluster %" PRIu64 " is unallocated (FAT value 0x%04X)\n",
+ cur_cluster,
+ p_fat_handle->p_fat16[cur_cluster]);
+ p_free_block_map=realloc(p_free_block_map,
+ (free_block_map_size+1)*sizeof(uint64_t));
+ if(p_free_block_map==NULL) return UNALLOCATED_MEMALLOC_FAILED;
+ p_free_block_map[free_block_map_size]=
+ cur_cluster*p_fat_vh->sectors_per_cluster*p_fat_vh->bytes_per_sector;
+ free_block_map_size++;
+ } else {
+ LOG_DEBUG("Cluster %" PRIu64 " is allocated (FAT value 0x%04X)\n",
+ cur_cluster,
+ p_fat_handle->p_fat16[cur_cluster]);
+ }
+ }
+ }
+
+ LOG_DEBUG("Found %" PRIu64 " unallocated FAT clusters\n",
+ free_block_map_size);
+
+ // Free FAT as it is no longer needed
+ if(p_fat_handle->fat_type==FatType_Fat32) {
+ free(p_fat_handle->p_fat32);
+ p_fat_handle->p_fat32=NULL;
+ } else {
+ free(p_fat_handle->p_fat16);
+ p_fat_handle->p_fat16=NULL;
+ }
+
+ *pp_free_block_map=p_free_block_map;
+ *p_free_block_map_size=free_block_map_size;
+ *p_block_size=p_fat_vh->bytes_per_sector*p_fat_vh->sectors_per_cluster;
+ return UNALLOCATED_OK;
+}
+
+/*
+ * GetFatInfos
+ */
+int GetFatInfos(pts_FatHandle p_fat_handle, char **pp_buf) {
+ pts_FatVH p_fat_vh=p_fat_handle->p_fat_vh;
+ int ret;
+ char *p_buf=NULL;
+ char *p_fat_type;
+
+ switch(p_fat_handle->fat_type) {
+ case FatType_Fat16:
+ p_fat_type="FAT16";
+ break;
+ case FatType_Fat32:
+ p_fat_type="FAT32";
+ break;
+ case FatType_Unknown:
+ default:
+ p_fat_type="Unknown";
+ }
+
+ ret=asprintf(&p_buf,
+ "FAT filesystem type: %s\n"
+ "FAT bytes per sector: %" PRIu16 "\n"
+ "FAT sectors per cluster: %" PRIu8 "\n"
+ "FAT reserved sectors: %" PRIu16 "\n"
+ "FAT count: %" PRIu8 "\n"
+ "FAT root entry count: %" PRIu16 "\n"
+ "FAT media type: 0x%02X\n"
+ "FAT total sector count (16bit): %" PRIu16 "\n"
+ "FAT sectors per FAT (16bit): %" PRIu16 "\n"
+ "FAT total sector count (32bit): %" PRIu32 "\n"
+ "FAT sectors per FAT (32bit): %" PRIu32,
+ p_fat_type,
+ p_fat_vh->bytes_per_sector,
+ p_fat_vh->sectors_per_cluster,
+ p_fat_vh->reserved_sectors,
+ p_fat_vh->fat_count,
+ p_fat_vh->root_entry_count,
+ p_fat_vh->media_type,
+ p_fat_vh->total_sectors_16,
+ p_fat_vh->fat16_sectors,
+ p_fat_vh->total_sectors_32,
+ p_fat_vh->fat32_sectors);
+
+ // Check if asprintf worked
+ if(ret<0 || p_buf==NULL) return UNALLOCATED_MEMALLOC_FAILED;
+
+ *pp_buf=p_buf;
+ return UNALLOCATED_OK;
}
diff --git a/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.h b/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.h
index f057013..b1e9fda 100644
--- a/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.h
+++ b/trunk/libxmount_morphing/libxmount_morphing_unallocated/fat_functions.h
@@ -1,61 +1,72 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program 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 3 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef FAT_FUNCTIONS_H
#define FAT_FUNCTIONS_H
#include "../libxmount_morphing.h"
// Supported FAT types
typedef enum e_FatType {
- FatType_Fat12=0,
+ FatType_Unknown=0,
FatType_Fat16,
FatType_Fat32
} te_FatType;
// Needed parts of the FAT volume header
typedef struct s_FatVH {
uint8_t jump_inst[3];
uint8_t oem_name[8];
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t root_entry_count;
uint16_t total_sectors_16;
uint8_t media_type;
uint16_t fat16_sectors;
uint64_t unused01;
uint32_t total_sectors_32;
// Following value is only valid for FAT32
uint32_t fat32_sectors;
} __attribute__ ((packed)) ts_FatVH, *pts_FatVH;
// FAT handle
typedef struct s_FatHandle {
te_FatType fat_type;
pts_FatVH p_fat_vh;
+ union {
+ uint16_t *p_fat16;
+ uint32_t *p_fat32;
+ };
uint8_t debug;
} ts_FatHandle, *pts_FatHandle;
int ReadFatHeader(pts_FatHandle p_fat_handle,
pts_LibXmountMorphingInputFunctions p_input_functions,
uint8_t debug);
void FreeFatHeader(pts_FatHandle p_fat_handle);
+int ReadFat(pts_FatHandle p_fat_handle,
+ pts_LibXmountMorphingInputFunctions p_input_functions);
+int BuildFatBlockMap(pts_FatHandle p_fat_handle,
+ uint64_t **pp_free_block_map,
+ uint64_t *p_free_block_map_size,
+ uint64_t *p_block_size);
+int GetFatInfos(pts_FatHandle p_fat_handle, char **pp_buf);
#endif // FAT_FUNCTIONS_H
diff --git a/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.c b/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.c
index 1ad9f67..167764b 100644
--- a/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.c
+++ b/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.c
@@ -1,228 +1,260 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program 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 3 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "hfs_functions.h"
#include "libxmount_morphing_unallocated_retvalues.h"
#define LOG_DEBUG(...) { \
LIBXMOUNT_LOG_DEBUG(p_hfs_handle->debug,__VA_ARGS__); \
}
/*
* ReadHfsHeader
*/
int ReadHfsHeader(pts_HfsHandle p_hfs_handle,
pts_LibXmountMorphingInputFunctions p_input_functions,
uint8_t debug)
{
pts_HfsVH p_hfs_vh;
int ret;
size_t bytes_read;
pts_HfsExtend p_extend;
// Init HFS handle
p_hfs_handle->p_hfs_vh=NULL;
p_hfs_handle->p_alloc_file=NULL;
p_hfs_handle->debug=debug;
LOG_DEBUG("Trying to read HFS volume header\n");
// Alloc buffer for header
p_hfs_vh=calloc(1,sizeof(ts_HfsVH));
if(p_hfs_vh==NULL) return UNALLOCATED_MEMALLOC_FAILED;
// Read VH from input image
ret=p_input_functions->Read(0,
(char*)(p_hfs_vh),
HFS_VH_OFFSET,
sizeof(ts_HfsVH),
&bytes_read);
if(ret!=0 || bytes_read!=sizeof(ts_HfsVH)) {
free(p_hfs_vh);
p_hfs_vh=NULL;
return UNALLOCATED_HFS_CANNOT_READ_HEADER;
}
// Convert VH to host endianness (HFS values are always stored in big endian)
p_hfs_vh->signature=be16toh(p_hfs_vh->signature);
p_hfs_vh->version=be16toh(p_hfs_vh->version);
p_hfs_vh->block_size=be32toh(p_hfs_vh->block_size);
p_hfs_vh->total_blocks=be32toh(p_hfs_vh->total_blocks);
p_hfs_vh->free_blocks=be32toh(p_hfs_vh->free_blocks);
p_hfs_vh->alloc_file_size=be64toh(p_hfs_vh->alloc_file_size);
p_hfs_vh->alloc_file_clump_size=be32toh(p_hfs_vh->alloc_file_clump_size);
p_hfs_vh->alloc_file_total_blocks=be32toh(p_hfs_vh->alloc_file_total_blocks);
for(int i=0;i<8;i++) {
p_extend=&(p_hfs_vh->alloc_file_extends[i]);
p_extend->start_block=be32toh(p_extend->start_block);
p_extend->block_count=be32toh(p_extend->block_count);
}
LOG_DEBUG("HFS VH signature: 0x%04X\n",p_hfs_vh->signature);
LOG_DEBUG("HFS VH version: %" PRIu16 "\n",p_hfs_vh->version);
LOG_DEBUG("HFS block size: %" PRIu32 " bytes\n",p_hfs_vh->block_size);
LOG_DEBUG("HFS total blocks: %" PRIu32 "\n",p_hfs_vh->total_blocks);
LOG_DEBUG("HFS free blocks: %" PRIu32 "\n",p_hfs_vh->free_blocks);
LOG_DEBUG("HFS allocation file size: %" PRIu64 " bytes\n",
p_hfs_vh->alloc_file_size);
LOG_DEBUG("HFS allocation file blocks: %" PRIu32 "\n",
p_hfs_vh->alloc_file_total_blocks);
// Check header signature and version
if(p_hfs_vh->signature!=HFS_VH_SIGNATURE ||
p_hfs_vh->version!=HFS_VH_VERSION)
{
free(p_hfs_vh);
p_hfs_vh=NULL;
return UNALLOCATED_HFS_INVALID_HEADER;
}
// We currently only support HFS+
p_hfs_handle->hfs_type=HfsType_HfsPlus;
LOG_DEBUG("HFS volume header read successfully\n");
p_hfs_handle->p_hfs_vh=p_hfs_vh;
return UNALLOCATED_OK;
}
/*
* FreeHfsHeader
*/
void FreeHfsHeader(pts_HfsHandle p_hfs_handle) {
if(p_hfs_handle==NULL) return;
if(p_hfs_handle->p_hfs_vh!=NULL) free(p_hfs_handle->p_hfs_vh);
if(p_hfs_handle->p_alloc_file!=NULL) free(p_hfs_handle->p_alloc_file);
}
/*
* ReadHfsAllocFile
*/
int ReadHfsAllocFile(pts_HfsHandle p_hfs_handle,
pts_LibXmountMorphingInputFunctions p_input_functions)
{
uint8_t *p_alloc_file;
pts_HfsExtend p_extend;
int ret;
char *p_buf;
size_t bytes_read;
uint64_t total_bytes_read=0;
LOG_DEBUG("Trying to read HFS allocation file\n");
// Alloc buffer for file
p_alloc_file=calloc(1,p_hfs_handle->p_hfs_vh->alloc_file_size);
if(p_alloc_file==NULL) return UNALLOCATED_MEMALLOC_FAILED;
// Loop over extends and read data
p_buf=(char*)(p_alloc_file);
for(int i=0;i<8;i++) {
p_extend=&(p_hfs_handle->p_hfs_vh->alloc_file_extends[i]);
// If start_block and block_count are zero, we parsed last extend
if(p_extend->start_block==0 && p_extend->block_count==0) break;
LOG_DEBUG("Extend %d contains %" PRIu32
" block(s) starting with block %" PRIu32 "\n",
i,
p_extend->block_count,
p_extend->start_block);
// Read data
for(uint32_t ii=0;ii<p_extend->block_count;ii++) {
LOG_DEBUG("Reading %" PRIu32 " bytes from block %" PRIu32
" at offset %" PRIu64 "\n",
p_hfs_handle->p_hfs_vh->block_size,
p_extend->start_block+ii,
(uint64_t)((p_extend->start_block+ii)*
p_hfs_handle->p_hfs_vh->block_size));
ret=p_input_functions->Read(0,
p_buf,
(p_extend->start_block+ii)*
p_hfs_handle->p_hfs_vh->block_size,
p_hfs_handle->p_hfs_vh->block_size,
&bytes_read);
if(ret!=0 || bytes_read!=p_hfs_handle->p_hfs_vh->block_size) {
free(p_alloc_file);
return UNALLOCATED_HFS_CANNOT_READ_ALLOC_FILE;
}
p_buf+=p_hfs_handle->p_hfs_vh->block_size;
total_bytes_read+=p_hfs_handle->p_hfs_vh->block_size;
}
}
// Alloc files with more than 8 extends aren't supported yet
if(total_bytes_read!=p_hfs_handle->p_hfs_vh->alloc_file_size) {
free(p_alloc_file);
return UNALLOCATED_HFS_ALLOC_FILE_HAS_TOO_MUCH_EXTENDS;
}
LOG_DEBUG("HFS allocation file read successfully\n");
p_hfs_handle->p_alloc_file=p_alloc_file;
return UNALLOCATED_OK;
}
/*
* BuildHfsBlockMap
*/
int BuildHfsBlockMap(pts_HfsHandle p_hfs_handle,
uint64_t **pp_free_block_map,
uint64_t *p_free_block_map_size,
uint64_t *p_block_size)
{
uint64_t *p_free_block_map=NULL;
uint64_t free_block_map_size=0;
LOG_DEBUG("Searching unallocated HFS blocks\n");
// Save offset of every unallocated block in block map
for(uint32_t cur_block=0;
cur_block<p_hfs_handle->p_hfs_vh->total_blocks;
cur_block++)
{
if((p_hfs_handle->p_alloc_file[cur_block/8] & (1<<(7-(cur_block%8))))==0) {
p_free_block_map=realloc(p_free_block_map,
(free_block_map_size+1)*sizeof(uint64_t));
if(p_free_block_map==NULL) return UNALLOCATED_MEMALLOC_FAILED;
p_free_block_map[free_block_map_size]=
cur_block*p_hfs_handle->p_hfs_vh->block_size;
free_block_map_size++;
}
}
LOG_DEBUG("Found %" PRIu64 " unallocated HFS blocks\n",
free_block_map_size);
if(p_hfs_handle->p_hfs_vh->free_blocks!=free_block_map_size) {
LIBXMOUNT_LOG_WARNING("According to VH, there should be %" PRIu64
" unallocated blocks but I found %" PRIu64 "\n",
p_hfs_handle->p_hfs_vh->free_blocks,
free_block_map_size);
}
// Free alloc file as it is no longer needed
free(p_hfs_handle->p_alloc_file);
p_hfs_handle->p_alloc_file=NULL;
*pp_free_block_map=p_free_block_map;
*p_free_block_map_size=free_block_map_size;
*p_block_size=p_hfs_handle->p_hfs_vh->block_size;
return UNALLOCATED_OK;
}
+/*
+ * GetHfsInfos
+ */
+int GetHfsInfos(pts_HfsHandle p_hfs_handle, char **pp_buf) {
+ pts_HfsVH p_hfs_vh=p_hfs_handle->p_hfs_vh;
+ char *p_buf=NULL;
+ int ret;
+
+ ret=asprintf(&p_buf,
+ "HFS filesystem type: HFS+\n"
+ "HFS VH signature: 0x%04X\n"
+ "HFS VH version: %" PRIu16 "\n"
+ "HFS block size: %" PRIu32 " bytes\n"
+ "HFS total blocks: %" PRIu32 "\n"
+ "HFS free blocks: %" PRIu32 "\n"
+ "HFS allocation file size: %" PRIu64 " bytes\n"
+ "HFS allocation file blocks: %" PRIu32,
+ p_hfs_vh->signature,
+ p_hfs_vh->version,
+ p_hfs_vh->block_size,
+ p_hfs_vh->total_blocks,
+ p_hfs_vh->free_blocks,
+ p_hfs_vh->alloc_file_size,
+ p_hfs_vh->alloc_file_total_blocks);
+
+ // Check if asprintf worked
+ if(ret<0 || p_buf==NULL) return UNALLOCATED_MEMALLOC_FAILED;
+
+ *pp_buf=p_buf;
+ return UNALLOCATED_OK;
+}
+
diff --git a/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.h b/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.h
index caaceb6..6e25652 100644
--- a/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.h
+++ b/trunk/libxmount_morphing/libxmount_morphing_unallocated/hfs_functions.h
@@ -1,72 +1,73 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program 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 3 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef HFS_FUNCTIONS_H
#define HFS_FUNCTIONS_H
#include "../libxmount_morphing.h"
// Supported HFS types
typedef enum e_HfsType {
HfsType_HfsPlus=0
} te_HfsType;
// HFS extend
typedef struct s_HfsExtend {
uint32_t start_block;
uint32_t block_count;
} __attribute__ ((packed)) ts_HfsExtend, *pts_HfsExtend;
// Needed parts of the HFS volume header
#define HFS_VH_OFFSET 1024
#define HFS_VH_SIGNATURE 0x482b //"H+"
#define HFS_VH_VERSION 4
typedef struct s_HfsVH {
uint16_t signature; // "H+"
uint16_t version; // Currently 4 for HFS+
uint32_t unused01[9];
uint32_t block_size;
uint32_t total_blocks;
uint32_t free_blocks;
uint32_t unused02[15];
uint64_t alloc_file_size;
uint32_t alloc_file_clump_size;
uint32_t alloc_file_total_blocks;
ts_HfsExtend alloc_file_extends[8];
} __attribute__ ((packed)) ts_HfsVH, *pts_HfsVH;
// HFS handle
typedef struct s_HfsHandle {
te_HfsType hfs_type;
pts_HfsVH p_hfs_vh;
uint8_t *p_alloc_file;
uint8_t debug;
} ts_HfsHandle, *pts_HfsHandle;
int ReadHfsHeader(pts_HfsHandle p_hfs_handle,
pts_LibXmountMorphingInputFunctions p_input_functions,
uint8_t debug);
void FreeHfsHeader(pts_HfsHandle p_hfs_handle);
int ReadHfsAllocFile(pts_HfsHandle p_hfs_handle,
pts_LibXmountMorphingInputFunctions p_input_functions);
int BuildHfsBlockMap(pts_HfsHandle p_hfs_handle,
uint64_t **pp_free_block_map,
uint64_t *p_free_block_map_size,
uint64_t *p_block_size);
+int GetHfsInfos(pts_HfsHandle p_hfs_handle, char **pp_buf);
#endif // HFS_FUNCTIONS_H
diff --git a/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated.c b/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated.c
index 6745a96..2529d4c 100644
--- a/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated.c
+++ b/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated.c
@@ -1,524 +1,511 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program 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 3 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "libxmount_morphing_unallocated.h"
#include "libxmount_morphing_unallocated_retvalues.h"
#define LOG_DEBUG(...) { \
LIBXMOUNT_LOG_DEBUG(p_unallocated_handle->debug,__VA_ARGS__); \
}
/*******************************************************************************
* LibXmount_Morphing API implementation
******************************************************************************/
/*
* LibXmount_Morphing_GetApiVersion
*/
uint8_t LibXmount_Morphing_GetApiVersion() {
return LIBXMOUNT_MORPHING_API_VERSION;
}
/*
* LibXmount_Morphing_GetSupportedFormats
*/
const char* LibXmount_Morphing_GetSupportedTypes() {
return "unallocated\0\0";
}
/*
* LibXmount_Morphing_GetFunctions
*/
void LibXmount_Morphing_GetFunctions(ts_LibXmountMorphingFunctions *p_functions)
{
p_functions->CreateHandle=&UnallocatedCreateHandle;
p_functions->DestroyHandle=&UnallocatedDestroyHandle;
p_functions->Morph=&UnallocatedMorph;
p_functions->Size=&UnallocatedSize;
p_functions->Read=&UnallocatedRead;
p_functions->OptionsHelp=&UnallocatedOptionsHelp;
p_functions->OptionsParse=&UnallocatedOptionsParse;
p_functions->GetInfofileContent=&UnallocatedGetInfofileContent;
p_functions->GetErrorMessage=&UnallocatedGetErrorMessage;
p_functions->FreeBuffer=&UnallocatedFreeBuffer;
}
/*******************************************************************************
* Private
******************************************************************************/
/*
* UnallocatedCreateHandle
*/
static int UnallocatedCreateHandle(void **pp_handle,
const char *p_format,
uint8_t debug)
{
pts_UnallocatedHandle p_unallocated_handle;
// Alloc new handle. Using calloc in order to set everything to 0x00
p_unallocated_handle=calloc(1,sizeof(ts_UnallocatedHandle));
if(p_unallocated_handle==NULL) return UNALLOCATED_MEMALLOC_FAILED;
// Init handle values
p_unallocated_handle->debug=debug;
p_unallocated_handle->fs_type=UnallocatedFsType_Unknown;
LOG_DEBUG("Created new LibXmount_Morphing_Unallocated handle\n");
// Return new handle
*pp_handle=p_unallocated_handle;
return UNALLOCATED_OK;
}
/*
* UnallocatedDestroyHandle
*/
static int UnallocatedDestroyHandle(void **pp_handle) {
pts_UnallocatedHandle p_unallocated_handle=(pts_UnallocatedHandle)*pp_handle;
LOG_DEBUG("Destroying LibXmount_Morphing_Unallocated handle\n");
// TODO: Return if p_unallocated_handle==NULL
// Free fs handle
switch(p_unallocated_handle->fs_type) {
case UnallocatedFsType_Hfs: {
FreeHfsHeader(&(p_unallocated_handle->hfs_handle));
break;
}
case UnallocatedFsType_Fat: {
FreeFatHeader(&(p_unallocated_handle->fat_handle));
break;
}
case UnallocatedFsType_Unknown:
default:
break;
}
// Free handle values and handle
if(p_unallocated_handle->p_free_block_map!=NULL)
free(p_unallocated_handle->p_free_block_map);
free(p_unallocated_handle);
*pp_handle=NULL;
return UNALLOCATED_OK;
}
/*
* UnallocatedMorph
*/
static int UnallocatedMorph(
void *p_handle,
pts_LibXmountMorphingInputFunctions p_input_functions)
{
pts_UnallocatedHandle p_unallocated_handle=(pts_UnallocatedHandle)p_handle;
uint64_t input_images_count;
int ret;
LOG_DEBUG("Initializing LibXmount_Morphing_Unallocated\n");
// Set input functions and get image count
p_unallocated_handle->p_input_functions=p_input_functions;
if(p_unallocated_handle->
p_input_functions->
ImageCount(&input_images_count)!=0)
{
return UNALLOCATED_CANNOT_GET_IMAGECOUNT;
}
// Make sure there is exactly one input image
if(input_images_count==0 || input_images_count>1) {
return UNALLOCATED_WRONG_INPUT_IMAGE_COUNT;
}
// Read filesystem header
switch(p_unallocated_handle->fs_type) {
case UnallocatedFsType_Hfs: {
// Read HFS VH
ret=ReadHfsHeader(&(p_unallocated_handle->hfs_handle),
p_unallocated_handle->p_input_functions,
p_unallocated_handle->debug);
if(ret!=UNALLOCATED_OK) return ret;
break;
}
case UnallocatedFsType_Fat: {
// Read FAT VH
ret=ReadFatHeader(&(p_unallocated_handle->fat_handle),
p_unallocated_handle->p_input_functions,
p_unallocated_handle->debug);
if(ret!=UNALLOCATED_OK) return ret;
break;
}
case UnallocatedFsType_Unknown: {
// Filesystem wasn't specified. Try to autodetect it by reading all
// available fs headers
+ LOG_DEBUG("Autodetecting filesystem\n");
+ LOG_DEBUG("Trying HFS\n");
ret=ReadHfsHeader(&(p_unallocated_handle->hfs_handle),
p_unallocated_handle->p_input_functions,
p_unallocated_handle->debug);
if(ret==UNALLOCATED_OK) {
- LOG_DEBUG("Detected HFS+ fs\n");
+ LOG_DEBUG("Detected HFS fs\n");
p_unallocated_handle->fs_type=UnallocatedFsType_Hfs;
break;
}
+ LOG_DEBUG("Trying FAT\n");
ret=ReadFatHeader(&(p_unallocated_handle->fat_handle),
p_unallocated_handle->p_input_functions,
p_unallocated_handle->debug);
if(ret==UNALLOCATED_OK) {
LOG_DEBUG("Detected FAT fs\n");
p_unallocated_handle->fs_type=UnallocatedFsType_Fat;
break;
}
LOG_DEBUG("Unable to autodetect fs\n");
return UNALLOCATED_NO_SUPPORTED_FS_DETECTED;
}
default: {
return UNALLOCATED_INTERNAL_ERROR;
}
}
// Extract unallocated blocks from input image
switch(p_unallocated_handle->fs_type) {
case UnallocatedFsType_Hfs: {
// Read HFS alloc file
ret=ReadHfsAllocFile(&(p_unallocated_handle->hfs_handle),
p_unallocated_handle->p_input_functions);
if(ret!=UNALLOCATED_OK) return ret;
// Build free block map
ret=BuildHfsBlockMap(&(p_unallocated_handle->hfs_handle),
&(p_unallocated_handle->p_free_block_map),
&(p_unallocated_handle->free_block_map_size),
&(p_unallocated_handle->block_size));
if(ret!=UNALLOCATED_OK) return ret;
break;
}
case UnallocatedFsType_Fat: {
- // TODO
+ // Read FAT
+ ret=ReadFat(&(p_unallocated_handle->fat_handle),
+ p_unallocated_handle->p_input_functions);
+ if(ret!=UNALLOCATED_OK) return ret;
+ // Build free block map
+ ret=BuildFatBlockMap(&(p_unallocated_handle->fat_handle),
+ &(p_unallocated_handle->p_free_block_map),
+ &(p_unallocated_handle->free_block_map_size),
+ &(p_unallocated_handle->block_size));
+ if(ret!=UNALLOCATED_OK) return ret;
break;
}
case UnallocatedFsType_Unknown:
default:
return UNALLOCATED_INTERNAL_ERROR;
}
// Calculate morphed image size
p_unallocated_handle->morphed_image_size=p_unallocated_handle->block_size*
p_unallocated_handle->free_block_map_size;
LOG_DEBUG("Total size of unallocated blocks is %" PRIu64 " bytes\n",
p_unallocated_handle->morphed_image_size);
return UNALLOCATED_OK;
}
/*
* UnallocatedSize
*/
static int UnallocatedSize(void *p_handle, uint64_t *p_size) {
*p_size=((pts_UnallocatedHandle)(p_handle))->morphed_image_size;
return UNALLOCATED_OK;
}
/*
* UnallocatedRead
*/
static int UnallocatedRead(void *p_handle,
char *p_buf,
off_t offset,
size_t count,
size_t *p_read)
{
pts_UnallocatedHandle p_unallocated_handle=(pts_UnallocatedHandle)p_handle;
uint64_t cur_block;
off_t cur_block_offset;
off_t cur_image_offset;
size_t cur_count;
int ret;
size_t bytes_read;
LOG_DEBUG("Reading %zu bytes at offset %zu from morphed image\n",
count,
offset);
// Make sure read parameters are within morphed image bounds
if(offset>=p_unallocated_handle->morphed_image_size ||
offset+count>p_unallocated_handle->morphed_image_size)
{
return UNALLOCATED_READ_BEYOND_END_OF_IMAGE;
}
// Calculate starting block and block offset
cur_block=offset/p_unallocated_handle->block_size;
cur_block_offset=offset-(cur_block*p_unallocated_handle->block_size);
// Init p_read
*p_read=0;
while(count!=0) {
// Calculate input image offset to read from
cur_image_offset=
p_unallocated_handle->p_free_block_map[cur_block]+cur_block_offset;
// Calculate how many bytes to read from current block
if(cur_block_offset+count>p_unallocated_handle->block_size) {
cur_count=p_unallocated_handle->block_size-cur_block_offset;
} else {
cur_count=count;
}
LOG_DEBUG("Reading %zu bytes at offset %zu (block %" PRIu64 ")\n",
cur_count,
cur_image_offset+cur_block_offset,
cur_block);
// Read bytes
ret=p_unallocated_handle->p_input_functions->
Read(0,
p_buf,
cur_image_offset+cur_block_offset,
cur_count,
&bytes_read);
if(ret!=0 || bytes_read!=cur_count) return UNALLOCATED_CANNOT_READ_DATA;
p_buf+=cur_count;
cur_block_offset=0;
count-=cur_count;
cur_block++;
(*p_read)+=cur_count;
}
return UNALLOCATED_OK;
}
/*
* UnallocatedOptionsHelp
*/
static int UnallocatedOptionsHelp(const char **pp_help) {
int ok;
char *p_buf;
ok=asprintf(&p_buf,
" unallocated_fs : Specify the filesystem to extract "
"unallocated blocks from. Supported filesystems are: "
"'hfs', 'fat'. "
"Default: autodetect.\n");
if(ok<0 || p_buf==NULL) {
*pp_help=NULL;
return UNALLOCATED_MEMALLOC_FAILED;
}
*pp_help=p_buf;
return UNALLOCATED_OK;
}
/*
* UnallocatedOptionsParse
*/
static int UnallocatedOptionsParse(void *p_handle,
uint32_t options_count,
const pts_LibXmountOptions *pp_options,
const char **pp_error)
{
pts_UnallocatedHandle p_unallocated_handle=(pts_UnallocatedHandle)p_handle;
int ok;
char *p_buf;
for(uint32_t i=0;i<options_count;i++) {
if(strcmp(pp_options[i]->p_key,"unallocated_fs")==0) {
if(strcmp(pp_options[i]->p_value,"hfs")==0) {
p_unallocated_handle->fs_type=UnallocatedFsType_Hfs;
} else if(strcmp(pp_options[i]->p_value,"fat")==0) {
p_unallocated_handle->fs_type=UnallocatedFsType_Fat;
} else {
ok=asprintf(&p_buf,
"Unsupported filesystem '%s' specified",
pp_options[i]->p_value);
if(ok<0 || p_buf==NULL) {
*pp_error=NULL;
return UNALLOCATED_MEMALLOC_FAILED;
}
*pp_error=p_buf;
return UNALLOCATED_UNSUPPORTED_FS_SPECIFIED;
}
LOG_DEBUG("Setting fs to %s\n",pp_options[i]->p_value);
pp_options[i]->valid=1;
}
}
return UNALLOCATED_OK;
}
/*
* UnallocatedGetInfofileContent
*/
static int UnallocatedGetInfofileContent(void *p_handle,
const char **pp_info_buf)
{
pts_UnallocatedHandle p_unallocated_handle=(pts_UnallocatedHandle)p_handle;
int ret=-1;
+ char *p_fs_buf=NULL;
char *p_buf=NULL;
switch(p_unallocated_handle->fs_type) {
case UnallocatedFsType_Hfs: {
- // TODO
-/*
- pts_HfsPlusVH p_hfsplus_vh=p_unallocated_handle->p_hfsplus_vh;
- ret=asprintf(&p_buf,
- "HFS+ VH signature: 0x%04X\n"
- "HFS+ VH version: %" PRIu16 "\n"
- "HFS+ block size: %" PRIu32 " bytes\n"
- "HFS+ total blocks: %" PRIu32 "\n"
- "HFS+ free blocks: %" PRIu32 "\n"
- "HFS+ allocation file size: %" PRIu64 " bytes\n"
- "HFS+ allocation file blocks: %" PRIu32 "\n"
- "Discovered free blocks: %" PRIu64 "\n"
- "Total unallocated size: %" PRIu64 " bytes (%0.3f GiB)\n",
- p_hfsplus_vh->signature,
- p_hfsplus_vh->version,
- p_hfsplus_vh->block_size,
- p_hfsplus_vh->total_blocks,
- p_hfsplus_vh->free_blocks,
- p_hfsplus_vh->alloc_file_size,
- p_hfsplus_vh->alloc_file_total_blocks,
- p_unallocated_handle->free_block_map_size,
- p_unallocated_handle->free_block_map_size*
- p_unallocated_handle->block_size,
- (p_unallocated_handle->free_block_map_size*
- p_unallocated_handle->block_size)/(1024.0*1024.0*1024.0));
-*/
+ ret=GetHfsInfos(&(p_unallocated_handle->hfs_handle),&p_fs_buf);
break;
}
case UnallocatedFsType_Fat: {
- // TODO
-/*
- pts_FatVH p_fat_vh=p_unallocated_handle->p_fat_vh;
- ret=asprintf(&p_buf,
- "FAT bytes per sector: %" PRIu16 "\n"
- "FAT sectors per cluster: %" PRIu8 "\n"
- "FAT reserved sectors: %" PRIu16 "\n"
- "FAT count: %" PRIu8 "\n"
- "FAT root entry count: %" PRIu16 "\n"
- "FAT media type: %02X\n"
- "FAT total sector count (16bit): %" PRIu16 "\n"
- "FAT sectors per FAT (16bit): %" PRIu16 "\n"
- "FAT total sector count (32bit): %" PRIu32 "\n"
- "FAT sectors per FAT (32bit): %" PRIu32 "\n"
- "Discovered free blocks: %" PRIu64 "\n"
- "Total unallocated size: %" PRIu64 " bytes (%0.3f GiB)\n",
- p_fat_vh->bytes_per_sector,
- p_fat_vh->sectors_per_cluster,
- p_fat_vh->reserved_sectors,
- p_fat_vh->fat_count,
- p_fat_vh->root_entry_count,
- p_fat_vh->media_type,
- p_fat_vh->total_sectors_16,
- p_fat_vh->fat16_sectors,
- p_fat_vh->total_sectors_32,
- p_fat_vh->fat32_sectors,
- p_unallocated_handle->free_block_map_size,
- p_unallocated_handle->free_block_map_size*
- p_unallocated_handle->block_size,
- (p_unallocated_handle->free_block_map_size*
- p_unallocated_handle->block_size)/(1024.0*1024.0*1024.0));
-*/
+ ret=GetFatInfos(&(p_unallocated_handle->fat_handle),&p_fs_buf);
break;
}
case UnallocatedFsType_Unknown:
default:
return UNALLOCATED_INTERNAL_ERROR;
}
+ if(ret!=UNALLOCATED_OK) return ret;
+
+ if(p_fs_buf!=NULL) {
+ ret=asprintf(&p_buf,
+ "%s\n"
+ "Discovered free blocks: %" PRIu64 "\n"
+ "Total unallocated size: %" PRIu64 " bytes (%0.3f GiB)\n",
+ p_fs_buf,
+ p_unallocated_handle->free_block_map_size,
+ p_unallocated_handle->free_block_map_size*
+ p_unallocated_handle->block_size,
+ (p_unallocated_handle->free_block_map_size*
+ p_unallocated_handle->block_size)/(1024.0*1024.0*1024.0));
+ free(p_fs_buf);
+ } else {
+ ret=asprintf(&p_buf,
+ "Discovered free blocks: %" PRIu64 "\n"
+ "Total unallocated size: %" PRIu64 " bytes (%0.3f GiB)\n",
+ p_unallocated_handle->free_block_map_size,
+ p_unallocated_handle->free_block_map_size*
+ p_unallocated_handle->block_size,
+ (p_unallocated_handle->free_block_map_size*
+ p_unallocated_handle->block_size)/(1024.0*1024.0*1024.0));
+ }
// Check if asprintf worked
if(ret<0 || p_buf==NULL) return UNALLOCATED_MEMALLOC_FAILED;
*pp_info_buf=p_buf;
return UNALLOCATED_OK;
}
/*
* UnallocatedGetErrorMessage
*/
static const char* UnallocatedGetErrorMessage(int err_num) {
switch(err_num) {
case UNALLOCATED_MEMALLOC_FAILED:
return "Unable to allocate memory";
break;
case UNALLOCATED_NO_SUPPORTED_FS_DETECTED:
return "Unable to detect a supported file system";
break;
case UNALLOCATED_UNSUPPORTED_FS_SPECIFIED:
return "Unsupported fs specified";
break;
case UNALLOCATED_INTERNAL_ERROR:
return "Internal error";
break;
case UNALLOCATED_CANNOT_GET_IMAGECOUNT:
return "Unable to get input image count";
break;
case UNALLOCATED_WRONG_INPUT_IMAGE_COUNT:
return "Only 1 input image is supported";
break;
case UNALLOCATED_CANNOT_GET_IMAGESIZE:
return "Unable to get input image size";
break;
case UNALLOCATED_READ_BEYOND_END_OF_IMAGE:
return "Unable to read data: Attempt to read past EOF";
break;
case UNALLOCATED_CANNOT_READ_DATA:
return "Unable to read data";
break;
case UNALLOCATED_CANNOT_PARSE_OPTION:
return "Unable to parse library option";
break;
// HFS errors
case UNALLOCATED_HFS_CANNOT_READ_HEADER:
return "Unable to read HFS volume header";
break;
case UNALLOCATED_HFS_INVALID_HEADER:
return "Found invalid HFS volume header";
break;
case UNALLOCATED_HFS_CANNOT_READ_ALLOC_FILE:
return "Unable to read HFS allocation file";
break;
case UNALLOCATED_HFS_ALLOC_FILE_HAS_TOO_MUCH_EXTENDS:
return "HFS allocation file has more than 8 extends. "
"This is unsupported";
break;
// FAT errors
case UNALLOCATED_FAT_CANNOT_READ_HEADER:
return "Unable to read FAT volume header";
break;
case UNALLOCATED_FAT_INVALID_HEADER:
return "Found invalid FAT volume header";
break;
+ case UNALLOCATED_FAT_UNSUPPORTED_FS_TYPE:
+ return "Found unsupported FAT type";
+ break;
+ case UNALLOCATED_FAT_CANNOT_READ_FAT:
+ return "Unable to read FAT";
+ break;
default:
return "Unknown error";
}
}
/*
* UnallocatedFreeBuffer
*/
static void UnallocatedFreeBuffer(void *p_buf) {
free(p_buf);
}
diff --git a/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated_retvalues.h b/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated_retvalues.h
index 6beda99..af24799 100644
--- a/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated_retvalues.h
+++ b/trunk/libxmount_morphing/libxmount_morphing_unallocated/libxmount_morphing_unallocated_retvalues.h
@@ -1,45 +1,47 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program 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 3 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, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef LIBXMOUNT_MORPHING_UNALLOCATED_RETVALUES_H
#define LIBXMOUNT_MORPHING_UNALLOCATED_RETVALUES_H
// Error codes
enum {
UNALLOCATED_OK=0,
UNALLOCATED_MEMALLOC_FAILED,
UNALLOCATED_NO_SUPPORTED_FS_DETECTED,
UNALLOCATED_UNSUPPORTED_FS_SPECIFIED,
UNALLOCATED_INTERNAL_ERROR,
UNALLOCATED_CANNOT_GET_IMAGECOUNT,
UNALLOCATED_WRONG_INPUT_IMAGE_COUNT,
UNALLOCATED_CANNOT_GET_IMAGESIZE,
UNALLOCATED_READ_BEYOND_END_OF_IMAGE,
UNALLOCATED_CANNOT_READ_DATA,
UNALLOCATED_CANNOT_PARSE_OPTION,
// HFS return values
UNALLOCATED_HFS_CANNOT_READ_HEADER,
UNALLOCATED_HFS_INVALID_HEADER,
UNALLOCATED_HFS_CANNOT_READ_ALLOC_FILE,
UNALLOCATED_HFS_ALLOC_FILE_HAS_TOO_MUCH_EXTENDS,
// FAT return values
UNALLOCATED_FAT_CANNOT_READ_HEADER,
- UNALLOCATED_FAT_INVALID_HEADER
+ UNALLOCATED_FAT_INVALID_HEADER,
+ UNALLOCATED_FAT_UNSUPPORTED_FS_TYPE,
+ UNALLOCATED_FAT_CANNOT_READ_FAT
};
#endif // LIBXMOUNT_MORPHING_UNALLOCATED_RETVALUES_H
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Dec 24, 3:12 AM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1176999
Default Alt Text
(53 KB)
Attached To
Mode
rXMOUNT xmount
Attached
Detach File
Event Timeline
Log In to Comment