Page MenuHomePhabricator

No OneTemporary

Size
53 KB
Referenced Files
None
Subscribers
None
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

Mime Type
text/x-diff
Expires
Tue, Dec 24, 3:12 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1176999
Default Alt Text
(53 KB)

Event Timeline