const uint64_t AEWF_DEFAULT_THREADS = 4; // There normally is no sense in using higher values, as - according to out statistics - we never get called for reading
// more than 128k of data (there's only 1 exception: the very 1st read request from xmount itself). With the default EWF
// chunk size of 32K, 4 threads are enough for running the whole decompression in parallel.
// ----------------------------
// Logging and error handling
// ----------------------------
#define LOG_HEADER_LEN 80
int LogvEntry (const char *pLogPath, uint8_t LogStdout, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments)
// 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. But this line could lead to reading beyond EOF...
if (ReadLen > pAewf->ChunkBuffSize)
{
LOG ("Chunk too big %u / %u", ReadLen, pAewf->ChunkBuffSize);
return AEWF_CHUNK_TOO_BIG;
}
ChunkSize = pAewf->ChunkSize;
if (AbsoluteChunk == (pAewf->Chunks-1)) // The very last chunk of the image may be smaller than the default
{ // chunk size if the image isn't a multiple of the chunk size.
// 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. But this line could lead to reading beyond EOF...
if (ReadLen > pAewf->ChunkBuffSize)
{
LOG ("Chunk too big %u / %u", ReadLen, pAewf->ChunkBuffSize);
CHK (AEWF_CHUNK_TOO_BIG)
}
ChunkSize = pAewf->ChunkSize;
if (AbsoluteChunk == (pAewf->Chunks-1)) // The very last chunk of the image may be smaller than the default
{ // chunk size if the image isn't a multiple of the chunk size.
ChunkSize = pAewf->ImageSize % pAewf->ChunkSize;
if (ChunkSize == 0)
ChunkSize = pAewf->ChunkSize;
}
for (int i=0; i<pAewf->Threads; i++)
{
t_pAewfThread pThread = &(pAewf->pThreadArr[i]);
if (pThread->State == AEWF_IDLE)
{
pThread->State = AEWF_LAUNCHED;
pThread->ChunkBuffCompressedDataLen = ReadLen;
pThread->ChunkBuffUncompressedDataLen = ChunkSize; // uncompress should return this size (if it's a compressed chunk)
pThread->ChunkInBuff = AbsoluteChunk;
pThread->pBuf = pBuf; // These 3 parameters specify which part
pThread->Ofs = Ofs; // of the resulting chunk data should be
LOG ("Maybe some segment files are missing. Perhaps you specified E01 instead of E?? or the segments continue beyond extension .EZZ.");
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)
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)
uint32_t ChunkCount; // The number of chunk; this is the same as pTableData->Chunkcount, however, pTableData might not be available (NULL)
uint64_t SectionSectorsPos; // Seek position of corresponding section SECTORS in segment file and its length. Silly EWF format has no clean way
uint32_t SectionSectorsSize; // of determining size of the last (possibly compressed) chunk of a table, that's why we need to memorise these values.
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;
#define AEWF_NONE UINT64_MAX
enum
{
READSIZE_32K = 0,
READSIZE_64K,
READSIZE_128K,
READSIZE_256K,
READSIZE_512K,
READSIZE_1M,
READSIZE_ABOVE_1M,
READSIZE_ARRLEN
};
typedef enum
{
AEWF_IDLE = 0,
AEWF_LAUNCHED
} t_AewfThreadState;
typedef struct _t_AewfThread
{
t_AewfThreadState State;
t_pcAewf pAewf; // Give the threads access to some Aewf constants - make sure the threads only have read access
pthread_t ID;
char *pChunkBuffCompressed;
uint64_t ChunkBuffCompressedDataLen;
char *pChunkBuffUncompressed; // This buffer serves as cache as well. ChunkInBuff contains the absolute chunk number whose data is stored here
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
uint64_t ChunkInBuff;
char *pBuf; // Job arguments to the thread: Copy the uncompressed
uint64_t Ofs; // chunk data starting at chunk offset Ofs to pBuf, Len
uint64_t Len; // bytes in total.
int ReturnCode;
} t_AewfThread, *t_pAewfThread;
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)
uint64_t Segments;
uint64_t Tables;
uint64_t Chunks; // Total number of chunks in all tables
uint64_t TotalTableSize; // Total size of 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
uint32_t ChunkBuffSize;
uint64_t ChunkInBuff; // Chunk currently residing in pChunkBuffUncompressed (AEWF_NONE if none)
char *pErrorText; // Used for assembling error text during option parsing
time_t LastStatsUpdate;
char *pInfo;
t_pAewfThread pThreadArr;
// 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;
uint64_t ReadSizesArr[READSIZE_ARRLEN]; // Distribution of the requested block sites to be read
uint64_t Errors;
int LastError;
// 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 *pStatsPath; // Statistics path
uint64_t StatsRefresh; // The time in seconds between update of the stats file
char *pLogPath; // Path for log file
uint8_t LogStdout;
uint64_t Threads; // Max. number of threads to be used in parallel actions. Currently only used for uncompression
} t_Aewf;
// ----------------
// Error codes
// ----------------
// AEWF Error codes are automatically mapped to errno codes by means of the groups
// below. AEWF uses these errno codes:
// ENOMEM memory allocation errors
// EINVAL wrong parameter(s) passed to an AEWF function
// EIO all others: AEWF function errors, EWF image errors
-\f0\fs26 \cf0 xmount Copyright (c) 2008-2015 by Gillen Daniel\
+\f0\fs26 \cf0 xmount Copyright (c) 2008-2016 by Gillen Daniel\
\
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/>.\
\
This version of xmount includes the following statically linked libraries:\
\
==== LIBEWF\
Copyright (c) 2006-2009, Joachim Metz <forensics@hoffmannbv.nl>, Hoffmann Investigations.\
\
This software is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\
\
This software 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 Lesser General Public License along with this software. If not, see <http://www.gnu.org/licenses/>.\
\
==== AFFLIB\
Copyright (c) 2005, 2006, 2007 Simson L. Garfinkel and Basis Technology Corp. All rights reserved.\
\
This code is derrived from software contributed by Simson L. Garfinkel\
\
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\
\
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\
3. All advertising materials mentioning features or use of this software must display the following acknowledgement:\
This product includes software developed by Simson L. Garfinkel and Basis Technology Corp.\
4. Neither the name of Simson L. Garfinkel, Basis Technology, or other contributors to this program may be used to endorse or promote products derived from this software without specific prior written permission.\
\
THIS SOFTWARE IS PROVIDED BY SIMSON L. GARFINKEL, BASIS TECHNOLOGY, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SIMSON L. GARFINKEL, BASIS TECHNOLOGY, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \
\
AFF and AFFLIB is a trademark of Simson Garfinkel and Basis Technology Corp.}]]>
\f0\fs26 \cf0 xmount allows you to convert on-the-fly between multiple input and output harddisk image formats. xmount creates a virtual file system using FUSE (Filesystem in Userspace) that contains a virtual representation of the input image. \
\
The virtual representation can be in raw DD, Apple's Disk Image format (DMG), VirtualBox's virtual disk file format (VDI), Microsoft's Virtual Hard Disk Image format (VHD) or in VmWare's VMDK file format. \
\
Input images can be raw DD, EWF (Expert Witness Compression Format) or AFF (Advanced Forensic Format) files. \
\
In addition, xmount also supports virtual write access to the output files that is redirected to a cache file. This makes it for example possible to boot acquired harddisk images using QEMU, KVM, VirtualBox, VmWare or alike.}]]>
<message>Your system is missing FUSE support. Please install FUSE for OS X from https://osxfuse.github.io/ prior to launching this installer.</message>