Page MenuHomePhabricator

No OneTemporary

Size
151 KB
Referenced Files
None
Subscribers
None
diff --git a/trunk/cmake_modules/FindLibZ.cmake b/trunk/cmake_modules/FindLibZ.cmake
new file mode 100644
index 0000000..634b2d7
--- /dev/null
+++ b/trunk/cmake_modules/FindLibZ.cmake
@@ -0,0 +1,18 @@
+find_package(PkgConfig)
+pkg_check_modules(PC_LIBZ QUIET zlib)
+set(LIBZ_DEFINITIONS ${PC_LIBZ_CFLAGS_OTHER})
+
+find_path(LIBZ_INCLUDE_DIR zlib.h
+ HINTS ${PC_LIBZ_INCLUDEDIR} ${PC_LIBZ_INCLUDE_DIRS}
+ PATH_SUFFIXES zlib)
+
+find_library(LIBZ_LIBRARY NAMES z libz
+ HINTS ${PC_LIBZ_LIBDIR} ${PC_LIBZ_LIBRARY_DIRS} )
+
+set(LIBZ_LIBRARIES ${LIBZ_LIBRARY})
+set(LIBZ_INCLUDE_DIRS ${LIBZ_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibZ DEFAULT_MSG LIBZ_LIBRARY LIBZ_INCLUDE_DIR)
+
+mark_as_advanced(LIBZ_INCLUDE_DIR LIBZ_LIBRARY)
diff --git a/trunk/libxmount_input/CMakeLists.txt b/trunk/libxmount_input/CMakeLists.txt
index a84c410..b99bd1e 100644
--- a/trunk/libxmount_input/CMakeLists.txt
+++ b/trunk/libxmount_input/CMakeLists.txt
@@ -1,10 +1,18 @@
+add_subdirectory(libxmount_input_dd)
+
find_package(LibEWF)
if(LIBEWF_FOUND)
add_subdirectory(libxmount_input_ewf)
endif(LIBEWF_FOUND)
#find_package(LibAFF)
#if(LIBAFF_FOUND)
# add_subdirectory(libxmount_input_aff)
#endif(LIBAFF_FOUND)
+find_package(LibZ)
+if(LIBZ_FOUND)
+ add_subdirectory(libxmount_input_aewf)
+ add_subdirectory(libxmount_input_aaff)
+endif(LIBZ_FOUND)
+
diff --git a/trunk/libxmount_input/libxmount_input.h b/trunk/libxmount_input/libxmount_input.h
index dd77370..e5dbc5e 100644
--- a/trunk/libxmount_input/libxmount_input.h
+++ b/trunk/libxmount_input/libxmount_input.h
@@ -1,132 +1,133 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* xmount is a small tool to "fuse mount" various image formats and enable *
* virtual write access. *
* *
* 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_INPUT_H
#define LIBXMOUNT_INPUT_H
#define LIBXMOUNT_INPUT_API_VERSION 1
-#include <stdint.h>
+#include <stdint.h> // For int*_t and uint*_t
+#include <inttypes.h> // For PRI*
//! Structure containing pointers to the lib's functions
typedef struct s_LibXmountInputFunctions {
/*!
* Function to open input image
*
* \param pp_handle Pointer to store handle of opened image to
* \param pp_filename_arr Array containing all specified input images
* \param filename_arr_len Length of pp_filename_arr
* \return 0 on success or error code
*/
int (*Open)(void **pp_handle,
const char **pp_filename_arr,
uint64_t filename_arr_len);
/*!
* Function to get the input image's size
*
* \param p_handle Handle to the opened image
* \param p_size Pointer to store input image's size to
* \return 0 on success or error code
*/
int (*Size)(void *p_handle,
uint64_t *p_size);
/*!
* Function to read data from input image
*
* \param p_handle Handle to the opened image
* \param offset Position at which to start reading
* \param p_buf Buffer to store read data to
* \param count Amount of bytes to read
* \return 0 on success or error code
*/
int (*Read)(void *p_handle,
uint64_t offset,
char *p_buf,
uint32_t count);
/*!
* Function to close an opened input image
*
* \param pp_handle Pointer to the handle of the opened image
* \return 0 on success or error code
*/
int (*Close)(void **pp_handle);
/*!
* Function to return a string containing help messages for any supported
* lib-specific options
*
* \param pp_help Pointer to a string to store null-terminated help text
* \return 0 on success or error code
*/
int (*OptionsHelp)(const char **pp_help);
/*!
* Function to parse any lib-specific options
*
* \param p_handle Handle to the opened image
* \param p_options String with specified options
* \param pp_error Pointer to a string with error message
* \return 0 on success or error code and error message
*/
int (*OptionsParse)(void *p_handle,
char *p_options,
char **pp_error);
/*!
* Function to get content to add to the info file
*
* \param p_handle Handle to the opened image
* \param pp_info_buf Pointer to store the null-terminated content
* \return 0 on success or error code
*/
int (*GetInfofileContent)(void *p_handle,
const char **pp_info_buf);
/*!
* Function to free buffers that were allocated by lib
*
* \param p_buf Buffer to free
*/
void (*FreeBuffer)(void *p_buf);
} ts_LibXmountInputFunctions, *pts_LibXmountInputFunctions;
//! Get library API version
/*!
* \param p_ver Supported version
*/
uint8_t LibXmount_Input_GetApiVersion();
typedef uint8_t (*t_LibXmount_Input_GetApiVersion)();
//! Get a list of supported formats
/*!
* Gets a list of supported input image formats. These are the strings
* specified with xmount's --in <string> command line option.
*
* \param ppp_arr Array containing supported format strings
* \return Length of ppp_arr
*/
const char* LibXmount_Input_GetSupportedFormats();
typedef const char* (*t_LibXmount_Input_GetSupportedFormats)();
//! Get the lib's s_LibXmountInputFunctions structure
/*!
* \param pp_functions Functions
*/
void LibXmount_Input_GetFunctions(ts_LibXmountInputFunctions *p_functions);
typedef void (*t_LibXmount_Input_GetFunctions)(ts_LibXmountInputFunctions*);
#endif // LIBXMOUNT_INPUT_H
diff --git a/trunk/libxmount_input/libxmount_input_aaff/CMakeLists.txt b/trunk/libxmount_input/libxmount_input_aaff/CMakeLists.txt
new file mode 100644
index 0000000..5b82e5a
--- /dev/null
+++ b/trunk/libxmount_input/libxmount_input_aaff/CMakeLists.txt
@@ -0,0 +1,8 @@
+project(libxmount_input_aaff)
+
+add_library(xmount_input_aaff SHARED libxmount_input_aaff.c)
+include_directories(${LIBZ_INCLUDE_DIRS})
+target_link_libraries(xmount_input_aaff ${LIBZ_LIBRARIES})
+
+install(TARGETS xmount_input_aaff DESTINATION lib/xmount)
+
diff --git a/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.c b/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.c
index a801e74..f94e88f 100644
--- a/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.c
+++ b/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.c
@@ -1,741 +1,713 @@
/*******************************************************************************
* xmount Copyright (c) 2008,2009, 2010, 2011, 2012 *
* by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This module has been written by Guy Voncken. It contains the functions for *
* accessing simple AFF images created by Guymager. *
* *
* xmount is a small tool to "fuse mount" various image formats as dd or vdi *
* files and enable virtual write access. *
* *
* 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 <netinet/in.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
#include <zlib.h>
-#include "aaff.h"
-
-// ----------------------
-// Constant definitions
-// ----------------------
+#include "../libxmount_input.h"
//#define AAFF_DEBUG
+#include "libxmount_input_aaff.h"
-#define AAFF_DEFAULT_PAGE_SEEK_MAX_ENTRIES 1000000 // Default max. number of cached seek points for fast page access
-
-#define AAFF_CURRENTPAGE_NOTSET ULONG_LONG_MAX
-
-#define GETMAX(a,b) ((a)>(b)?(a):(b))
-#define GETMIN(a,b) ((a)<(b)?(a):(b))
-
-// -----------------
-// AFF definitions
-// -----------------
-
-#define AFF_GID_LENGTH 16
-#define AFF_SEGARG_U64 2 // Used as argument for segments that contain a 64 bit unsigned in the data field
-
-#define AFF_HEADER "AFF10\r\n"
-#define AFF_SEGMENT_HEADER_MAGIC "AFF"
-#define AFF_SEGMENT_FOOTER_MAGIC "ATT"
-#define AFF_BADSECTOR_HEADER "BAD SECTOR"
-#define AFF_FILE_TYPE "AFF"
-
-#define AFF_SEGNAME_BADFLAG "badflag"
-#define AFF_SEGNAME_AFFLIB_VERSION "afflib_version"
-#define AFF_SEGNAME_FILETYPE "aff_file_type"
-#define AFF_SEGNAME_GID "image_gid"
-#define AFF_SEGNAME_SECTORS "devicesectors"
-#define AFF_SEGNAME_SECTORSIZE "sectorsize"
-#define AFF_SEGNAME_IMAGESIZE "imagesize"
-#define AFF_SEGNAME_PAGESIZE "pagesize"
-#define AFF_SEGNAME_BADSECTORS "badsectors"
-#define AFF_SEGNAME_MD5 "md5"
-#define AFF_SEGNAME_SHA256 "sha256"
-#define AFF_SEGNAME_DURATION "acquisition_seconds"
-#define AFF_SEGNAME_PAGE "page"
-
-#define AAFF_SEGNAME_COMMAND_LINE "acquisition_commandline"
-#define AAFF_SEGNAME_MACADDR "acquisition_macaddr"
-#define AAFF_SEGNAME_DATE "acquisition_date" // Format: YYYY-MM-DD HH:MM:SS TZT
-#define AAFF_SEGNAME_DEVICE "acquisition_device"
-#define AAFF_SEGNAME_MODEL "device_model"
-#define AAFF_SEGNAME_SN "device_sn"
-
-#define AFF_PAGEFLAGS_UNCOMPRESSED 0x0000
-#define AFF_PAGEFLAGS_COMPRESSED_ZLIB 0x0001
-#define AFF_PAGEFLAGS_COMPRESSED_ZERO 0x0033
-
-#define AAFF_MD5_LEN 16
-#define AAFF_SHA256_LEN 32
-#define AAFF_BADSECTORMARKER_MAXLEN 65536
-
-typedef struct
-{
- char Magic[4];
- unsigned int NameLen;
- unsigned int DataLen;
- unsigned int Argument; // Named "flags" in original aff source, named "arg" in afinfo output.
- char Name[]; //lint !e1501
-} __attribute__ ((packed)) t_AffSegmentHeader;
-typedef t_AffSegmentHeader *t_pAffSegmentHeader;
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+int AaffOpen(void **pp_handle,
+ const char **pp_filename_arr,
+ uint64_t filename_arr_len);
+int AaffSize(void *p_handle,
+ uint64_t *p_size);
+int AaffRead(void *p_handle,
+ uint64_t seek,
+ char *p_buf,
+ uint32_t count);
+int AaffClose(void **pp_handle);
+int AaffOptionsHelp(const char **pp_help);
+int AaffOptionsParse(void *p_handle,
+ char *p_options,
+ char **pp_error);
+int AaffGetInfofileContent(void *p_handle,
+ const char **pp_info_buf);
+void AaffFreeBuffer(void *p_buf);
-// Between header and footer lie the segment name and the data
+/*******************************************************************************
+ * LibXmount_Input API implementation
+ ******************************************************************************/
+/*
+ * LibXmount_Input_GetApiVersion
+ */
+uint8_t LibXmount_Input_GetApiVersion() {
+ return LIBXMOUNT_INPUT_API_VERSION;
+}
-typedef struct
-{
- char Magic[4];
- unsigned int SegmentLen;
-} __attribute__ ((packed)) t_AffSegmentFooter;
+/*
+ * LibXmount_Input_GetSupportedFormats
+ */
+const char* LibXmount_Input_GetSupportedFormats() {
+ return "aaff\0\0";
+}
-const int AaffInfoBuffLen = 1024*1024;
+/*
+ * LibXmount_Input_GetFunctions
+ */
+void LibXmount_Input_GetFunctions(ts_LibXmountInputFunctions *p_functions) {
+ p_functions->Open=&AaffOpen;
+ p_functions->Size=&AaffSize;
+ p_functions->Read=&AaffRead;
+ p_functions->Close=&AaffClose;
+ p_functions->OptionsHelp=&AaffOptionsHelp;
+ p_functions->OptionsParse=&AaffOptionsParse;
+ p_functions->GetInfofileContent=&AaffGetInfofileContent;
+ p_functions->FreeBuffer=&AaffFreeBuffer;
+}
-typedef struct _t_Aaff
-{
- char *pFilename;
- FILE *pFile;
-
- char *pLibVersion; // AFF File Header info
- char *pFileType;
- unsigned int PageSize;
- unsigned int SectorSize;
- unsigned long long Sectors;
- unsigned long long ImageSize;
- unsigned long long TotalPages;
-
- char *pNameBuff; // Buffers
- unsigned char *pDataBuff;
- unsigned int NameBuffLen;
- unsigned int DataBuffLen;
-
- unsigned long long CurrentPage;
- unsigned char *pPageBuff; // Length is PageSize, contains data of CurrentPage
- unsigned int PageBuffDataLen; // Length of current data in PageBuff (the same for all pages, but the last one might contain less data)
-
- char *pInfoBuff;
- char *pInfoBuffConst;
-
- unsigned long long *pPageSeekArr;
- unsigned long long PageSeekArrLen;
- unsigned long long Interleave; // The number of pages lying between 2 entries in the PageSeekArr
-} t_Aaff;
-
-
-// ----------------
-// Error handling
-// ----------------
-
-#ifdef AAFF_DEBUG
- #define CHK(ChkVal) \
- { \
- int ChkValRc; \
- if ((ChkValRc=(ChkVal)) != AAFF_OK) \
- { \
- printf ("Err %d in %s, %d\n", ChkValRc, __FILE__, __LINE__); \
- return ChkValRc; \
- } \
- }
- #define DEBUG_PRINTF(pFormat, ...) \
- printf (pFormat, ##__VA_ARGS__);
-#else
- #define CHK(ChkVal) \
- { \
- int ChkValRc; \
- if ((ChkValRc=(ChkVal)) != AAFF_OK) \
- return ChkValRc; \
- }
- #define DEBUG_PRINTF(...)
-#endif
+/*******************************************************************************
+ * Private
+ ******************************************************************************/
// ---------------------------
// Internal static functions
// ---------------------------
static int AaffCreateHandle (t_pAaff *ppAaff)
{
t_pAaff pAaff;
pAaff = (t_pAaff) malloc (sizeof(t_Aaff));
if (pAaff == NULL)
return AAFF_MEMALLOC_FAILED;
memset (pAaff, 0, sizeof(t_Aaff));
*ppAaff = pAaff;
return AAFF_OK;
}
static int AaffDestroyHandle (t_pAaff *ppAaff)
{
t_pAaff pAaff = *ppAaff;
if (pAaff->pFilename) free (pAaff->pFilename);
if (pAaff->pPageSeekArr) free (pAaff->pPageSeekArr);
if (pAaff->pLibVersion) free (pAaff->pLibVersion);
if (pAaff->pFileType) free (pAaff->pFileType);
if (pAaff->pNameBuff) free (pAaff->pNameBuff);
if (pAaff->pDataBuff) free (pAaff->pDataBuff);
if (pAaff->pPageBuff) free (pAaff->pPageBuff);
if (pAaff->pInfoBuffConst) free (pAaff->pInfoBuffConst);
if (pAaff->pInfoBuff) free (pAaff->pInfoBuff);
memset (pAaff, 0, sizeof(t_Aaff));
free (pAaff);
*ppAaff = NULL;
return AAFF_OK;
}
-unsigned long long AaffU64 (unsigned char *pData)
+uint64_t AaffU64 (char *pData)
{
- unsigned long long Val=0;
- int i;
+ uint64_t Val=0;
+ int i;
for (i=4; i<8; i++) Val = (Val << 8) | pData[i];
for (i=0; i<4; i++) Val = (Val << 8) | pData[i];
return Val;
}
-static int AaffPageNumberFromSegmentName (char *pSegmentName, unsigned long long *pPageNumber)
+static int AaffPageNumberFromSegmentName (char *pSegmentName, uint64_t *pPageNumber)
{
char *pSegmentNamePageNumber;
char *pTail;
pSegmentNamePageNumber = &pSegmentName[strlen(AFF_SEGNAME_PAGE)];
*pPageNumber = strtoull (pSegmentNamePageNumber, &pTail, 10);
if (*pTail != '\0')
return AAFF_INVALID_PAGE_NUMBER; // There should be no extra chars after the number
return AAFF_OK;
}
-static inline unsigned long long AaffGetCurrentSeekPos (t_Aaff *pAaff)
+static inline uint64_t AaffGetCurrentSeekPos (t_Aaff *pAaff)
{
return ftello (pAaff->pFile);
}
-static inline unsigned long long AaffSetCurrentSeekPos (t_Aaff *pAaff, unsigned long long Val, int Whence)
+static inline uint64_t AaffSetCurrentSeekPos (t_Aaff *pAaff, uint64_t Val, int Whence)
{
if (fseeko (pAaff->pFile, Val, Whence) != 0)
return AAFF_CANNOT_SEEK;
return AAFF_OK;
}
-static int AaffReadFile (t_Aaff *pAaff, void *pData, unsigned int DataLen)
+static int AaffReadFile (t_Aaff *pAaff, void *pData, uint32_t DataLen)
{
if (fread (pData, DataLen, 1, pAaff->pFile) != 1)
return AAFF_CANNOT_READ_DATA;
return AAFF_OK;
}
-static int AaffRealloc (void **ppBuff, unsigned int *pCurrentLen, unsigned int NewLen)
+static int AaffRealloc (void **ppBuff, uint32_t *pCurrentLen, uint32_t NewLen)
{
if (NewLen > *pCurrentLen)
{
*ppBuff = realloc (*ppBuff, NewLen);
if (*ppBuff == NULL)
return AAFF_MEMALLOC_FAILED;
*pCurrentLen = NewLen;
}
return AAFF_OK;
}
-static int AaffReadSegment (t_pAaff pAaff, char **ppName, unsigned int *pArg, unsigned char **ppData, unsigned int *pDataLen)
+static int AaffReadSegment (t_pAaff pAaff, char **ppName, uint32_t *pArg, char **ppData, uint32_t *pDataLen)
{
t_AffSegmentHeader Header;
t_AffSegmentFooter Footer;
CHK (AaffReadFile (pAaff, &Header, offsetof(t_AffSegmentHeader, Name)))
if (strcmp (&Header.Magic[0], AFF_SEGMENT_HEADER_MAGIC) != 0)
return AAFF_INVALID_HEADER;
Header.NameLen = ntohl (Header.NameLen );
Header.DataLen = ntohl (Header.DataLen );
Header.Argument = ntohl (Header.Argument);
CHK (AaffRealloc ((void**)&pAaff->pNameBuff, &pAaff->NameBuffLen, Header.NameLen+1)) // alloc +1, as is might be a string which can be more
CHK (AaffRealloc ((void**)&pAaff->pDataBuff, &pAaff->DataBuffLen, Header.DataLen+1)) // easily handled by the calling fn when adding a \0
CHK (AaffReadFile (pAaff, pAaff->pNameBuff, Header.NameLen))
if (Header.DataLen)
CHK (AaffReadFile (pAaff, pAaff->pDataBuff, Header.DataLen))
pAaff->pNameBuff[Header.NameLen] = '\0';
pAaff->pDataBuff[Header.DataLen] = '\0';
if (ppName) *ppName = pAaff->pNameBuff;
if (pArg ) *pArg = Header.Argument;
if (ppData) *ppData = pAaff->pDataBuff;
if (pDataLen) *pDataLen = Header.DataLen;
// Read footer and position file pointer to next segemnt at the same time
// ----------------------------------------------------------------------
CHK (AaffReadFile (pAaff, &Footer, sizeof(Footer)))
if (strcmp (&Footer.Magic[0], AFF_SEGMENT_FOOTER_MAGIC) != 0)
return AAFF_INVALID_FOOTER;
return AAFF_OK;
}
-static int AaffReadSegmentPage (t_pAaff pAaff, unsigned long long SearchPage, unsigned long long *pFoundPage, unsigned char **ppData, unsigned int *pDataLen)
+static int AaffReadSegmentPage (t_pAaff pAaff, uint64_t SearchPage, uint64_t *pFoundPage, char **ppData, uint32_t *pDataLen)
{
t_AffSegmentHeader Header;
t_AffSegmentFooter Footer;
char SearchPageStr[128];
int rc = AAFF_OK;
*ppData = NULL;
*pDataLen = 0;
- sprintf (SearchPageStr, "page%llu", SearchPage);
+ sprintf (SearchPageStr, "page%" PRIu64, SearchPage);
CHK (AaffReadFile (pAaff, &Header, offsetof(t_AffSegmentHeader, Name)))
if (strcmp (&Header.Magic[0], AFF_SEGMENT_HEADER_MAGIC) != 0)
return AAFF_INVALID_HEADER;
Header.NameLen = ntohl (Header.NameLen );
Header.DataLen = ntohl (Header.DataLen );
Header.Argument = ntohl (Header.Argument);
CHK (AaffRealloc ((void**)&pAaff->pNameBuff, &pAaff->NameBuffLen, Header.NameLen+1))
CHK (AaffReadFile (pAaff, pAaff->pNameBuff, Header.NameLen))
pAaff->pNameBuff[Header.NameLen] = '\0';
if (strncmp (pAaff->pNameBuff, AFF_SEGNAME_PAGE, strlen(AFF_SEGNAME_PAGE)) != 0)
return AAFF_WRONG_SEGMENT;
CHK (AaffPageNumberFromSegmentName (pAaff->pNameBuff, pFoundPage))
if (*pFoundPage == SearchPage)
{
unsigned int Len;
uLongf ZLen;
int zrc;
switch (Header.Argument)
{
case AFF_PAGEFLAGS_UNCOMPRESSED:
DEBUG_PRINTF ("\nuncompressed");
CHK (AaffReadFile (pAaff, pAaff->pPageBuff, Header.DataLen))
pAaff->PageBuffDataLen = Header.DataLen;
break;
case AFF_PAGEFLAGS_COMPRESSED_ZERO:
DEBUG_PRINTF ("\nzero");
CHK (AaffReadFile (pAaff, &Len, sizeof(Len)))
Len = ntohl (Len);
memset (pAaff->pPageBuff, 0, Len);
pAaff->PageBuffDataLen = Len;
break;
case AFF_PAGEFLAGS_COMPRESSED_ZLIB:
DEBUG_PRINTF ("\ncompressed");
CHK (AaffRealloc ((void**)&pAaff->pDataBuff, &pAaff->DataBuffLen, Header.DataLen));
CHK (AaffReadFile (pAaff, pAaff->pDataBuff, Header.DataLen)) // read into pDataBuff
ZLen = pAaff->PageSize; // size of pPageBuff
- zrc = uncompress (pAaff->pPageBuff, &ZLen, pAaff->pDataBuff, Header.DataLen); // uncompress into pPageBuff
+ zrc = uncompress ((unsigned char*)(pAaff->pPageBuff), &ZLen, (unsigned char*)(pAaff->pDataBuff), Header.DataLen); // uncompress into pPageBuff
pAaff->PageBuffDataLen = ZLen;
if (zrc != Z_OK)
return AAFF_UNCOMPRESS_FAILED;
break;
default:
return AAFF_INVALID_PAGE_ARGUMENT;
}
*ppData = pAaff->pPageBuff;
*pDataLen = pAaff->PageBuffDataLen;
pAaff->CurrentPage = *pFoundPage;
rc = AAFF_FOUND;
}
else
{
CHK (AaffSetCurrentSeekPos (pAaff, Header.DataLen, SEEK_CUR))
}
// Read footer and position file pointer to next segemnt at the same time
// ----------------------------------------------------------------------
CHK (AaffReadFile (pAaff, &Footer, sizeof(Footer)))
if (strcmp (&Footer.Magic[0], AFF_SEGMENT_FOOTER_MAGIC) != 0)
return AAFF_INVALID_FOOTER;
return rc;
}
-static int AaffReadPage (t_pAaff pAaff, unsigned long long Page, unsigned char **ppBuffer, unsigned int *pLen)
+static int AaffReadPage (t_pAaff pAaff, uint64_t Page, char **ppBuffer, uint32_t *pLen)
{
if (Page >= pAaff->TotalPages)
return AAFF_READ_BEYOND_LAST_PAGE;
// Check if it's the current page
// ------------------------------
if (Page == pAaff->CurrentPage)
{
*ppBuffer = pAaff->pPageBuff;
*pLen = pAaff->PageBuffDataLen;
return AAFF_OK;
}
// Set the seek position for startig the search
// --------------------------------------------
int MaxHops;
if ((pAaff->CurrentPage != AAFF_CURRENTPAGE_NOTSET) &&
(pAaff->CurrentPage+1 == Page)) // The current seek pos already is the correct one
{
MaxHops = 1;
}
else // Find the closest entry in PageSeekArr
{
- long long Entry;
+ int64_t Entry;
Entry = Page / pAaff->Interleave;
while (pAaff->pPageSeekArr[Entry] == 0)
{
Entry--;
if (Entry<0)
return AAFF_SEEKARR_CORRUPT;
}
AaffSetCurrentSeekPos (pAaff, pAaff->pPageSeekArr[Entry], SEEK_SET);
MaxHops = Page - (Entry * pAaff->Interleave) +1;
}
// Run through segment list until page is found
// --------------------------------------------
- unsigned long long Seek;
- unsigned long long FoundPage;
+ uint64_t Seek;
+ uint64_t FoundPage;
int rc;
- DEBUG_PRINTF ("\nSearching for page %llu, MaxHops=%d -- ", Page, MaxHops);
+ DEBUG_PRINTF ("\nSearching for page %" PRIu64 ", MaxHops=%d -- ", Page, MaxHops);
while (MaxHops--)
{
Seek = AaffGetCurrentSeekPos (pAaff);
rc = AaffReadSegmentPage (pAaff, Page, &FoundPage, ppBuffer, pLen);
- DEBUG_PRINTF (" %llu (%d)", FoundPage, rc);
+ DEBUG_PRINTF (" %" PRIu64 " (%d)", FoundPage, rc);
if ((FoundPage % pAaff->Interleave) == 0)
pAaff->pPageSeekArr[FoundPage/pAaff->Interleave] = Seek;
if (rc == AAFF_FOUND)
break;
}
DEBUG_PRINTF ("\n");
if (MaxHops<0)
return AAFF_PAGE_NOT_FOUND;
return AAFF_OK;
}
// ---------------
// API functions
// ---------------
-int AaffOpen (t_pAaff *ppAaff, const char *pFilename, unsigned long long MaxPageArrMem)
+/*
+ * AaffOpen
+ */
+int AaffOpen(void **pp_handle,
+ const char **pp_filename_arr,
+ uint64_t filename_arr_len)
{
- t_pAaff pAaff;
- char Signature[strlen(AFF_HEADER)+1];
- unsigned long long Seek;
-
- *ppAaff = NULL;
- CHK (AaffCreateHandle (&pAaff))
-
- pAaff->pFilename = strdup (pFilename);
- pAaff->pFile = fopen (pFilename, "r");
- if (pAaff->pFile == NULL)
- {
- AaffDestroyHandle (&pAaff);
- return AAFF_FILE_OPEN_FAILED;
- }
-
- // Check signature
- // ---------------
- CHK (AaffReadFile (pAaff, &Signature, sizeof(Signature)))
- if (memcmp (Signature, AFF_HEADER, sizeof(Signature)) != 0)
- {
- (void) AaffClose (&pAaff);
- return AAFF_INVALID_SIGNATURE;
- }
-
- // Read header segments
- // --------------------
- char *pName;
- unsigned int Arg;
- unsigned char *pData;
- unsigned int DataLen;
- const int MAX_HEADER_SEGMENTS = 100;
- int Seg;
- unsigned int i;
- int wr;
- int Pos = 0;
- const unsigned HexStrLen = 32;
- char HexStr[HexStrLen+1];
-
- #define REM (AaffInfoBuffLen-Pos)
-
- pAaff->pInfoBuffConst = malloc (AaffInfoBuffLen);
- pAaff->pInfoBuff = malloc (AaffInfoBuffLen*2);
- for (Seg=0; Seg<MAX_HEADER_SEGMENTS; Seg++) // Search for known segments at the image start
- {
- Seek = AaffGetCurrentSeekPos (pAaff);
- CHK (AaffReadSegment (pAaff, &pName, &Arg, &pData, &DataLen))
-
- if (strcmp (pName, AFF_SEGNAME_PAGESIZE ) == 0) pAaff->PageSize = Arg;
- else if (strcmp (pName, AFF_SEGNAME_SECTORSIZE ) == 0) pAaff->SectorSize = Arg;
- else if (strcmp (pName, AFF_SEGNAME_SECTORS ) == 0) pAaff->Sectors = AaffU64 (pData);
- else if (strcmp (pName, AFF_SEGNAME_IMAGESIZE ) == 0) pAaff->ImageSize = AaffU64 (pData);
- else if (strcmp (pName, AFF_SEGNAME_AFFLIB_VERSION) == 0) pAaff->pLibVersion = strdup ((char*)pData);
- else if (strcmp (pName, AFF_SEGNAME_FILETYPE ) == 0) pAaff->pFileType = strdup ((char*)pData);
- else if ((strcmp (pName, AFF_SEGNAME_GID ) == 0) ||
- (strcmp (pName, AFF_SEGNAME_BADFLAG ) == 0))
- {
- wr=0;
- for (i=0; i<GETMIN(DataLen,HexStrLen/2); i++)
- wr += sprintf (&HexStr[wr], "%02X", pData[i]);
- HexStr[i] = '\0';
- Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"%-25s %s", pName, HexStr);
- if (i<DataLen)
- Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"...");
- Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"\n");
- }
- else if (strncmp (pName, AFF_SEGNAME_PAGE, strlen(AFF_SEGNAME_PAGE)) == 0) break;
- else
- {
- if ((Arg == 0) && DataLen)
- Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"%-25s %s\n", pName, pData);
- }
- }
- #undef REM
-
- if (Seg >= MAX_HEADER_SEGMENTS)
- {
- (void) AaffClose (&pAaff);
- return AAFF_TOO_MANY_HEADER_SEGEMENTS;
- }
-
- if (strstr (pAaff->pLibVersion, "Guymager") == NULL)
- {
- (void) AaffClose (&pAaff);
- return AAFF_NOT_CREATED_BY_GUYMAGER;
- }
-
- // Prepare page seek array
- // -----------------------
- unsigned long long MaxEntries;
- int ArrBytes;
-
- pAaff->TotalPages = pAaff->ImageSize / pAaff->PageSize;
- if (pAaff->ImageSize % pAaff->PageSize)
- pAaff->TotalPages++;
-
- if (MaxPageArrMem)
- MaxEntries = (MaxPageArrMem / sizeof (unsigned long long *)) + 1; // +1 in order not to risk a result of 0
- else MaxEntries = AAFF_DEFAULT_PAGE_SEEK_MAX_ENTRIES;
-
- MaxEntries = GETMIN (MaxEntries, pAaff->TotalPages);
- pAaff->Interleave = pAaff->TotalPages / MaxEntries;
- if (pAaff->TotalPages % MaxEntries)
- pAaff->Interleave++;
-
- pAaff->PageSeekArrLen = pAaff->TotalPages / pAaff->Interleave;
- ArrBytes = pAaff->PageSeekArrLen * sizeof(unsigned long long *);
- pAaff->pPageSeekArr = (unsigned long long *)malloc (ArrBytes);
- memset (pAaff->pPageSeekArr, 0, ArrBytes);
- CHK (AaffPageNumberFromSegmentName (pName, &pAaff->CurrentPage));
- if (pAaff->CurrentPage != 0)
- {
- (void) AaffClose (&pAaff);
- return AAFF_UNEXPECTED_PAGE_NUMBER;
- }
- pAaff->pPageSeekArr[0] = Seek;
-
- // Alloc Buffers
- // -------------
- pAaff->pPageBuff = malloc (pAaff->PageSize);
- pAaff->CurrentPage = AAFF_CURRENTPAGE_NOTSET;
-
- *ppAaff = pAaff;
-
- return AAFF_OK;
+ t_pAaff pAaff;
+ char Signature[strlen(AFF_HEADER)+1];
+ uint64_t Seek;
+
+ if(filename_arr_len!=1) {
+ // Split aff files are not supported
+ // TODO: Set correct error
+ return 1;
+ }
+
+ *pp_handle=NULL;
+ CHK(AaffCreateHandle(&pAaff))
+
+ pAaff->pFilename=strdup(pp_filename_arr[0]);
+ pAaff->pFile=fopen(pp_filename_arr[0],"r");
+ if(pAaff->pFile==NULL) {
+ AaffDestroyHandle(&pAaff);
+ return AAFF_FILE_OPEN_FAILED;
+ }
+
+ // Check signature
+ // ---------------
+ CHK(AaffReadFile(pAaff,&Signature,sizeof(Signature)))
+ if(memcmp(Signature,AFF_HEADER,sizeof(Signature))!=0) {
+ (void)AaffClose((void**)&pAaff);
+ return AAFF_INVALID_SIGNATURE;
+ }
+
+ // Read header segments
+ // --------------------
+ char *pName;
+ uint32_t Arg;
+ char *pData;
+ uint32_t DataLen;
+ const int MAX_HEADER_SEGMENTS = 100;
+ int Seg;
+ unsigned int i;
+ int wr;
+ int Pos = 0;
+ const unsigned HexStrLen = 32;
+ char HexStr[HexStrLen+1];
+
+ #define REM (AaffInfoBuffLen-Pos)
+
+ pAaff->pInfoBuffConst = malloc (AaffInfoBuffLen);
+ pAaff->pInfoBuff = malloc (AaffInfoBuffLen*2);
+ // Search for known segments at the image start
+ for (Seg=0; Seg<MAX_HEADER_SEGMENTS; Seg++) {
+ Seek = AaffGetCurrentSeekPos (pAaff);
+ CHK (AaffReadSegment (pAaff, &pName, &Arg, &pData, &DataLen))
+
+ if(strcmp(pName,AFF_SEGNAME_PAGESIZE)==0) {
+ pAaff->PageSize=Arg;
+ } else if(strcmp(pName,AFF_SEGNAME_SECTORSIZE)==0) {
+ pAaff->SectorSize=Arg;
+ } else if(strcmp(pName,AFF_SEGNAME_SECTORS)==0) {
+ pAaff->Sectors=AaffU64(pData);
+ } else if(strcmp(pName,AFF_SEGNAME_IMAGESIZE)==0) {
+ pAaff->ImageSize=AaffU64(pData);
+ } else if(strcmp(pName,AFF_SEGNAME_AFFLIB_VERSION)==0) {
+ pAaff->pLibVersion=strdup((char*)pData);
+ } else if(strcmp(pName,AFF_SEGNAME_FILETYPE)==0) {
+ pAaff->pFileType=strdup((char*)pData);
+ } else if((strcmp(pName,AFF_SEGNAME_GID)==0) ||
+ (strcmp(pName, AFF_SEGNAME_BADFLAG)==0))
+ {
+ wr=0;
+ for (i=0; i<GETMIN(DataLen,HexStrLen/2); i++)
+ wr += sprintf (&HexStr[wr], "%02X", pData[i]);
+ HexStr[i] = '\0';
+ Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"%-25s %s", pName, HexStr);
+ if (i<DataLen) Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"...");
+ Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"\n");
+ } else if(strncmp(pName,AFF_SEGNAME_PAGE,strlen(AFF_SEGNAME_PAGE))==0) {
+ break;
+ } else {
+ if ((Arg == 0) && DataLen)
+ Pos += snprintf (&(pAaff->pInfoBuffConst[Pos]), REM,"%-25s %s\n", pName, pData);
+ }
+ }
+ #undef REM
+
+ if (Seg >= MAX_HEADER_SEGMENTS) {
+ (void) AaffClose ((void**)&pAaff);
+ return AAFF_TOO_MANY_HEADER_SEGEMENTS;
+ }
+
+ if (strstr (pAaff->pLibVersion, "Guymager") == NULL) {
+ (void) AaffClose ((void**)&pAaff);
+ return AAFF_NOT_CREATED_BY_GUYMAGER;
+ }
+
+ // Prepare page seek array
+ // -----------------------
+ uint64_t MaxEntries;
+ int ArrBytes;
+
+ pAaff->TotalPages = pAaff->ImageSize / pAaff->PageSize;
+ if (pAaff->ImageSize % pAaff->PageSize) pAaff->TotalPages++;
+
+ // TODO: MaxPageArrMem was a uint64_t parameter of this function
+ MaxEntries = AAFF_DEFAULT_PAGE_SEEK_MAX_ENTRIES;
+/*
+ if (MaxPageArrMem) {
+ // +1 in order not to risk a result of 0
+ MaxEntries = (MaxPageArrMem / sizeof (unsigned long long *)) + 1;
+ } else MaxEntries = AAFF_DEFAULT_PAGE_SEEK_MAX_ENTRIES;
+*/
+
+ MaxEntries = GETMIN (MaxEntries, pAaff->TotalPages);
+ pAaff->Interleave = pAaff->TotalPages / MaxEntries;
+ if (pAaff->TotalPages % MaxEntries) pAaff->Interleave++;
+
+ pAaff->PageSeekArrLen = pAaff->TotalPages / pAaff->Interleave;
+ ArrBytes = pAaff->PageSeekArrLen * sizeof(uint64_t *);
+ pAaff->pPageSeekArr = (uint64_t*)malloc (ArrBytes);
+ memset (pAaff->pPageSeekArr, 0, ArrBytes);
+ CHK (AaffPageNumberFromSegmentName (pName, &pAaff->CurrentPage));
+ if (pAaff->CurrentPage != 0)
+ {
+ (void) AaffClose ((void**)&pAaff);
+ return AAFF_UNEXPECTED_PAGE_NUMBER;
+ }
+ pAaff->pPageSeekArr[0] = Seek;
+
+ // Alloc Buffers
+ // -------------
+ pAaff->pPageBuff = malloc (pAaff->PageSize);
+ pAaff->CurrentPage = AAFF_CURRENTPAGE_NOTSET;
+
+ *pp_handle=(void*)pAaff;
+
+ return AAFF_OK;
}
-int AaffClose (t_pAaff *ppAaff)
-{
- int rc = AAFF_OK;
-
- if (fclose ((*ppAaff)->pFile))
- rc = AAFF_CANNOT_CLOSE_FILE;
+/*
+ * AaffClose
+ */
+int AaffClose(void **pp_handle) {
+ int rc=AAFF_OK;
- CHK (AaffDestroyHandle (ppAaff))
+ if(fclose((*(t_pAaff*)pp_handle)->pFile)) rc=AAFF_CANNOT_CLOSE_FILE;
+ CHK(AaffDestroyHandle((t_pAaff*)pp_handle))
- return rc;
+ return rc;
}
-int AaffInfo (t_pAaff pAaff, char **ppInfoBuff)
-{
- unsigned long long i;
- unsigned long long Entries = 0;
- int Pos = 0;
+/*
+ * AaffGetInfofileContent
+ */
+int AaffGetInfofileContent(void *p_handle, const char **pp_info_buf) {
+ uint64_t i;
+ uint64_t Entries = 0;
+ int Pos = 0;
#define REM (AaffInfoBuffLen-Pos)
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "AFF IMAGE INFORMATION");
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\n---------------------");
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nAFF file %s" , pAaff->pFilename );
-
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nPage size %u" , pAaff->PageSize );
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nSector size %d" , pAaff->SectorSize );
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nSectors %llu", pAaff->Sectors );
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nImage size %llu (%0.1f GiB)", pAaff->ImageSize, pAaff->ImageSize/(1024.0*1024.0*1024.0));
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nTotal pages %llu", pAaff->TotalPages );
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\n");
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\n%s", pAaff->pInfoBuffConst);
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\n");
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nCurrent page ");
- if (pAaff->CurrentPage == AAFF_CURRENTPAGE_NOTSET)
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "not set");
- else Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "%llu", pAaff->CurrentPage);
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nSeek array length %llu", pAaff->PageSeekArrLen);
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nSeek interleave %llu", pAaff->Interleave);
-
- for (i=0; i<pAaff->PageSeekArrLen; i++)
- if (pAaff->pPageSeekArr[i])
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "AFF IMAGE INFORMATION");
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\n---------------------");
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nAFF file %s" , ((t_pAaff)p_handle)->pFilename );
+
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nPage size %u" , ((t_pAaff)p_handle)->PageSize );
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nSector size %d" , ((t_pAaff)p_handle)->SectorSize );
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nSectors %" PRIu64, ((t_pAaff)p_handle)->Sectors );
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nImage size %" PRIu64 " (%0.1f GiB)", ((t_pAaff)p_handle)->ImageSize, ((t_pAaff)p_handle)->ImageSize/(1024.0*1024.0*1024.0));
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nTotal pages %" PRIu64, ((t_pAaff)p_handle)->TotalPages );
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\n");
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\n%s", ((t_pAaff)p_handle)->pInfoBuffConst);
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\n");
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nCurrent page ");
+ if (((t_pAaff)p_handle)->CurrentPage == AAFF_CURRENTPAGE_NOTSET)
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "not set");
+ else Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "%" PRIu64, ((t_pAaff)p_handle)->CurrentPage);
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nSeek array length %" PRIu64, ((t_pAaff)p_handle)->PageSeekArrLen);
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nSeek interleave %" PRIu64, ((t_pAaff)p_handle)->Interleave);
+
+ for (i=0; i<((t_pAaff)p_handle)->PageSeekArrLen; i++)
+ if (((t_pAaff)p_handle)->pPageSeekArr[i])
Entries++;
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\nSeek array entries %llu", Entries);
- Pos += snprintf (&pAaff->pInfoBuff[Pos], REM, "\n");
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\nSeek array entries %" PRIu64, Entries);
+ Pos += snprintf (&((t_pAaff)p_handle)->pInfoBuff[Pos], REM, "\n");
#undef REM
- *ppInfoBuff = pAaff->pInfoBuff;
+ *pp_info_buf = ((t_pAaff)p_handle)->pInfoBuff;
return AAFF_OK;
}
-int AaffSize (t_pAaff pAaff, unsigned long long *pSize)
-{
- *pSize = pAaff->ImageSize;
- return AAFF_OK;
+/*
+ * AaffSize
+ */
+int AaffSize(void *p_handle, uint64_t *p_size) {
+ *p_size=((t_pAaff)p_handle)->ImageSize;
+ return AAFF_OK;
}
-int AaffRead (t_pAaff pAaff, unsigned long long Seek, unsigned char *pBuffer, unsigned int Count)
+/*
+ * AaffRead
+ */
+int AaffRead(void *p_handle,
+ uint64_t seek,
+ char *p_buf,
+ uint32_t count)
{
- unsigned long long Page;
- unsigned char *pPageBuffer;
- unsigned int PageLen;
- unsigned int Ofs;
- unsigned int ToCopy;
-
- if ((Seek+Count) > pAaff->ImageSize)
- return AAFF_READ_BEYOND_IMAGE_LENGTH;
+ uint64_t page;
+ char *p_page_buffer;
+ uint32_t page_len, ofs, to_copy;
+
+ if((seek+count)>((t_pAaff)p_handle)->ImageSize) {
+ return AAFF_READ_BEYOND_IMAGE_LENGTH;
+ }
+
+ page=seek/((t_pAaff)p_handle)->PageSize;
+ ofs=seek%((t_pAaff)p_handle)->PageSize;
+
+ while(count) {
+ CHK(AaffReadPage((t_pAaff)p_handle,page,&p_page_buffer,&page_len))
+ to_copy=GETMIN(page_len-ofs,count);
+ memcpy(p_buf,p_page_buffer+ofs,to_copy);
+ count-=to_copy;
+ p_buf+=to_copy;
+ ofs=0;
+ page++;
+ }
+
+ return AAFF_OK;
+}
- Page = Seek / pAaff->PageSize;
- Ofs = Seek % pAaff->PageSize;
+/*
+ * AaffOptionsHelp
+ */
+int AaffOptionsHelp(const char **pp_help) {
+ *pp_help=NULL;
+ return AAFF_OK;
+}
- while (Count)
- {
- CHK (AaffReadPage (pAaff, Page, &pPageBuffer, &PageLen))
- ToCopy = GETMIN (PageLen-Ofs, Count);
- memcpy (pBuffer, pPageBuffer+Ofs, ToCopy);
- Count -= ToCopy;
- pBuffer += ToCopy;
- Ofs = 0;
- Page++;
- }
+/*
+ * AaffOptionsParse
+ */
+int AaffOptionsParse(void *p_handle, char *p_options, char **pp_error) {
+ return AAFF_OK;
+}
- return AAFF_OK;
+/*
+ * AaffFreeBuffer
+ */
+void AaffFreeBuffer(void *p_buf) {
+ free(p_buf);
}
// -----------------------------------------------------
// Small main routine for testing
// It converts an aff file to dd
// -----------------------------------------------------
#ifdef AAFF_MAIN_FOR_TESTING
int main(int argc, char *argv[])
{
- t_pAaff pAaff;
- char *pInfoBuff;
- unsigned long long Remaining;
- unsigned long long CurrentPos=0;
- int rc;
- int Percent;
- int PercentOld;
+ t_pAaff pAaff;
+ char *pInfoBuff;
+ uint64_t Remaining;
+ uint64_t CurrentPos=0;
+ int rc;
+ int Percent;
+ int PercentOld;
setbuf (stdout, NULL);
setbuf (stderr, NULL);
setlocale (LC_ALL, "");
printf ("AFF to DD converter\n");
if (argc != 3)
{
printf ("Usage: %s <aff source file> <dd destination file>\n", argv[0]);
exit (1);
}
// rc = AaffOpen (&pAaff, argv[1], 1024); // weird seek array size for testing
- rc = AaffOpen (&pAaff, argv[1], 0);
+ rc = AaffOpen (&pAaff, argv[1], 1);
if (rc)
{
printf ("Error %d while opening file %s\n", rc, argv[1]);
exit (2);
}
rc = AaffInfo (pAaff, &pInfoBuff);
if (rc)
{
printf ("Could not retrieve info\n");
exit (2);
}
printf ("%s", pInfoBuff);
// Create destination file and fill it with data from aff
// ------------------------------------------------------
FILE *pFile;
pFile = fopen (argv[2], "w");
// const unsigned BuffSize = 13; // weird Buffsize for testing
const unsigned BuffSize = 65536;
unsigned char *pBuff;
unsigned int Bytes;
Remaining = pAaff->ImageSize;
pBuff = malloc (BuffSize);
CurrentPos=0;
PercentOld = -1;
while (Remaining)
{
Bytes = GETMIN (Remaining, BuffSize);
rc = AaffRead (pAaff, CurrentPos, pBuff, Bytes);
if (rc != AAFF_OK)
{
printf ("Could not read data from aff file, error %d\n", rc);
exit (2);
}
if (fwrite (pBuff, Bytes, 1, pFile) != 1)
{
printf ("Could not write to destinationfile\n");
exit (2);
}
CurrentPos += Bytes;
Remaining -= Bytes;
Percent = (100*CurrentPos) / pAaff->ImageSize;
if (Percent != PercentOld)
{
printf ("\r%d%% done...", Percent);
PercentOld = Percent;
}
}
free (pBuff);
fclose (pFile);
return 0;
}
#endif
+
diff --git a/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.h b/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.h
index 65925a6..08af468 100644
--- a/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.h
+++ b/trunk/libxmount_input/libxmount_input_aaff/libxmount_input_aaff.h
@@ -1,64 +1,187 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This module has been written by Guy Voncken. It contains the functions for *
* accessing simple AFF images created by Guymager. *
* *
* xmount is a small tool to "fuse mount" various harddisk image formats as dd, *
* vdi, vhd or vmdk files and enable virtual write access to them. *
* *
* 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 AAFF_H
#define AAFF_H
typedef struct _t_Aaff *t_pAaff;
-int AaffOpen (t_pAaff *ppAaff, const char *pFilename, unsigned long long MaxPageArrMem);
-int AaffInfo (t_pAaff pAaff, char **ppInfoBuff);
-int AaffSize (t_pAaff pAaff, unsigned long long *pSize);
-int AaffRead (t_pAaff pAaff, unsigned long long Seek, unsigned char *pBuffer, unsigned int Count);
-int AaffClose (t_pAaff *ppAaff);
+// ----------------------
+// Constant definitions
+// ----------------------
+#define AAFF_DEFAULT_PAGE_SEEK_MAX_ENTRIES 1000000 // Default max. number of cached seek points for fast page access
+
+#define AAFF_CURRENTPAGE_NOTSET ULONG_LONG_MAX
+
+#define GETMAX(a,b) ((a)>(b)?(a):(b))
+#define GETMIN(a,b) ((a)<(b)?(a):(b))
+
+// -----------------
+// AFF definitions
+// -----------------
+
+#define AFF_GID_LENGTH 16
+#define AFF_SEGARG_U64 2 // Used as argument for segments that contain a 64 bit unsigned in the data field
+
+#define AFF_HEADER "AFF10\r\n"
+#define AFF_SEGMENT_HEADER_MAGIC "AFF"
+#define AFF_SEGMENT_FOOTER_MAGIC "ATT"
+#define AFF_BADSECTOR_HEADER "BAD SECTOR"
+#define AFF_FILE_TYPE "AFF"
+
+#define AFF_SEGNAME_BADFLAG "badflag"
+#define AFF_SEGNAME_AFFLIB_VERSION "afflib_version"
+#define AFF_SEGNAME_FILETYPE "aff_file_type"
+#define AFF_SEGNAME_GID "image_gid"
+#define AFF_SEGNAME_SECTORS "devicesectors"
+#define AFF_SEGNAME_SECTORSIZE "sectorsize"
+#define AFF_SEGNAME_IMAGESIZE "imagesize"
+#define AFF_SEGNAME_PAGESIZE "pagesize"
+#define AFF_SEGNAME_BADSECTORS "badsectors"
+#define AFF_SEGNAME_MD5 "md5"
+#define AFF_SEGNAME_SHA256 "sha256"
+#define AFF_SEGNAME_DURATION "acquisition_seconds"
+#define AFF_SEGNAME_PAGE "page"
+
+#define AAFF_SEGNAME_COMMAND_LINE "acquisition_commandline"
+#define AAFF_SEGNAME_MACADDR "acquisition_macaddr"
+#define AAFF_SEGNAME_DATE "acquisition_date" // Format: YYYY-MM-DD HH:MM:SS TZT
+#define AAFF_SEGNAME_DEVICE "acquisition_device"
+#define AAFF_SEGNAME_MODEL "device_model"
+#define AAFF_SEGNAME_SN "device_sn"
+
+#define AFF_PAGEFLAGS_UNCOMPRESSED 0x0000
+#define AFF_PAGEFLAGS_COMPRESSED_ZLIB 0x0001
+#define AFF_PAGEFLAGS_COMPRESSED_ZERO 0x0033
+
+#define AAFF_MD5_LEN 16
+#define AAFF_SHA256_LEN 32
+#define AAFF_BADSECTORMARKER_MAXLEN 65536
+
+typedef struct
+{
+ char Magic[4];
+ unsigned int NameLen;
+ unsigned int DataLen;
+ unsigned int Argument; // Named "flags" in original aff source, named "arg" in afinfo output.
+ char Name[]; //lint !e1501
+} __attribute__ ((packed)) t_AffSegmentHeader;
+typedef t_AffSegmentHeader *t_pAffSegmentHeader;
+
+// Between header and footer lie the segment name and the data
+
+typedef struct
+{
+ char Magic[4];
+ unsigned int SegmentLen;
+} __attribute__ ((packed)) t_AffSegmentFooter;
+
+const int AaffInfoBuffLen = 1024*1024;
+
+typedef struct _t_Aaff
+{
+ char *pFilename;
+ FILE *pFile;
+
+ char *pLibVersion; // AFF File Header info
+ char *pFileType;
+ unsigned int PageSize;
+ unsigned int SectorSize;
+ uint64_t Sectors;
+ uint64_t ImageSize;
+ uint64_t TotalPages;
+
+ char *pNameBuff; // Buffers
+ char *pDataBuff;
+ unsigned int NameBuffLen;
+ unsigned int DataBuffLen;
+
+ uint64_t CurrentPage;
+ char *pPageBuff; // Length is PageSize, contains data of CurrentPage
+ unsigned int PageBuffDataLen; // Length of current data in PageBuff (the same for all pages, but the last one might contain less data)
+
+ char *pInfoBuff;
+ char *pInfoBuffConst;
+
+ uint64_t *pPageSeekArr;
+ uint64_t PageSeekArrLen;
+ uint64_t Interleave; // The number of pages lying between 2 entries in the PageSeekArr
+} t_Aaff;
+
+
+// ----------------
+// Error handling
+// ----------------
+
+#ifdef AAFF_DEBUG
+ #define CHK(ChkVal) \
+ { \
+ int ChkValRc; \
+ if ((ChkValRc=(ChkVal)) != AAFF_OK) \
+ { \
+ printf ("Err %d in %s, %d\n", ChkValRc, __FILE__, __LINE__); \
+ return ChkValRc; \
+ } \
+ }
+ #define DEBUG_PRINTF(pFormat, ...) \
+ printf (pFormat, ##__VA_ARGS__);
+#else
+ #define CHK(ChkVal) \
+ { \
+ int ChkValRc; \
+ if ((ChkValRc=(ChkVal)) != AAFF_OK) \
+ return ChkValRc; \
+ }
+ #define DEBUG_PRINTF(...)
+#endif
// Possible error codes
enum
{
AAFF_OK = 0,
AAFF_FOUND,
AAFF_MEMALLOC_FAILED=100,
AAFF_FILE_OPEN_FAILED,
AAFF_INVALID_SIGNATURE,
AAFF_CANNOT_READ_DATA,
AAFF_INVALID_HEADER,
AAFF_INVALID_FOOTER, // 105
AAFF_TOO_MANY_HEADER_SEGEMENTS,
AAFF_NOT_CREATED_BY_GUYMAGER,
AAFF_INVALID_PAGE_NUMBER,
AAFF_UNEXPECTED_PAGE_NUMBER,
AAFF_CANNOT_CLOSE_FILE, // 110
AAFF_CANNOT_SEEK,
AAFF_WRONG_SEGMENT,
AAFF_UNCOMPRESS_FAILED,
AAFF_INVALID_PAGE_ARGUMENT,
AAFF_SEEKARR_CORRUPT, // 115
AAFF_PAGE_NOT_FOUND,
AAFF_READ_BEYOND_IMAGE_LENGTH,
AAFF_READ_BEYOND_LAST_PAGE
};
#endif
diff --git a/trunk/libxmount_input/libxmount_input_aewf/CMakeLists.txt b/trunk/libxmount_input/libxmount_input_aewf/CMakeLists.txt
new file mode 100644
index 0000000..6a39f59
--- /dev/null
+++ b/trunk/libxmount_input/libxmount_input_aewf/CMakeLists.txt
@@ -0,0 +1,8 @@
+project(libxmount_input_aewf)
+
+add_library(xmount_input_aewf SHARED libxmount_input_aewf.c)
+include_directories(${LIBZ_INCLUDE_DIRS})
+target_link_libraries(xmount_input_aewf ${LIBZ_LIBRARIES})
+
+install(TARGETS xmount_input_aewf DESTINATION lib/xmount)
+
diff --git a/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.c b/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.c
index c485bd8..d0851d7 100644
--- a/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.c
+++ b/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.c
@@ -1,1353 +1,1232 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This module has been written by Guy Voncken. It contains the functions for *
* accessing EWF images created by Guymager and others. *
* *
* xmount is a small tool to "fuse mount" various harddisk image formats as dd, *
* vdi, vhd or vmdk files and enable virtual write access to them. *
* *
* 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/>. *
*******************************************************************************/
// Aewf has been written in order to reduce xmount's memory footprint when
// operating on large EWF images. Before Aewf, xmount exclusively relied on
// libewf for accessing EWF images, resulting in enormous memory consumption.
//
// Aewf uses 2 main structures for handling image access: pAewf->pSegmentArr
// contains everything about the image files (segments) and pAewf->pTableArr
// handles the EWF chunk offset tables.
//
// At the same time, those structures serve as caches for the two most vital
// ressouces, namely the number of segment files opened in parallel and the
// memory consumed by the chunk offset tables.
//
// The max. values for both are configurable, see pAewf->MaxOpenSegments and
// pAewf->MaxTableCache.
-
-//#define AEWF_MAIN_FOR_TESTING
-//#define AEWF_DEBUG
-
-#ifdef AEWF_MAIN_FOR_TESTING
- #define CREATE_REVERSE_FILE
-// #define REVERSE_FILE_USES_SEPARATE_HANDLE
-#endif
-
-#ifdef AEWF_MAIN_FOR_TESTING
- #define _GNU_SOURCE
-#endif
-
-#ifdef LINT_CODE_CHECK
- #define _LARGEFILE_SOURCE
- #define _FILE_OFFSET_BITS 64
-#endif
-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
#include <time.h> //lint !e537 !e451 Repeated include
#include <zlib.h>
#include <unistd.h> //lint !e537 !e451 Repeated include
#include <wchar.h> //lint !e537 !e451 Repeated include
#include <stdarg.h> //lint !e537 !e451 Repeated include
#include <limits.h> //lint !e537 !e451 Repeated include
-#include "aewf.h"
-
-// ----------------------
-// Constant definitions
-// ----------------------
-
-#define GETMAX(a,b) ((a)>(b)?(a):(b))
-#define GETMIN(a,b) ((a)<(b)?(a):(b))
-
-#define FALSE 0
-#define TRUE 1
-
+#include "../libxmount_input.h"
-#define ASPRINTF(...) \
-{ \
- if (asprintf(__VA_ARGS__) < 0) \
- return AEWF_ASPRINTF_FAILED; \
-}
+//#define AEWF_DEBUG
+#include "libxmount_input_aewf.h"
-// ---------------------
-// Types and strutures
-// ---------------------
+//#define AEWF_MAIN_FOR_TESTING
-typedef struct
-{
- unsigned char Signature[8];
- unsigned char StartOfFields; // 0x01;
- unsigned short int SegmentNumber;
- unsigned short int EndOfFields; // 0x0000
-} __attribute__ ((packed)) t_AewfFileHeader, *t_AewfpFileHeader;
+#ifdef AEWF_MAIN_FOR_TESTING
+ #define CREATE_REVERSE_FILE
+// #define REVERSE_FILE_USES_SEPARATE_HANDLE
+#endif
-typedef struct
-{
- unsigned char Type[16];
- unsigned long long OffsetNextSection;
- unsigned long long Size;
- unsigned char Padding[40];
- unsigned int Checksum;
- char Data[]; //lint !e1501 data member has zero size
-} __attribute__ ((packed)) t_AewfSection, *t_pAewfSection;
-
-typedef struct
-{
- unsigned char MediaType;
- unsigned char Unknown1[3]; // contains 0x00
- unsigned int ChunkCount;
- unsigned int SectorsPerChunk;
- unsigned int BytesPerSector;
- unsigned long long SectorCount;
- unsigned int CHS_Cylinders;
- unsigned int CHS_Heads;
- unsigned int CHS_Sectors;
- unsigned char MediaFlags;
- unsigned char Unknown2[3]; // contains 0x00
- unsigned int PalmVolumeStartSector;
- unsigned char Padding1[4]; // contains 0x00
- unsigned int SmartLogsStartSector;
- unsigned char CompressionLevel;
- unsigned char Unknown3[3]; // contains 0x00
- unsigned int ErrorBlockSize;
- unsigned char Unknown4[4];
- unsigned char AcquirySystemGUID[16];
- unsigned char Padding2[963];
- unsigned char Reserved [5];
- unsigned int Checksum;
-} __attribute__ ((packed)) t_AewfSectionVolume, *t_pAewfSectionVolume;
-
-typedef struct
-{
- unsigned int ChunkCount;
- unsigned char Padding1 [4];
- unsigned long long TableBaseOffset;
- unsigned char Padding2 [4];
- unsigned int Checksum;
- unsigned int OffsetArray[]; //lint !e1501 data member has zero size
-} __attribute__ ((packed)) t_AewfSectionTable, *t_pAewfSectionTable;
+#ifdef AEWF_MAIN_FOR_TESTING
+ #define _GNU_SOURCE
+#endif
-const unsigned int AEWF_COMPRESSED = 0x80000000;
+#ifdef LINT_CODE_CHECK
+ #define _LARGEFILE_SOURCE
+ #define _FILE_OFFSET_BITS 64
+#endif
-typedef struct
-{
- unsigned int FirstSector;
- unsigned int NumberOfSectors;
-} __attribute__ ((packed)) t_AewfSectionErrorEntry, *t_pAewfSectionErrorEntry;
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+int AewfOpen(void **pp_handle,
+ const char **pp_filename_arr,
+ uint64_t filename_arr_len);
+int AewfSize(void *p_handle,
+ uint64_t *p_size);
+int AewfRead(void *p_handle,
+ uint64_t seek,
+ char *p_buf,
+ uint32_t count);
+int AewfClose(void **pp_handle);
+int AewfOptionsHelp(const char **pp_help);
+int AewfOptionsParse(void *p_handle,
+ char *p_options,
+ char **pp_error);
+int AewfGetInfofileContent(void *p_handle,
+ const char **pp_info_buf);
+void AewfFreeBuffer(void *p_buf);
-typedef struct
-{
- unsigned int NumberOfErrors;
- unsigned char Padding[512];
- unsigned int Checksum;
- t_AewfSectionErrorEntry ErrorArr[0]; //lint !e1501 data member has zero size
- unsigned int ChecksumArr;
-} __attribute__ ((packed)) t_AewfSectionError, *t_pAewfSectionError;
-
-typedef struct
-{
- unsigned char MD5[16];
- unsigned char Unknown[16];
- unsigned int Checksum;
-} __attribute__ ((packed)) t_AewfSectionHash, *t_pAewfSectionHash;
+/*******************************************************************************
+ * LibXmount_Input API implementation
+ ******************************************************************************/
+/*
+ * LibXmount_Input_GetApiVersion
+ */
+uint8_t LibXmount_Input_GetApiVersion() {
+ return LIBXMOUNT_INPUT_API_VERSION;
+}
+/*
+ * LibXmount_Input_GetSupportedFormats
+ */
+const char* LibXmount_Input_GetSupportedFormats() {
+ return "aewf\0\0";
+}
-typedef struct
-{
- char *pName;
- unsigned Number;
- FILE *pFile; // NULL if file is not opened (never read or kicked out form cache)
- time_t LastUsed;
-} t_Segment, *t_pSegment;
+/*
+ * LibXmount_Input_GetFunctions
+ */
+void LibXmount_Input_GetFunctions(ts_LibXmountInputFunctions *p_functions) {
+ p_functions->Open=&AewfOpen;
+ p_functions->Size=&AewfSize;
+ p_functions->Read=&AewfRead;
+ p_functions->Close=&AewfClose;
+ p_functions->OptionsHelp=&AewfOptionsHelp;
+ p_functions->OptionsParse=&AewfOptionsParse;
+ p_functions->GetInfofileContent=&AewfGetInfofileContent;
+ p_functions->FreeBuffer=&AewfFreeBuffer;
+}
-typedef struct
-{
- unsigned long long Nr; // The table's position in the pAewf->pTableArr, for debug output only
- unsigned long long ChunkFrom; // Number of the chunk referred to by the first entry of this table (very first chunk has number 0)
- unsigned long long ChunkTo; // Number of the chunk referred to by the last entry of this table
- t_pSegment pSegment; // The file segment where the table is located
- unsigned long long Offset; // The offset of the table inside the segment file (start of t_AewfSectionTable, not of the preceding t_AewfSection)
- unsigned long Size; // The length of the table (same as allocated length for pEwfTable)
- unsigned int ChunkCount; // The number of chunk; this is the same as pTableData->Chunkcount, however, pTableData might not be available (NULL)
- unsigned int SectionSectorsSize; // Silly EWF format has no clean way of knowing size of the last (possibly compressed) chunk of a table
- time_t LastUsed; // Last usage of this table, for cache management
- t_pAewfSectionTable pEwfTable; // Contains the original EWF table section or NULL, if never read or kicked out from cache
-} t_Table, *t_pTable;
-
-typedef struct _t_Aewf
-{
- t_pSegment pSegmentArr; // Array of all segment files (in correct order)
- t_pTable pTableArr; // Array of all chunk offset tables found in the segment files (in correct order)
- unsigned Segments;
- unsigned Tables;
- unsigned long long Chunks; // Total number of chunks in all tables
- unsigned long long TableCache; // Current amount RAM used by tables, in bytes
- unsigned long long OpenSegments; // Current number of open segment files
- unsigned long long SectorSize;
- unsigned long long Sectors;
- unsigned long long ChunkSize;
- unsigned long long ImageSize; // Equals to Sectors * SectorSize
- unsigned char *pChunkBuffCompressed;
- unsigned char *pChunkBuffUncompressed;
- unsigned long long ChunkBuffUncompressedDataLen; // This normally always is equal to the chunk size (32K), except maybe for the last chunk, if the image's total size is not a multiple of the chunk size
- unsigned int ChunkBuffSize;
- unsigned long long ChunkInBuff; // Chunk currently residing in pChunkBuffUncompressed
- char *pErrorText; // Used for assembling error text during option parsing
- time_t LastStatsUpdate;
- char *pInfo;
-
- // Statistics
- unsigned long long SegmentCacheHits;
- unsigned long long SegmentCacheMisses;
- unsigned long long TableCacheHits;
- unsigned long long TableCacheMisses;
- unsigned long long ChunkCacheHits;
- unsigned long long ChunkCacheMisses;
- unsigned long long ReadOperations; // How many times did xmount call the function AewfRead
- unsigned long long DataReadFromImage; // The data (in bytes) read from the image
- unsigned long long DataReadFromImageRaw; // The same data (in bytes), after uncompression (if any)
- unsigned long long DataRequestedByCaller; // How much data was given back to the caller
- unsigned long long TablesReadFromImage; // The overhead of the table read operations (in bytes)
-
- unsigned long long ChunksRead;
- unsigned long long BytesRead;
-
- // Options
- unsigned long long MaxTableCache; // Max. amount of bytes in pTableArr[x].pTableData, in bytes
- unsigned long long MaxOpenSegments; // Max. number of open files in pSegmentArr
- char *pStatsFilename; // Statistics file
- unsigned long long StatsRefresh; // The time in seconds between update of the stats file
-} t_Aewf;
-
-// ----------------
-// Error handling
-// ----------------
-
-#ifdef AEWF_DEBUG
- #define CHK(ChkVal) \
- { \
- int ChkValRc; \
- if ((ChkValRc=(ChkVal)) != AEWF_OK) \
- { \
- printf ("Err %d in %s, %d\n", ChkValRc, __FILE__, __LINE__); \
- return ChkValRc; \
- } \
- }
- #define DEBUG_PRINTF(pFormat, ...) \
- printf (pFormat, ##__VA_ARGS__);
-#else
- #define CHK(ChkVal) \
- { \
- int ChkValRc; \
- if ((ChkValRc=(ChkVal)) != AEWF_OK) \
- return ChkValRc; \
- }
- #define DEBUG_PRINTF(...)
-#endif
+/*******************************************************************************
+ * Private
+ ******************************************************************************/
// ---------------------------
// Internal static functions
// ---------------------------
static int OpenFile (FILE **ppFile, const char *pFilename)
{
*ppFile = fopen (pFilename, "r");
if (*ppFile == NULL)
return AEWF_FILE_OPEN_FAILED;
return AEWF_OK;
}
static int CloseFile (FILE **ppFile)
{
if (fclose (*ppFile))
return AEWF_FILE_CLOSE_FAILED;
*ppFile = NULL;
return AEWF_OK;
}
-static int ReadFilePos (FILE *pFile, void *pMem, unsigned int Size, unsigned long long Pos)
+static int ReadFilePos (FILE *pFile, void *pMem, unsigned int Size, uint64_t Pos)
{
if (Size == 0)
return AEWF_OK;
if (Pos != ULLONG_MAX)
{
if (fseeko (pFile, Pos, SEEK_SET))
return AEWF_FILE_SEEK_FAILED;
}
if (fread (pMem, Size, 1, pFile) != 1)
return AEWF_FILE_READ_FAILED;
return AEWF_OK;
}
//static int ReadFile (FILE *pFile, void *pMem, unsigned int Size)
//{
// CHK (ReadFilePos (pFile, pMem, Size, ULLONG_MAX))
//
// return AEWF_OK;
//}
-static int ReadFileAllocPos (FILE *pFile, void **ppMem, unsigned int Size, unsigned long long Pos)
+static int ReadFileAllocPos (FILE *pFile, void **ppMem, unsigned int Size, uint64_t Pos)
{
*ppMem = (void*) malloc (Size);
if (*ppMem == NULL)
return AEWF_MEMALLOC_FAILED;
CHK (ReadFilePos (pFile, *ppMem, Size, Pos))
return AEWF_OK;
}
static int ReadFileAlloc (FILE *pFile, void **ppMem, unsigned int Size)
{
CHK (ReadFileAllocPos (pFile, ppMem, Size, ULLONG_MAX))
return AEWF_OK;
}
static int QsortCompareSegments (const void *pA, const void *pB)
{
const t_pSegment pSegmentA = ((const t_pSegment)pA); //lint !e1773 Attempt to cast way const
const t_pSegment pSegmentB = ((const t_pSegment)pB); //lint !e1773 Attempt to cast way const
return (int)pSegmentA->Number - (int)pSegmentB->Number;
}
// ---------------
// API functions
// ---------------
-static int CreateInfoData (t_pAewf pAewf, t_pAewfSectionVolume pVolume, unsigned char *pHeader , unsigned HeaderLen,
- unsigned char *pHeader2, unsigned Header2Len)
+static int CreateInfoData (t_pAewf pAewf, t_pAewfSectionVolume pVolume, char *pHeader , unsigned HeaderLen,
+ char *pHeader2, unsigned Header2Len)
{
char *pInfo1;
char *pInfo2;
char *pInfo3 = NULL;
char *pInfo4;
char *pInfo5;
- unsigned char *pHdr = NULL;
+ char *pHdr = NULL;
unsigned HdrLen= 0;
char *pText = NULL;
char *pCurrent;
char *pDesc = NULL;
char *pData = NULL;
char *pEnd;
uLongf DstLen0;
int zrc;
const int MaxTextSize = 65536;
unsigned UncompressedLen;
- ASPRINTF(&pInfo1, "Image size %llu (%0.2f GiB)\n"
+ ASPRINTF(&pInfo1, "Image size %" PRIu64 " (%0.2f GiB)\n"
"Bytes per sector %u\n"
- "Sector count %llu\n"
+ "Sector count %" PRIu64 "\n"
"Sectors per chunk %u\n"
"Chunk count %u\n"
"Error block size %u\n"
"Compression level %u\n"
"Media type %02X\n"
"Cylinders/Heads/Sectors %u/%u/%u\n"
"Media flags %02X\n"
"Palm volume start sector %u\n"
"Smart logs start sector %u\n",
pAewf->ImageSize, pAewf->ImageSize / (1024.0 * 1024.0* 1024.0),
pVolume->BytesPerSector,
pVolume->SectorCount,
pVolume->SectorsPerChunk,
pVolume->ChunkCount,
pVolume->ErrorBlockSize,
pVolume->CompressionLevel,
pVolume->MediaType,
pVolume->CHS_Cylinders, pVolume->CHS_Heads, pVolume->CHS_Sectors,
pVolume->MediaFlags,
pVolume->PalmVolumeStartSector,
pVolume->SmartLogsStartSector);
ASPRINTF (&pInfo2, "AcquirySystemGUID %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
pVolume->AcquirySystemGUID[ 0], pVolume->AcquirySystemGUID[ 1], pVolume->AcquirySystemGUID[ 2], pVolume->AcquirySystemGUID[ 3],
pVolume->AcquirySystemGUID[ 4], pVolume->AcquirySystemGUID[ 5], pVolume->AcquirySystemGUID[ 6], pVolume->AcquirySystemGUID[ 7],
pVolume->AcquirySystemGUID[ 8], pVolume->AcquirySystemGUID[ 9], pVolume->AcquirySystemGUID[10], pVolume->AcquirySystemGUID[11],
pVolume->AcquirySystemGUID[12], pVolume->AcquirySystemGUID[13], pVolume->AcquirySystemGUID[14], pVolume->AcquirySystemGUID[15]);
if (pHeader2) { pHdr = pHeader2; HdrLen = Header2Len; }
else if (pHeader ) { pHdr = pHeader; HdrLen = HeaderLen; }
// pHdr = pHeader; HdrLen = HeaderLen;
if (pHdr)
{
pText = (char *) malloc (MaxTextSize);
if (pText == NULL)
return AEWF_MEMALLOC_FAILED;
DstLen0 = MaxTextSize;
- zrc = uncompress ((unsigned char *)pText, &DstLen0, pHdr, HdrLen);
+ zrc = uncompress ((unsigned char *)pText, &DstLen0, (const Bytef*)pHdr, HdrLen);
UncompressedLen = DstLen0;
if (zrc != Z_OK)
return AEWF_UNCOMPRESS_HEADER_FAILED;
if (pHeader2) // We must convert from silly Windows 2 byte wchar_t to
{ // correct Unix 4 byte wchar_t, before we can convert to UTF8
wchar_t *pTemp = (wchar_t*) malloc ((UncompressedLen/2)*sizeof(wchar_t));
if (pTemp == NULL)
return AEWF_MEMALLOC_FAILED;
for (unsigned i=0; i<(UncompressedLen/2); i++)
pTemp[i] = (wchar_t) (((unsigned char*)pText)[2*i ]) |
(((wchar_t) (((unsigned char*)pText)[2*i+1])) << 8);
wcstombs(pText, pTemp, UncompressedLen/2);
free (pTemp);
}
// Extract descriptor and data lines
// ---------------------------------
pCurrent = pText; // pText may start with BOM (Header2), but that's no problem as
while (pCurrent) // first line anyway never is the "main" line.
{
if (strcasestr(pCurrent, "main") == pCurrent) // The header line is the one that
break; // follows the line beginning with "main"
pCurrent = strstr (pCurrent, "\n");
if (pCurrent)
pCurrent++;
}
if (pCurrent)
{
pDesc = strstr (pCurrent, "\n");
if (pDesc)
{
*pDesc++ = '\0';
pData = strstr (pDesc, "\n");
if (pData)
{
*pData++ = '\0';
pEnd = strstr (pData, "\n");
if (pEnd)
*pEnd = '\0';
}
}
}
// Scan descriptor and data lines
// ------------------------------
char *pCurDesc = pDesc;
char *pCurData = pData;
const char *pField;
char *pTabDesc;
char *pTabData;
char *pValue;
int wr = 0;
time_t Time;
struct tm *pTM;
char TimeBuff[64];
if (pDesc && pData)
{
pInfo3 = (char *) malloc (strlen (pData) + 4096);
if (pInfo3 == NULL)
return AEWF_MEMALLOC_FAILED;
while (*pCurDesc && *pCurData)
{
pTabDesc = strstr (pCurDesc, "\t");
pTabData = strstr (pCurData, "\t");
if (pTabDesc) *pTabDesc = '\0';
if (pTabData) *pTabData = '\0';
if (strcasecmp(pCurDesc, "a" ) == 0) pField = "Description";
else if (strcasecmp(pCurDesc, "c" ) == 0) pField = "Case";
else if (strcasecmp(pCurDesc, "n" ) == 0) pField = "Evidence";
else if (strcasecmp(pCurDesc, "e" ) == 0) pField = "Examiner";
else if (strcasecmp(pCurDesc, "t" ) == 0) pField = "Notes";
else if (strcasecmp(pCurDesc, "md") == 0) pField = "Model";
else if (strcasecmp(pCurDesc, "sn") == 0) pField = "Serial number";
else if (strcasecmp(pCurDesc, "av") == 0) pField = "Imager version";
else if (strcasecmp(pCurDesc, "ov") == 0) pField = "OS version";
else if (strcasecmp(pCurDesc, "m" ) == 0) pField = "Acquired time";
else if (strcasecmp(pCurDesc, "u" ) == 0) pField = "System time";
else if (strcasecmp(pCurDesc, "p" ) == 0) pField = NULL;
else if (strcasecmp(pCurDesc, "dc") == 0) pField = NULL;
else pField = "--";
if (pField)
{
pValue = pCurData;
if (strstr (pField, "time"))
{
size_t w;
Time = atoll (pCurData);
pTM = localtime (&Time);
pValue = &TimeBuff[0];
w = strftime (pValue, sizeof(TimeBuff), "%Y-%m-%d %H:%M:%S (%z)", pTM);
sprintf (&pValue[w], " (epoch %s)", pCurData);
}
wr += sprintf (&pInfo3[wr], "%-17s %s\n", pField, pValue);
}
if (!pTabDesc || !pTabData)
break;
pCurDesc = pTabDesc+1;
pCurData = pTabData+1;
}
}
}
if (pAewf->Segments == 1)
ASPRINTF (&pInfo4, "%u segment file: %s\n",
pAewf->Segments,
pAewf->pSegmentArr[0].pName)
else ASPRINTF (&pInfo4, "%u segment files\n First: %s\n Last: %s\n",
pAewf->Segments,
pAewf->pSegmentArr[0 ].pName,
pAewf->pSegmentArr[pAewf->Segments-1].pName);
ASPRINTF (&pInfo5, "%u tables\n", pAewf->Tables);
if (pInfo3)
ASPRINTF (&pAewf->pInfo, "%s%s\n%s\n%s%s", pInfo1, pInfo2, pInfo3, pInfo4, pInfo5)
else ASPRINTF (&pAewf->pInfo, "%s%s%s%s" , pInfo1, pInfo2, pInfo4, pInfo5)
free (pInfo1);
free (pInfo2);
free (pInfo4);
free (pInfo5);
if (pText ) free (pText );
if (pInfo3) free (pInfo3);
return AEWF_OK;
}
-int AewfOpen (t_pAewf *ppAewf, unsigned FilenameArrLen, const char **ppFilenameArr)
+/*
+ * AewfOpen
+ */
+int AewfOpen(void **pp_handle,
+ const char **pp_filename_arr,
+ uint64_t filename_arr_len)
{
t_pAewf pAewf;
t_AewfFileHeader FileHeader;
t_AewfSection Section;
FILE *pFile;
t_pSegment pSegment;
t_pTable pTable;
- unsigned long long Pos;
+ uint64_t Pos;
t_pAewfSectionTable pEwfTable = NULL;
t_pAewfSectionVolume pVolume = NULL;
- unsigned char *pHeader = NULL;
- unsigned char *pHeader2 = NULL;
+ char *pHeader = NULL;
+ char *pHeader2 = NULL;
int LastSection;
unsigned int SectionSectorsSize;
unsigned HeaderLen = 0;
unsigned Header2Len = 0;
// Create handle and clear it
// --------------------------
- *ppAewf = NULL;
+ *pp_handle = NULL;
pAewf = (t_pAewf) malloc (sizeof(t_Aewf));
if (pAewf == NULL)
return AEWF_MEMALLOC_FAILED;
memset (pAewf, 0, sizeof(t_Aewf));
pAewf->ChunkInBuff = ULONG_LONG_MAX;
pAewf->pErrorText = NULL;
pAewf->pStatsFilename = NULL;
pAewf->StatsRefresh = 10;
pAewf->SegmentCacheHits = 0;
pAewf->SegmentCacheMisses = 0;
pAewf->TableCacheHits = 0;
pAewf->TableCacheMisses = 0;
pAewf->ChunkCacheHits = 0;
pAewf->ChunkCacheMisses = 0;
pAewf->ReadOperations = 0;
pAewf->DataReadFromImage = 0;
pAewf->DataReadFromImageRaw = 0;
pAewf->DataRequestedByCaller= 0;
pAewf->TablesReadFromImage = 0;
// Create pSegmentArr and put the segment files in it
// --------------------------------------------------
- int SegmentArrLen = FilenameArrLen * sizeof(t_Segment);
+ int SegmentArrLen = filename_arr_len * sizeof(t_Segment);
pAewf->pSegmentArr = (t_pSegment) malloc (SegmentArrLen);
- pAewf->Segments = FilenameArrLen;
+ pAewf->Segments = filename_arr_len;
if (pAewf->pSegmentArr == NULL)
return AEWF_MEMALLOC_FAILED;
memset (pAewf->pSegmentArr, 0, SegmentArrLen);
- for (unsigned i=0; i<FilenameArrLen; i++)
+ for (unsigned i=0; i<filename_arr_len; i++)
{
pSegment = &pAewf->pSegmentArr[i];
- pSegment->pName = canonicalize_file_name (ppFilenameArr[i]); // canonicalize_file_name allocates a buffer
+ pSegment->pName = canonicalize_file_name (pp_filename_arr[i]); // canonicalize_file_name allocates a buffer
CHK (OpenFile (&pFile, pSegment->pName))
CHK (ReadFilePos (pFile, (void*)&FileHeader, sizeof(FileHeader), 0))
-// DEBUG_PRINTF ("Segment %s - %d \n", ppFilenameArr[i], FileHeader.SegmentNumber);
+// DEBUG_PRINTF ("Segment %s - %d \n", pp_filename_arr[i], FileHeader.SegmentNumber);
pSegment->Number = FileHeader.SegmentNumber;
pSegment->LastUsed = 0;
pSegment->pFile = NULL;
CHK (CloseFile (&pFile))
}
// Put segment array into correct sequence and check if segment number are correct
// -------------------------------------------------------------------------------
qsort (pAewf->pSegmentArr, pAewf->Segments, sizeof (t_Segment), &QsortCompareSegments);
for (unsigned i=0; i<pAewf->Segments; i++)
{
if ((i+1) != pAewf->pSegmentArr[i].Number)
return AEWF_INVALID_SEGMENT_NUMBER;
}
// Find all tables in the segment files
// ------------------------------------
pAewf->pTableArr = NULL;
pAewf->Tables = 0;
pAewf->Chunks = 0;
SectionSectorsSize = 0;
DEBUG_PRINTF ("Reading tables\n");
for (unsigned i=0; i<pAewf->Segments; i++)
{
pSegment = &pAewf->pSegmentArr[i];
CHK (OpenFile (&pFile, pSegment->pName))
CHK (ReadFilePos (pFile, &FileHeader, sizeof(FileHeader), 0))
Pos = sizeof (FileHeader);
DEBUG_PRINTF ("Segment %s ", pSegment->pName);
do
{
CHK (ReadFilePos (pFile, &Section, sizeof (t_AewfSection), Pos))
if (strcasecmp ((char *)Section.Type, "sectors") == 0)
{
SectionSectorsSize = Section.Size;
}
else if (strcasecmp ((char *)Section.Type, "table") == 0)
{
if (pVolume == NULL)
return AEWF_VOLUME_MUST_PRECEDE_TABLES;
if (SectionSectorsSize == 0)
return AEWF_SECTORS_MUST_PRECEDE_TABLES;
pAewf->Tables++;
pAewf->pTableArr = (t_pTable) realloc (pAewf->pTableArr, pAewf->Tables * sizeof (t_Table));
CHK (ReadFileAlloc (pFile, (void**) &pEwfTable, sizeof(t_AewfSectionTable))) // No need to read the actual offset table
pTable = &pAewf->pTableArr[pAewf->Tables-1];
pTable->Nr = pAewf->Tables-1;
pTable->pSegment = pSegment;
pTable->Offset = Pos + sizeof (t_AewfSection);
pTable->Size = Section.Size;
pTable->ChunkCount = pEwfTable->ChunkCount;
pTable->LastUsed = 0;
pTable->pEwfTable = NULL;
pTable->ChunkFrom = pAewf->Chunks;
pTable->SectionSectorsSize = SectionSectorsSize;
pAewf->Chunks += pTable->ChunkCount;
pTable->ChunkTo = pAewf->Chunks-1;
DEBUG_PRINTF ("t%d", pTable->ChunkCount)
free (pEwfTable);
pEwfTable = NULL;
SectionSectorsSize = 0;
}
else if ((strcasecmp ((char *)Section.Type, "header") == 0) && (pHeader==NULL))
{
HeaderLen = Section.Size - sizeof(t_AewfSection);
CHK (ReadFileAlloc (pFile, (void**) &pHeader, HeaderLen))
}
else if ((strcasecmp ((char *)Section.Type, "header2") == 0) && (pHeader2==NULL))
{
Header2Len = Section.Size - sizeof(t_AewfSection);
CHK (ReadFileAlloc (pFile, (void**) &pHeader2, Header2Len))
}
else if ((strcasecmp ((char *)Section.Type, "volume") == 0) && (pVolume==NULL))
{
CHK (ReadFileAlloc (pFile, (void**) &pVolume, sizeof(t_AewfSectionVolume)))
pAewf->Sectors = pVolume->SectorCount;
pAewf->SectorSize = pVolume->BytesPerSector;
pAewf->ChunkSize = pVolume->SectorsPerChunk * pVolume->BytesPerSector;
pAewf->ImageSize = pAewf->Sectors * pAewf->SectorSize;
DEBUG_PRINTF ("%lld sectors à %lld bytes", pAewf->Sectors, pAewf->SectorSize)
}
LastSection = (Pos == Section.OffsetNextSection);
Pos = Section.OffsetNextSection;
} while (!LastSection);
DEBUG_PRINTF ("\n");
CHK (CloseFile (&pFile))
}
if (pVolume == NULL)
return AEWF_VOLUME_MISSING;
if (pAewf->Chunks != pVolume->ChunkCount)
return AEWF_WRONG_CHUNK_COUNT;
pAewf->ChunkBuffSize = pAewf->ChunkSize + 4096; // reserve some extra space (for CRC and as compressed data might be slightly larger than uncompressed data with some imagers)
- pAewf->pChunkBuffCompressed = (unsigned char *) malloc (pAewf->ChunkBuffSize);
- pAewf->pChunkBuffUncompressed = (unsigned char *) malloc (pAewf->ChunkBuffSize);
+ pAewf->pChunkBuffCompressed = (char *) malloc (pAewf->ChunkBuffSize);
+ pAewf->pChunkBuffUncompressed = (char *) malloc (pAewf->ChunkBuffSize);
if ((pAewf->pChunkBuffCompressed == NULL) ||
(pAewf->pChunkBuffUncompressed == NULL))
return AEWF_MEMALLOC_FAILED;
pAewf->MaxTableCache = 10*1024*1024;
pAewf->MaxOpenSegments = 10;
pAewf->TableCache = 0;
pAewf->OpenSegments = 0;
- *ppAewf = pAewf;
+ *((t_pAewf**)pp_handle)=(void*)pAewf;
CHK (CreateInfoData (pAewf, pVolume, pHeader, HeaderLen, pHeader2, Header2Len))
free (pVolume);
free (pHeader);
free (pHeader2);
return AEWF_OK;
}
-int AewfInfo (t_pAewf pAewf, const char **ppInfoBuff)
-{
- *ppInfoBuff = pAewf->pInfo;
- return AEWF_OK;
+/*
+ * AewfInfo
+ */
+int AewfGetInfofileContent(void *p_handle, const char **pp_info_buf) {
+ *pp_info_buf=((t_pAewf)p_handle)->pInfo;
+ return AEWF_OK;
}
-int AewfSize (t_pAewf pAewf, unsigned long long *pSize)
-{
- *pSize = pAewf->ImageSize;
- return AEWF_OK;
+/*
+ * AewfSize
+ */
+int AewfSize(void *p_handle, uint64_t *p_size) {
+ *p_size = ((t_pAewf)p_handle)->ImageSize;
+ return AEWF_OK;
}
static int AewfOpenSegment (t_pAewf pAewf, t_pTable pTable)
{
t_pSegment pOldestSegment;
if (pTable->pSegment->pFile != NULL) // is already opened ?
{
pAewf->SegmentCacheHits++;
return AEWF_OK;
}
pAewf->SegmentCacheMisses++;
// Check if another segment file must be closed first
// --------------------------------------------------
while (pAewf->OpenSegments >= pAewf->MaxOpenSegments)
{
pOldestSegment = NULL;
for (unsigned i=0; i<pAewf->Segments; i++)
{
if (pAewf->pSegmentArr[i].pFile == NULL)
continue;
if (pOldestSegment == NULL)
{
pOldestSegment = &pAewf->pSegmentArr[i];
}
else
{
if (pAewf->pSegmentArr[i].LastUsed < pOldestSegment->LastUsed)
pOldestSegment = &pAewf->pSegmentArr[i];
}
}
if (pOldestSegment == NULL)
break;
DEBUG_PRINTF ("Closing %s\n", pOldestSegment->pName);
CHK (CloseFile (&pOldestSegment->pFile))
pAewf->OpenSegments--;
}
// Read the desired table into RAM
// -------------------------------
DEBUG_PRINTF ("Opening %s\n", pTable->pSegment->pName);
CHK (OpenFile(&pTable->pSegment->pFile, pTable->pSegment->pName))
pAewf->OpenSegments++;
return AEWF_OK;
}
static int AewfLoadEwfTable (t_pAewf pAewf, t_pTable pTable)
{
t_pTable pOldestTable = NULL;
if (pTable->pEwfTable != NULL) // is already loaded?
{
pAewf->TableCacheHits++;
return AEWF_OK;
}
pAewf->TableCacheMisses++;
// Check if another pEwfTable must be given up first
// -------------------------------------------------
while ((pAewf->TableCache + pTable->Size) > pAewf->MaxTableCache)
{
pOldestTable = NULL;
for (unsigned i=0; i<pAewf->Tables; i++)
{
if (pAewf->pTableArr[i].pEwfTable == NULL)
continue;
if (pOldestTable == NULL)
{
pOldestTable = &pAewf->pTableArr[i];
}
else
{
if (pAewf->pTableArr[i].LastUsed < pOldestTable->LastUsed)
pOldestTable = &pAewf->pTableArr[i];
}
}
if (pOldestTable == NULL)
break;
pAewf->TableCache -= pOldestTable->Size;
free (pOldestTable->pEwfTable);
pOldestTable->pEwfTable = NULL;
- DEBUG_PRINTF ("Releasing table %llu (%lu bytes)\n", pOldestTable->Nr, pOldestTable->Size);
+ DEBUG_PRINTF ("Releasing table %" PRIu64 " (%lu bytes)\n", pOldestTable->Nr, pOldestTable->Size);
}
// Read the desired table into RAM
// -------------------------------
- DEBUG_PRINTF ("Loading table %llu (%lu bytes)\n", pTable->Nr, pTable->Size);
+ DEBUG_PRINTF ("Loading table %" PRIu64 " (%lu bytes)\n", pTable->Nr, pTable->Size);
CHK (AewfOpenSegment (pAewf, pTable));
CHK (ReadFileAllocPos (pTable->pSegment->pFile, (void**) &pTable->pEwfTable, pTable->Size, pTable->Offset))
pAewf->TableCache += pTable->Size;
pAewf->TablesReadFromImage = pTable->Size;
return AEWF_OK;
}
// AewfReadChunk0 reads one chunk. It expects that the EWF table is present
// in memory and the required segment file is opened.
-static int AewfReadChunk0 (t_pAewf pAewf, t_pTable pTable, unsigned long long AbsoluteChunk, unsigned TableChunk)
+static int AewfReadChunk0 (t_pAewf pAewf, t_pTable pTable, uint64_t AbsoluteChunk, unsigned TableChunk)
{
int Compressed;
- unsigned long long SeekPos;
+ uint64_t SeekPos;
t_pAewfSectionTable pEwfTable;
unsigned int Offset;
unsigned int ReadLen;
uLongf DstLen0;
int zrc;
uint CalcCRC;
uint *pStoredCRC;
- unsigned long long ChunkSize;
+ uint64_t ChunkSize;
pEwfTable = pTable->pEwfTable;
if (pEwfTable == NULL)
return AEWF_ERROR_EWF_TABLE_NOT_READY;
if (pTable->pSegment->pFile == NULL)
return AEWF_ERROR_EWF_SEGMENT_NOT_READY;
Compressed = pEwfTable->OffsetArray[TableChunk] & AEWF_COMPRESSED;
Offset = pEwfTable->OffsetArray[TableChunk] & ~AEWF_COMPRESSED;
SeekPos = pEwfTable->TableBaseOffset + Offset;
if (TableChunk < (pEwfTable->ChunkCount-1))
ReadLen = (pEwfTable->OffsetArray[TableChunk+1] & ~AEWF_COMPRESSED) - Offset;
else ReadLen = (pTable->SectionSectorsSize - sizeof(t_AewfSection)) - (Offset - (pEwfTable->OffsetArray[0] & ~AEWF_COMPRESSED));
// else ReadLen = pAewf->ChunkBuffSize; // This also works! It looks as if uncompress is able to find out by itself the real size of the input data.
if (ReadLen > pAewf->ChunkBuffSize)
return AEWF_CHUNK_TOO_BIG;
if (Compressed)
{
CHK (ReadFilePos (pTable->pSegment->pFile, pAewf->pChunkBuffCompressed, ReadLen, SeekPos))
DstLen0 = pAewf->ChunkBuffSize;
- zrc = uncompress (pAewf->pChunkBuffUncompressed, &DstLen0, pAewf->pChunkBuffCompressed, ReadLen);
+ zrc = uncompress ((unsigned char*)pAewf->pChunkBuffUncompressed, &DstLen0, (const Bytef*)pAewf->pChunkBuffCompressed, ReadLen);
if (zrc != Z_OK)
return AEWF_UNCOMPRESS_FAILED;
else if (DstLen0 != pAewf->ChunkSize)
return AEWF_BAD_UNCOMPRESSED_LENGTH;
ChunkSize = DstLen0;
}
else
{
ChunkSize = pAewf->ChunkSize;
if (AbsoluteChunk == (pAewf->Chunks-1))
{
ChunkSize = pAewf->ImageSize % pAewf->ChunkSize;
if (ChunkSize == 0)
ChunkSize = pAewf->ChunkSize;
- printf ("Last chunk size %llu\n", ChunkSize);
+ printf ("Last chunk size %" PRIu64 "\n", ChunkSize);
printf ("ReadLen %u\n", ReadLen);
}
CHK (ReadFilePos (pTable->pSegment->pFile, pAewf->pChunkBuffUncompressed, ReadLen, SeekPos))
CalcCRC = adler32 (1, (const Bytef *) pAewf->pChunkBuffUncompressed, ChunkSize);
pStoredCRC = (uint *) (pAewf->pChunkBuffUncompressed + ChunkSize);
if (CalcCRC != *pStoredCRC)
return AEWF_CHUNK_CRC_ERROR;
}
pAewf->ChunkInBuff = AbsoluteChunk;
pAewf->ChunkBuffUncompressedDataLen = ChunkSize;
pAewf->DataReadFromImage += ReadLen;
pAewf->DataReadFromImageRaw += ChunkSize;
return AEWF_OK;
}
-static int AewfReadChunk (t_pAewf pAewf, unsigned long long AbsoluteChunk, unsigned char **ppBuffer, unsigned int *pLen)
+static int AewfReadChunk (t_pAewf pAewf, uint64_t AbsoluteChunk, char **ppBuffer, unsigned int *pLen)
{
t_pTable pTable;
int Found=FALSE;
unsigned TableChunk;
unsigned TableNr;
*ppBuffer = pAewf->pChunkBuffUncompressed;
if (pAewf->ChunkInBuff == AbsoluteChunk)
{
*pLen = pAewf->ChunkBuffUncompressedDataLen;
pAewf->ChunkCacheHits++;
return AEWF_OK;
}
pAewf->ChunkCacheMisses++;
// Find table containing desired chunk
// -----------------------------------
for (TableNr=0; TableNr<pAewf->Tables; TableNr++)
{
pTable = &pAewf->pTableArr[TableNr];
Found = (AbsoluteChunk >= pTable->ChunkFrom) &&
(AbsoluteChunk <= pTable->ChunkTo);
if (Found)
break;
}
if (!Found)
return AEWF_CHUNK_NOT_FOUND;
// Load corresponding table and get chunk
// --------------------------------------
pTable->LastUsed = time(NULL); // Update LastUsed here, in order not to
pTable->pSegment->LastUsed = pTable->LastUsed; // remove the required data from cache
CHK (AewfLoadEwfTable (pAewf, pTable))
CHK (AewfOpenSegment (pAewf, pTable));
if ((AbsoluteChunk - pTable->ChunkFrom) > ULONG_MAX)
return AEWF_ERROR_IN_CHUNK_NUMBER;
TableChunk = AbsoluteChunk - pTable->ChunkFrom;
-// DEBUG_PRINTF ("table %d / entry %llu (%s)\n", TableNr, TableChunk, pTable->pSegment->pName)
+// DEBUG_PRINTF ("table %d / entry %" PRIu64 " (%s)\n", TableNr, TableChunk, pTable->pSegment->pName)
CHK (AewfReadChunk0 (pAewf, pTable, AbsoluteChunk, TableChunk))
*pLen = pAewf->ChunkBuffUncompressedDataLen;
return AEWF_OK;
}
static int UpdateStats (t_pAewf pAewf, int Force)
{
time_t NowT;
pid_t pid;
FILE *pFile;
char *pFilename = NULL;
char *pCurrentWorkDir = NULL;
time (&NowT);
if (pAewf->pStatsFilename)
{
if (((NowT - pAewf->LastStatsUpdate) >= (int)pAewf->StatsRefresh) || Force)
{
pAewf->LastStatsUpdate = NowT;
pid = getpid ();
ASPRINTF (&pFilename, "%s_%d", pAewf->pStatsFilename, pid)
pFile = fopen (pFilename, "w");
if (pFile == NULL) // May be the file is locked by someone else, let's retry in 1 second
{
pAewf->LastStatsUpdate = NowT - pAewf->StatsRefresh + 1;
return AEWF_OK;
}
fprintf (pFile, "Cache hits misses ratio\n");
fprintf (pFile, "-------------------------------------\n");
- fprintf (pFile, "Segment %10llu %10llu %5.1f%%\n", pAewf->SegmentCacheHits, pAewf->SegmentCacheMisses, (100.0*pAewf->SegmentCacheHits)/(pAewf->SegmentCacheHits+pAewf->SegmentCacheMisses));
- fprintf (pFile, "Table %10llu %10llu %5.1f%%\n", pAewf->TableCacheHits , pAewf->TableCacheMisses , (100.0*pAewf->TableCacheHits) /(pAewf->TableCacheHits +pAewf->TableCacheMisses ));
- fprintf (pFile, "Chunk %10llu %10llu %5.1f%%\n", pAewf->ChunkCacheHits , pAewf->ChunkCacheMisses , (100.0*pAewf->ChunkCacheHits) /(pAewf->ChunkCacheHits +pAewf->ChunkCacheMisses ));
+ fprintf (pFile, "Segment %10" PRIu64 " %10" PRIu64 " %5.1f%%\n", pAewf->SegmentCacheHits, pAewf->SegmentCacheMisses, (100.0*pAewf->SegmentCacheHits)/(pAewf->SegmentCacheHits+pAewf->SegmentCacheMisses));
+ fprintf (pFile, "Table %10" PRIu64 " %10" PRIu64 " %5.1f%%\n", pAewf->TableCacheHits , pAewf->TableCacheMisses , (100.0*pAewf->TableCacheHits) /(pAewf->TableCacheHits +pAewf->TableCacheMisses ));
+ fprintf (pFile, "Chunk %10" PRIu64 " %10" PRIu64 " %5.1f%%\n", pAewf->ChunkCacheHits , pAewf->ChunkCacheMisses , (100.0*pAewf->ChunkCacheHits) /(pAewf->ChunkCacheHits +pAewf->ChunkCacheMisses ));
fprintf (pFile, "\n");
- fprintf (pFile, "Read operations %10llu\n", pAewf->ReadOperations);
+ fprintf (pFile, "Read operations %10" PRIu64 "\n", pAewf->ReadOperations);
fprintf (pFile, "Data read from image %10.1f MiB (compressed)\n", pAewf->DataReadFromImage / (1024.0*1024.0));
fprintf (pFile, "Data read from image %10.1f MiB (raw)\n" , pAewf->DataReadFromImageRaw / (1024.0*1024.0));
fprintf (pFile, "Data requested by caller %10.1f MiB\n" , pAewf->DataRequestedByCaller/ (1024.0*1024.0));
fprintf (pFile, "Tables read from image %10.1f MiB\n" , pAewf->TablesReadFromImage / (1024.0*1024.0));
pCurrentWorkDir = getcwd (NULL, 0);
if (pCurrentWorkDir == NULL)
return AEWF_MEMALLOC_FAILED;
fprintf (pFile, "\nCurrent working directory: %s\n", pCurrentWorkDir);
free (pCurrentWorkDir);
(void) fclose (pFile);
free (pFilename);
return AEWF_OK;
}
}
return AEWF_OK;
}
-int AewfRead (t_pAewf pAewf, unsigned long long Seek, unsigned char *pBuffer, unsigned int Count)
+/*
+ * AewfRead
+ */
+int AewfRead(void *p_handle,
+ uint64_t seek,
+ char *p_buf,
+ uint32_t count)
{
- unsigned long long Chunk;
- unsigned char *pChunkBuffer;
- unsigned int ChunkLen;
- unsigned int Ofs;
- unsigned int ToCopy;
-
- pAewf->ReadOperations++;
- pAewf->DataRequestedByCaller += Count;
-
- if ((Seek+Count) > pAewf->ImageSize)
- return AEWF_READ_BEYOND_IMAGE_LENGTH;
-
- Chunk = Seek / pAewf->ChunkSize;
- Ofs = Seek % pAewf->ChunkSize;
-
- while (Count)
- {
-// DEBUG_PRINTF ("Reading chunk %llu -> ", Chunk)
- CHK (AewfReadChunk (pAewf, Chunk, &pChunkBuffer, &ChunkLen))
- ToCopy = GETMIN (ChunkLen-Ofs, Count);
- memcpy (pBuffer, pChunkBuffer+Ofs, ToCopy);
- Count -= ToCopy;
- pBuffer += ToCopy;
- Ofs = 0;
- Chunk++;
- }
- CHK(UpdateStats(pAewf, FALSE))
-
- return AEWF_OK;
+ uint64_t chunk;
+ char *p_chunk_buffer;
+ unsigned int chunk_len, ofs, to_copy;
+
+ ((t_pAewf)p_handle)->ReadOperations++;
+ ((t_pAewf)p_handle)->DataRequestedByCaller+=count;
+
+ if((seek+count)>((t_pAewf)p_handle)->ImageSize) {
+ return AEWF_READ_BEYOND_IMAGE_LENGTH;
+ }
+
+ chunk=seek/((t_pAewf)p_handle)->ChunkSize;
+ ofs=seek%((t_pAewf)p_handle)->ChunkSize;
+
+ while(count) {
+ CHK(AewfReadChunk((t_pAewf)p_handle,chunk,&p_chunk_buffer,&chunk_len))
+ to_copy=GETMIN(chunk_len-ofs,count);
+ memcpy(p_buf,p_chunk_buffer+ofs,to_copy);
+ count-=to_copy;
+ p_buf+=to_copy;
+ ofs=0;
+ chunk++;
+ }
+ CHK(UpdateStats((t_pAewf)p_handle,FALSE))
+
+ return AEWF_OK;
}
-int AewfClose (t_pAewf *ppAewf)
-{
- t_pTable pTable;
- t_pSegment pSegment;
- t_pAewf pAewf = *ppAewf;
-
- CHK (UpdateStats (pAewf, TRUE))
-
- for (unsigned i=0; i<pAewf->Tables; i++)
- {
- pTable = &pAewf->pTableArr[i];
- if (pTable->pEwfTable)
- free (pTable->pEwfTable);
- }
-
- for (unsigned i=0; i<pAewf->Segments; i++)
- {
- pSegment = &pAewf->pSegmentArr[i];
- if (pSegment->pFile)
- CloseFile(&pSegment->pFile);
- free (pSegment->pName);
- }
-
- free (pAewf->pTableArr);
- free (pAewf->pSegmentArr);
- free (pAewf->pChunkBuffCompressed );
- free (pAewf->pChunkBuffUncompressed);
- if (pAewf->pStatsFilename)
- free (pAewf->pStatsFilename);
- memset (pAewf, 0, sizeof(t_Aewf));
- free (pAewf);
- *ppAewf = NULL;
-
- return AEWF_OK;
+/*
+ * AewfClose
+ */
+int AewfClose(void **pp_handle) {
+ t_pTable p_table;
+ t_pSegment p_segment;
+ t_pAewf p_aewf=*((t_pAewf*)pp_handle);
+
+ CHK(UpdateStats(p_aewf,TRUE))
+
+ for(unsigned i=0;i<p_aewf->Tables;i++) {
+ p_table=&p_aewf->pTableArr[i];
+ if(p_table->pEwfTable) free(p_table->pEwfTable);
+ }
+
+ for(unsigned i=0;i<p_aewf->Segments;i++) {
+ p_segment=&p_aewf->pSegmentArr[i];
+ if(p_segment->pFile) CloseFile(&pSegment->pFile);
+ free(p_segment->pName);
+ }
+
+ free(p_aewf->pTableArr);
+ free(p_aewf->pSegmentArr);
+ free(p_aewf->pChunkBuffCompressed);
+ free(p_aewf->pChunkBuffUncompressed);
+ if(p_aewf->pStatsFilename) free(p_aewf->pStatsFilename);
+ memset(p_aewf,0,sizeof(t_Aewf));
+ free(p_aewf);
+ *pp_handle=NULL;
+
+ return AEWF_OK;
}
// Option handling
// ---------------
static const char *pOptionPrefix = "aewf_";
static const char OptionSeparator = ',';
static int SetError (t_pAewf pAewf, char **ppError, const char *pFormat, ...)
{
va_list VaList;
if (pAewf->pErrorText)
free (pAewf->pErrorText);
va_start(VaList, pFormat);
if (vasprintf (&pAewf->pErrorText, pFormat, VaList) < 0)
return AEWF_VASPRINTF_FAILED;
va_end(VaList);
*ppError = pAewf->pErrorText;
return AEWF_OK;
}
static int CheckOption (const char *pOption, int OptionLen, const char *pOptionName, const char **ppValue, int *pValueLen)
{
int Found;
*ppValue = NULL;
*pValueLen = 0;
Found = (strcasestr (pOption, pOptionName) == pOption);
if (Found)
{
*ppValue = pOption + strlen (pOptionName);
*pValueLen = OptionLen - strlen (pOptionName);
}
return Found;
}
static int ValueToInt (t_pAewf pAewf, const char *pValue, int ValueLen, char **ppError)
{
char *pTail;
int Value;
*ppError = NULL;
Value = strtoll (pValue, &pTail, 10);
if (pTail != (pValue + ValueLen))
CHK (SetError(pAewf, ppError, "Invalid option value %s", pValue))
return Value;
}
static char *ValueToStr (t_pAewf pAewf, const char *pValue, int ValueLen, char **ppError)
{
*ppError = NULL;
return strndup (pValue, ValueLen);
}
static int ReadOption (t_pAewf pAewf, char *pOption, int OptionLen, char **ppError)
{
const char *pValue;
int ValueLen;
*ppError = NULL;
if (CheckOption (pOption, OptionLen, "maxfiles=", &pValue, &ValueLen)) pAewf->MaxOpenSegments = ValueToInt (pAewf, pValue, ValueLen, ppError);
else if (CheckOption (pOption, OptionLen, "maxmem=" , &pValue, &ValueLen)) pAewf->MaxTableCache = ValueToInt (pAewf, pValue, ValueLen, ppError)*1024*1024;
else if (CheckOption (pOption, OptionLen, "stats=" , &pValue, &ValueLen)) pAewf->pStatsFilename = ValueToStr (pAewf, pValue, ValueLen, ppError);
else if (CheckOption (pOption, OptionLen, "refresh=" , &pValue, &ValueLen)) pAewf->StatsRefresh = ValueToInt (pAewf, pValue, ValueLen, ppError);
else CHK (SetError(pAewf, ppError, "Unknown option %s%s", pOptionPrefix, pOption))
return AEWF_OK;
}
-int AewfOptions(t_pAewf pAewf, char *pOptions, char **ppError)
-{
+/*
+ * AewfOptionsParse
+ */
+int AewfOptionsParse(void *p_handle, char *p_options, char **pp_error) {
char *pCurrent;
char *pOption;
char *pSep;
int Found;
- pCurrent = pOptions;
+ pCurrent = p_options;
while (*pCurrent)
{
pSep = strchr (pCurrent, OptionSeparator);
if (pSep == NULL)
pSep = pCurrent + strlen(pCurrent);
Found = FALSE;
if ((pSep - pCurrent) >= (int)strlen(pOptionPrefix)) // Check for options starting with our prefix
{
Found = (strncasecmp (pCurrent, pOptionPrefix, strlen(pOptionPrefix)) == 0);
if (Found)
{
pOption = pCurrent + strlen(pOptionPrefix);
- CHK (ReadOption (pAewf, pOption, pSep-pOption, ppError))
- if (*ppError)
+ CHK (ReadOption ((t_pAewf)p_handle, pOption, pSep-pOption, pp_error))
+ if (*pp_error)
break;
memmove (pCurrent, pSep+1, strlen(pSep)+1);
}
}
if (!Found)
{
if (*pSep)
pCurrent = pSep+1;
else pCurrent = pSep;
}
}
- if (pOptions[strlen(pOptions)-1] == OptionSeparator) // Remove trailing separator if there is one
- pOptions[strlen(pOptions)-1] = '\0';
+ if (p_options[strlen(p_options)-1] == OptionSeparator) // Remove trailing separator if there is one
+ p_options[strlen(p_options)-1] = '\0';
- DEBUG_PRINTF ("Max open segment files %llu\n" , pAewf->MaxOpenSegments)
- DEBUG_PRINTF ("Max table cache %llu bytes (%0.1f MiB)\n", pAewf->MaxTableCache, pAewf->MaxTableCache / (1024.0*1024.0))
- DEBUG_PRINTF ("Stats file %s\n" , pAewf->pStatsFilename ? pAewf->pStatsFilename : "-none-")
- DEBUG_PRINTF ("Stats refresh %llus\n" , pAewf->StatsRefresh);
+ DEBUG_PRINTF ("Max open segment files %" PRIu64 "\n" , ((t_pAewf)p_handle)->MaxOpenSegments)
+ DEBUG_PRINTF ("Max table cache %" PRIu64 " bytes (%0.1f MiB)\n", ((t_pAewf)p_handle)->MaxTableCache, ((t_pAewf)p_handle)->MaxTableCache / (1024.0*1024.0))
+ DEBUG_PRINTF ("Stats file %s\n" , ((t_pAewf)p_handle)->pStatsFilename ? ((t_pAewf)p_handle)->pStatsFilename : "-none-")
+ DEBUG_PRINTF ("Stats refresh %" PRIu64 "s\n" , ((t_pAewf)p_handle)->StatsRefresh);
DEBUG_PRINTF ("Unused options %s\n" , pOptions);
return AEWF_OK;
}
-int AewfOptionHelp (const char **ppHelp)
-{
- *ppHelp = " aewf_maxmem The maximum amount of memory (in MiB) used for caching image offset\n"
+int AewfOptionsHelp(const char **pp_help) {
+ *pp_help = " aewf_maxmem The maximum amount of memory (in MiB) used for caching image offset\n"
" tables.\n"
" aewf_maxfiles The maximum number of image segment files opened at the same time.\n"
" aewf_stats A filename that will be used for outputting statistical data at\n"
" regular intervals. The process id is automatically appended to the\n"
" given filename.\n"
" aewf_refresh The update interval, in seconds, for the statistical data output.\n"
" Ignored if aewf_stats is not set. The default value is 10.\n"
" Example: aewf_maxmem=64,aewf_stats=mystats,aewf_refresh=2"
;
- return AEWF_OK;
+ return AEWF_OK;
+}
+
+void AewfFreeBuffer(void *p_buf) {
+ free(p_buf);
}
// -----------------------------------------------------
// Small main routine for testing
// It converts an EWF file into dd
// -----------------------------------------------------
#ifdef AEWF_MAIN_FOR_TESTING
int main(int argc, const char *argv[])
{
t_pAewf pAewf;
- unsigned long long TotalSize;
- unsigned long long Remaining;
- unsigned long long Read;
- unsigned long long Pos;
+ uint64_t TotalSize;
+ uint64_t Remaining;
+ uint64_t Read;
+ uint64_t Pos;
unsigned int BuffSize = 13*65536; // A multiple of chunk size for good performance
- unsigned char Buff[BuffSize];
+ char Buff[BuffSize];
FILE *pFile;
int Percent;
int PercentOld;
int rc;
char *pOptions = NULL;
char *pError = NULL;
const char *pHelp;
const char *pInfoBuff;
#ifdef CREATE_REVERSE_FILE
FILE *pFileRev;
- unsigned long long PosRev;
+ uint64_t PosRev;
#ifdef REVERSE_FILE_USES_SEPARATE_HANDLE
t_pAewf pAewfRev;
#else
#define pAewfRev pAewf
#endif
#endif
setbuf(stdout, NULL);
setbuf(stderr, NULL);
setlocale (LC_ALL, "");
#define PRINT_ERROR_AND_EXIT(...) \
{ \
printf (__VA_ARGS__); \
exit (1); \
}
printf ("EWF to DD converter - result file is named dd\n");
printf (" Result file is named dd");
#ifdef CREATE_REVERSE_FILE
printf ("; Also creates a backwards read file named rev");
#ifdef REVERSE_FILE_USES_SEPARATE_HANDLE
printf ("; Uses separate AEWF handle for reverse file");
#else
printf ("; Uses the same AEWF handle for reverse file");
#endif
#endif
printf ("\n");
if (argc < 2)
{
(void) AewfOptionHelp (&pHelp);
printf ("Usage: %s <EWF segment file 1> <EWF segment file 2> <...> [-comma_separated_options]\n", argv[0]);
printf ("Possible options:\n%s\n", pHelp);
printf ("The output file will be named dd.\n");
exit (1);
}
if (argv[argc-1][0] == '-')
{
pOptions = strdup (&(argv[argc-1][1]));
argc--;
}
rc = AewfOpen (&pAewf, argc-1, &argv[1]);
if (rc != AEWF_OK)
PRINT_ERROR_AND_EXIT ("Cannot open EWF files, rc=%d\n", rc)
if (pOptions)
CHK (AewfOptions(pAewf, pOptions, &pError))
if (pError)
PRINT_ERROR_AND_EXIT ("Error while setting options: %s", pError);
#if defined(CREATE_REVERSE_FILE) && defined(REVERSE_FILE_USES_SEPARATE_HANDLE)
rc = AewfOpen (&pAewfRev, argc-1, &argv[1]);
if (rc != AEWF_OK)
PRINT_ERROR_AND_EXIT ("Cannot open EWF files, rc=%d\n", rc)
if (pOptions)
CHK (AewfOptions(pAewfRev, pOptions, &pError))
if (pError)
PRINT_ERROR_AND_EXIT ("Error while setting options: %s", pError);
#endif
CHK (AewfInfo (pAewf, &pInfoBuff))
if (pInfoBuff)
printf ("Contents of info buffer:\n%s\n", pInfoBuff);
CHK (AewfSize (pAewf, &TotalSize))
- printf ("Total size: %llu bytes\n", TotalSize);
+ printf ("Total size: %" PRIu64 " bytes\n", TotalSize);
Remaining = TotalSize;
pFile = fopen ("dd", "w");
if (pFile == NULL)
PRINT_ERROR_AND_EXIT("Cannot open destination file\n");
#ifdef CREATE_REVERSE_FILE
pFileRev = fopen ("rev", "w");
if (pFileRev == NULL)
PRINT_ERROR_AND_EXIT("Cannot open reverse destination file\n");
PosRev = TotalSize;
#endif
Remaining = TotalSize;
Pos = 0;
PercentOld = -1;
while (Remaining)
{
-// DEBUG_PRINTF ("Pos %llu -- Remaining %llu ", Pos, Remaining);
+// DEBUG_PRINTF ("Pos %" PRIu64 " -- Remaining %" PRIu64 " ", Pos, Remaining);
Read = GETMIN (Remaining, BuffSize);
rc = AewfRead (pAewf, Pos, &Buff[0], Read);
if (rc != AEWF_OK)
PRINT_ERROR_AND_EXIT("Error %d while calling AewfRead\n", rc);
if (fwrite (Buff, Read, 1, pFile) != 1)
PRINT_ERROR_AND_EXIT("Could not write to destination file\n");
Remaining -= Read;
Pos += Read;
#ifdef CREATE_REVERSE_FILE
PosRev -= Read;
rc = AewfRead (pAewf, PosRev, &Buff[0], Read);
if (rc != AEWF_OK)
PRINT_ERROR_AND_EXIT("Error %d while reverse calling AewfRead\n", rc);
if (fseeko (pFileRev, PosRev, SEEK_SET))
return AEWF_FILE_SEEK_FAILED;
if (fwrite (Buff, Read, 1, pFileRev) != 1)
PRINT_ERROR_AND_EXIT("Could not write to reverse destination file\n");
#endif
Percent = (100*Pos) / TotalSize;
if (Percent != PercentOld)
{
printf ("\r%d%% done...", Percent);
PercentOld = Percent;
}
}
if (AewfClose (&pAewf))
PRINT_ERROR_AND_EXIT("Error while closing EWF files\n");
if (fclose (pFile))
PRINT_ERROR_AND_EXIT ("Error while closing destination file\n");
#ifdef CREATE_REVERSE_FILE
#ifdef REVERSE_FILE_USES_SEPARATE_HANDLE
if (AewfClose (&pAewfRev))
PRINT_ERROR_AND_EXIT("Error while closing reverse EWF files\n");
#endif
if (fclose (pFileRev))
PRINT_ERROR_AND_EXIT ("Error while closing reverse destination file\n");
#endif
printf ("\n");
return 0;
}
#endif
+
diff --git a/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.h b/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.h
index 7ab7065..5731684 100644
--- a/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.h
+++ b/trunk/libxmount_input/libxmount_input_aewf/libxmount_input_aewf.h
@@ -1,71 +1,256 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This module has been written by Guy Voncken. It contains the functions for *
* accessing EWF images created by Guymager and others. *
* *
* xmount is a small tool to "fuse mount" various harddisk image formats as dd, *
* vdi, vhd or vmdk files and enable virtual write access to them. *
* *
* 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 AEWF_H
#define AEWF_H
typedef struct _t_Aewf *t_pAewf;
-int AewfOptionHelp (const char **pHelp);
-int AewfOpen (t_pAewf *ppAewf, unsigned FilenameArrLen, const char **ppFilenameArr);
-int AewfOptions (t_pAewf pAewf, char *pOptions, char **pError);
-int AewfInfo (t_pAewf pAewf, const char **ppInfoBuff);
-int AewfSize (t_pAewf pAewf, unsigned long long *pSize);
-int AewfRead (t_pAewf pAewf, unsigned long long Seek, unsigned char *pBuffer, unsigned int Count);
-int AewfClose (t_pAewf *ppAewf);
+// ----------------------
+// Constant definitions
+// ----------------------
+
+#define GETMAX(a,b) ((a)>(b)?(a):(b))
+#define GETMIN(a,b) ((a)<(b)?(a):(b))
+
+#define FALSE 0
+#define TRUE 1
+
+
+#define ASPRINTF(...) \
+{ \
+ if (asprintf(__VA_ARGS__) < 0) \
+ return AEWF_ASPRINTF_FAILED; \
+}
+
+// ---------------------
+// Types and strutures
+// ---------------------
+
+typedef struct
+{
+ unsigned char Signature[8];
+ unsigned char StartOfFields; // 0x01;
+ unsigned short int SegmentNumber;
+ unsigned short int EndOfFields; // 0x0000
+} __attribute__ ((packed)) t_AewfFileHeader, *t_AewfpFileHeader;
+
+typedef struct
+{
+ unsigned char Type[16];
+ uint64_t OffsetNextSection;
+ uint64_t Size;
+ unsigned char Padding[40];
+ unsigned int Checksum;
+ char Data[]; //lint !e1501 data member has zero size
+} __attribute__ ((packed)) t_AewfSection, *t_pAewfSection;
+
+typedef struct
+{
+ unsigned char MediaType;
+ unsigned char Unknown1[3]; // contains 0x00
+ unsigned int ChunkCount;
+ unsigned int SectorsPerChunk;
+ unsigned int BytesPerSector;
+ uint64_t SectorCount;
+ unsigned int CHS_Cylinders;
+ unsigned int CHS_Heads;
+ unsigned int CHS_Sectors;
+ unsigned char MediaFlags;
+ unsigned char Unknown2[3]; // contains 0x00
+ unsigned int PalmVolumeStartSector;
+ unsigned char Padding1[4]; // contains 0x00
+ unsigned int SmartLogsStartSector;
+ unsigned char CompressionLevel;
+ unsigned char Unknown3[3]; // contains 0x00
+ unsigned int ErrorBlockSize;
+ unsigned char Unknown4[4];
+ unsigned char AcquirySystemGUID[16];
+ unsigned char Padding2[963];
+ unsigned char Reserved [5];
+ unsigned int Checksum;
+} __attribute__ ((packed)) t_AewfSectionVolume, *t_pAewfSectionVolume;
+
+typedef struct
+{
+ unsigned int ChunkCount;
+ unsigned char Padding1 [4];
+ uint64_t TableBaseOffset;
+ unsigned char Padding2 [4];
+ unsigned int Checksum;
+ unsigned int OffsetArray[]; //lint !e1501 data member has zero size
+} __attribute__ ((packed)) t_AewfSectionTable, *t_pAewfSectionTable;
+
+const unsigned int AEWF_COMPRESSED = 0x80000000;
+
+typedef struct
+{
+ unsigned int FirstSector;
+ unsigned int NumberOfSectors;
+} __attribute__ ((packed)) t_AewfSectionErrorEntry, *t_pAewfSectionErrorEntry;
+
+typedef struct
+{
+ unsigned int NumberOfErrors;
+ unsigned char Padding[512];
+ unsigned int Checksum;
+ t_AewfSectionErrorEntry ErrorArr[0]; //lint !e1501 data member has zero size
+ unsigned int ChecksumArr;
+} __attribute__ ((packed)) t_AewfSectionError, *t_pAewfSectionError;
+
+typedef struct
+{
+ unsigned char MD5[16];
+ unsigned char Unknown[16];
+ unsigned int Checksum;
+} __attribute__ ((packed)) t_AewfSectionHash, *t_pAewfSectionHash;
+
+
+typedef struct
+{
+ char *pName;
+ unsigned Number;
+ FILE *pFile; // NULL if file is not opened (never read or kicked out form cache)
+ time_t LastUsed;
+} t_Segment, *t_pSegment;
+
+typedef struct
+{
+ uint64_t Nr; // The table's position in the pAewf->pTableArr, for debug output only
+ uint64_t ChunkFrom; // Number of the chunk referred to by the first entry of this table (very first chunk has number 0)
+ uint64_t ChunkTo; // Number of the chunk referred to by the last entry of this table
+ t_pSegment pSegment; // The file segment where the table is located
+ uint64_t Offset; // The offset of the table inside the segment file (start of t_AewfSectionTable, not of the preceding t_AewfSection)
+ unsigned long Size; // The length of the table (same as allocated length for pEwfTable)
+ unsigned int ChunkCount; // The number of chunk; this is the same as pTableData->Chunkcount, however, pTableData might not be available (NULL)
+ unsigned int SectionSectorsSize; // Silly EWF format has no clean way of knowing size of the last (possibly compressed) chunk of a table
+ time_t LastUsed; // Last usage of this table, for cache management
+ t_pAewfSectionTable pEwfTable; // Contains the original EWF table section or NULL, if never read or kicked out from cache
+} t_Table, *t_pTable;
+
+typedef struct _t_Aewf
+{
+ t_pSegment pSegmentArr; // Array of all segment files (in correct order)
+ t_pTable pTableArr; // Array of all chunk offset tables found in the segment files (in correct order)
+ unsigned Segments;
+ unsigned Tables;
+ uint64_t Chunks; // Total number of chunks in all tables
+ uint64_t TableCache; // Current amount RAM used by tables, in bytes
+ uint64_t OpenSegments; // Current number of open segment files
+ uint64_t SectorSize;
+ uint64_t Sectors;
+ uint64_t ChunkSize;
+ uint64_t ImageSize; // Equals to Sectors * SectorSize
+ char *pChunkBuffCompressed;
+ char *pChunkBuffUncompressed;
+ uint64_t ChunkBuffUncompressedDataLen; // This normally always is equal to the chunk size (32K), except maybe for the last chunk, if the image's total size is not a multiple of the chunk size
+ unsigned int ChunkBuffSize;
+ uint64_t ChunkInBuff; // Chunk currently residing in pChunkBuffUncompressed
+ char *pErrorText; // Used for assembling error text during option parsing
+ time_t LastStatsUpdate;
+ char *pInfo;
+
+ // Statistics
+ uint64_t SegmentCacheHits;
+ uint64_t SegmentCacheMisses;
+ uint64_t TableCacheHits;
+ uint64_t TableCacheMisses;
+ uint64_t ChunkCacheHits;
+ uint64_t ChunkCacheMisses;
+ uint64_t ReadOperations; // How many times did xmount call the function AewfRead
+ uint64_t DataReadFromImage; // The data (in bytes) read from the image
+ uint64_t DataReadFromImageRaw; // The same data (in bytes), after uncompression (if any)
+ uint64_t DataRequestedByCaller; // How much data was given back to the caller
+ uint64_t TablesReadFromImage; // The overhead of the table read operations (in bytes)
+
+ uint64_t ChunksRead;
+ uint64_t BytesRead;
+
+ // Options
+ uint64_t MaxTableCache; // Max. amount of bytes in pTableArr[x].pTableData, in bytes
+ uint64_t MaxOpenSegments; // Max. number of open files in pSegmentArr
+ char *pStatsFilename; // Statistics file
+ uint64_t StatsRefresh; // The time in seconds between update of the stats file
+} t_Aewf;
+
+// ----------------
+// Error handling
+// ----------------
+
+#ifdef AEWF_DEBUG
+ #define CHK(ChkVal) \
+ { \
+ int ChkValRc; \
+ if ((ChkValRc=(ChkVal)) != AEWF_OK) \
+ { \
+ printf ("Err %d in %s, %d\n", ChkValRc, __FILE__, __LINE__); \
+ return ChkValRc; \
+ } \
+ }
+ #define DEBUG_PRINTF(pFormat, ...) \
+ printf (pFormat, ##__VA_ARGS__);
+#else
+ #define CHK(ChkVal) \
+ { \
+ int ChkValRc; \
+ if ((ChkValRc=(ChkVal)) != AEWF_OK) \
+ return ChkValRc; \
+ }
+ #define DEBUG_PRINTF(...)
+#endif
// Possible error codes for the above functions
enum
{
AEWF_OK = 0,
AEWF_FOUND,
AEWF_MEMALLOC_FAILED=100, // 100
AEWF_FILE_OPEN_FAILED,
AEWF_FILE_CLOSE_FAILED,
AEWF_FILE_SEEK_FAILED,
AEWF_FILE_READ_FAILED,
AEWF_READFILE_BAD_MEM, // 105
AEWF_INVALID_SEGMENT_NUMBER,
AEWF_WRONG_SEGMENT_FILE_COUNT,
AEWF_VOLUME_MUST_PRECEDE_TABLES,
AEWF_SECTORS_MUST_PRECEDE_TABLES,
AEWF_WRONG_CHUNK_COUNT, // 110
AEWF_READ_BEYOND_IMAGE_LENGTH,
AEWF_CHUNK_NOT_FOUND,
AEWF_VOLUME_MISSING,
AEWF_ERROR_EWF_TABLE_NOT_READY,
AEWF_ERROR_EWF_SEGMENT_NOT_READY, // 115
AEWF_CHUNK_TOO_BIG,
AEWF_UNCOMPRESS_FAILED,
AEWF_BAD_UNCOMPRESSED_LENGTH,
AEWF_CHUNK_CRC_ERROR,
AEWF_ERROR_IN_CHUNK_NUMBER, // 120
AEWF_VASPRINTF_FAILED,
AEWF_UNCOMPRESS_HEADER_FAILED,
AEWF_ASPRINTF_FAILED,
};
#endif
diff --git a/trunk/libxmount_input/libxmount_input_dd/CMakeLists.txt b/trunk/libxmount_input/libxmount_input_dd/CMakeLists.txt
new file mode 100644
index 0000000..5b8dc1f
--- /dev/null
+++ b/trunk/libxmount_input/libxmount_input_dd/CMakeLists.txt
@@ -0,0 +1,6 @@
+project(libxmount_input_dd)
+
+add_library(xmount_input_dd SHARED libxmount_input_dd.c)
+
+install(TARGETS xmount_input_dd DESTINATION lib/xmount)
+
diff --git a/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.c b/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.c
index fd2af78..4ac8c91 100644
--- a/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.c
+++ b/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.c
@@ -1,346 +1,444 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This module has been written by Guy Voncken. It contains the functions for *
* accessing dd images. Split dd is supported as well. *
* *
* xmount is a small tool to "fuse mount" various harddisk image formats as dd, *
* vdi, vhd or vmdk files and enable virtual write access to them. *
* *
* 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 <string.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
-#include "dd.h"
+#include "../libxmount_input.h"
+
+#include "libxmount_input_dd.h"
+
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+int DdOpen(void **pp_handle,
+ const char **pp_filename_arr,
+ uint64_t filename_arr_len);
+int DdSize(void *p_handle,
+ uint64_t *p_size);
+int DdRead(void *p_handle,
+ uint64_t seek,
+ char *p_buf,
+ uint32_t count);
+int DdClose(void **pp_handle);
+int DdOptionsHelp(const char **pp_help);
+int DdOptionsParse(void *p_handle,
+ char *p_options,
+ char **pp_error);
+int DdGetInfofileContent(void *p_handle,
+ const char **pp_info_buf);
+void DdFreeBuffer(void *p_buf);
+
+/*******************************************************************************
+ * LibXmount_Input API implementation
+ ******************************************************************************/
+/*
+ * LibXmount_Input_GetApiVersion
+ */
+uint8_t LibXmount_Input_GetApiVersion() {
+ return LIBXMOUNT_INPUT_API_VERSION;
+}
+
+/*
+ * LibXmount_Input_GetSupportedFormats
+ */
+const char* LibXmount_Input_GetSupportedFormats() {
+ return "dd\0\0";
+}
+
+/*
+ * LibXmount_Input_GetFunctions
+ */
+void LibXmount_Input_GetFunctions(ts_LibXmountInputFunctions *p_functions) {
+ p_functions->Open=&DdOpen;
+ p_functions->Size=&DdSize;
+ p_functions->Read=&DdRead;
+ p_functions->Close=&DdClose;
+ p_functions->OptionsHelp=&DdOptionsHelp;
+ p_functions->OptionsParse=&DdOptionsParse;
+ p_functions->GetInfofileContent=&DdGetInfofileContent;
+ p_functions->FreeBuffer=&DdFreeBuffer;
+}
+
+/*******************************************************************************
+ * Private
+ ******************************************************************************/
// ----------------------
// Constant definitions
// ----------------------
#define GETMAX(a,b) ((a)>(b)?(a):(b))
#define GETMIN(a,b) ((a)<(b)?(a):(b))
// ---------------------
// Types and strutures
// ---------------------
typedef struct
{
char *pFilename;
unsigned long long FileSize;
FILE *pFile;
} t_Piece, *t_pPiece;
typedef struct _t_dd
{
t_pPiece pPieceArr;
unsigned int Pieces;
unsigned long long TotalSize;
char *pInfo;
} t_dd;
// ----------------
// Error handling
// ----------------
#ifdef DD_DEBUG
#define CHK(ChkVal) \
{ \
int ChkValRc; \
if ((ChkValRc=(ChkVal)) != DD_OK) \
{ \
printf ("Err %d in %s, %d\n", ChkValRc, __FILE__, __LINE__); \
return ChkValRc; \
} \
}
#define DEBUG_PRINTF(pFormat, ...) \
printf (pFormat, ##__VA_ARGS__);
#else
#define CHK(ChkVal) \
{ \
int ChkValRc; \
if ((ChkValRc=(ChkVal)) != DD_OK) \
return ChkValRc; \
}
#define DEBUG_PRINTF(...)
#endif
// ---------------------------
// Internal static functions
// ---------------------------
-static inline unsigned long long ddGetCurrentSeekPos (t_pPiece pPiece)
+static inline unsigned long long DdGetCurrentSeekPos (t_pPiece pPiece)
{
return ftello (pPiece->pFile);
}
-static inline int ddSetCurrentSeekPos (t_pPiece pPiece, unsigned long long Val, int Whence)
+static inline int DdSetCurrentSeekPos (t_pPiece pPiece, unsigned long long Val, int Whence)
{
if (fseeko (pPiece->pFile, Val, Whence) != 0)
return DD_CANNOT_SEEK;
return DD_OK;
}
-int ddDestroyHandle (t_pdd *ppdd)
+int DdDestroyHandle (t_pdd *ppdd)
{
t_pdd pdd = *ppdd;
t_pPiece pPiece;
int CloseErrors = 0;
if (pdd->pPieceArr)
{
for (int i=0; i < pdd->Pieces; i++)
{
pPiece = &pdd->pPieceArr[i];
if (pPiece->pFile)
if (fclose (pPiece->pFile))
CloseErrors++;
if (pPiece->pFilename)
free (pPiece->pFilename);
}
free (pdd->pPieceArr);
}
if (pdd->pInfo)
free (pdd->pInfo);
free (pdd);
*ppdd = NULL;
if (CloseErrors)
return DD_CANNOT_CLOSE_FILE;
return DD_OK;
}
-static int ddCreateHandle (t_pdd *ppdd, unsigned FilenameArrLen, const char **ppFilenameArr)
+static int DdCreateHandle (t_pdd *ppdd, unsigned FilenameArrLen, const char **ppFilenameArr)
{
t_pdd pdd;
t_pPiece pPiece;
*ppdd = NULL;
pdd = (t_pdd) malloc (sizeof(t_dd));
if (pdd == NULL)
return DD_MEMALLOC_FAILED;
memset (pdd, 0, sizeof(t_dd));
pdd->Pieces = FilenameArrLen;
pdd->pPieceArr = (t_pPiece) malloc (pdd->Pieces * sizeof(t_Piece));
if (pdd->pPieceArr == NULL)
{
- (void) ddDestroyHandle (&pdd);
+ (void) DdDestroyHandle (&pdd);
return DD_MEMALLOC_FAILED;
}
pdd->TotalSize = 0;
for (int i=0; i < pdd->Pieces; i++)
{
pPiece = &pdd->pPieceArr[i];
pPiece->pFilename = strdup (ppFilenameArr[i]);
if (pPiece->pFilename == NULL)
{
- (void) ddDestroyHandle (&pdd);
+ (void) DdDestroyHandle (&pdd);
return DD_MEMALLOC_FAILED;
}
pPiece->pFile = fopen (pPiece->pFilename, "r");
if (pPiece->pFile == NULL)
{
- (void) ddDestroyHandle (&pdd);
+ (void) DdDestroyHandle (&pdd);
return DD_FILE_OPEN_FAILED;
}
- CHK(ddSetCurrentSeekPos(pPiece, 0, SEEK_END))
- pPiece->FileSize = ddGetCurrentSeekPos (pPiece);
+ CHK(DdSetCurrentSeekPos(pPiece, 0, SEEK_END))
+ pPiece->FileSize = DdGetCurrentSeekPos (pPiece);
pdd->TotalSize += pPiece->FileSize;
}
asprintf (&pdd->pInfo, "dd image made of %u pieces, %llu bytes in total (%0.3f GiB)", pdd->Pieces, pdd->TotalSize, pdd->TotalSize / (1024.0*1024.0*1024.0));
*ppdd = pdd;
return DD_OK;
}
// ---------------
// API functions
// ---------------
-int ddOpen (t_pdd *ppdd, unsigned FilenameArrLen, const char **pFilenameArr)
+/*
+ * DdOpen
+ */
+int DdOpen(void **pp_handle,
+ const char **pp_filename_arr,
+ uint64_t filename_arr_len)
{
- CHK (ddCreateHandle (ppdd, FilenameArrLen, pFilenameArr))
-
- return DD_OK;
+ CHK(DdCreateHandle((t_pdd*)pp_handle,filename_arr_len,pp_filename_arr))
+ return DD_OK;
}
-int ddSize (t_pdd pdd, unsigned long long *pSize)
-{
- *pSize = pdd->TotalSize;
-
- return DD_OK;
+/*
+ * DdSize
+ */
+int DdSize(void *p_handle, uint64_t *p_size) {
+ *p_size=((t_pdd)p_handle)->TotalSize;
+ return DD_OK;
}
-int ddRead0 (t_pdd pdd, unsigned long long Seek, unsigned char *pBuffer, unsigned int *pCount)
+/*
+ * DdRead0
+ */
+int DdRead0 (t_pdd pdd, uint64_t Seek, char *pBuffer, uint32_t *pCount)
{
t_pPiece pPiece;
int i;
// Find correct piece to read from
// -------------------------------
for (i=0; i<pdd->Pieces; i++)
{
pPiece = &pdd->pPieceArr[i];
if (Seek < pPiece->FileSize)
break;
Seek -= pPiece->FileSize;
}
if (i >= pdd->Pieces)
return DD_READ_BEYOND_END_OF_IMAGE;
// Read from this piece
// --------------------
- CHK (ddSetCurrentSeekPos (pPiece, Seek, SEEK_SET))
+ CHK (DdSetCurrentSeekPos (pPiece, Seek, SEEK_SET))
*pCount = GETMIN (*pCount, pPiece->FileSize - Seek);
if (fread (pBuffer, *pCount, 1, pPiece->pFile) != 1)
return DD_CANNOT_READ_DATA;
return DD_OK;
}
-
-int ddRead (t_pdd pdd, unsigned long long Seek, unsigned char *pBuffer, unsigned int Count)
+/*
+ * DdRead
+ */
+int DdRead(void *p_handle,
+ uint64_t seek,
+ char *p_buf,
+ uint32_t count)
{
- unsigned Remaining = Count;
- unsigned Read;
+ uint32_t remaining=count;
+ uint32_t read;
+
+ if((seek+count)>((t_pdd)p_handle)->TotalSize) {
+ return DD_READ_BEYOND_END_OF_IMAGE;
+ }
+
+ do {
+ read=remaining;
+ CHK(DdRead0((t_pdd)p_handle,seek,p_buf,&read))
+ remaining-=read;
+ p_buf+=read;
+ seek+=read;
+ } while(remaining);
+
+ return DD_OK;
+}
- if ((Seek + Count) > pdd->TotalSize)
- return DD_READ_BEYOND_END_OF_IMAGE;
+/*
+ * DdInfo
+ */
+int DdGetInfofileContent(void *p_handle, const char **pp_info_buf) {
+ *pp_info_buf=((t_pdd)p_handle)->pInfo;
+ return DD_OK;
+}
- do
- {
- Read = Remaining;
- CHK (ddRead0 (pdd, Seek, pBuffer, &Read))
- Remaining -= Read;
- pBuffer += Read;
- Seek += Read;
- } while (Remaining);
+/*
+ * DdClose
+ */
+int DdClose(void **pp_handle) {
+ CHK (DdDestroyHandle((t_pdd*)pp_handle))
+ return DD_OK;
+}
- return DD_OK;
+/*
+ * DdOptionsHelp
+ */
+int DdOptionsHelp(const char **pp_help) {
+ *pp_help=NULL;
+ return DD_OK;
}
-int ddInfo (t_pdd pdd, char **ppInfoBuff)
-{
- *ppInfoBuff = pdd->pInfo;
- return DD_OK;
+/*
+ * DdOptionsParse
+ */
+int DdOptionsParse(void *p_handle, char *p_options, char **pp_error) {
+ return DD_OK;
}
-int ddClose (t_pdd *ppdd)
-{
- CHK (ddDestroyHandle(ppdd))
- return DD_OK;
+/*
+ * DdFreeBuffer
+ */
+void DdFreeBuffer(void *p_buf) {
+ free(p_buf);
}
// -----------------------------------------------------
// Small main routine for testing
// It a split dd file to non-split dd
// -----------------------------------------------------
#ifdef DD_MAIN_FOR_TESTING
int main(int argc, const char *argv[])
{
t_pdd pdd;
- unsigned long long TotalSize;
- unsigned long long Remaining;
- unsigned long long Read;
- unsigned long long Pos;
- unsigned int BuffSize = 1024;
- unsigned char Buff[BuffSize];
+ uint64_t TotalSize;
+ uint64_t Remaining;
+ uint64_t Read;
+ uint64_t Pos;
+ uint32_t BuffSize = 1024;
+ char Buff[BuffSize];
FILE *pFile;
int Percent;
int PercentOld;
int rc;
printf ("Split DD to DD converter\n");
if (argc < 3)
{
printf ("Usage: %s <dd part 1> <dd part 2> <...> <dd destination>\n", argv[0]);
exit (1);
}
- if (ddOpen (&pdd, argc-2, &argv[1]) != DD_OK)
+ if (DdOpen ((void**)&pdd, argc-2, &argv[1]) != DD_OK)
{
printf ("Cannot open split dd file\n");
exit (1);
}
- CHK (ddSize (pdd, &TotalSize))
+ CHK (DdSize ((void*)pdd, &TotalSize))
printf ("Total size: %llu bytes\n", TotalSize);
Remaining = TotalSize;
pFile = fopen (argv[argc-1], "w");
if (pFile == NULL)
{
printf ("Cannot open destination file\n");
exit (1);
}
Remaining = TotalSize;
Pos = 0;
PercentOld = -1;
while (Remaining)
{
Read = GETMIN (Remaining, BuffSize);
- rc = ddRead (pdd, Pos, &Buff[0], Read);
+ rc = DdRead ((void*)pdd, Pos, &Buff[0], Read);
if (rc != DD_OK)
{
- printf ("Error %d while calling ddRead\n", rc);
+ printf ("Error %d while calling DdRead\n", rc);
exit (1);
}
if (fwrite (Buff, Read, 1, pFile) != 1)
{
printf ("Could not write to destinationfile\n");
exit (2);
}
Remaining -= Read;
Pos += Read;
Percent = (100*Pos) / TotalSize;
if (Percent != PercentOld)
{
printf ("\r%d%% done...", Percent);
PercentOld = Percent;
}
}
if (fclose (pFile))
{
printf ("Error while closing destinationfile\n");
exit (3);
}
printf ("\n");
return 0;
}
#endif
+
diff --git a/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.h b/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.h
index da64c94..126fe4f 100644
--- a/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.h
+++ b/trunk/libxmount_input/libxmount_input_dd/libxmount_input_dd.h
@@ -1,51 +1,44 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2013 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This module has been written by Guy Voncken. It contains the functions for *
* accessing dd images. Split dd is supported as well. *
* *
* xmount is a small tool to "fuse mount" various harddisk image formats as dd, *
* vdi, vhd or vmdk files and enable virtual write access to them. *
* *
* 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 DD_H
#define DD_H
typedef struct _t_dd *t_pdd;
-int ddOpen (t_pdd *ppdd, unsigned FilenameArrLen, const char **pFilenameArr);
-int ddInfo (t_pdd pdd, char **ppInfoBuff);
-int ddSize (t_pdd pdd, unsigned long long *pSize);
-int ddRead (t_pdd pdd, unsigned long long Seek, unsigned char *pBuffer, unsigned int Count);
-int ddClose (t_pdd *ppdd);
-
-
// Possible error codes
enum
{
DD_OK = 0,
DD_FOUND,
DD_MEMALLOC_FAILED=100,
DD_FILE_OPEN_FAILED,
DD_CANNOT_READ_DATA,
DD_CANNOT_CLOSE_FILE,
DD_CANNOT_SEEK,
DD_READ_BEYOND_END_OF_IMAGE
};
#endif
diff --git a/trunk/libxmount_input/libxmount_input_ewf/CMakeLists.txt b/trunk/libxmount_input/libxmount_input_ewf/CMakeLists.txt
index f9f35e5..ade5dd2 100644
--- a/trunk/libxmount_input/libxmount_input_ewf/CMakeLists.txt
+++ b/trunk/libxmount_input/libxmount_input_ewf/CMakeLists.txt
@@ -1,7 +1,9 @@
-cmake_minimum_required(VERSION 2.8)
project(libxmount_input_ewf)
+
add_library(xmount_input_ewf SHARED libxmount_input_ewf.c)
-install(TARGETS xmount_input_ewf DESTINATION lib/xmount)
include_directories(${LIBEWF_INCLUDE_DIRS})
set(LIBS ${LIBS} ${LIBEWF_LIBRARIES})
target_link_libraries(xmount_input_ewf ${LIBS})
+
+install(TARGETS xmount_input_ewf DESTINATION lib/xmount)
+
diff --git a/trunk/libxmount_input/libxmount_input_ewf/libxmount_input_ewf.c b/trunk/libxmount_input/libxmount_input_ewf/libxmount_input_ewf.c
index ec095d4..a514869 100644
--- a/trunk/libxmount_input/libxmount_input_ewf/libxmount_input_ewf.c
+++ b/trunk/libxmount_input/libxmount_input_ewf/libxmount_input_ewf.c
@@ -1,301 +1,284 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2014 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* xmount is a small tool to "fuse mount" various image formats and enable *
* virtual write access. *
* *
* 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/>. *
*******************************************************************************/
#undef HAVE_LIBEWF_STATIC
#include <stdlib.h>
#include <string.h>
#include "../libxmount_input.h"
#ifndef HAVE_LIBEWF_STATIC
#include <libewf.h>
#else
#include "libewf/include/libewf.h"
#endif
#if !defined(LIBEWF_HANDLE)
// libewf version 2 no longer defines LIBEWF_HANDLE
#define HAVE_LIBEWF_V2_API
#endif
/*******************************************************************************
* Forward declarations
******************************************************************************/
int EwfOpen(void **pp_handle,
const char **pp_filename_arr,
uint64_t filename_arr_len);
int EwfSize(void *p_handle,
uint64_t *p_size);
int EwfRead(void *p_handle,
uint64_t seek,
char *p_buf,
uint32_t count);
int EwfClose(void **pp_handle);
int EwfOptionsHelp(const char **pp_help);
int EwfOptionsParse(void *p_handle,
char *p_options,
char **pp_error);
int EwfGetInfofileContent(void *p_handle,
const char **pp_info_buf);
void EwfFreeBuffer(void *p_buf);
/*******************************************************************************
* LibXmount_Input API implementation
******************************************************************************/
/*
* LibXmount_Input_GetApiVersion
*/
uint8_t LibXmount_Input_GetApiVersion() {
return LIBXMOUNT_INPUT_API_VERSION;
}
/*
* LibXmount_Input_GetSupportedFormats
*/
const char* LibXmount_Input_GetSupportedFormats() {
-/*
- // Alloc array containing 1 element with content "ewf"
- *ppp_arr=(char**)malloc(sizeof(char*));
- if(*ppp_arr==NULL) {
- *p_arr_len=0;
- return;
- }
- **ppp_arr=(char*)malloc(sizeof(char)*4);
- if(**ppp_arr==NULL) {
- free(*ppp_arr);
- *ppp_arr=NULL;
- *p_arr_len=0;
- return;
- }
- strcpy(**ppp_arr,"ewf");
- *p_arr_len=1;
-*/
return "ewf\0\0";
}
/*
* LibXmount_Input_GetFunctions
*/
void LibXmount_Input_GetFunctions(ts_LibXmountInputFunctions *p_functions) {
p_functions->Open=&EwfOpen;
p_functions->Size=&EwfSize;
p_functions->Read=&EwfRead;
p_functions->Close=&EwfClose;
p_functions->OptionsHelp=&EwfOptionsHelp;
p_functions->OptionsParse=&EwfOptionsParse;
p_functions->GetInfofileContent=&EwfGetInfofileContent;
p_functions->FreeBuffer=&EwfFreeBuffer;
}
/*******************************************************************************
* Private
******************************************************************************/
/*
* EwfOpen
*/
int EwfOpen(void **pp_handle,
const char **pp_filename_arr,
uint64_t filename_arr_len)
{
// We need at least one file
if(filename_arr_len==0) return 1;
// Make sure all files are EWF files
for(uint64_t i=0;i<filename_arr_len;i++) {
if(libewf_check_file_signature(pp_filename_arr[i],NULL)!=1) return 1;
}
// Init handle
*pp_handle=NULL;
if(libewf_handle_initialize((libewf_handle_t**)pp_handle,NULL)!=1) {
// LOG_ERROR("Couldn't create EWF handle!\n")
return 1;
}
// Open EWF file
if(libewf_handle_open((libewf_handle_t*)*pp_handle,
(char* const*)pp_filename_arr,
filename_arr_len,
libewf_get_access_flags_read(),
NULL)!=1)
{
// LOG_ERROR("Couldn't open EWF file(s)!\n")
return 1;
}
return 0;
}
/*
* EwfSize
*/
int EwfSize(void *p_handle, uint64_t *p_size) {
if(libewf_handle_get_media_size((libewf_handle_t*)p_handle,p_size,NULL)!=1) {
return 1;
}
return 0;
}
/*
* EwfRead
*/
int EwfRead(void *p_handle,
uint64_t offset,
char *p_buf,
uint32_t count)
{
if(libewf_handle_seek_offset((libewf_handle_t*)p_handle,
offset,
SEEK_SET,
NULL)!=-1)
{
if(libewf_handle_read_buffer((libewf_handle_t*)p_handle,
p_buf,
count,
NULL)!=count)
{
return 1;
}
} else {
return 1;
}
return 0;
}
/*
* EwfClose
*/
int EwfClose(void **pp_handle) {
// Close EWF handle
if(libewf_handle_close((libewf_handle_t*)*pp_handle,NULL)!=0) {
return 1;
}
// Free EWF handle
if(libewf_handle_free((libewf_handle_t**)pp_handle,NULL)!=1) {
return 1;
}
*pp_handle=NULL;
return 0;
}
/*
* EwfOptionsHelp
*/
int EwfOptionsHelp(const char **pp_help) {
*pp_help=NULL;
return 0;
}
/*
* EwfOptionsParse
*/
int EwfOptionsParse(void *p_handle, char *p_options, char **pp_error) {
return 0;
}
/*
* EwfGetInfofileContent
*/
int EwfGetInfofileContent(void *p_handle, const char **pp_info_buf) {
/*
#define M_SAVE_VALUE(DESC,SHORT_DESC) { \
if(ret==1) { \
XMOUNT_REALLOC(pVirtualImageInfoFile,char*, \
(strlen(pVirtualImageInfoFile)+strlen(buf)+strlen(DESC)+2)) \
strncpy((pVirtualImageInfoFile+strlen(pVirtualImageInfoFile)),DESC,strlen(DESC)+1); \
strncpy((pVirtualImageInfoFile+strlen(pVirtualImageInfoFile)),buf,strlen(buf)+1); \
strncpy((pVirtualImageInfoFile+strlen(pVirtualImageInfoFile)),"\n",2); \
} else if(ret==-1) { \
LOG_WARNING("Couldn't query EWF image header value '%s'\n",SHORT_DESC) \
} \
}
case TOrigImageType_EWF:
// Original image is an EWF file. Extract various infos from ewf file and
// add them to the virtual image info file content.
#if defined( HAVE_LIBEWF_V2_API )
ret=libewf_handle_get_utf8_header_value_case_number(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Case number: ","Case number")
ret=libewf_handle_get_utf8_header_value_description(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Description: ","Description")
ret=libewf_handle_get_utf8_header_value_examiner_name(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Examiner: ","Examiner")
ret=libewf_handle_get_utf8_header_value_evidence_number(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Evidence number: ","Evidence number")
ret=libewf_handle_get_utf8_header_value_notes(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Notes: ","Notes")
ret=libewf_handle_get_utf8_header_value_acquiry_date(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Acquiry date: ","Acquiry date")
ret=libewf_handle_get_utf8_header_value_system_date(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("System date: ","System date")
ret=libewf_handle_get_utf8_header_value_acquiry_operating_system(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Acquiry os: ","Acquiry os")
ret=libewf_handle_get_utf8_header_value_acquiry_software_version(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("Acquiry sw version: ","Acquiry sw version")
ret=libewf_handle_get_utf8_hash_value_md5(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("MD5 hash: ","MD5 hash")
ret=libewf_handle_get_utf8_hash_value_sha1(hEwfFile,buf,sizeof(buf),NULL);
M_SAVE_VALUE("SHA1 hash: ","SHA1 hash")
#else
ret=libewf_get_header_value_case_number(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Case number: ","Case number")
ret=libewf_get_header_value_description(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Description: ","Description")
ret=libewf_get_header_value_examiner_name(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Examiner: ","Examiner")
ret=libewf_get_header_value_evidence_number(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Evidence number: ","Evidence number")
ret=libewf_get_header_value_notes(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Notes: ","Notes")
ret=libewf_get_header_value_acquiry_date(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Acquiry date: ","Acquiry date")
ret=libewf_get_header_value_system_date(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("System date: ","System date")
ret=libewf_get_header_value_acquiry_operating_system(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Acquiry os: ","Acquiry os")
ret=libewf_get_header_value_acquiry_software_version(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("Acquiry sw version: ","Acquiry sw version")
ret=libewf_get_hash_value_md5(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("MD5 hash: ","MD5 hash")
ret=libewf_get_hash_value_sha1(hEwfFile,buf,sizeof(buf));
M_SAVE_VALUE("SHA1 hash: ","SHA1 hash")
#endif
break;
#undef M_SAVE_VALUE
*/
*pp_info_buf=NULL;
return 0;
}
/*
* EwfFreeBuffer
*/
void EwfFreeBuffer(void *p_buf) {
free(p_buf);
}
/*
----- Change history -----
20140724: * Initial version implementing EwfOpen, EwfSize, EwfRead, EwfClose,
EwfOptionsHelp, EwfOptionsParse and EwfFreeBuffer
*/

File Metadata

Mime Type
text/x-diff
Expires
Wed, Dec 25, 4:08 AM (43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1177267
Default Alt Text
(151 KB)

Event Timeline