Page MenuHomePhabricator

No OneTemporary

Size
195 KB
Referenced Files
None
Subscribers
None
diff --git a/src/xmount.c b/src/xmount.c
index 6cfc522..d967f7e 100755
--- a/src/xmount.c
+++ b/src/xmount.c
@@ -1,1891 +1,1660 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2016 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* 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 <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h> // For PRI*
#include <errno.h>
#include <dlfcn.h> // For dlopen, dlclose, dlsym
#include <dirent.h> // For opendir, readdir, closedir
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h> // For fstat
#include <sys/types.h>
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h> // For SEEK_* ??
#endif
#if !defined(__APPLE__) && defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
#include <grp.h> // For getgrnam, struct group
#include <pwd.h> // For getpwuid, struct passwd
#endif
#include <pthread.h>
#include <time.h> // For time
#include "xmount.h"
#include "xmount_fuse.h"
#include "md5.h"
#include "macros.h"
-#include "../libxmount/libxmount.h"
#define XMOUNT_COPYRIGHT_NOTICE \
"xmount v%s Copyright (c) 2008-2016 by Gillen Daniel <gillen.dan@pinguin.lu>"
#define LOG_WARNING(...) { \
LIBXMOUNT_LOG_WARNING(__VA_ARGS__); \
}
#define LOG_ERROR(...) { \
LIBXMOUNT_LOG_ERROR(__VA_ARGS__); \
}
#define LOG_DEBUG(...) { \
LIBXMOUNT_LOG_DEBUG(glob_xmount.debug,__VA_ARGS__); \
}
#define HASH_AMOUNT (1024*1024)*10 // Amount of data used to construct a
// "unique" hash for every input image
// (10MByte)
/*******************************************************************************
* Forward declarations
******************************************************************************/
/*
* Misc
*/
static int InitResources();
static void FreeResources();
static void PrintUsage(char*);
static void CheckFuseSettings();
static int ParseCmdLine(const int, char**);
static int ExtractOutputFileNames(char*);
static int CalculateInputImageHash(uint64_t*, uint64_t*);
/*
* Info file
*/
static int InitInfoFile();
/*
* Lib related
*/
static int LoadLibs();
-static int FindOutputLib();
/*
* Functions exported to LibXmount_Morphing
*/
static int LibXmount_Morphing_ImageCount(uint64_t*);
static int LibXmount_Morphing_Size(uint64_t, uint64_t*);
static int LibXmount_Morphing_Read(uint64_t, char*, off_t, size_t, size_t*);
static int LibXmount_Morphing_Write(uint64_t, char*, off_t, size_t, size_t*);
/*
* Functions exported to LibXmount_Output
*/
static int LibXmount_Output_Size(uint64_t*);
static int LibXmount_Output_Read(char*, off_t, size_t, size_t*);
static int LibXmount_Output_Write(char*, off_t, size_t, size_t*);
/*******************************************************************************
* Helper functions
******************************************************************************/
//! Print usage instructions (cmdline options etc..)
/*!
* \param p_prog_name Program name (argv[0])
*/
static void PrintUsage(char *p_prog_name) {
char *p_buf;
int first;
int ret;
printf("\n" XMOUNT_COPYRIGHT_NOTICE "\n",XMOUNT_VERSION);
printf("\nUsage:\n");
printf(" %s [fopts] <xopts> <mntp>\n\n",p_prog_name);
printf("Options:\n");
printf(" fopts:\n");
printf(" -d : Enable FUSE's and xmount's debug mode.\n");
printf(" -h : Display this help message.\n");
printf(" -s : Run single threaded.\n");
printf(" -o no_allow_other : Disable automatic addition of FUSE's "
"allow_other option.\n");
printf(" -o <fopts> : Specify fuse mount options. Will also disable "
"automatic addition of FUSE's allow_other option!\n");
printf("\n");
printf(" xopts:\n");
printf(" --cache <cfile> : Enable virtual write support.\n");
printf(" <cfile> specifies the cache file to use.\n");
printf(" --in <itype> <ifile> : Input image format and source file(s). "
"May be specified multiple times.\n");
printf(" <itype> can be ");
#define PRINTUSAGE__LIST_SUPP_LIB_TYPES(fun,handle,ret_ok) do { \
first=1; \
if(fun(handle,&p_buf)==ret_ok) { \
while(*p_buf!='\0') { \
if(first==1) { \
printf("\"%s\"",p_buf); \
first=0; \
} else printf(", \"%s\"",p_buf); \
p_buf+=(strlen(p_buf)+1); \
} \
free(p_buf); \
} \
printf(".\n"); \
} while(0)
// List supported input formats
PRINTUSAGE__LIST_SUPP_LIB_TYPES(XmountInput_GetSupportedFormats,
glob_xmount.h_input,
e_XmountInput_Error_None);
printf(" <ifile> specifies the source file. If your image is split into "
"multiple files, you have to specify them all!\n");
printf(" --inopts <iopts> : Specify input library specific options.\n");
printf(" <iopts> specifies a comma separated list of key=value options. "
"See below for details.\n");
printf(" --info : Print out infos about used compiler and libraries.\n");
printf(" --morph <mtype> : Morphing function to apply to input image(s). "
"If not specified, defaults to \"combine\".\n");
printf(" <mtype> can be ");
// List supported morphing functions
PRINTUSAGE__LIST_SUPP_LIB_TYPES(XmountMorphing_GetSupportedTypes,
glob_xmount.h_morphing,
e_XmountMorphError_None);
printf(" --morphopts <mopts> : Specify morphing library specific "
"options.\n");
printf(" <mopts> specifies a comma separated list of key=value options. "
"See below for details.\n");
printf(" --offset <off> : Move the output image data start <off> bytes "
"into the input image(s).\n");
printf(" --out <otype> : Output image format. If not specified, "
"defaults to ");
#ifdef __APPLE__
printf("\"dmg\".\n");
#else
printf("\"raw\".\n");
#endif
printf(" <otype> can be ");
// List supported morphing functions
- PRINTUSAGE__LIST_SUPP_LIB_TYPES(XmountOutput_GetSupportedTypes,
+ PRINTUSAGE__LIST_SUPP_LIB_TYPES(XmountOutput_GetSupportedFormats,
glob_xmount.h_output,
e_XmountOutputError_None);
printf(" --outopts <oopts> : Specify output library specific "
"options.\n");
printf(" --owcache <file> : Same as --cache <file> but overwrites "
"existing cache file.\n");
printf(" --sizelimit <size> : The data end of input image(s) is set to no "
"more than <size> bytes after the data start.\n");
printf(" --version : Same as --info.\n");
printf("\n");
printf(" mntp:\n");
printf(" Mount point where output image should be located.\n");
printf("\n");
printf("Infos:\n");
printf(" * One --in option and a mount point are mandatory!\n");
printf(" * If you specify --in multiple times, data from all images is "
"morphed into one output image using the specified morphing "
"function.\n");
printf(" * For VMDK emulation, you have to uncomment \"user_allow_other\" "
"in /etc/fuse.conf or run xmount as root.\n");
printf("\n");
printf("Input / Morphing / Output library specific options:\n");
printf(" Input / Morphing libraries might support an own set of "
"options to configure / tune their behaviour.\n");
printf(" Libraries supporting this feature (if any) and their "
"options are listed below.\n");
printf("\n");
#define PRINTUSAGE__LIST_LIB_OPT_HELP(fun,handle,ret_ok) do { \
if(fun(handle,&p_buf)==ret_ok) { \
printf("%s",p_buf); \
free(p_buf); \
} \
} while(0)
// List input, morphing and output lib options
PRINTUSAGE__LIST_LIB_OPT_HELP(XmountInput_GetOptionsHelpText,
glob_xmount.h_input,
e_XmountInput_Error_None);
PRINTUSAGE__LIST_LIB_OPT_HELP(XmountMorphing_GetOptionsHelpText,
glob_xmount.h_morphing,
e_XmountMorphError_None);
PRINTUSAGE__LIST_LIB_OPT_HELP(XmountOutput_GetOptionsHelpText,
glob_xmount.h_output,
e_XmountOutputError_None);
#undef PRINTUSAGE__LIST_LIB_OPT_HELP
#undef PRINTUSAGE__LIST_SUPPORTED_LIB_OPTS
}
//! Check fuse settings
/*!
* Check if FUSE allows us to pass the -o allow_other parameter. This only works
* if we are root or user_allow_other is set in /etc/fuse.conf.
*
* In addition, this function also checks if the user is member of the fuse
* group which is generally needed to use fuse at all.
*/
static void CheckFuseSettings() {
#if !defined(__APPLE__) && defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
struct group *p_group;
struct passwd *p_passwd;
#endif
int found;
FILE *h_fuse_conf;
char line[256];
glob_xmount.may_set_fuse_allow_other=FALSE;
if(geteuid()==0) {
// Running as root, there should be no problems
glob_xmount.may_set_fuse_allow_other=TRUE;
return;
}
#if !defined(__APPLE__) && defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
// Check if a fuse group exists and if so, make sure user is a member of it.
// Makes only sense on Linux because as far as I know osxfuse has no own group
p_group=getgrnam("fuse");
if(p_group!=NULL) {
// Get effective user name
p_passwd=getpwuid(geteuid());
if(p_passwd==NULL) {
printf("\nWARNING: Unable to determine your effective user name. If "
"mounting works, you can ignore this message.\n\n");
return;
}
// Check if user is member of fuse group
found=FALSE;
while(*(p_group->gr_mem)!=NULL) {
if(strcmp(*(p_group->gr_mem),p_passwd->pw_name)==0) {
found=TRUE;
break;
}
p_group->gr_mem++;
}
if(found==FALSE) {
printf("\nWARNING: You are not a member of the \"fuse\" group. This will "
"prevent you from mounting images using xmount. Please add "
"yourself to the \"fuse\" group using the command "
"\"sudo usermod -a -G fuse %s\" and reboot your system or "
"execute xmount as root.\n\n",
p_passwd->pw_name);
return;
}
} else {
printf("\nWARNING: Your system does not seem to have a \"fuse\" group. If "
"mounting works, you can ignore this message.\n\n");
}
#endif
// Read FUSE's config file /etc/fuse.conf and check for set user_allow_other
h_fuse_conf=(FILE*)FOPEN("/etc/fuse.conf","r");
if(h_fuse_conf!=NULL) {
// Search conf file for set user_allow_others
found=FALSE;
while(fgets(line,sizeof(line),h_fuse_conf)!=NULL) {
// TODO: This works as long as there is no other parameter beginning with
// "user_allow_other" :)
if(strncmp(line,"user_allow_other",16)==0) {
found=TRUE;
break;
}
}
fclose(h_fuse_conf);
if(found==TRUE) {
glob_xmount.may_set_fuse_allow_other=TRUE;
} else {
printf("\nWARNING: FUSE will not allow other users nor root to access "
"your virtual harddisk image. To change this behavior, please "
"add \"user_allow_other\" to /etc/fuse.conf or execute xmount "
"as root.\n\n");
}
} else {
printf("\nWARNING: Unable to open /etc/fuse.conf. If mounting works, you "
"can ignore this message. If you encounter issues, please create "
"the file and add a single line containing the string "
"\"user_allow_other\" or execute xmount as root.\n\n");
return;
}
}
//! Parse command line options
/*!
* \param argc Number of cmdline params
* \param pp_argv Array containing cmdline params
* \return TRUE on success, FALSE on error
*/
static int ParseCmdLine(const int argc, char **pp_argv) {
int i=1;
int FuseMinusOControl=TRUE;
int FuseAllowOther=TRUE;
- int first;
uint64_t buf;
char *p_buf;
char **pp_buf;
int ret;
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
+ te_XmountOutputError output_ret=e_XmountOutputError_None;
// add pp_argv[0] to FUSE's argv
XMOUNT_MALLOC(glob_xmount.pp_fuse_argv,char**,sizeof(char*));
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[0],pp_argv[0]);
glob_xmount.fuse_argc=1;
// Parse options
while(i<argc && *pp_argv[i]=='-') {
if(strlen(pp_argv[i])>1 && *(pp_argv[i]+1)!='-') {
// Options beginning with one - are mostly FUSE specific
if(strcmp(pp_argv[i],"-d")==0) {
// Enable FUSE's and xmount's debug mode
XMOUNT_REALLOC(glob_xmount.pp_fuse_argv,
char**,
(glob_xmount.fuse_argc+1)*sizeof(char*));
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc],
pp_argv[i])
glob_xmount.fuse_argc++;
glob_xmount.debug=TRUE;
input_ret=XmountInput_EnableDebugging(glob_xmount.h_input);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to enable input debugging: Error code %u!\n",
input_ret);
return FALSE;
}
morph_ret=XmountMorphing_EnableDebugging(glob_xmount.h_morphing);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to enable morphing debugging: Error code %u!\n",
morph_ret);
return FALSE;
}
} else if(strcmp(pp_argv[i],"-h")==0) {
// Print help message
PrintUsage(pp_argv[0]);
exit(0);
} else if(strcmp(pp_argv[i],"-o")==0) {
// Next parameter specifies fuse mount options
if((i+1)<argc) {
i++;
// As the user specified the -o option, we assume he knows what he is
// doing. We won't append allow_other automatically. And we allow him
// to disable allow_other by passing a single "-o no_allow_other"
// which won't be passed to FUSE as it is xmount specific.
if(strcmp(pp_argv[i],"no_allow_other")!=0) {
glob_xmount.fuse_argc+=2;
XMOUNT_REALLOC(glob_xmount.pp_fuse_argv,
char**,
glob_xmount.fuse_argc*sizeof(char*));
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-2],
pp_argv[i-1]);
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-1],
pp_argv[i]);
FuseMinusOControl=FALSE;
} else FuseAllowOther=FALSE;
} else {
LOG_ERROR("Couldn't parse fuse mount options!\n")
return FALSE;
}
} else if(strcmp(pp_argv[i],"-s")==0) {
// Enable FUSE's single threaded mode
XMOUNT_REALLOC(glob_xmount.pp_fuse_argv,
char**,
(glob_xmount.fuse_argc+1)*sizeof(char*));
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc],
pp_argv[i]);
glob_xmount.fuse_argc++;
} else if(strcmp(pp_argv[i],"-V")==0) {
// Display FUSE version info
XMOUNT_REALLOC(glob_xmount.pp_fuse_argv,
char**,
(glob_xmount.fuse_argc+1)*sizeof(char*));
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc],
pp_argv[i]);
glob_xmount.fuse_argc++;
} else {
LOG_ERROR("Unknown command line option \"%s\"\n",pp_argv[i]);
return FALSE;
}
} else {
// Options beginning with -- are xmount specific
if(strcmp(pp_argv[i],"--cache")==0 /*|| strcmp(pp_argv[i],"--rw")==0*/) {
// Emulate writable access to mounted image
// Next parameter must be cache file to read/write changes from/to
if((i+1)<argc) {
i++;
XMOUNT_STRSET(glob_xmount.args.p_cache_file,pp_argv[i])
- glob_xmount.output.writable=TRUE;
+ glob_xmount.args.writable=TRUE;
} else {
LOG_ERROR("You must specify a cache file!\n")
return FALSE;
}
LOG_DEBUG("Enabling virtual write support using cache file \"%s\"\n",
glob_xmount.args.p_cache_file)
} else if(strcmp(pp_argv[i],"--in")==0) {
// Input image format and source files
if((i+2)<argc) {
i++;
// Save format
p_buf=pp_argv[i];
// Parse input image filename(s) and save to temporary array
i++;
buf=0;
pp_buf=NULL;
while(i<(argc-1) && strncmp(pp_argv[i],"--",2)!=0) {
buf++;
XMOUNT_REALLOC(pp_buf,char**,buf*sizeof(char*));
pp_buf[buf-1]=pp_argv[i];
i++;
}
i--;
if(buf==0) {
LOG_ERROR("No input files specified for \"--in %s\"!\n",p_buf);
return FALSE;
}
// Add input image
if((input_ret=XmountInput_AddImage(glob_xmount.h_input,
p_buf,
buf,
(const char**)pp_buf)
)!=e_XmountInput_Error_None)
{
LOG_ERROR("Unable to load input image: Error code %u!\n",input_ret);
XMOUNT_FREE(pp_buf);
return FALSE;
}
// Save first image path to generate fsname later on
if(glob_xmount.p_first_input_image_name==NULL) {
XMOUNT_STRSET(glob_xmount.p_first_input_image_name,
pp_buf[0]);
}
} else {
LOG_ERROR("You must specify an input image format and source file!\n");
return FALSE;
}
} else if(strcmp(pp_argv[i],"--inopts")==0) {
// Set input lib options
if((i+1)<argc) {
i++;
input_ret=XmountInput_SetOptions(glob_xmount.h_input,pp_argv[i]);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to parse input library options: Error code %u!\n",
input_ret);
return FALSE;
}
} else {
LOG_ERROR("You must specify special options!\n");
return FALSE;
}
} else if(strcmp(pp_argv[i],"--morph")==0) {
// Set morphing lib to use
if((i+1)<argc) {
i++;
morph_ret=XmountMorphing_SetType(glob_xmount.h_morphing,
pp_argv[i]);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to set morphing type: Error code %u!\n",
morph_ret);
return FALSE;
}
} else {
LOG_ERROR("You must specify morphing type!\n");
return FALSE;
}
} else if(strcmp(pp_argv[i],"--morphopts")==0) {
// Set morphing lib options
if((i+1)<argc) {
i++;
morph_ret=XmountMorphing_SetOptions(glob_xmount.h_morphing,
pp_argv[i]);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to parse morphing library options: "
"Error code %u!\n",
morph_ret);
return FALSE;
}
} else {
LOG_ERROR("You must specify special morphing lib params!\n");
return FALSE;
}
} else if(strcmp(pp_argv[i],"--offset")==0) {
// Set input image offset
if((i+1)<argc) {
i++;
buf=StrToUint64(pp_argv[i],&ret);
if(ret==0) {
LOG_ERROR("Unable to convert '%s' to a number!\n",pp_argv[i]);
return FALSE;
}
input_ret=XmountInput_SetInputOffset(glob_xmount.h_input,buf);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to set input offset: Error code %u!\n",input_ret);
return FALSE;
}
} else {
LOG_ERROR("You must specify an offset!\n")
return FALSE;
}
} else if(strcmp(pp_argv[i],"--out")==0) {
// Set output lib to use
if((i+1)<argc) {
i++;
- if(glob_xmount.output.p_output_format==NULL) {
- XMOUNT_STRSET(glob_xmount.output.p_output_format,pp_argv[i]);
- } else {
- LOG_ERROR("You can only specify --out once!")
+ output_ret=XmountOutput_SetFormat(glob_xmount.h_output,
+ pp_argv[i]);
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to set output format: Error code %u!\n",
+ output_ret);
return FALSE;
}
} else {
LOG_ERROR("You must specify an output format!\n");
return FALSE;
}
} else if(strcmp(pp_argv[i],"--outopts")==0) {
// Set output lib options
if((i+1)<argc) {
i++;
- if(glob_xmount.output.pp_lib_params==NULL) {
- if(XmountLib_SplitLibParams(pp_argv[i],
- &(glob_xmount.output.lib_params_count),
- &(glob_xmount.output.pp_lib_params)
- )==FALSE)
- {
- LOG_ERROR("Unable to parse output library options '%s'!\n",
- pp_argv[i]);
- return FALSE;
- }
- } else {
- LOG_ERROR("You can only specify --outopts once!")
+ output_ret=XmountOutput_SetOptions(glob_xmount.h_output,
+ pp_argv[i]);
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to parse output library options: "
+ "Error code %u!\n",
+ output_ret);
return FALSE;
}
} else {
LOG_ERROR("You must specify special output lib params!\n");
return FALSE;
}
} else if(strcmp(pp_argv[i],"--owcache")==0) {
// Enable writable access to mounted image and overwrite existing cache
// Next parameter must be cache file to read/write changes from/to
if((i+1)<argc) {
i++;
XMOUNT_STRSET(glob_xmount.args.p_cache_file,pp_argv[i])
- glob_xmount.output.writable=TRUE;
+ glob_xmount.args.writable=TRUE;
glob_xmount.args.overwrite_cache=TRUE;
} else {
LOG_ERROR("You must specify a cache file!\n")
return FALSE;
}
LOG_DEBUG("Enabling virtual write support overwriting cache file %s\n",
glob_xmount.args.p_cache_file)
} else if(strcmp(pp_argv[i],"--sizelimit")==0) {
// Set input image size limit
if((i+1)<argc) {
i++;
buf=StrToUint64(pp_argv[i],&ret);
if(ret==0) {
LOG_ERROR("Unable to convert '%s' to a number!\n",pp_argv[i]);
return FALSE;
}
input_ret=XmountInput_SetInputSizeLimit(glob_xmount.h_input,buf);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to set input size limit: Error code %u!\n",
input_ret);
return FALSE;
}
} else {
LOG_ERROR("You must specify a size limit!\n")
return FALSE;
}
} else if(strcmp(pp_argv[i],"--version")==0 ||
strcmp(pp_argv[i],"--info")==0)
{
// Print xmount info
printf(XMOUNT_COPYRIGHT_NOTICE "\n\n",XMOUNT_VERSION);
#ifdef __GNUC__
printf(" compile timestamp: %s %s\n",__DATE__,__TIME__);
printf(" gcc version: %s\n",__VERSION__);
#endif
#define PARSECMDLINE__PRINT_LOADED_LIBINFO(text,libret,fun,handle,err_ok) do { \
printf(text); \
libret=fun(handle,&p_buf); \
if(p_buf==NULL || libret!=err_ok) { \
LOG_ERROR("Unable to get library infos: Error code %u!\n",libret); \
return FALSE; \
} \
printf("%s",p_buf); \
XMOUNT_FREE(p_buf); \
} while(0)
PARSECMDLINE__PRINT_LOADED_LIBINFO(" loaded input libraries:\n",
input_ret,
XmountInput_GetLibsInfoText,
glob_xmount.h_input,
e_XmountInput_Error_None);
PARSECMDLINE__PRINT_LOADED_LIBINFO(" loaded morphing libraries:\n",
morph_ret,
XmountMorphing_GetLibsInfoText,
glob_xmount.h_morphing,
e_XmountMorphError_None);
+ PARSECMDLINE__PRINT_LOADED_LIBINFO(" loaded output libraries:\n",
+ output_ret,
+ XmountOutput_GetLibsInfoText,
+ glob_xmount.h_output,
+ e_XmountOutputError_None);
- printf(" loaded output libraries:\n");
- for(uint32_t ii=0;ii<glob_xmount.output.libs_count;ii++) {
- printf(" - %s supporting ",
- glob_xmount.output.pp_libs[ii]->p_name);
- p_buf=glob_xmount.output.pp_libs[ii]->p_supported_output_formats;
- first=TRUE;
- while(*p_buf!='\0') {
- if(first) {
- printf("\"%s\"",p_buf);
- first=FALSE;
- } else printf(", \"%s\"",p_buf);
- p_buf+=(strlen(p_buf)+1);
- }
- printf("\n");
- }
printf("\n");
exit(0);
} else {
LOG_ERROR("Unknown command line option \"%s\"\n",pp_argv[i]);
return FALSE;
}
}
i++;
}
// Extract mountpoint
if(i==(argc-1)) {
XMOUNT_STRSET(glob_xmount.p_mountpoint,pp_argv[argc-1])
XMOUNT_REALLOC(glob_xmount.pp_fuse_argv,
char**,
(glob_xmount.fuse_argc+1)*sizeof(char*));
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc],
glob_xmount.p_mountpoint);
glob_xmount.fuse_argc++;
} else {
LOG_ERROR("No mountpoint specified!\n")
return FALSE;
}
if(FuseMinusOControl==TRUE) {
// We control the -o flag, set subtype, fsname and allow_other options
glob_xmount.fuse_argc+=2;
XMOUNT_REALLOC(glob_xmount.pp_fuse_argv,
char**,
glob_xmount.fuse_argc*sizeof(char*));
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-2],"-o");
XMOUNT_STRSET(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-1],
"subtype=xmount");
if(glob_xmount.p_first_input_image_name!=NULL) {
// Set name of first source file as fsname
XMOUNT_STRAPP(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-1],
",fsname='");
// If possible, use full path
p_buf=realpath(glob_xmount.p_first_input_image_name,NULL);
if(p_buf==NULL) {
XMOUNT_STRSET(p_buf,glob_xmount.p_first_input_image_name);
}
// Make sure fsname does not include some forbidden chars
for(uint32_t i=0;i<strlen(p_buf);i++) {
if(p_buf[i]=='\'') p_buf[i]='_';
}
// Set fsname
XMOUNT_STRAPP(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-1],
p_buf);
XMOUNT_STRAPP(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-1],
"'");
free(p_buf);
}
if(FuseAllowOther==TRUE) {
// Add "allow_other" option if allowed
if(glob_xmount.may_set_fuse_allow_other) {
XMOUNT_STRAPP(glob_xmount.pp_fuse_argv[glob_xmount.fuse_argc-1],
",allow_other");
}
}
}
#undef PARSECMDLINE__PRINT_LOADED_LIBINFO
return TRUE;
}
//! Extract output file name from input image name
/*!
* \param p_orig_name Name of input image (may include a path)
* \return TRUE on success, FALSE on error
*/
static int ExtractOutputFileNames(char *p_orig_name) {
+ // TODO: Reimplement in output lib
+/*
char *tmp;
// Truncate any leading path
tmp=strrchr(p_orig_name,'/');
if(tmp!=NULL) p_orig_name=tmp+1;
// Extract file extension
tmp=strrchr(p_orig_name,'.');
// Set leading '/'
XMOUNT_STRSET(glob_xmount.output.p_virtual_image_path,"/");
- XMOUNT_STRSET(glob_xmount.output.p_info_path,"/");
+ XMOUNT_STRSET(glob_xmount.p_info_path,"/");
// Copy filename
if(tmp==NULL) {
// Input image filename has no extension
XMOUNT_STRAPP(glob_xmount.output.p_virtual_image_path,p_orig_name);
- XMOUNT_STRAPP(glob_xmount.output.p_info_path,p_orig_name);
- XMOUNT_STRAPP(glob_xmount.output.p_info_path,".info");
+ XMOUNT_STRAPP(glob_xmount.p_info_path,p_orig_name);
+ XMOUNT_STRAPP(glob_xmount.p_info_path,".info");
} else {
XMOUNT_STRNAPP(glob_xmount.output.p_virtual_image_path,p_orig_name,
strlen(p_orig_name)-strlen(tmp));
- XMOUNT_STRNAPP(glob_xmount.output.p_info_path,p_orig_name,
+ XMOUNT_STRNAPP(glob_xmount.p_info_path,p_orig_name,
strlen(p_orig_name)-strlen(tmp));
- XMOUNT_STRAPP(glob_xmount.output.p_info_path,".info");
+ XMOUNT_STRAPP(glob_xmount.p_info_path,".info");
}
// Add virtual file extensions
// TODO: Get from output lib and add
//XMOUNT_STRAPP(glob_xmount.output.p_virtual_image_path,".dd");
LOG_DEBUG("Set virtual image name to \"%s\"\n",
glob_xmount.output.p_virtual_image_path);
LOG_DEBUG("Set virtual image info name to \"%s\"\n",
- glob_xmount.output.p_info_path);
- return TRUE;
+ glob_xmount.p_info_path);
+*/
+ return FALSE;
}
//! Calculates an MD5 hash of the first HASH_AMOUNT bytes of the input image
/*!
* \param p_hash_low Pointer to the lower 64 bit of the hash
* \param p_hash_high Pointer to the higher 64 bit of the hash
* \return TRUE on success, FALSE on error
*/
static int CalculateInputImageHash(uint64_t *p_hash_low,
uint64_t *p_hash_high)
{
// TODO: Reimplement
/*
char hash[16];
md5_state_t md5_state;
char *p_buf;
int ret;
size_t read_data;
XMOUNT_MALLOC(p_buf,char*,HASH_AMOUNT*sizeof(char));
ret=ReadMorphedImageData(p_buf,0,HASH_AMOUNT,&read_data);
if(ret!=TRUE || read_data==0) {
LOG_ERROR("Couldn't read data from morphed image file!\n")
free(p_buf);
return FALSE;
}
// Calculate MD5 hash
md5_init(&md5_state);
md5_append(&md5_state,(const md5_byte_t*)p_buf,read_data);
md5_finish(&md5_state,(md5_byte_t*)hash);
// Convert MD5 hash into two 64bit integers
*p_hash_low=*((uint64_t*)hash);
*p_hash_high=*((uint64_t*)(hash+8));
free(p_buf);
*/
return TRUE;
}
//! Create info file
/*!
* \return TRUE on success, FALSE on error
*/
static int InitInfoFile() {
char *p_buf;
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
// Start with static input header
- XMOUNT_MALLOC(glob_xmount.output.p_info_file,
+ XMOUNT_MALLOC(glob_xmount.p_info_file,
char*,
strlen(IMAGE_INFO_INPUT_HEADER)+1);
- strncpy(glob_xmount.output.p_info_file,
+ strncpy(glob_xmount.p_info_file,
IMAGE_INFO_INPUT_HEADER,
strlen(IMAGE_INFO_INPUT_HEADER)+1);
#define INITINFOFILE__GET_CONTENT(libret,fun,handle,err_ok,err_msg) do { \
libret=fun(handle,&p_buf); \
if(p_buf==NULL || libret!=err_ok) { \
LOG_ERROR(err_msg "Error code %u!\n",libret); \
return FALSE; \
} \
- XMOUNT_STRAPP(glob_xmount.output.p_info_file,p_buf); \
+ XMOUNT_STRAPP(glob_xmount.p_info_file,p_buf); \
XMOUNT_FREE(p_buf); \
} while(0)
// Get and add infos from input lib(s)
INITINFOFILE__GET_CONTENT(input_ret,
XmountInput_GetInfoFileContent,
glob_xmount.h_input,
e_XmountInput_Error_None,
"Unable to get info file content from input lib: ");
// Add static morphing header
- XMOUNT_STRAPP(glob_xmount.output.p_info_file,IMAGE_INFO_MORPHING_HEADER);
+ XMOUNT_STRAPP(glob_xmount.p_info_file,IMAGE_INFO_MORPHING_HEADER);
// Get and add infos from morphing lib
INITINFOFILE__GET_CONTENT(morph_ret,
XmountMorphing_GetInfoFileContent,
glob_xmount.h_morphing,
e_XmountMorphError_None,
"Unable to get info file content from morphing "
"lib: ");
#undef INITINFOFILE__GET_CONTENT
return TRUE;
}
//! Load input / morphing libs
/*!
* \return TRUE on success, FALSE on error
*/
static int LoadLibs() {
DIR *p_dir=NULL;
struct dirent *p_dirent=NULL;
- int base_library_path_len=0;
- char *p_library_path=NULL;
- void *p_libxmount=NULL;
- t_LibXmount_Output_GetApiVersion pfun_output_GetApiVersion;
- t_LibXmount_Output_GetSupportedFormats pfun_output_GetSupportedFormats;
- t_LibXmount_Output_GetFunctions pfun_output_GetFunctions;
- const char *p_supported_formats=NULL;
- const char *p_buf;
- uint32_t supported_formats_len=0;
uint32_t input_lib_count=0;
uint32_t morphing_lib_count=0;
- pts_OutputLib p_output_lib=NULL;
+ uint32_t output_lib_count=0;
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
+ te_XmountOutputError output_ret=e_XmountOutputError_None;
LOG_DEBUG("Searching for xmount libraries in '%s'.\n",
XMOUNT_LIBRARY_PATH);
// Open lib dir
p_dir=opendir(XMOUNT_LIBRARY_PATH);
if(p_dir==NULL) {
LOG_ERROR("Unable to access xmount library directory '%s'!\n",
XMOUNT_LIBRARY_PATH);
return FALSE;
}
- // Construct base library path
- base_library_path_len=strlen(XMOUNT_LIBRARY_PATH);
- XMOUNT_STRSET(p_library_path,XMOUNT_LIBRARY_PATH);
- if(XMOUNT_LIBRARY_PATH[base_library_path_len]!='/') {
- base_library_path_len++;
- XMOUNT_STRAPP(p_library_path,"/");
- }
-
-#define LIBXMOUNT_LOAD(path) { \
- p_libxmount=dlopen(path,RTLD_NOW); \
- if(p_libxmount==NULL) { \
- LOG_ERROR("Unable to load input library '%s': %s!\n", \
- path, \
- dlerror()); \
- continue; \
- } \
-}
-#define LIBXMOUNT_LOAD_SYMBOL(name,pfun) { \
- if((pfun=dlsym(p_libxmount,name))==NULL) { \
- LOG_ERROR("Unable to load symbol '%s' from library '%s'!\n", \
- name, \
- p_library_path); \
- dlclose(p_libxmount); \
- p_libxmount=NULL; \
- continue; \
- } \
-}
-
// Loop over lib dir
while((p_dirent=readdir(p_dir))!=NULL) {
LOG_DEBUG("Trying to load '%s'\n",p_dirent->d_name);
- // Construct full path to found object
- p_library_path=realloc(p_library_path,
- base_library_path_len+strlen(p_dirent->d_name)+1);
- if(p_library_path==NULL) {
- LOG_ERROR("Couldn't allocate memory!\n");
- exit(1);
- }
- strcpy(p_library_path+base_library_path_len,p_dirent->d_name);
-
if(strncmp(p_dirent->d_name,
XMOUNT_INPUT_LIBRARY_NAMING_SCHEME,
strlen(XMOUNT_INPUT_LIBRARY_NAMING_SCHEME))==0)
{
// Found possible input lib. Try to load it
input_ret=XmountInput_AddLibrary(glob_xmount.h_input,p_dirent->d_name);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to add input library '%s': Error code %u!\n",
p_dirent->d_name,
input_ret);
continue;
}
} if(strncmp(p_dirent->d_name,
XMOUNT_MORPHING_LIBRARY_NAMING_SCHEME,
strlen(XMOUNT_MORPHING_LIBRARY_NAMING_SCHEME))==0)
{
// Found possible morphing lib. Try to load it
morph_ret=XmountMorphing_AddLibrary(glob_xmount.h_morphing,
p_dirent->d_name);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to add morphing library '%s': Error code %u!\n",
p_dirent->d_name,
morph_ret);
continue;
}
} if(strncmp(p_dirent->d_name,"libxmount_output_",17)==0) {
// Found possible output lib. Try to load it
- LIBXMOUNT_LOAD(p_library_path);
-
- // Load library symbols
- LIBXMOUNT_LOAD_SYMBOL("LibXmount_Output_GetApiVersion",
- pfun_output_GetApiVersion);
-
- // Check library's API version
- if(pfun_output_GetApiVersion()!=LIBXMOUNT_OUTPUT_API_VERSION) {
- LOG_DEBUG("Failed! Wrong API version.\n");
- LOG_ERROR("Unable to load output library '%s'. Wrong API version\n",
- p_library_path);
- dlclose(p_libxmount);
- continue;
- }
-
- LIBXMOUNT_LOAD_SYMBOL("LibXmount_Output_GetSupportedFormats",
- pfun_output_GetSupportedFormats);
- LIBXMOUNT_LOAD_SYMBOL("LibXmount_Output_GetFunctions",
- pfun_output_GetFunctions);
-
- // Construct new entry for our library list
- XMOUNT_MALLOC(p_output_lib,pts_OutputLib,sizeof(ts_OutputLib));
- // Initialize lib_functions structure to NULL
- memset(&(p_output_lib->lib_functions),
- 0,
- sizeof(ts_LibXmountOutput_Functions));
-
- // Set name and handle
- XMOUNT_STRSET(p_output_lib->p_name,p_dirent->d_name);
- p_output_lib->p_lib=p_libxmount;
-
- // Get and set supported types
- p_supported_formats=pfun_output_GetSupportedFormats();
- supported_formats_len=0;
- p_buf=p_supported_formats;
- while(*p_buf!='\0') {
- supported_formats_len+=(strlen(p_buf)+1);
- p_buf+=(strlen(p_buf)+1);
- }
- supported_formats_len++;
- XMOUNT_MALLOC(p_output_lib->p_supported_output_formats,
- char*,
- supported_formats_len);
- memcpy(p_output_lib->p_supported_output_formats,
- p_supported_formats,
- supported_formats_len);
-
- // Get, set and check lib_functions
- pfun_output_GetFunctions(&(p_output_lib->lib_functions));
- if(p_output_lib->lib_functions.CreateHandle==NULL ||
- p_output_lib->lib_functions.DestroyHandle==NULL ||
- p_output_lib->lib_functions.Transform==NULL ||
- p_output_lib->lib_functions.Size==NULL ||
- p_output_lib->lib_functions.Read==NULL ||
- p_output_lib->lib_functions.Write==NULL ||
- p_output_lib->lib_functions.OptionsHelp==NULL ||
- p_output_lib->lib_functions.OptionsParse==NULL ||
- p_output_lib->lib_functions.GetInfofileContent==NULL ||
- p_output_lib->lib_functions.GetErrorMessage==NULL ||
- p_output_lib->lib_functions.FreeBuffer==NULL)
- {
- LOG_DEBUG("Missing implemention of one or more functions in lib %s!\n",
- p_dirent->d_name);
- free(p_output_lib->p_supported_output_formats);
- free(p_output_lib->p_name);
- free(p_output_lib);
- dlclose(p_libxmount);
+ output_ret=XmountOutput_AddLibrary(glob_xmount.h_output,
+ p_dirent->d_name);
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to add output library '%s': Error code %u!\n",
+ p_dirent->d_name,
+ output_ret);
continue;
}
-
- // Add entry to the input library list
- XMOUNT_REALLOC(glob_xmount.output.pp_libs,
- pts_OutputLib*,
- sizeof(pts_OutputLib)*
- (glob_xmount.output.libs_count+1));
- glob_xmount.output.pp_libs[glob_xmount.output.libs_count++]=
- p_output_lib;
-
- LOG_DEBUG("Output library '%s' loaded successfully\n",p_dirent->d_name);
} else {
LOG_DEBUG("Ignoring '%s'.\n",p_dirent->d_name);
continue;
}
}
#undef LIBXMOUNT_LOAD_SYMBOL
#undef LIBXMOUNT_LOAD
// Get loaded library counts
input_ret=XmountInput_GetLibraryCount(glob_xmount.h_input,&input_lib_count);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to get input library count: Error code %u!\n",input_ret);
return FALSE;
}
morph_ret=XmountMorphing_GetLibraryCount(glob_xmount.h_morphing,
&morphing_lib_count);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to get morphing library count: Error code %u!\n",
- input_ret);
+ morph_ret);
+ return FALSE;
+ }
+ output_ret=XmountOutput_GetLibraryCount(glob_xmount.h_output,
+ &output_lib_count);
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to get output library count: Error code %u!\n",
+ output_ret);
return FALSE;
}
LOG_DEBUG("A total of %u input libs, %u morphing libs and %u output libs "
"were loaded.\n",
input_lib_count,
morphing_lib_count,
- glob_xmount.output.libs_count);
+ output_lib_count);
- free(p_library_path);
closedir(p_dir);
return ((input_lib_count>0 &&
morphing_lib_count>0 &&
- glob_xmount.output.libs_count>0) ? TRUE : FALSE);
-}
-
-//! Search an appropriate output lib for the specified output format
-/*!
- * \return TRUE on success, FALSE on error
- */
-static int FindOutputLib() {
- char *p_buf;
-
- LOG_DEBUG("Trying to find suitable library for output format '%s'.\n",
- glob_xmount.output.p_output_format);
-
- // Loop over all loaded output libs
- for(uint32_t i=0;i<glob_xmount.output.libs_count;i++) {
- LOG_DEBUG("Checking output library %s\n",
- glob_xmount.output.pp_libs[i]->p_name);
- p_buf=glob_xmount.output.pp_libs[i]->p_supported_output_formats;
- while(*p_buf!='\0') {
- if(strcmp(p_buf,glob_xmount.output.p_output_format)==0) {
- // Library supports output type, set lib functions
- LOG_DEBUG("Output library '%s' pretends to handle that output format.\n",
- glob_xmount.output.pp_libs[i]->p_name);
- glob_xmount.output.p_functions=
- &(glob_xmount.output.pp_libs[i]->lib_functions);
- return TRUE;
- }
- p_buf+=(strlen(p_buf)+1);
- }
- }
-
- LOG_DEBUG("Couldn't find any suitable library.\n");
-
- // No library supporting output format found
- return FALSE;
+ output_lib_count>0) ? TRUE : FALSE);
}
static int InitResources() {
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
+ te_XmountOutputError output_ret=e_XmountOutputError_None;
// Args
glob_xmount.args.overwrite_cache=FALSE;
glob_xmount.args.p_cache_file=NULL;
+ glob_xmount.args.writable=FALSE;
// Input
input_ret=XmountInput_CreateHandle(&(glob_xmount.h_input));
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to create input handle: Error code %u!\n",input_ret);
return FALSE;
}
// Morphing
morph_ret=XmountMorphing_CreateHandle(&(glob_xmount.h_morphing),
&LibXmount_Morphing_ImageCount,
&LibXmount_Morphing_Size,
&LibXmount_Morphing_Read,
&LibXmount_Morphing_Write);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to create morphing handle: Error code %u!\n",morph_ret);
return FALSE;
}
// Cache
glob_xmount.h_cache=NULL;
// Output
- glob_xmount.output.libs_count=0;
- glob_xmount.output.pp_libs=NULL;
- glob_xmount.output.p_output_format=NULL;
- glob_xmount.output.lib_params_count=0;
- glob_xmount.output.pp_lib_params=NULL;
- glob_xmount.output.p_handle=NULL;
- glob_xmount.output.p_functions=NULL;
- glob_xmount.output.input_functions.Size=&LibXmount_Output_Size;
- glob_xmount.output.input_functions.Read=&LibXmount_Output_Read;
- glob_xmount.output.input_functions.Write=&LibXmount_Output_Write;
- glob_xmount.output.image_size=0;
- glob_xmount.output.writable=FALSE;
- glob_xmount.output.p_virtual_image_path=NULL;
- glob_xmount.output.p_info_path=NULL;
- glob_xmount.output.p_info_file=NULL;
+ output_ret=XmountOutput_CreateHandle(&(glob_xmount.h_output),
+ &LibXmount_Output_Size,
+ &LibXmount_Output_Read,
+ &LibXmount_Output_Write);
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to create output handle: Error code %u!\n",output_ret);
+ return FALSE;
+ }
// Misc data
glob_xmount.debug=FALSE;
glob_xmount.may_set_fuse_allow_other=FALSE;
glob_xmount.fuse_argc=0;
glob_xmount.pp_fuse_argv=NULL;
glob_xmount.p_mountpoint=NULL;
glob_xmount.p_first_input_image_name=NULL;
+ glob_xmount.p_info_path=NULL;
+ glob_xmount.p_info_file=NULL;
glob_xmount.image_hash_lo=0;
glob_xmount.image_hash_hi=0;
return TRUE;
}
/*
* FreeResources
*/
static void FreeResources() {
int ret;
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
te_XmountCache_Error cache_ret=e_XmountCache_Error_None;
+ te_XmountOutputError output_ret=e_XmountOutputError_None;
LOG_DEBUG("Freeing all resources\n");
// Misc
if(glob_xmount.p_first_input_image_name!=NULL) {
XMOUNT_FREE(glob_xmount.p_first_input_image_name);
}
if(glob_xmount.pp_fuse_argv!=NULL) {
- for(int i=0;i<glob_xmount.fuse_argc;i++) free(glob_xmount.pp_fuse_argv[i]);
- free(glob_xmount.pp_fuse_argv);
+ for(int i=0;i<glob_xmount.fuse_argc;i++) {
+ XMOUNT_FREE(glob_xmount.pp_fuse_argv[i]);
+ }
+ XMOUNT_FREE(glob_xmount.pp_fuse_argv);
}
- if(glob_xmount.p_mountpoint!=NULL) free(glob_xmount.p_mountpoint);
+ if(glob_xmount.p_mountpoint!=NULL) XMOUNT_FREE(glob_xmount.p_mountpoint);
+ if(glob_xmount.p_info_path!=NULL) XMOUNT_FREE(glob_xmount.p_info_path);
+ if(glob_xmount.p_info_file!=NULL) XMOUNT_FREE(glob_xmount.p_info_file);
// Output
- if(glob_xmount.output.p_functions!=NULL) {
- if(glob_xmount.output.p_handle!=NULL) {
- // Destroy output handle
- ret=glob_xmount.output.p_functions->
- DestroyHandle(&(glob_xmount.output.p_handle));
- if(ret!=0) {
- LOG_ERROR("Unable to destroy output handle: %s!\n",
- glob_xmount.output.p_functions->GetErrorMessage(ret));
- }
- }
- }
- if(glob_xmount.output.pp_lib_params!=NULL) {
- for(uint32_t i=0;i<glob_xmount.output.lib_params_count;i++)
- free(glob_xmount.output.pp_lib_params[i]);
- free(glob_xmount.output.pp_lib_params);
+ output_ret=XmountOutput_DestroyHandle(&(glob_xmount.h_output));
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to destroy output handle: Error code %u: Ignoring!\n",
+ output_ret);
}
- if(glob_xmount.output.p_output_format!=NULL)
- free(glob_xmount.output.p_output_format);
- if(glob_xmount.output.pp_libs!=NULL) {
- // Unload output libs
- for(uint32_t i=0;i<glob_xmount.output.libs_count;i++) {
- if(glob_xmount.output.pp_libs[i]==NULL) continue;
- if(glob_xmount.output.pp_libs[i]->p_supported_output_formats!=NULL)
- free(glob_xmount.output.pp_libs[i]->p_supported_output_formats);
- if(glob_xmount.output.pp_libs[i]->p_lib!=NULL)
- dlclose(glob_xmount.output.pp_libs[i]->p_lib);
- if(glob_xmount.output.pp_libs[i]->p_name!=NULL)
- free(glob_xmount.output.pp_libs[i]->p_name);
- free(glob_xmount.output.pp_libs[i]);
- }
- free(glob_xmount.output.pp_libs);
- }
- if(glob_xmount.output.p_info_path!=NULL)
- free(glob_xmount.output.p_info_path);
- if(glob_xmount.output.p_info_file!=NULL)
- free(glob_xmount.output.p_info_file);
- if(glob_xmount.output.p_virtual_image_path!=NULL)
- free(glob_xmount.output.p_virtual_image_path);
// Cache
if(glob_xmount.h_cache!=NULL) {
cache_ret=XmountCache_Close(&(glob_xmount.h_cache));
if(cache_ret!=e_XmountCache_Error_None) {
LOG_ERROR("Unable to close cache file: Error code %u: Ignoring!\n",
cache_ret);
}
}
// Morphing
morph_ret=XmountMorphing_DestroyHandle(&(glob_xmount.h_morphing));
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to destroy morphing handle: Error code %u: Ignoring!\n",
morph_ret);
}
// Input
// Just in case close was not already called, call it now
input_ret=XmountInput_Close(glob_xmount.h_input);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to close input image(s): Error code %u: Ignoring!\n",
input_ret);
}
input_ret=XmountInput_DestroyHandle(&(glob_xmount.h_input));
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to destroy input handle: Error code %u: Ignoring!\n",
input_ret);
}
// Args
if(glob_xmount.args.p_cache_file!=NULL) {
XMOUNT_FREE(glob_xmount.args.p_cache_file);
}
// Before we return, initialize everything in case ReleaseResources would be
// called again.
+ // TODO: This is bad as it will re-create handles etc... Get rid of it!!
InitResources();
}
/*******************************************************************************
* LibXmount_Morphing function implementation
******************************************************************************/
//! Function to get the amount of input images
/*!
* \param p_count Count of input images
* \return 0 on success
*/
static int LibXmount_Morphing_ImageCount(uint64_t *p_count) {
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
input_ret=XmountInput_GetImageCount(glob_xmount.h_input,p_count);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to get input image count: Error code %u!\n",input_ret);
return -EIO;
}
return 0;
}
//! Function to get the size of the morphed data
/*!
* \param image Image number
* \param p_size Pointer to store input image's size to
* \return 0 on success
*/
static int LibXmount_Morphing_Size(uint64_t image, uint64_t *p_size) {
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
input_ret=XmountInput_GetSize(glob_xmount.h_input,image,p_size);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to get size of input image %" PRIu64 ": Error code %u!\n",
image,
input_ret);
return -EIO;
}
return 0;
}
//! Function to read data from input image
/*!
* \param image Image number
* \param p_buf Buffer to store read data to
* \param offset Position at which to start reading
* \param count Amount of bytes to read
* \param p_read Number of read bytes on success
* \return 0 on success or negated error code on error
*/
static int LibXmount_Morphing_Read(uint64_t image,
char *p_buf,
off_t offset,
size_t count,
size_t *p_read)
{
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
input_ret=XmountInput_ReadData(glob_xmount.h_input,
image,
p_buf,
offset,
count,
p_read);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to read data of input image %" PRIu64
": Error code %u!\n",
image,
input_ret);
return -EIO;
}
return 0;
}
static int LibXmount_Morphing_Write(uint64_t image,
char *p_buf,
off_t offset,
size_t count,
size_t *p_written)
{
// TODO: Implement
/*
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
input_ret=XmountInput_ReadData(glob_xmount.h_input,
image,
p_buf,
offset,
count,
p_read);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to read data of input image %" PRIu64
": Error code %u!\n",
image,
input_ret);
return -EIO;
}
*/
return 0;
}
/*******************************************************************************
* LibXmount_Output function implementation
******************************************************************************/
//! Function to get the size of the morphed image
/*!
* \param p_size Pointer to store morphed image's size to
* \return 0 on success
*/
static int LibXmount_Output_Size(uint64_t *p_size) {
te_XmountMorphError morph_ret=e_XmountMorphError_None;
morph_ret=XmountMorphing_GetSize(glob_xmount.h_morphing,p_size);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to get morphed image size: Error code %u!\n",morph_ret);
return FALSE;
}
return TRUE;
}
//! Function to read data from the morphed image
/*!
* \param p_buf Buffer to store read data to
* \param offset Position at which to start reading
* \param count Amount of bytes to read
* \param p_read Number of read bytes on success
* \return 0 on success or negated error code on error
*/
static int LibXmount_Output_Read(char *p_buf,
off_t offset,
size_t count,
size_t *p_read)
{
uint64_t block_off=0;
uint64_t cur_block=0;
uint64_t cur_to_read=0;
uint64_t image_size=0;
size_t read=0;
size_t to_read=0;
uint8_t is_block_cached=FALSE;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
te_XmountCache_Error cache_ret=e_XmountCache_Error_None;
// Make sure we aren't reading past EOF of image file
morph_ret=XmountMorphing_GetSize(glob_xmount.h_morphing,&image_size);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Couldn't get size of morphed image: Error code %u!\n",morph_ret);
return -EIO;
}
if(offset>=image_size) {
// Offset is beyond image size
LOG_DEBUG("Offset %zu is at / beyond size of morphed image.\n",offset);
*p_read=0;
return FALSE;
}
if(offset+count>image_size) {
// Attempt to read data past EOF of morphed image file
to_read=image_size-offset;
LOG_DEBUG("Attempt to read data past EOF of morphed image. Corrected size "
"from %zu to %" PRIu64 ".\n",
count,
to_read);
} else to_read=count;
// Calculate block to start reading data from
cur_block=offset/XMOUNT_CACHE_BLOCK_SIZE;
block_off=offset%XMOUNT_CACHE_BLOCK_SIZE;
// Read image data
while(to_read!=0) {
// Calculate how many bytes we have to read from this block
if(block_off+to_read>XMOUNT_CACHE_BLOCK_SIZE) {
cur_to_read=XMOUNT_CACHE_BLOCK_SIZE-block_off;
} else cur_to_read=to_read;
// Determine if we have to read cached data
is_block_cached=FALSE;
- if(glob_xmount.output.writable==TRUE) {
+ if(glob_xmount.args.writable==TRUE) {
cache_ret=XmountCache_IsBlockCached(glob_xmount.h_cache,cur_block);
if(cache_ret==e_XmountCache_Error_None) is_block_cached=TRUE;
else if(cache_ret!=e_XmountCache_Error_UncachedBlock) {
LOG_ERROR("Unable to determine if block %" PRIu64 " is cached: "
"Error code %u!\n",
cur_block,
cache_ret);
return -EIO;
}
}
// Check if block is cached
if(is_block_cached==TRUE) {
// Write support enabled and need to read altered data from cachefile
LOG_DEBUG("Reading %zu bytes from block cache file\n",cur_to_read);
cache_ret=XmountCache_BlockCacheRead(glob_xmount.h_cache,
p_buf,
cur_block,
block_off,
cur_to_read);
if(cache_ret!=e_XmountCache_Error_None) {
LOG_ERROR("Unable to read %" PRIu64
" bytes of cached data from cache block %" PRIu64
" at cache block offset %" PRIu64 ": Error code %u!\n",
cur_to_read,
cur_block,
block_off,
cache_ret);
return -EIO;
}
} else {
// No write support or data not cached
morph_ret=XmountMorphing_ReadData(glob_xmount.h_morphing,
p_buf,
(cur_block*XMOUNT_CACHE_BLOCK_SIZE)+
block_off,
cur_to_read,
&read);
if(morph_ret!=e_XmountMorphError_None || read!=cur_to_read) {
LOG_ERROR("Couldn't read %zu bytes at offset %zu from morphed image: "
"Error code %u!\n",
cur_to_read,
offset,
morph_ret);
return -EIO;
}
LOG_DEBUG("Read %" PRIu64 " bytes at offset %" PRIu64
" from morphed image file\n",
cur_to_read,
(cur_block*XMOUNT_CACHE_BLOCK_SIZE)+block_off);
}
cur_block++;
block_off=0;
p_buf+=cur_to_read;
to_read-=cur_to_read;
}
*p_read=to_read;
return TRUE;
}
//! Function to write data to the morphed image
/*!
* \param p_buf Buffer with data to write
* \param offset Position at which to start writing
* \param count Amount of bytes to write
* \param p_written Number of written bytes on success
* \return 0 on success or negated error code on error
*/
static int LibXmount_Output_Write(char *p_buf,
off_t offset,
size_t count,
size_t *p_written)
{
uint64_t block_off=0;
uint64_t cur_block=0;
uint64_t cur_to_read=0;
uint64_t cur_to_write=0;
uint64_t image_size=0;
uint64_t read=0;
size_t to_write=0;
char *p_buf2=NULL;
uint8_t is_block_cached=FALSE;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
te_XmountCache_Error cache_ret=e_XmountCache_Error_None;
// Make sure we aren't writing past EOF of image file
morph_ret=XmountMorphing_GetSize(glob_xmount.h_morphing,&image_size);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Couldn't get size of morphed image: Error code %u!\n",morph_ret);
return -EIO;
}
if(offset>=image_size) {
// Offset is beyond image size
LOG_DEBUG("Offset %zu is at / beyond size of morphed image.\n",offset);
*p_written=0;
return 0;
}
if(offset+count>image_size) {
// Attempt to write data past EOF of morphed image file
to_write=image_size-offset;
LOG_DEBUG("Attempt to write data past EOF of morphed image. Corrected size "
"from %zu to %" PRIu64 ".\n",
count,
to_write);
} else to_write=count;
// Calculate block to start writing data to
cur_block=offset/XMOUNT_CACHE_BLOCK_SIZE;
block_off=offset%XMOUNT_CACHE_BLOCK_SIZE;
while(to_write!=0) {
// Calculate how many bytes we have to write to this block
if(block_off+to_write>XMOUNT_CACHE_BLOCK_SIZE) {
cur_to_write=XMOUNT_CACHE_BLOCK_SIZE-block_off;
} else cur_to_write=to_write;
// Determine if block is already in cache
is_block_cached=FALSE;
cache_ret=XmountCache_IsBlockCached(glob_xmount.h_cache,cur_block);
if(cache_ret==e_XmountCache_Error_None) is_block_cached=TRUE;
else if(cache_ret!=e_XmountCache_Error_UncachedBlock) {
LOG_ERROR("Unable to determine if block %" PRIu64 " is cached: "
"Error code %u!\n",
cur_block,
cache_ret);
return -EIO;
}
// Check if block is cached
if(is_block_cached==TRUE) {
// Block is cached
cache_ret=XmountCache_BlockCacheWrite(glob_xmount.h_cache,
p_buf,
cur_block,
block_off,
cur_to_write);
if(cache_ret!=e_XmountCache_Error_None) {
LOG_ERROR("Unable to write %" PRIu64
" bytes of data to cache block %" PRIu64
" at cache block offset %" PRIu64 ": Error code %u!\n",
cur_to_write,
cur_block,
block_off,
cache_ret);
return -EIO;
}
LOG_DEBUG("Wrote %" PRIu64 " bytes to block cache\n",cur_to_write);
} else {
// Uncached block. Need to cache entire new block
// Prepare new write buffer
XMOUNT_MALLOC(p_buf2,char*,XMOUNT_CACHE_BLOCK_SIZE);
memset(p_buf2,0x00,XMOUNT_CACHE_BLOCK_SIZE);
// Read full block from morphed image
cur_to_read=XMOUNT_CACHE_BLOCK_SIZE;
if((cur_block*XMOUNT_CACHE_BLOCK_SIZE)+XMOUNT_CACHE_BLOCK_SIZE>image_size) {
cur_to_read=XMOUNT_CACHE_BLOCK_SIZE-(((cur_block*XMOUNT_CACHE_BLOCK_SIZE)+
XMOUNT_CACHE_BLOCK_SIZE)-image_size);
}
morph_ret=XmountMorphing_ReadData(glob_xmount.h_morphing,
p_buf,
cur_block*XMOUNT_CACHE_BLOCK_SIZE,
cur_to_read,
&read);
if(morph_ret!=e_XmountMorphError_None || read!=cur_to_read) {
LOG_ERROR("Couldn't read %" PRIu64 " bytes at offset %zu "
"from morphed image: Error code %u!\n",
cur_to_read,
offset,
morph_ret);
XMOUNT_FREE(p_buf2);
return -EIO;
}
// Set changed data
memcpy(p_buf2+block_off,p_buf,cur_to_write);
cache_ret=XmountCache_BlockCacheAppend(glob_xmount.h_cache,
p_buf,
cur_block);
if(cache_ret!=e_XmountCache_Error_None) {
LOG_ERROR("Unable to append new block cache block %" PRIu64
": Error code %u!\n",
cur_block,
cache_ret);
XMOUNT_FREE(p_buf2);
return -EIO;
}
XMOUNT_FREE(p_buf2);
LOG_DEBUG("Appended new block cache block %" PRIu64 "\n",cur_block);
}
block_off=0;
cur_block++;
p_buf+=cur_to_write;
to_write-=cur_to_write;
}
*p_written=to_write;
return TRUE;
}
/*******************************************************************************
* Main
******************************************************************************/
int main(int argc, char *argv[]) {
uint64_t input_image_count=0;
struct stat file_stat;
int ret;
int fuse_ret;
char *p_err_msg;
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
//te_XmountCache_Error cache_ret=e_XmountCache_Error_None;
+ te_XmountOutputError output_ret=e_XmountOutputError_None;
// Set implemented FUSE functions
struct fuse_operations xmount_operations = {
//.access=FuseAccess,
.getattr=Xmount_FuseGetAttr,
.mkdir=Xmount_FuseMkDir,
.mknod=Xmount_FuseMkNod,
.open=Xmount_FuseOpen,
.readdir=Xmount_FuseReadDir,
.read=Xmount_FuseRead,
.rename=Xmount_FuseRename,
.rmdir=Xmount_FuseRmDir,
//.statfs=FuseStatFs,
.unlink=Xmount_FuseUnlink,
.write=Xmount_FuseWrite
};
// Disable std output / input buffering
setbuf(stdout,NULL);
setbuf(stderr,NULL);
// Init glob_xmount
if(InitResources()==FALSE) {
LOG_ERROR("Unable to initialize internal resources!\n");
return 1;
}
// Load input, morphing and output libs
if(!LoadLibs()) {
LOG_ERROR("Unable to load any libraries!\n")
return 1;
}
// Check FUSE settings
CheckFuseSettings();
// Parse command line options
if(ParseCmdLine(argc,argv)!=TRUE) {
PrintUsage(argv[0]);
FreeResources();
return 1;
}
// Check command line options
input_ret=XmountInput_GetImageCount(glob_xmount.h_input,&input_image_count);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to get input image count: Error code %u!\n",input_ret);
return 1;
}
if(input_image_count==0) {
LOG_ERROR("No --in command line option specified!\n")
PrintUsage(argv[0]);
FreeResources();
return 1;
}
if(glob_xmount.fuse_argc<2) {
LOG_ERROR("Couldn't parse command line options!\n")
PrintUsage(argv[0]);
FreeResources();
return 1;
}
// TODO: Add default output image format here
// Check if mountpoint is a valid dir
if(stat(glob_xmount.p_mountpoint,&file_stat)!=0) {
LOG_ERROR("Unable to stat mount point '%s'!\n",glob_xmount.p_mountpoint);
PrintUsage(argv[0]);
FreeResources();
return 1;
}
if(!S_ISDIR(file_stat.st_mode)) {
LOG_ERROR("Mount point '%s' is not a directory!\n",
glob_xmount.p_mountpoint);
PrintUsage(argv[0]);
FreeResources();
return 1;
}
if(glob_xmount.debug==TRUE) {
LOG_DEBUG("Options passed to FUSE: ")
for(int i=0;i<glob_xmount.fuse_argc;i++) {
printf("%s ",glob_xmount.pp_fuse_argv[i]);
}
printf("\n");
}
// Init mutexes
pthread_mutex_init(&(glob_xmount.mutex_image_rw),NULL);
pthread_mutex_init(&(glob_xmount.mutex_info_read),NULL);
// Open input image(s)
input_ret=XmountInput_Open(glob_xmount.h_input);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Failed opening input image(s): Error code %u!\n",input_ret);
FreeResources();
return 1;
}
// Morph input image(s)
morph_ret=XmountMorphing_StartMorphing(glob_xmount.h_morphing);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to start morphing: Error code %u!\n",morph_ret);
FreeResources();
return 1;
}
// Open / Create cache if needed
- if(glob_xmount.output.writable) {
+ if(glob_xmount.args.writable) {
// Init cache file and cache file block index
// TODO: Add cache file creration / opening
/*
if(glob_xmount.args.overwrite_cache==TRUE) {
cache_ret=XmountCache_Create(&(glob_xmount.h_cache),
glob_xmount.args.p_cache_file,
} else {
cache_ret=XmountCache_Open
}
te_XmountCache_Error cache_ret=e_XmountCache_Error_None;
if(!InitCacheFile()) {
LOG_ERROR("Couldn't initialize cache file!\n")
FreeResources();
return 1;
}
*/
LOG_DEBUG("Cache file initialized successfully\n")
}
// Init random generator
srand(time(NULL));
// Calculate partial MD5 hash of input image file
if(CalculateInputImageHash(&(glob_xmount.image_hash_lo),
&(glob_xmount.image_hash_hi))==FALSE)
{
LOG_ERROR("Couldn't calculate partial hash of morphed image!\n")
return 1;
}
if(glob_xmount.debug==TRUE) {
LOG_DEBUG("Partial MD5 hash of morphed image: ")
for(int i=0;i<8;i++)
printf("%02hhx",*(((char*)(&(glob_xmount.image_hash_lo)))+i));
for(int i=0;i<8;i++)
printf("%02hhx",*(((char*)(&(glob_xmount.image_hash_hi)))+i));
printf("\n");
}
- if(!ExtractOutputFileNames(glob_xmount.p_first_input_image_name)) {
- LOG_ERROR("Couldn't extract virtual file names!\n");
- FreeResources();
- return 1;
- }
- LOG_DEBUG("Virtual file names extracted successfully\n")
-
- // Find output lib
- if(FindOutputLib()!=TRUE) {
- LOG_ERROR("Unable to find a library supporting the output format '%s'!\n",
- glob_xmount.output.p_output_format);
+ // Transform morphed image into output format
+ output_ret=XmountOutput_Transform(glob_xmount.h_output);
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to transform output image: Error code %u!\n",output_ret);
FreeResources();
return 1;
}
- // Init output
- ret=glob_xmount.output.p_functions->
- CreateHandle(&glob_xmount.output.p_handle,
- glob_xmount.output.p_output_format,
- glob_xmount.debug);
- if(ret!=0) {
- LOG_ERROR("Unable to create output handle: %s!\n",
- glob_xmount.output.p_functions->GetErrorMessage(ret));
- FreeResources();
- return 1;
- }
-
- // Parse output lib specific options
- if(glob_xmount.output.pp_lib_params!=NULL) {
- p_err_msg=NULL;
- ret=glob_xmount.output.p_functions->
- OptionsParse(glob_xmount.output.p_handle,
- glob_xmount.output.lib_params_count,
- glob_xmount.output.pp_lib_params,
- (const char**)&p_err_msg);
- if(ret!=0) {
- if(p_err_msg!=NULL) {
- LOG_ERROR("Unable to parse output library specific options: %s: %s!\n",
- glob_xmount.output.p_functions->GetErrorMessage(ret),
- p_err_msg);
- glob_xmount.output.p_functions->FreeBuffer(p_err_msg);
- FreeResources();
- return 1;
- } else {
- LOG_ERROR("Unable to parse output library specific options: %s!\n",
- glob_xmount.output.p_functions->GetErrorMessage(ret));
- FreeResources();
- return 1;
- }
- }
- }
-
// Gather infos for info file
if(!InitInfoFile()) {
LOG_ERROR("Couldn't gather infos for virtual image info file!\n")
FreeResources();
return 1;
}
LOG_DEBUG("Virtual image info file build successfully\n")
// Call fuse_main to do the fuse magic
fuse_ret=fuse_main(glob_xmount.fuse_argc,
glob_xmount.pp_fuse_argv,
&xmount_operations,
NULL);
// Destroy mutexes
pthread_mutex_destroy(&(glob_xmount.mutex_image_rw));
pthread_mutex_destroy(&(glob_xmount.mutex_info_read));
// Free allocated memory
FreeResources();
return fuse_ret;
}
diff --git a/src/xmount.h b/src/xmount.h
index f601498..d146250 100755
--- a/src/xmount.h
+++ b/src/xmount.h
@@ -1,99 +1,106 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2016 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 XMOUNT_H
#define XMOUNT_H
+#include "../libxmount/libxmount.h"
#include "xmount_input.h"
#include "xmount_morphing.h"
#include "xmount_cache.h"
#include "xmount_output.h"
#undef FALSE
#undef TRUE
#define FALSE 0
#define TRUE 1
/*
* Constants
*/
#define IMAGE_INFO_INPUT_HEADER \
"------> The following values are supplied by the used input library(ies) " \
"<------\n"
#define IMAGE_INFO_MORPHING_HEADER \
"\n------> The following values are supplied by the used morphing library " \
"<------\n\n"
/*******************************************************************************
* Xmount specific structures
******************************************************************************/
//! Structure containing xmount arguments
typedef struct s_XmountArgs {
//! Cache file
char *p_cache_file;
//! If set to 1, overwrite any existing cache file
uint8_t overwrite_cache;
+ //! Writable? (Set to 1 if --cache was specified)
+ uint8_t writable;
} ts_XmountArgs;
//! Structure containing global xmount runtime infos
typedef struct s_XmountData {
//! Parsed xmount arguments
ts_XmountArgs args;
//! Input image related data
pts_XmountInputHandle h_input;
//! Morphing related data
pts_XmountMorphHandle h_morphing;
//! Cache file handle
pts_XmountCacheHandle h_cache;
//! Output image related data
pts_XmountOutputHandle h_output;
//! Enable debug output
uint8_t debug;
//! Set if we are allowed to set fuse's allow_other option
uint8_t may_set_fuse_allow_other;
//! Argv for FUSE
int fuse_argc;
//! Argv for FUSE
char **pp_fuse_argv;
//! Mount point
char *p_mountpoint;
//! First input image's path/name
char *p_first_input_image_name;
+ //! Path of virtual image info file
+ char *p_info_path;
+ //! Pointer to virtual info file
+ char *p_info_file;
//! MD5 hash of partial input image (lower 64 bit) (after morph)
uint64_t image_hash_lo;
//! MD5 hash of partial input image (higher 64 bit) (after morph)
uint64_t image_hash_hi;
//! Mutex to control concurrent read & write access on output image
pthread_mutex_t mutex_image_rw;
//! Mutex to control concurrent read access on info file
pthread_mutex_t mutex_info_read;
} ts_XmountData;
/*******************************************************************************
* Global vars
******************************************************************************/
//! Struct that contains various runtime configuration options
ts_XmountData glob_xmount;
/*******************************************************************************
* Xmount functions
******************************************************************************/
#endif // XMOUNT_H
diff --git a/src/xmount_input.c b/src/xmount_input.c
index abd6503..994157f 100644
--- a/src/xmount_input.c
+++ b/src/xmount_input.c
@@ -1,921 +1,922 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2016 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include <stdlib.h> // For calloc
#include <string.h> // For memcpy
#include <dlfcn.h> // For dlopen, dlclose, dlsym
#include "xmount_input.h"
#include "xmount.h"
#include "macros.h"
#include "../libxmount_input/libxmount_input.h"
/*******************************************************************************
* Private definitions / macros
******************************************************************************/
#define LOG_WARNING(...) { \
LIBXMOUNT_LOG_WARNING(__VA_ARGS__); \
}
#define LOG_ERROR(...) { \
LIBXMOUNT_LOG_ERROR(__VA_ARGS__); \
}
#define LOG_DEBUG(...) { \
LIBXMOUNT_LOG_DEBUG(glob_xmount.debug,__VA_ARGS__); \
}
/*******************************************************************************
* Private types / structures / enums
******************************************************************************/
//! Structure containing infos about input libs
typedef struct s_XmountInputLib {
//! Filename of lib (without path)
char *p_name;
//! Handle to the loaded lib
void *p_lib;
//! Array of supported input types
char *p_supported_input_types;
//! Struct containing lib functions
ts_LibXmountInputFunctions lib_functions;
} ts_XmountInputLib, *pts_XmountInputLib;
//! Structure containing infos about input images
typedef struct s_XmountInputImage {
//! Image type
char *p_type;
//! Image source file count
uint64_t files_count;
//! Image source files
char **pp_files;
//! Input lib functions for this image
pts_LibXmountInputFunctions p_functions;
//! Image handle
void *p_handle;
//! Image size
uint64_t size;
} ts_XmountInputImage, *pts_XmountInputImage;
typedef struct s_XmountInputHandle {
//! Loaded input lib count
uint32_t libs_count;
//! Array containing infos about loaded input libs
pts_XmountInputLib *pp_libs;
//! Amount of input lib params (--inopts)
uint32_t lib_params_count;
//! Input lib params (--inopts)
pts_LibXmountOptions *pp_lib_params;
//! Input image count
uint64_t images_count;
//! Input images
pts_XmountInputImage *pp_images;
//! Input image offset (--offset)
uint64_t image_offset;
//! Input image size limit (--sizelimit)
uint64_t image_size_limit;
//! Enable debugging
uint8_t debug;
} ts_XmountInputHandle;
/*******************************************************************************
* Private functions declarations
******************************************************************************/
/*!
* \brief Find an input lib for a given input image
*
* Searches trough the list of loaded input libraries to find one that supports
* the given input image's format. On success, that library is associated with
* the given image.
*
* \param p_h Input handle
* \param p_input_image Input image to search input lib for
* \return e_XmountInput_Error_None on success
*/
te_XmountInput_Error XmountInput_FindLib(pts_XmountInputHandle p_h,
pts_XmountInputImage p_input_image);
/*******************************************************************************
* Public functions implementations
******************************************************************************/
/*
* XmountInput_CreateHandle
*/
te_XmountInput_Error XmountInput_CreateHandle(pts_XmountInputHandle *pp_h) {
pts_XmountInputHandle p_h=NULL;
// Params check
if(pp_h==NULL) return e_XmountInput_Error_InvalidHandlePointer;
// Alloc new handle
p_h=(pts_XmountInputHandle)calloc(1,sizeof(ts_XmountInputHandle));
if(p_h==NULL) {
return e_XmountInput_Error_Alloc;
}
// Init values
p_h->pp_libs=NULL;
p_h->pp_lib_params=NULL;
p_h->pp_images=NULL;
*pp_h=p_h;
return e_XmountInput_Error_None;
}
/*
* XmountInput_DestroyHandle
*/
te_XmountInput_Error XmountInput_DestroyHandle(pts_XmountInputHandle *pp_h) {
pts_XmountInputHandle p_h=NULL;
// Params check
if(pp_h==NULL) return e_XmountInput_Error_InvalidHandlePointer;
if(*pp_h==NULL) return e_XmountInput_Error_InvalidHandle;
p_h=*pp_h;
// Free resources
if(p_h->images_count!=0 && p_h->pp_images!=NULL) {
// TODO: Close images
}
if(p_h->libs_count>0 && p_h->pp_libs!=NULL) {
// Unload all input libs
for(uint32_t i=0;i<p_h->libs_count;i++) {
if(p_h->pp_libs[i]->p_supported_input_types!=NULL) {
XMOUNT_FREE(p_h->pp_libs[i]->p_supported_input_types);
}
if(p_h->pp_libs[i]->p_lib!=NULL) {
dlclose(p_h->pp_libs[i]->p_lib);
p_h->pp_libs[i]->p_lib=NULL;
}
if(p_h->pp_libs[i]->p_name!=NULL) {
XMOUNT_FREE(p_h->pp_libs[i]->p_name);
}
XMOUNT_FREE(p_h->pp_libs[i]);
}
XMOUNT_FREE(p_h->pp_libs);
p_h->libs_count=0;
}
if(p_h->lib_params_count!=0 && p_h->pp_lib_params!=NULL) {
// Free library parameter array
for(uint32_t i=0;i<p_h->lib_params_count;i++) {
XMOUNT_FREE(p_h->pp_lib_params[i]);
}
XMOUNT_FREE(p_h->pp_lib_params);
p_h->lib_params_count=0;
}
+ *pp_h=NULL;
return e_XmountInput_Error_None;
}
/*
* XmountInput_EnableDebugging
*/
te_XmountInput_Error XmountInput_EnableDebugging(pts_XmountInputHandle p_h) {
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
p_h->debug=1;
return e_XmountInput_Error_None;
}
/*
* XmountInput_AddLibrary
*/
te_XmountInput_Error XmountInput_AddLibrary(pts_XmountInputHandle p_h,
const char *p_lib_name)
{
uint32_t supported_formats_len=0;
t_LibXmount_Input_GetApiVersion pfun_input_GetApiVersion;
t_LibXmount_Input_GetSupportedFormats pfun_input_GetSupportedFormats;
t_LibXmount_Input_GetFunctions pfun_input_GetFunctions;
void *p_libxmount=NULL;
pts_XmountInputLib p_input_lib=NULL;
char *p_buf=NULL;
char *p_library_path=NULL;
char *p_supported_formats=NULL;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(p_lib_name==NULL) return e_XmountInput_Error_InvalidString;
// Construct full library path
XMOUNT_STRSET(p_library_path,XMOUNT_LIBRARY_PATH);
if(p_library_path[strlen(p_library_path)]!='/') {
XMOUNT_STRAPP(p_library_path,"/");
}
XMOUNT_STRAPP(p_library_path,p_lib_name);
#define XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL(name,pfun) { \
if((pfun=dlsym(p_libxmount,name))==NULL) { \
LOG_ERROR("Unable to load symbol '%s' from library '%s'!\n", \
name, \
p_library_path); \
dlclose(p_libxmount); \
return e_XmountInput_Error_FailedLoadingSymbol; \
} \
}
// Try to load given library
p_libxmount=dlopen(p_library_path,RTLD_NOW);
if(p_libxmount==NULL) {
LOG_ERROR("Unable to load input library '%s': %s!\n",
p_library_path,
dlerror());
return e_XmountInput_Error_FailedLoadingLibrary;
}
// Load library symbols
XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Input_GetApiVersion",
pfun_input_GetApiVersion);
// Check library's API version
if(pfun_input_GetApiVersion()!=LIBXMOUNT_INPUT_API_VERSION) {
LOG_DEBUG("Failed! Wrong API version.\n");
LOG_ERROR("Unable to load input library '%s'. Wrong API version\n",
p_library_path);
dlclose(p_libxmount);
return e_XmountInput_Error_WrongLibraryApiVersion;
}
XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Input_GetSupportedFormats",
pfun_input_GetSupportedFormats);
XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Input_GetFunctions",
pfun_input_GetFunctions);
// Construct new entry for our library list
XMOUNT_MALLOC(p_input_lib,pts_XmountInputLib,sizeof(ts_XmountInputLib));
// Initialize lib_functions structure to NULL
memset(&(p_input_lib->lib_functions),
0,
sizeof(ts_LibXmountInputFunctions));
// Set name and handle
XMOUNT_STRSET(p_input_lib->p_name,p_lib_name);
p_input_lib->p_lib=p_libxmount;
// Get and set supported formats
p_supported_formats=pfun_input_GetSupportedFormats();
p_buf=p_supported_formats;
while(*p_buf!='\0') {
supported_formats_len+=(strlen(p_buf)+1);
p_buf+=(strlen(p_buf)+1);
}
supported_formats_len++;
XMOUNT_MALLOC(p_input_lib->p_supported_input_types,
char*,
supported_formats_len);
memcpy(p_input_lib->p_supported_input_types,
p_supported_formats,
supported_formats_len);
// Get, set and check lib_functions
pfun_input_GetFunctions(&(p_input_lib->lib_functions));
if(p_input_lib->lib_functions.CreateHandle==NULL ||
p_input_lib->lib_functions.DestroyHandle==NULL ||
p_input_lib->lib_functions.Open==NULL ||
p_input_lib->lib_functions.Close==NULL ||
p_input_lib->lib_functions.Size==NULL ||
p_input_lib->lib_functions.Read==NULL ||
p_input_lib->lib_functions.OptionsHelp==NULL ||
p_input_lib->lib_functions.OptionsParse==NULL ||
p_input_lib->lib_functions.GetInfofileContent==NULL ||
p_input_lib->lib_functions.GetErrorMessage==NULL ||
p_input_lib->lib_functions.FreeBuffer==NULL)
{
LOG_DEBUG("Missing implemention of one or more functions in lib %s!\n",
p_lib_name);
XMOUNT_FREE(p_input_lib->p_supported_input_types);
XMOUNT_FREE(p_input_lib->p_name);
XMOUNT_FREE(p_input_lib);
dlclose(p_libxmount);
return e_XmountInput_Error_MissingLibraryFunction;
}
// Add entry to the input library list
XMOUNT_REALLOC(p_h->pp_libs,
pts_XmountInputLib*,
sizeof(pts_XmountInputLib)*(p_h->libs_count+1));
p_h->pp_libs[p_h->libs_count++]=p_input_lib;
LOG_DEBUG("Input library '%s' loaded successfully\n",p_lib_name);
#undef XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL
return e_XmountInput_Error_None;
}
te_XmountInput_Error XmountInput_GetLibraryCount(pts_XmountInputHandle p_h,
uint32_t *p_count)
{
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(p_count==NULL) return e_XmountInput_Error_InvalidBuffer;
*p_count=p_h->libs_count;
return e_XmountInput_Error_None;
}
/*
* XmountInput_GetSupportedFormats
*/
te_XmountInput_Error XmountInput_GetSupportedFormats(pts_XmountInputHandle p_h,
char **pp_formats)
{
char *p_buf=NULL;
char *p_formats=NULL;
uint32_t cur_len=0;
uint32_t vector_len=0;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(pp_formats==NULL) return e_XmountInput_Error_InvalidBuffer;
// Loop over all loaded libs, extract supported formats and add to our vector
// TODO: IMPROVEMENT: Final vector could be sorted
for(uint32_t i=0;i<p_h->libs_count;i++) {
p_buf=p_h->pp_libs[i]->p_supported_input_types;
while(p_buf!=NULL && *p_buf!='\0') p_buf+=(strlen(p_buf)+1);
cur_len=(uint32_t)(p_buf-p_h->pp_libs[i]->p_supported_input_types);
if(cur_len==0) continue;
p_formats=(char*)realloc(p_formats,vector_len+cur_len);
if(p_formats==NULL) return e_XmountInput_Error_Alloc;
memcpy(p_formats+vector_len,
p_h->pp_libs[i]->p_supported_input_types,
cur_len);
vector_len+=cur_len;
}
// Null-terminate vector
p_formats=(char*)realloc(p_formats,vector_len+1);
if(p_formats==NULL) return e_XmountInput_Error_Alloc;
p_formats[vector_len]='\0';
*pp_formats=p_formats;
return e_XmountInput_Error_None;
}
/*
* XmountInput_SetOptions
*/
te_XmountInput_Error XmountInput_SetOptions(pts_XmountInputHandle p_h,
char *p_options)
{
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(p_options==NULL) return e_XmountInput_Error_InvalidString;
// Make sure library parameters haven't been set previously
if(p_h->pp_lib_params!=NULL) {
LOG_ERROR("Input library options already set!\n");
return e_XmountInput_Error_LibOptionsAlreadySet;
}
// Save options
if(XmountLib_SplitLibParams(p_options,
&(p_h->lib_params_count),
&(p_h->pp_lib_params))!=0)
{
LOG_ERROR("Unable to parse input library options '%s'!\n",p_options);
return e_XmountInput_Error_FailedParsingOptions;
}
return e_XmountInput_Error_None;
}
/*
* XmountInput_GetOptionsHelpText
*/
te_XmountInput_Error XmountInput_GetOptionsHelpText(pts_XmountInputHandle p_h,
char **pp_help_text)
{
const char *p_buf=NULL;
char *p_help=NULL;
int ret=0;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(pp_help_text==NULL) return e_XmountInput_Error_InvalidBuffer;
// Loop over all loaded libs, extract help and add to our text buffer
// TODO: IMPROVEMENT: Final text should be sorted by lib's name
for(uint32_t i=0;i<p_h->libs_count;i++) {
ret=p_h->pp_libs[i]->lib_functions.OptionsHelp(&p_buf);
if(ret!=0) {
LOG_ERROR("Unable to get options help for library '%s': %s!\n",
p_h->pp_libs[i]->p_name,
p_h->pp_libs[i]->lib_functions.GetErrorMessage(ret));
continue;
}
if(p_buf==NULL) continue;
XMOUNT_STRAPP(p_help," - ");
XMOUNT_STRAPP(p_help,p_h->pp_libs[i]->p_name);
XMOUNT_STRAPP(p_help,"\n");
XMOUNT_STRAPP(p_help,p_buf);
XMOUNT_STRAPP(p_help,"\n");
ret=p_h->pp_libs[i]->lib_functions.FreeBuffer(p_buf);
if(ret!=0) {
LOG_ERROR("Unable to free options help text from library '%s': %s!\n",
p_h->pp_libs[i]->p_name,
p_h->pp_libs[i]->lib_functions.GetErrorMessage(ret));
}
}
*pp_help_text=p_help;
return e_XmountInput_Error_None;
}
/*
* XmountInput_GetLibsInfoText
*/
te_XmountInput_Error XmountInput_GetLibsInfoText(pts_XmountInputHandle p_h,
char **pp_info_text)
{
char *p_buf=NULL;
char *p_info_text=NULL;
uint8_t first=0;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(pp_info_text==NULL) return e_XmountInput_Error_InvalidBuffer;
// Loop over all loaded libs, extract name and supported formats and add to
// our text buffer
// TODO: IMPROVEMENT: Final text should be sorted by lib's name
for(uint32_t i=0;i<p_h->libs_count;i++) {
XMOUNT_STRAPP(p_info_text," - ");
XMOUNT_STRAPP(p_info_text,p_h->pp_libs[i]->p_name);
XMOUNT_STRAPP(p_info_text," supporting ");
XMOUNT_STRAPP(p_info_text," - ");
XMOUNT_STRAPP(p_info_text," - ");
p_buf=p_h->pp_libs[i]->p_supported_input_types;
first=1;
while(*p_buf!='\0') {
if(first==1) {
XMOUNT_STRAPP(p_info_text,"\"");
XMOUNT_STRAPP(p_info_text,p_buf);
XMOUNT_STRAPP(p_info_text,"\"");
first=0;
} else {
XMOUNT_STRAPP(p_info_text,", \"");
XMOUNT_STRAPP(p_info_text,p_buf);
XMOUNT_STRAPP(p_info_text,"\"");
}
p_buf+=(strlen(p_buf)+1);
}
XMOUNT_STRAPP(p_info_text,"\n");
}
*pp_info_text=p_info_text;
return e_XmountInput_Error_None;
}
/*
* XmountInput_AddImage
*/
te_XmountInput_Error XmountInput_AddImage(pts_XmountInputHandle p_h,
const char *p_format,
uint64_t files_count,
const char **pp_files)
{
pts_XmountInputImage p_image=NULL;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(p_format==NULL) return e_XmountInput_Error_InvalidString;
if(pp_files==NULL) return e_XmountInput_Error_InvalidArray;
// Alloc and fill new image structure
XMOUNT_CALLOC(p_image,pts_XmountInputImage,sizeof(ts_XmountInputImage));
XMOUNT_STRSET(p_image->p_type,p_format);
p_image->files_count=files_count;
XMOUNT_CALLOC(p_image->pp_files,char**,p_image->files_count*sizeof(char*));
for(uint64_t i=0;i<p_image->files_count;i++) {
XMOUNT_STRSET(p_image->pp_files[i],pp_files[i]);
}
p_image->p_functions=NULL;
p_image->p_handle=NULL;
// TODO: Find lib and open input file
// Add image to our image array
XMOUNT_REALLOC(p_h->pp_images,pts_XmountInputImage*,p_h->images_count+1);
p_h->pp_images[p_h->images_count++]=p_image;
return e_XmountInput_Error_None;
}
/*!
* \brief Get input image count
*
* Get input image count.
*
* \param p_h Input handle
* \param p_count Input image count is returned in this variable
* \return e_XmountInput_Error_None on success
*/
te_XmountInput_Error XmountInput_GetImageCount(pts_XmountInputHandle p_h,
uint64_t *p_count)
{
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(p_count==NULL) return e_XmountInput_Error_InvalidBuffer;
*p_count=p_h->images_count;
return e_XmountInput_Error_None;
}
/*
* XmountInput_SetInputOffset
*/
te_XmountInput_Error XmountInput_SetInputOffset(pts_XmountInputHandle p_h,
uint64_t offset)
{
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
LOG_DEBUG("Setting input image offset to \"%" PRIu64 "\"\n",offset);
p_h->image_offset=offset;
return e_XmountInput_Error_None;
}
/*
* XmountInput_SetInputSizeLimit
*/
te_XmountInput_Error XmountInput_SetInputSizeLimit(pts_XmountInputHandle p_h,
uint64_t size_limit)
{
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
LOG_DEBUG("Setting input image size limit to \"%" PRIu64 "\"\n",size_limit);
p_h->image_size_limit=size_limit;
return e_XmountInput_Error_None;
}
/*
* XmountInput_Open
*/
te_XmountInput_Error XmountInput_Open(pts_XmountInputHandle p_h) {
int ret=0;
const char *p_err_msg;
te_XmountInput_Error input_ret=e_XmountInput_Error_None;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
for(uint64_t i=0;i<p_h->images_count;i++) {
if(p_h->debug==TRUE) {
if(p_h->pp_images[i]->files_count==1) {
LOG_DEBUG("Loading image file \"%s\"...\n",
p_h->pp_images[i]->pp_files[0]);
} else {
LOG_DEBUG("Loading image files \"%s .. %s\"...\n",
p_h->pp_images[i]->pp_files[0],
p_h->pp_images[i]->
pp_files[p_h->pp_images[i]->files_count-1]);
}
}
// Find input lib
input_ret=XmountInput_FindLib(p_h,p_h->pp_images[i]);
if(input_ret!=e_XmountInput_Error_None) {
LOG_ERROR("Unable to find input library for input image format '%s' "
"of input image '%s': Error code %u!\n",
p_h->pp_images[i]->p_type,
p_h->pp_images[i]->pp_files[0],
input_ret);
return input_ret;
}
// Init input image handle
ret=p_h->pp_images[i]->p_functions->
CreateHandle(&(p_h->pp_images[i]->p_handle),
p_h->pp_images[i]->p_type,
p_h->debug);
if(ret!=0) {
LOG_ERROR("Unable to init input handle for input image '%s': %s!\n",
p_h->pp_images[i]->pp_files[0],
p_h->pp_images[i]->p_functions->
GetErrorMessage(ret));
return e_XmountInput_Error_FailedCreatingImageHandle;
}
// Parse input lib specific options
if(p_h->pp_lib_params!=NULL) {
ret=p_h->pp_images[i]->p_functions->
OptionsParse(p_h->pp_images[i]->p_handle,
p_h->lib_params_count,
p_h->pp_lib_params,
&p_err_msg);
if(ret!=0) {
if(p_err_msg!=NULL) {
LOG_ERROR("Unable to parse input library specific options for image "
"'%s': %s: %s!\n",
p_h->pp_images[i]->pp_files[0],
p_h->pp_images[i]->p_functions->
GetErrorMessage(ret),
p_err_msg);
p_h->pp_images[i]->p_functions->FreeBuffer(p_err_msg);
} else {
LOG_ERROR("Unable to parse input library specific options for image "
"'%s': %s!\n",
p_h->pp_images[i]->pp_files[0],
p_h->pp_images[i]->p_functions->
GetErrorMessage(ret));
}
return e_XmountInput_Error_FailedParsingLibParams;
}
}
// Open input image
ret=p_h->pp_images[i]->p_functions->Open(p_h->pp_images[i]->p_handle,
(const char**)(p_h->pp_images[i]->
pp_files),
p_h->pp_images[i]->files_count);
if(ret!=0) {
LOG_ERROR("Unable to open input image file '%s': %s!\n",
p_h->pp_images[i]->pp_files[0],
p_h->pp_images[i]->p_functions->
GetErrorMessage(ret));
return e_XmountInput_Error_FailedOpeningImage;
}
// Determine input image size
ret=p_h->pp_images[i]->p_functions->Size(p_h->pp_images[i]->p_handle,
&(p_h->pp_images[i]->size));
if(ret!=0) {
LOG_ERROR("Unable to determine size of input image '%s': %s!\n",
p_h->pp_images[i]->pp_files[0],
p_h->pp_images[i]->
p_functions->GetErrorMessage(ret));
return e_XmountInput_Error_FailedGettingImageSize;
}
// If an offset was specified, check it against offset and change size
if(p_h->image_offset!=0) {
if(p_h->image_offset>p_h->pp_images[i]->size) {
LOG_ERROR("The specified offset is larger than the size of the input "
"image '%s'! (%" PRIu64 " > %" PRIu64 ")\n",
p_h->pp_images[i]->pp_files[0],
p_h->image_offset,
p_h->pp_images[i]->size);
return e_XmountInput_Error_OffsetExceedsImageSize;
}
p_h->pp_images[i]->size-=p_h->image_offset;
}
// If a size limit was specified, check it and change size
if(p_h->image_size_limit!=0) {
if(p_h->pp_images[i]->size<p_h->image_size_limit) {
LOG_ERROR("The specified size limit is larger than the size of the "
"input image '%s'! (%" PRIu64 " > %" PRIu64 ")\n",
p_h->pp_images[i]->pp_files[0],
p_h->image_size_limit,
p_h->pp_images[i]->size);
return e_XmountInput_Error_SizelimitExceedsImageSize;
}
p_h->pp_images[i]->size=p_h->image_size_limit;
}
LOG_DEBUG("Input image loaded successfully\n")
}
return e_XmountInput_Error_None;
}
/*
* XmountInput_Close
*/
te_XmountInput_Error XmountInput_Close(pts_XmountInputHandle p_h) {
int ret=0;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(p_h->pp_images!=NULL) {
// Close all input images
for(uint64_t i=0;i<p_h->images_count;i++) {
if(p_h->pp_images[i]==NULL) continue;
if(p_h->pp_images[i]->p_functions!=NULL) {
if(p_h->pp_images[i]->p_handle!=NULL) {
ret=p_h->pp_images[i]->p_functions->
Close(p_h->pp_images[i]->p_handle);
if(ret!=0) {
LOG_ERROR("Unable to close input image '%s': %s\n",
p_h->pp_images[i]->pp_files[0]!=NULL ?
p_h->pp_images[i]->pp_files[0] : "n/a",
p_h->pp_images[i]->p_functions->GetErrorMessage(ret));
}
ret=p_h->pp_images[i]->p_functions->
DestroyHandle(&(p_h->pp_images[i]->p_handle));
if(ret!=0) {
LOG_ERROR("Unable to destroy handle of input image '%s': %s\n",
p_h->pp_images[i]->pp_files[0]!=NULL ?
p_h->pp_images[i]->pp_files[0] : "n/a",
p_h->pp_images[i]->p_functions->GetErrorMessage(ret));
}
p_h->pp_images[i]->p_handle=NULL;
}
}
if(p_h->pp_images[i]->pp_files!=NULL) {
for(uint64_t ii=0;ii<p_h->pp_images[i]->files_count;ii++) {
if(p_h->pp_images[i]->pp_files[ii]!=NULL)
XMOUNT_FREE(p_h->pp_images[i]->pp_files[ii]);
}
XMOUNT_FREE(p_h->pp_images[i]->pp_files);
}
if(p_h->pp_images[i]->p_type!=NULL) {
XMOUNT_FREE(p_h->pp_images[i]->p_type);
}
XMOUNT_FREE(p_h->pp_images[i]);
}
XMOUNT_FREE(p_h->pp_images);
}
return e_XmountInput_Error_None;
}
/*
* XmountInput_GetSize
*/
te_XmountInput_Error XmountInput_GetSize(pts_XmountInputHandle p_h,
uint64_t image_nr,
uint64_t *p_size)
{
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(image_nr>=p_h->images_count) return e_XmountInput_Error_NoSuchImage;
if(p_size==NULL) return e_XmountInput_Error_InvalidBuffer;
*p_size=p_h->pp_images[image_nr]->size;
return e_XmountInput_Error_None;
}
/*
* XmountInput_ReadData
*/
te_XmountInput_Error XmountInput_ReadData(pts_XmountInputHandle p_h,
uint64_t image_nr,
char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_read)
{
uint64_t to_read=0;
int ret=0;
int read_errno=0;
pts_XmountInputImage p_image=NULL;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(image_nr>=p_h->images_count) return e_XmountInput_Error_NoSuchImage;
if(p_buf==NULL) return e_XmountInput_Error_InvalidBuffer;
p_image=p_h->pp_images[image_nr];
LOG_DEBUG("Reading %zu bytes at offset %zu from input image '%s'\n",
count,
offset,
p_image->pp_files[0]);
// Make sure we aren't reading past EOF of image file
if(offset>=p_image->size) {
// Offset is beyond image size
LOG_DEBUG("Offset %zu is at / beyond size of input image '%s'\n",
offset,
p_image->pp_files[0]);
*p_read=0;
return 0;
}
if(offset+count>p_image->size) {
// Attempt to read data past EOF of image file
to_read=p_image->size-offset;
LOG_DEBUG("Attempt to read data past EOF of input image '%s'. "
"Correcting size from %zu to %zu\n",
p_image->pp_files[0],
count,
to_read);
} else to_read=count;
// Read data from image file (adding input image offset if one was specified)
ret=p_image->p_functions->Read(p_image->p_handle,
p_buf,
offset+p_h->image_offset,
to_read,
p_read,
&read_errno);
if(ret!=0) {
LOG_ERROR("Couldn't read %zu bytes at offset %zu from input image "
"'%s': %s: Error code %u!\n",
to_read,
offset,
p_image->pp_files[0],
p_image->p_functions->GetErrorMessage(ret),
read_errno);
return e_XmountInput_Error_FailedReadingData;
}
return e_XmountInput_Error_None;
}
/*
* XmountInput_WriteData
*/
te_XmountInput_Error XmountInput_WriteData(pts_XmountInputHandle p_h,
uint64_t image_nr,
const char *p_buf,
uint64_t offset,
uint64_t count)
{
// TODO: Implement
return e_XmountInput_Error_None;
}
/*
* XmountInput_GetInfoFileContent
*/
te_XmountInput_Error XmountInput_GetInfoFileContent(pts_XmountInputHandle p_h,
char **pp_content)
{
int ret=0;
char *p_buf=NULL;
char *p_content=NULL;
// Params check
if(p_h==NULL) return e_XmountInput_Error_InvalidHandle;
if(pp_content==NULL) return e_XmountInput_Error_InvalidBuffer;
for(uint64_t i=0;i<p_h->images_count;i++) {
ret=p_h->pp_images[i]->p_functions->
GetInfofileContent(p_h->pp_images[i]->p_handle,(const char**)&p_buf);
if(ret!=0) {
LOG_ERROR("Unable to get info file content for image '%s': %s!\n",
p_h->pp_images[i]->pp_files[0],
p_h->pp_images[i]->p_functions->GetErrorMessage(ret));
return e_XmountInput_Error_FailedGettingInfoFileContent;
}
// Add infos to main buffer and free p_buf
XMOUNT_STRAPP(p_content,"\n--> ");
XMOUNT_STRAPP(p_content,p_h->pp_images[i]->pp_files[0]);
XMOUNT_STRAPP(p_content," <--\n");
if(p_buf!=NULL) {
XMOUNT_STRAPP(p_content,p_buf);
p_h->pp_images[i]->p_functions->FreeBuffer(p_buf);
} else {
XMOUNT_STRAPP(p_content,"None\n");
}
}
*pp_content=p_content;
return e_XmountInput_Error_None;
}
/*******************************************************************************
* Private functions implementations
******************************************************************************/
/*
* FindInputLib
*/
te_XmountInput_Error XmountInput_FindLib(pts_XmountInputHandle p_h,
pts_XmountInputImage p_input_image)
{
char *p_buf;
LOG_DEBUG("Trying to find suitable library for input type '%s'.\n",
p_input_image->p_type);
// Loop over all loaded libs
for(uint32_t i=0;i<p_h->libs_count;i++) {
LOG_DEBUG("Checking input library %s\n",p_h->pp_libs[i]->p_name);
p_buf=p_h->pp_libs[i]->p_supported_input_types;
while(*p_buf!='\0') {
if(strcmp(p_buf,p_input_image->p_type)==0) {
// Library supports input type, set lib functions
LOG_DEBUG("Input library '%s' pretends to handle that input type.\n",
p_h->pp_libs[i]->p_name);
p_input_image->p_functions=&(p_h->pp_libs[i]->lib_functions);
return e_XmountInput_Error_None;
}
p_buf+=(strlen(p_buf)+1);
}
}
LOG_DEBUG("Couldn't find any suitable library.\n");
// No library supporting input type found
return e_XmountInput_Error_UnsupportedFormat;
}
diff --git a/src/xmount_morphing.c b/src/xmount_morphing.c
index 62c8d96..6c91be2 100644
--- a/src/xmount_morphing.c
+++ b/src/xmount_morphing.c
@@ -1,736 +1,738 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2016 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include <stdlib.h> // For calloc
#include <string.h> // For memcpy
#include <dlfcn.h> // For dlopen, dlclose, dlsym
#include "../libxmount_morphing/libxmount_morphing.h"
#include "xmount_morphing.h"
#include "xmount.h"
#include "macros.h"
/*******************************************************************************
* Private definitions / macros
******************************************************************************/
#define XMOUNT_MORPHING_DEFAULT_MORPH_TYPE "combine"
#define LOG_WARNING(...) { \
LIBXMOUNT_LOG_WARNING(__VA_ARGS__); \
}
#define LOG_ERROR(...) { \
LIBXMOUNT_LOG_ERROR(__VA_ARGS__); \
}
#define LOG_DEBUG(...) { \
LIBXMOUNT_LOG_DEBUG(glob_xmount.debug,__VA_ARGS__); \
}
/*******************************************************************************
* Private types / structures / enums
******************************************************************************/
//! Structure containing infos about morphing libs
typedef struct s_XmountMorphingLib {
//! Filename of lib (without path)
char *p_name;
//! Handle to the loaded lib
void *p_lib;
//! Array of supported morphing types
char *p_supported_morphing_types;
//! Struct containing lib functions
ts_LibXmountMorphingFunctions lib_functions;
} ts_XmountMorphingLib, *pts_XmountMorphingLib;
//! Structures and vars needed for morph support
typedef struct s_XmountMorphHandle {
//! Loaded morphing lib count
uint32_t libs_count;
//! Array containing infos about loaded morphing libs
pts_XmountMorphingLib *pp_libs;
//! Specified morphing type (--morph)
char *p_morph_type;
//! Amount of specified morphing lib params (--morphopts)
uint32_t lib_params_count;
//! Specified morphing lib params (--morphopts)
pts_LibXmountOptions *pp_lib_params;
//! Handle to initialized morphing lib
void *p_handle;
//! Debug
uint8_t debug;
//! Morphing functions of initialized lib
pts_LibXmountMorphingFunctions p_functions;
//! Input image functions passed to morphing lib
ts_LibXmountMorphingInputFunctions input_image_functions;
} ts_XmountMorphHandle;
/*******************************************************************************
* Private functions declarations
******************************************************************************/
/*!
* \brief Find a morphing lib for a given morph type
*
* Searches trough the list of loaded morphing libraries to find one that
* supports the given morph type. On success, that library is associated with
* the given handle.
*
* \param p_h Morphing handle
* \return e_XmountInput_Error_None on success
*/
te_XmountMorphError XmountMorphing_FindMorphLib(pts_XmountMorphHandle p_h);
/*******************************************************************************
* Public functions implementations
******************************************************************************/
/*
* XmountMorphing_CreateHandle
*/
te_XmountMorphError
XmountMorphing_CreateHandle(pts_XmountMorphHandle *pp_h,
tfun_XmountMorphing_InputImageCount p_img_count,
tfun_XmountMorphing_InputImageSize p_img_size,
tfun_XmountMorphing_InputImageRead p_img_read,
tfun_XmountMorphing_InputImageWrite p_img_write)
{
pts_XmountMorphHandle p_h=NULL;
// Params check
if(pp_h==NULL) return e_XmountMorphError_InvalidHandlePointer;
// Alloc new handle
p_h=(pts_XmountMorphHandle)calloc(1,sizeof(ts_XmountMorphHandle));
if(p_h==NULL) return e_XmountMorphError_Alloc;
// Init values
p_h->pp_libs=NULL;
p_h->p_morph_type=NULL;
p_h->pp_lib_params=NULL;
p_h->p_handle=NULL;
p_h->p_functions=NULL;
p_h->input_image_functions.ImageCount=p_img_count;
p_h->input_image_functions.Size=p_img_size;
p_h->input_image_functions.Read=p_img_read;
//p_h->input_image_functions.Write=p_img_write;
*pp_h=p_h;
return e_XmountMorphError_None;
}
/*
* XmountMorphing_DestroyHandle
*/
te_XmountMorphError XmountMorphing_DestroyHandle(pts_XmountMorphHandle *pp_h) {
int ret=0;
pts_XmountMorphHandle p_h=NULL;
// Params check
if(pp_h==NULL) return e_XmountMorphError_InvalidHandlePointer;
if(*pp_h==NULL) return e_XmountMorphError_InvalidHandle;
p_h=*pp_h;
if(p_h->p_functions!=NULL) {
if(p_h->p_handle!=NULL) {
// Destroy morphing handle
ret=p_h->p_functions->DestroyHandle(&(p_h->p_handle));
if(ret!=0) {
LOG_ERROR("Unable to destroy morphing handle: %s!\n",
p_h->p_functions->GetErrorMessage(ret));
}
}
}
if(p_h->pp_lib_params!=NULL) {
for(uint32_t i=0;i<p_h->lib_params_count;i++) {
XMOUNT_FREE(p_h->pp_lib_params[i]);
}
XMOUNT_FREE(p_h->pp_lib_params);
}
if(p_h->p_morph_type!=NULL) XMOUNT_FREE(p_h->p_morph_type);
if(p_h->pp_libs!=NULL) {
// Unload morphing libs
for(uint32_t i=0;i<p_h->libs_count;i++) {
if(p_h->pp_libs[i]==NULL) continue;
if(p_h->pp_libs[i]->p_supported_morphing_types!=NULL)
XMOUNT_FREE(p_h->pp_libs[i]->p_supported_morphing_types);
if(p_h->pp_libs[i]->p_lib!=NULL)
dlclose(p_h->pp_libs[i]->p_lib);
if(p_h->pp_libs[i]->p_name!=NULL)
XMOUNT_FREE(p_h->pp_libs[i]->p_name);
XMOUNT_FREE(p_h->pp_libs[i]);
}
XMOUNT_FREE(p_h->pp_libs);
}
*pp_h=NULL;
return e_XmountMorphError_None;
}
/*
* XmountMorphing_EnableDebugging
*/
te_XmountMorphError XmountMorphing_EnableDebugging(pts_XmountMorphHandle p_h) {
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
p_h->debug=1;
return e_XmountMorphError_None;
}
/*
* XmountMorphing_AddLibrary
*/
te_XmountMorphError XmountMorphing_AddLibrary(pts_XmountMorphHandle p_h,
const char *p_lib_name)
{
uint32_t supported_types_len=0;
t_LibXmount_Morphing_GetApiVersion pfun_morphing_GetApiVersion;
t_LibXmount_Morphing_GetSupportedTypes pfun_morphing_GetSupportedTypes;
t_LibXmount_Morphing_GetFunctions pfun_morphing_GetFunctions;
void *p_libxmount=NULL;
pts_XmountMorphingLib p_morphing_lib=NULL;
char *p_buf=NULL;
char *p_library_path=NULL;
char *p_supported_types=NULL;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(p_lib_name==NULL) return e_XmountMorphError_InvalidString;
// Construct full library path
XMOUNT_STRSET(p_library_path,XMOUNT_LIBRARY_PATH);
if(p_library_path[strlen(p_library_path)]!='/') {
XMOUNT_STRAPP(p_library_path,"/");
}
XMOUNT_STRAPP(p_library_path,p_lib_name);
#define XMOUNTMORPHING_LOADLIBS__LOAD_SYMBOL(name,pfun) { \
if((pfun=dlsym(p_libxmount,name))==NULL) { \
LOG_ERROR("Unable to load symbol '%s' from library '%s'!\n", \
name, \
p_library_path); \
dlclose(p_libxmount); \
return e_XmountMorphError_FailedLoadingSymbol; \
} \
}
// Try to load given library
p_libxmount=dlopen(p_library_path,RTLD_NOW);
if(p_libxmount==NULL) {
LOG_ERROR("Unable to load morphing library '%s': %s!\n",
p_library_path,
dlerror());
return e_XmountMorphError_FailedLoadingLibrary;
}
// Load library symbols
XMOUNTMORPHING_LOADLIBS__LOAD_SYMBOL("LibXmount_Morphing_GetApiVersion",
pfun_morphing_GetApiVersion);
// Check library's API version
if(pfun_morphing_GetApiVersion()!=LIBXMOUNT_MORPHING_API_VERSION) {
LOG_DEBUG("Failed! Wrong API version.\n");
LOG_ERROR("Unable to load morphing library '%s'. Wrong API version\n",
p_library_path);
dlclose(p_libxmount);
return e_XmountMorphError_WrongLibraryApiVersion;
}
XMOUNTMORPHING_LOADLIBS__LOAD_SYMBOL("LibXmount_Morphing_GetSupportedTypes",
pfun_morphing_GetSupportedTypes);
XMOUNTMORPHING_LOADLIBS__LOAD_SYMBOL("LibXmount_Morphing_GetFunctions",
pfun_morphing_GetFunctions);
// Construct new entry for our library list
XMOUNT_MALLOC(p_morphing_lib,
pts_XmountMorphingLib,
sizeof(ts_XmountMorphingLib));
// Initialize lib_functions structure to NULL
memset(&(p_morphing_lib->lib_functions),
0,
sizeof(ts_LibXmountMorphingFunctions));
// Set name and handle
XMOUNT_STRSET(p_morphing_lib->p_name,p_lib_name);
p_morphing_lib->p_lib=p_libxmount;
// Get and set supported types
p_supported_types=pfun_morphing_GetSupportedTypes();
supported_types_len=0;
p_buf=p_supported_types;
while(*p_buf!='\0') {
supported_types_len+=(strlen(p_buf)+1);
p_buf+=(strlen(p_buf)+1);
}
supported_types_len++;
XMOUNT_MALLOC(p_morphing_lib->p_supported_morphing_types,
char*,
supported_types_len);
memcpy(p_morphing_lib->p_supported_morphing_types,
p_supported_types,
supported_types_len);
// Get, set and check lib_functions
pfun_morphing_GetFunctions(&(p_morphing_lib->lib_functions));
if(p_morphing_lib->lib_functions.CreateHandle==NULL ||
p_morphing_lib->lib_functions.DestroyHandle==NULL ||
p_morphing_lib->lib_functions.Morph==NULL ||
p_morphing_lib->lib_functions.Size==NULL ||
p_morphing_lib->lib_functions.Read==NULL ||
p_morphing_lib->lib_functions.OptionsHelp==NULL ||
p_morphing_lib->lib_functions.OptionsParse==NULL ||
p_morphing_lib->lib_functions.GetInfofileContent==NULL ||
p_morphing_lib->lib_functions.GetErrorMessage==NULL ||
p_morphing_lib->lib_functions.FreeBuffer==NULL)
{
LOG_DEBUG("Missing implemention of one or more functions in lib %s!\n",
p_lib_name);
XMOUNT_FREE(p_morphing_lib->p_supported_morphing_types);
XMOUNT_FREE(p_morphing_lib->p_name);
XMOUNT_FREE(p_morphing_lib);
dlclose(p_libxmount);
return e_XmountMorphError_MissingLibraryFunction;
}
// Add entry to the input library list
XMOUNT_REALLOC(p_h->pp_libs,
pts_XmountMorphingLib*,
sizeof(pts_XmountMorphingLib)*(p_h->libs_count+1));
p_h->pp_libs[p_h->libs_count++]=p_morphing_lib;
LOG_DEBUG("Morphing library '%s' loaded successfully\n",p_lib_name);
return e_XmountMorphError_None;
}
/*
* XmountMorphing_GetLibraryCount
*/
te_XmountMorphError XmountMorphing_GetLibraryCount(pts_XmountMorphHandle p_h,
uint32_t *p_count)
{
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
// TODO: Impement
return e_XmountMorphError_None;
}
/*
* XmountMorphing_GetSupportedTypes
*/
te_XmountMorphError XmountMorphing_GetSupportedTypes(pts_XmountMorphHandle p_h,
char **pp_types)
{
char *p_buf=NULL;
char *p_types=NULL;
uint32_t cur_len=0;
uint32_t vector_len=0;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(pp_types==NULL) return e_XmountMorphError_InvalidBuffer;
// Loop over all loaded libs, extract supported types and add to our vector
// TODO: IMPROVEMENT: Final vector could be sorted
for(uint32_t i=0;i<p_h->libs_count;i++) {
p_buf=p_h->pp_libs[i]->p_supported_morphing_types;
while(p_buf!=NULL && *p_buf!='\0') p_buf+=(strlen(p_buf)+1);
cur_len=(uint32_t)(p_buf-p_h->pp_libs[i]->p_supported_morphing_types);
if(cur_len==0) continue;
p_types=(char*)realloc(p_types,vector_len+cur_len);
if(p_types==NULL) return e_XmountInput_Error_Alloc;
memcpy(p_types+vector_len,
p_h->pp_libs[i]->p_supported_morphing_types,
cur_len);
vector_len+=cur_len;
}
// Null-terminate vector
p_types=(char*)realloc(p_types,vector_len+1);
if(p_types==NULL) return e_XmountInput_Error_Alloc;
p_types[vector_len]='\0';
*pp_types=p_types;
return e_XmountMorphError_None;
}
/*
* XmountMorphing_SetOptions
*/
te_XmountMorphError XmountMorphing_SetOptions(pts_XmountMorphHandle p_h,
char *p_options)
{
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(p_options==NULL) return e_XmountMorphError_InvalidString;
// Make sure library parameters haven't been set previously
if(p_h->pp_lib_params!=NULL) {
LOG_ERROR("Morphing library options already set!\n");
return e_XmountMorphError_LibOptionsAlreadySet;
}
// Save options
if(XmountLib_SplitLibParams(p_options,
&(p_h->lib_params_count),
&(p_h->pp_lib_params))!=0)
{
LOG_ERROR("Unable to parse morphing library options '%s'!\n",p_options);
return e_XmountMorphError_FailedParsingOptions;
}
return e_XmountMorphError_None;
}
/*
* XmountMorphing_GetOptionsHelpText
*/
te_XmountMorphError XmountMorphing_GetOptionsHelpText(pts_XmountMorphHandle p_h,
char **pp_help_text)
{
char *p_buf=NULL;
char *p_help=NULL;
int ret=0;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(pp_help_text==NULL) return e_XmountMorphError_InvalidBuffer;
// Loop over all loaded libs, extract help and add to our text buffer
// TODO: IMPROVEMENT: Final text should be sorted by lib's name
for(uint32_t i=0;i<p_h->libs_count;i++) {
ret=p_h->pp_libs[i]->lib_functions.OptionsHelp(&p_buf);
if(ret!=0) {
LOG_ERROR("Unable to get options help for library '%s': %s!\n",
p_h->pp_libs[i]->p_name,
p_h->pp_libs[i]->lib_functions.GetErrorMessage(ret));
continue;
}
if(p_buf==NULL) continue;
XMOUNT_STRAPP(p_help," - ");
XMOUNT_STRAPP(p_help,p_h->pp_libs[i]->p_name);
XMOUNT_STRAPP(p_help,"\n");
XMOUNT_STRAPP(p_help,p_buf);
XMOUNT_STRAPP(p_help,"\n");
p_h->pp_libs[i]->lib_functions.FreeBuffer(p_buf);
}
*pp_help_text=p_help;
return e_XmountMorphError_None;
}
/*
* XmountMorphingt_GetLibsInfoText
*/
te_XmountMorphError XmountMorphing_GetLibsInfoText(pts_XmountMorphHandle p_h,
char **pp_info_text)
{
char *p_buf=NULL;
char *p_info_text=NULL;
uint8_t first=0;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(pp_info_text==NULL) return e_XmountMorphError_InvalidBuffer;
// Loop over all loaded libs, extract name and supported types and add to
// our text buffer
// TODO: IMPROVEMENT: Final text should be sorted by lib's name
for(uint32_t i=0;i<p_h->libs_count;i++) {
XMOUNT_STRAPP(p_info_text," - ");
XMOUNT_STRAPP(p_info_text,p_h->pp_libs[i]->p_name);
XMOUNT_STRAPP(p_info_text," supporting ");
XMOUNT_STRAPP(p_info_text," - ");
XMOUNT_STRAPP(p_info_text," - ");
p_buf=p_h->pp_libs[i]->p_supported_morphing_types;
first=1;
while(*p_buf!='\0') {
if(first==1) {
XMOUNT_STRAPP(p_info_text,"\"");
XMOUNT_STRAPP(p_info_text,p_buf);
XMOUNT_STRAPP(p_info_text,"\"");
first=0;
} else {
XMOUNT_STRAPP(p_info_text,", \"");
XMOUNT_STRAPP(p_info_text,p_buf);
XMOUNT_STRAPP(p_info_text,"\"");
}
p_buf+=(strlen(p_buf)+1);
}
XMOUNT_STRAPP(p_info_text,"\n");
}
*pp_info_text=p_info_text;
return e_XmountMorphError_None;
}
/*
* XmountMorphing_SetType
*/
te_XmountMorphError XmountMorphing_SetType(pts_XmountMorphHandle p_h,
char *p_type)
{
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(p_type==NULL) return e_XmountMorphError_InvalidString;
+ // Set morphing type
XMOUNT_STRSET(p_h->p_morph_type,p_type);
+
return e_XmountMorphError_None;
}
/*
* XmountMorphing_StartMorphing
*/
te_XmountMorphError XmountMorphing_StartMorphing(pts_XmountMorphHandle p_h) {
const char *p_err_msg=NULL;
int ret=0;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
// Set default morph type if none was set previously
if(p_h->p_morph_type==NULL) {
XMOUNT_STRSET(p_h->p_morph_type,XMOUNT_MORPHING_DEFAULT_MORPH_TYPE);
}
// Find morphing lib
morph_ret=XmountMorphing_FindMorphLib(p_h);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Unable to find a library supporting the morphing type '%s'!\n",
p_h->p_morph_type);
return morph_ret;
}
// Init morphing
ret=p_h->p_functions->CreateHandle(&(p_h->p_handle),
p_h->p_morph_type,
p_h->debug);
if(ret!=0) {
LOG_ERROR("Unable to create morphing handle: %s!\n",
p_h->p_functions->GetErrorMessage(ret));
return e_XmountMorphError_FailedCreatingMorphHandle;
}
// Parse morphing lib specific options
if(p_h->pp_lib_params!=NULL) {
p_err_msg=NULL;
ret=p_h->p_functions->OptionsParse(p_h->p_handle,
p_h->lib_params_count,
p_h->pp_lib_params,
&p_err_msg);
if(ret!=0) {
if(p_err_msg!=NULL) {
LOG_ERROR("Unable to parse morphing library specific options: %s: %s!\n",
p_h->p_functions->GetErrorMessage(ret),
p_err_msg);
p_h->p_functions->FreeBuffer(p_err_msg);
} else {
LOG_ERROR("Unable to parse morphing library specific options: %s!\n",
p_h->p_functions->GetErrorMessage(ret));
}
- return e_XmountInput_Error_FailedParsingLibParams;
+ return e_XmountMorphError_FailedParsingLibParams;
}
}
// Morph image
ret=p_h->p_functions->Morph(p_h->p_handle,&(p_h->input_image_functions));
if(ret!=0) {
LOG_ERROR("Unable to start morphing: %s!\n",
p_h->p_functions->GetErrorMessage(ret));
return e_XmountMorphError_FailedCreatingMorphHandle;
}
return e_XmountMorphError_None;
}
/*
* XmountInput_StopMorphing
*/
te_XmountMorphError XmountInput_StopMorphing(pts_XmountMorphHandle p_h) {
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
// TODO: Impement
return e_XmountMorphError_None;
}
/*
* XmountMorphing_GetSize
*/
te_XmountMorphError XmountMorphing_GetSize(pts_XmountMorphHandle p_h,
uint64_t *p_size)
{
int ret=0;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(p_size==NULL) return e_XmountMorphError_InvalidBuffer;
// Get morphed image size
ret=p_h->p_functions->Size(p_h->p_handle,p_size);
if(ret!=0) {
LOG_ERROR("Unable to get morphed image size: %s!\n",
p_h->p_functions->GetErrorMessage(ret));
return e_XmountMorphError_FailedGettingImageSize;
}
return e_XmountMorphError_None;
}
/*
* XmountMorphing_ReadData
*/
te_XmountMorphError XmountMorphing_ReadData(pts_XmountMorphHandle p_h,
char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_read)
{
uint64_t image_size=0;
size_t to_read=0;
int ret;
te_XmountMorphError morph_ret=e_XmountMorphError_None;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
// Make sure we aren't reading past EOF of image file
morph_ret=XmountMorphing_GetSize(p_h,&image_size);
if(morph_ret!=e_XmountMorphError_None) {
LOG_ERROR("Couldn't get size of morphed image: Error code %u!\n",morph_ret);
return morph_ret;
}
if(offset>=image_size) {
// Offset is beyond image size
LOG_DEBUG("Offset %zu is at / beyond size of morphed image.\n",offset);
*p_read=0;
return e_XmountMorphError_OffsetExceedsImageSize;
}
if(offset+count>image_size) {
// Attempt to read data past EOF of morphed image file
to_read=image_size-offset;
LOG_DEBUG("Attempt to read data past EOF of morphed image. Corrected size "
"from %zu to %" PRIu64 ".\n",
count,
to_read);
} else to_read=count;
ret=p_h->p_functions->Read(p_h->p_handle,
p_buf,
offset,
to_read,
p_read);
if(ret!=0) {
LOG_ERROR("Couldn't read %zu bytes at offset %zu from morphed image: %s!\n",
to_read,
offset,
p_h->p_functions->GetErrorMessage(ret));
return e_XmountMorphError_FailedReadingData;
}
LOG_DEBUG("Read %" PRIu64 " bytes at offset %" PRIu64
" from morphed image file\n",
to_read,
offset);
return e_XmountMorphError_None;
}
/*
* XmountMorphing_WriteData
*/
te_XmountMorphError XmountMorphing_WriteData(pts_XmountMorphHandle p_h,
const char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_written)
{
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
// TODO: Impement
return e_XmountMorphError_None;
}
/*
* XmountMorphing_GetInfoFileContent
*/
te_XmountMorphError XmountMorphing_GetInfoFileContent(pts_XmountMorphHandle p_h,
char **pp_content)
{
int ret=0;
char *p_buf=NULL;
char *p_content=NULL;
// Params check
if(p_h==NULL) return e_XmountMorphError_InvalidHandle;
if(pp_content==NULL) return e_XmountMorphError_InvalidBuffer;
ret=p_h->p_functions->GetInfofileContent(p_h->p_handle,(const char**)&p_buf);
if(ret!=0) {
LOG_ERROR("Unable to get info file content from morphing lib: %s!\n",
p_h->p_functions->GetErrorMessage(ret));
return e_XmountMorphError_FailedGettingInfoFileContent;
}
// Add infos to main buffer and free p_buf
if(p_buf!=NULL) {
XMOUNT_STRAPP(p_content,p_buf);
p_h->p_functions->FreeBuffer(p_buf);
} else {
XMOUNT_STRAPP(p_content,"None\n");
}
*pp_content=p_content;
return e_XmountMorphError_None;
}
/*******************************************************************************
* Private functions implementations
******************************************************************************/
/*
* XmountMorphing_FindMorphLib
*/
te_XmountMorphError XmountMorphing_FindMorphLib(pts_XmountMorphHandle p_h) {
char *p_buf;
LOG_DEBUG("Trying to find suitable library for morph type '%s'.\n",
p_h->p_morph_type);
// Loop over all loaded libs
for(uint32_t i=0;i<p_h->libs_count;i++) {
LOG_DEBUG("Checking morphing library %s\n",p_h->pp_libs[i]->p_name);
p_buf=p_h->pp_libs[i]->p_supported_morphing_types;
while(*p_buf!='\0') {
if(strcmp(p_buf,p_h->p_morph_type)==0) {
// Library supports morph type, set lib functions
LOG_DEBUG("Morphing library '%s' pretends to handle that morph type.\n",
p_h->pp_libs[i]->p_name);
p_h->p_functions=&(p_h->pp_libs[i]->lib_functions);
return e_XmountMorphError_None;
}
p_buf+=(strlen(p_buf)+1);
}
}
LOG_DEBUG("Couldn't find any suitable library.\n");
// No library supporting morph type found
return e_XmountMorphError_UnsupportedType;
}
diff --git a/src/xmount_morphing.h b/src/xmount_morphing.h
index 56d6492..386d0a1 100644
--- a/src/xmount_morphing.h
+++ b/src/xmount_morphing.h
@@ -1,343 +1,344 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2016 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef XMOUNT_MORPHING_H
#define XMOUNT_MORPHING_H
/*******************************************************************************
* Public definitions / macros
******************************************************************************/
//! Naming scheme of morphing libraries
#define XMOUNT_MORPHING_LIBRARY_NAMING_SCHEME "libxmount_morph_"
/*******************************************************************************
* Public types / structures / enums
******************************************************************************/
//! Morphing handle
typedef struct s_XmountMorphHandle *pts_XmountMorphHandle;
/*!
* \brief Function to get the amount of input images
*
* Function to get the amount of input images
*
* \param p_count Count of input images
* \return 0 on success
*/
typedef int (*tfun_XmountMorphing_InputImageCount)(uint64_t *p_count);
/*!
* \brief Function to get the size of the morphed data
*
* Function to get the size of the morphed data
*
* \param image Image number
* \param p_size Pointer to store input image's size to
* \return 0 on success
*/
-typedef int (*tfun_XmountMorphing_InputImageSize)(uint64_t image, uint64_t *p_size);
+typedef int (*tfun_XmountMorphing_InputImageSize)(uint64_t image,
+ uint64_t *p_size);
//! Function to read data from input image
/*!
* \param image Image number
* \param p_buf Buffer to store read data to
* \param offset Position at which to start reading
* \param count Amount of bytes to read
* \param p_read Number of read bytes on success
* \return 0 on success or negated error code on error
*/
typedef int (*tfun_XmountMorphing_InputImageRead)(uint64_t image,
char *p_buf,
off_t offset,
size_t count,
size_t *p_read);
//! Function to write data to input image
/*!
* \param image Image number
* \param p_buf Buffer to store read data to
* \param offset Position at which to start reading
* \param count Amount of bytes to read
* \param p_read Number of read bytes on success
* \return 0 on success or negated error code on error
*/
typedef int (*tfun_XmountMorphing_InputImageWrite)(uint64_t image,
char *p_buf,
off_t offset,
size_t count,
size_t *p_written);
typedef enum e_XmountMorphError {
//! No error
e_XmountMorphError_None=0,
//! Error to allocate memory
e_XmountMorphError_Alloc,
//! Invalid morphing handle
e_XmountMorphError_InvalidHandle,
//! Invalid pointer to a morphing handle
e_XmountMorphError_InvalidHandlePointer,
//! A given buffer is invalid
e_XmountMorphError_InvalidBuffer,
//! A given string is invalid
e_XmountMorphError_InvalidString,
//! Library options have already been set
e_XmountMorphError_LibOptionsAlreadySet,
//! Library options couldn't be parsed
e_XmountMorphError_FailedParsingOptions,
//! Unable to get info file content from library
e_XmountMorphError_FailedGettingInfoFileContent,
//! Unable to load library file
e_XmountMorphError_FailedLoadingLibrary,
//! Unable to load a library symbol
e_XmountMorphError_FailedLoadingSymbol,
//! Library has wrong API version
e_XmountMorphError_WrongLibraryApiVersion,
//! Library is missing a function
e_XmountMorphError_MissingLibraryFunction,
//! Unsupported morphing type
e_XmountMorphError_UnsupportedType,
//! Unable to create morphing image handle
e_XmountMorphError_FailedCreatingMorphHandle,
//! Unable to parse morphing library options
e_XmountMorphError_FailedParsingLibParams,
//! Unable to get image size
e_XmountMorphError_FailedGettingImageSize,
//! A specified offset is larger than the image
e_XmountMorphError_OffsetExceedsImageSize,
//! Unable to read data from morphed image
e_XmountMorphError_FailedReadingData
} te_XmountMorphError;
/*******************************************************************************
* Public functions declarations
******************************************************************************/
/*!
* \brief Create new morphing handle
*
* Creates a new morphing handle.
*
* \param pp_h Pointer to morphing handle
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError
XmountMorphing_CreateHandle(pts_XmountMorphHandle *pp_h,
tfun_XmountMorphing_InputImageCount p_img_count,
tfun_XmountMorphing_InputImageSize p_img_size,
tfun_XmountMorphing_InputImageRead p_img_read,
tfun_XmountMorphing_InputImageWrite p_img_write);
/*!
* \brief Destroy morphing handle
*
* Invalidates the given handle and frees all used resources.
*
* \param pp_h Pointer to morphing handle
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_DestroyHandle(pts_XmountMorphHandle *pp_h);
/*!
* \brief Enable internal debugging
*
* Enables the generation of intrernal debugging messages.
*
* \param p_h Morphing handle
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_EnableDebugging(pts_XmountMorphHandle p_h);
/*!
* \brief Load a morphing library
*
* Loads a given morphing library.
*
* \param p_h Morphing handle
* \param p_lib Library name (without path)
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_AddLibrary(pts_XmountMorphHandle p_h,
const char *p_lib_name);
/*!
* \brief Get loaded morphing library count
*
* Returns the number of successfully loaded morphing libraries.
*
* \param p_h Morphing handle
* \param p_count Library count is returned in this variable
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_GetLibraryCount(pts_XmountMorphHandle p_h,
uint32_t *p_count);
/*!
* \brief Return all supported morphing types
*
* Returns a null-terminated vector of all supported morphing types.
*
* The returned vector must be freed by the caller.
*
* \param p_h Morphing handle
* \param pp_types Supported types vector is returned in this var
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_GetSupportedTypes(pts_XmountMorphHandle p_h,
char **pp_types);
/*!
* \brief Set library options
*
* Parses the given library option string (as given after --morphopts).
*
* \param p_h Morphing handle
* \param p_options Library option string
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_SetOptions(pts_XmountMorphHandle p_h,
char *p_options);
/*!
* \brief Return all library specific option help texts
*
* Returns a string containing help messages for all loaded morphing lib
* options. The string is pre-formated to be used in xmount's help output.
*
* The caller must free the returned string.
*
* \param p_h Morphing handle
* \param pp_help_text Help text is returned in this parameter
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_GetOptionsHelpText(pts_XmountMorphHandle p_h,
char **pp_help_text);
/*!
* \brief Returns a string containing infos about loaded libs
*
* Returns a string containing infos about loaded morphing libraries. The
* string is pre-formated to be used in xmount's info output.
*
* The caller must free the returned string.
*
* \param p_h Morphing handle
* \param pp_info_text Info text is returned in this parameter
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_GetLibsInfoText(pts_XmountMorphHandle p_h,
char **pp_info_text);
/*!
* \brief Set morphing type
*
* Set the morphing type that should be applied to the input image.
*
* \param p_h Morphing handle
* \param p_type Morphing type string as specified with xmount's --morph option.
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_SetType(pts_XmountMorphHandle p_h,
char *p_type);
/*!
* \brief Start the morphing process
*
* Begins the morphing process.
*
* \param p_h Morphing handle
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_StartMorphing(pts_XmountMorphHandle p_h);
/*!
* \brief Stop the morphing process
*
* Ends the morphing process.
*
* \param p_h Morphing handle
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_StopMorphing(pts_XmountMorphHandle p_h);
/*!
* \brief Get the size of the morphed image
*
* Returns the size (in bytes) of the morphed image.
*
* \param p_h Morphing handle
* \param image_nr Image number for which to return the size
* \param p_size On success, size is returned in this variable
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_GetSize(pts_XmountMorphHandle p_h,
uint64_t *p_size);
/*!
* \brief Read data from the morphed image
*
* Reads count bytes from the morphed image starting at given offset and
* copies the data into p_buf.
*
* The given buffer must be pre-allocated to hold as many bytes as should be
* read!
*
* \param p_h Morphing handle
* \param p_buf Buffer into which to copy read data
* \param offset Offset at which to start reading
* \param count Amount of bytes to read
* \param p_read On success, amount of bytes read is returned in this variable
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_ReadData(pts_XmountMorphHandle p_h,
char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_read);
/*!
* \brief Writes data to the morphed image
*
* Writes count bytes from p_buf to the morphed image starting at the given
* offset.
*
* \param p_h Morphing handle
* \param p_buf Buffer with data to write
* \param offset Offset at which to start writing
* \param count Amount of bytes to write
* \param p_written On success, amount of bytes written is returned here
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_WriteData(pts_XmountMorphHandle p_h,
const char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_written);
/*!
* \brief Get info text to be added to xmount's info file
*
* Generates a string containing informations about the currently morphed image.
*
* The caller must free the returned string.
*
* \param p_h Morphing handle
* \param pp_content Buffer in which text is returned
* \return e_XmountMorphError_None on success
*/
te_XmountMorphError XmountMorphing_GetInfoFileContent(pts_XmountMorphHandle p_h,
char **pp_content);
#endif // XMOUNT_MORPHING_H
diff --git a/src/xmount_output.c b/src/xmount_output.c
index 3805880..3a1575d 100644
--- a/src/xmount_output.c
+++ b/src/xmount_output.c
@@ -1,791 +1,859 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2016 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include <stdlib.h> // For calloc
#include <string.h> // For memcpy
#include <dlfcn.h> // For dlopen, dlclose, dlsym
#include "../libxmount_output/libxmount_output.h"
#include "xmount_output.h"
#include "xmount.h"
#include "macros.h"
/*******************************************************************************
* Private definitions / macros
******************************************************************************/
#define LOG_WARNING(...) { \
LIBXMOUNT_LOG_WARNING(__VA_ARGS__); \
}
#define LOG_ERROR(...) { \
LIBXMOUNT_LOG_ERROR(__VA_ARGS__); \
}
#define LOG_DEBUG(...) { \
LIBXMOUNT_LOG_DEBUG(glob_xmount.debug,__VA_ARGS__); \
}
/*******************************************************************************
* Private types / structures / enums
******************************************************************************/
//! Structure containing infos about output libs
typedef struct s_XmountOutputLib {
//! Filename of lib (without path)
char *p_name;
//! Handle to the loaded lib
void *p_lib;
//! Array of supported output formats
char *p_supported_output_formats;
//! Struct containing lib functions
ts_LibXmountOutput_Functions lib_functions;
} ts_XmountOutputLib, *pts_XmountOutputLib;
//! Structure containing infos about output image
typedef struct s_XmountOutputHandle {
//! Loaded output lib count
uint32_t libs_count;
//! Array containing infos about loaded output libs
pts_XmountOutputLib *pp_libs;
//! Specified output format (--out)
char *p_output_format;
//! Amount of specified output lib params
uint32_t lib_params_count;
//! Specified output lib params (--outopts)
pts_LibXmountOptions *pp_lib_params;
//! Handle to initialized output lib
void *p_handle;
//! Transformation functions of initialized lib
pts_LibXmountOutput_Functions p_functions;
//! Output image functions passed to output lib
ts_LibXmountOutput_Functions output_functions;
//! Size
uint64_t image_size;
- //! Writable? (Set to 1 if --cache was specified)
- uint8_t writable;
//! Path of virtual image file
char *p_virtual_image_path;
- //! Path of virtual image info file
- char *p_info_path;
- //! Pointer to virtual info file
- char *p_info_file;
//! Debug
uint8_t debug;
} ts_XmountOutputHandle;
/*******************************************************************************
* Private functions declarations
******************************************************************************/
/*!
* \brief Find an input lib for a given input image
*
* Searches trough the list of loaded input libraries to find one that supports
* the given input image's format. On success, that library is associated with
* the given image.
*
* \param p_h Output handle
* \param p_input_image Output image to search input lib for
* \return e_XmountOutputError_None on success
*/
te_XmountOutputError XmountOutput_FindLib(pts_XmountOutputHandle p_h);
/*******************************************************************************
* Public functions implementations
******************************************************************************/
/*
* XmountOutput_CreateHandle
*/
te_XmountOutputError
XmountOutput_CreateHandle(pts_XmountOutputHandle *pp_h,
tfun_XmountOutput_InputImageSize p_img_size,
tfun_XmountOutput_InputImageRead p_img_read,
tfun_XmountOutput_InputImageWrite p_img_write)
{
pts_XmountOutputHandle p_h=NULL;
// Params check
if(pp_h==NULL) return e_XmountOutputError_InvalidHandlePointer;
- // TODO: Implement
-
-/*
// Alloc new handle
p_h=(pts_XmountOutputHandle)calloc(1,sizeof(ts_XmountOutputHandle));
if(p_h==NULL) {
return e_XmountOutputError_Alloc;
}
// Init values
p_h->pp_libs=NULL;
+ p_h->p_output_format=NULL;
p_h->pp_lib_params=NULL;
- p_h->pp_images=NULL;
-*/
+ p_h->p_handle=NULL;
+ p_h->p_functions=NULL;
+ p_h->output_functions.Size=p_img_size;
+ p_h->output_functions.Read=p_img_read;
+ p_h->output_functions.Write=p_img_write;
+ p_h->p_virtual_image_path=NULL;
*pp_h=p_h;
return e_XmountOutputError_None;
}
/*
* XmountOutput_DestroyHandle
*/
te_XmountOutputError XmountOutput_DestroyHandle(pts_XmountOutputHandle *pp_h) {
+ int ret=0;
pts_XmountOutputHandle p_h=NULL;
- // TODO: Implement
-/*
// Params check
if(pp_h==NULL) return e_XmountOutputError_InvalidHandlePointer;
if(*pp_h==NULL) return e_XmountOutputError_InvalidHandle;
p_h=*pp_h;
// Free resources
- if(p_h->images_count!=0 && p_h->pp_images!=NULL) {
- // TODO: Close images
- }
- if(p_h->libs_count>0 && p_h->pp_libs!=NULL) {
- // Unload all input libs
- for(uint32_t i=0;i<p_h->libs_count;i++) {
- if(p_h->pp_libs[i]->p_supported_input_types!=NULL) {
- XMOUNT_FREE(p_h->pp_libs[i]->p_supported_input_types);
- }
- if(p_h->pp_libs[i]->p_lib!=NULL) {
- dlclose(p_h->pp_libs[i]->p_lib);
- p_h->pp_libs[i]->p_lib=NULL;
+ if(p_h->p_functions!=NULL) {
+ if(p_h->p_handle!=NULL) {
+ // Destroy output handle
+ ret=p_h->p_functions->DestroyHandle(&(p_h->p_handle));
+ if(ret!=0) {
+ LOG_ERROR("Unable to destroy output handle: %s!\n",
+ p_h->p_functions->GetErrorMessage(ret));
}
- if(p_h->pp_libs[i]->p_name!=NULL) {
- XMOUNT_FREE(p_h->pp_libs[i]->p_name);
- }
- XMOUNT_FREE(p_h->pp_libs[i]);
}
- XMOUNT_FREE(p_h->pp_libs);
- p_h->libs_count=0;
}
- if(p_h->lib_params_count!=0 && p_h->pp_lib_params!=NULL) {
- // Free library parameter array
+ if(p_h->pp_lib_params!=NULL) {
for(uint32_t i=0;i<p_h->lib_params_count;i++) {
XMOUNT_FREE(p_h->pp_lib_params[i]);
}
XMOUNT_FREE(p_h->pp_lib_params);
- p_h->lib_params_count=0;
}
-*/
+ if(p_h->p_output_format!=NULL) XMOUNT_FREE(p_h->p_output_format);
+ if(p_h->pp_libs!=NULL) {
+ // Unload output libs
+ for(uint32_t i=0;i<p_h->libs_count;i++) {
+ if(p_h->pp_libs[i]==NULL) continue;
+ if(p_h->pp_libs[i]->p_supported_output_formats!=NULL) {
+ XMOUNT_FREE(p_h->pp_libs[i]->p_supported_output_formats);
+ }
+ if(p_h->pp_libs[i]->p_lib!=NULL) dlclose(p_h->pp_libs[i]->p_lib);
+ if(p_h->pp_libs[i]->p_name!=NULL) XMOUNT_FREE(p_h->pp_libs[i]->p_name);
+ XMOUNT_FREE(p_h->pp_libs[i]);
+ }
+ XMOUNT_FREE(p_h->pp_libs);
+ }
+ if(p_h->p_virtual_image_path!=NULL) XMOUNT_FREE(p_h->p_virtual_image_path);
+
+ *pp_h=NULL;
return e_XmountOutputError_None;
}
/*
* XmountOutput_EnableDebugging
*/
te_XmountOutputError XmountOutput_EnableDebugging(pts_XmountOutputHandle p_h) {
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
// Enable debugging
p_h->debug=1;
return e_XmountOutputError_None;
}
/*
* XmountOutput_AddLibrary
*/
te_XmountOutputError XmountOutput_AddLibrary(pts_XmountOutputHandle p_h,
const char *p_lib_name)
{
- // TODO: Implement
-/*
uint32_t supported_formats_len=0;
- t_LibXmount_Output_GetApiVersion pfun_input_GetApiVersion;
- t_LibXmount_Output_GetSupportedFormats pfun_input_GetSupportedFormats;
- t_LibXmount_Output_GetFunctions pfun_input_GetFunctions;
+ t_LibXmount_Output_GetApiVersion pfun_output_GetApiVersion;
+ t_LibXmount_Output_GetSupportedFormats pfun_output_GetSupportedFormats;
+ t_LibXmount_Output_GetFunctions pfun_output_GetFunctions;
void *p_libxmount=NULL;
- pts_XmountOutputLib p_input_lib=NULL;
+ pts_XmountOutputLib p_output_lib=NULL;
char *p_buf=NULL;
char *p_library_path=NULL;
char *p_supported_formats=NULL;
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(p_lib_name==NULL) return e_XmountOutputError_InvalidString;
// Construct full library path
XMOUNT_STRSET(p_library_path,XMOUNT_LIBRARY_PATH);
if(p_library_path[strlen(p_library_path)]!='/') {
XMOUNT_STRAPP(p_library_path,"/");
}
XMOUNT_STRAPP(p_library_path,p_lib_name);
-#define XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL(name,pfun) { \
+#define XMOUNTOUTPUT_LOADLIBS__LOAD_SYMBOL(name,pfun) { \
if((pfun=dlsym(p_libxmount,name))==NULL) { \
LOG_ERROR("Unable to load symbol '%s' from library '%s'!\n", \
name, \
p_library_path); \
dlclose(p_libxmount); \
return e_XmountOutputError_FailedLoadingSymbol; \
} \
}
// Try to load given library
p_libxmount=dlopen(p_library_path,RTLD_NOW);
if(p_libxmount==NULL) {
- LOG_ERROR("Unable to load input library '%s': %s!\n",
+ LOG_ERROR("Unable to load output library '%s': %s!\n",
p_library_path,
dlerror());
return e_XmountOutputError_FailedLoadingLibrary;
}
// Load library symbols
- XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Output_GetApiVersion",
- pfun_input_GetApiVersion);
+ XMOUNTOUTPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Output_GetApiVersion",
+ pfun_output_GetApiVersion);
// Check library's API version
- if(pfun_input_GetApiVersion()!=LIBXMOUNT_INPUT_API_VERSION) {
+ if(pfun_output_GetApiVersion()!=LIBXMOUNT_OUTPUT_API_VERSION) {
LOG_DEBUG("Failed! Wrong API version.\n");
- LOG_ERROR("Unable to load input library '%s'. Wrong API version\n",
+ LOG_ERROR("Unable to load output library '%s'. Wrong API version\n",
p_library_path);
dlclose(p_libxmount);
return e_XmountOutputError_WrongLibraryApiVersion;
}
- XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Output_GetSupportedFormats",
- pfun_input_GetSupportedFormats);
- XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Output_GetFunctions",
- pfun_input_GetFunctions);
+ XMOUNTOUTPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Output_GetSupportedFormats",
+ pfun_output_GetSupportedFormats);
+ XMOUNTOUTPUT_LOADLIBS__LOAD_SYMBOL("LibXmount_Output_GetFunctions",
+ pfun_output_GetFunctions);
// Construct new entry for our library list
- XMOUNT_MALLOC(p_input_lib,pts_XmountOutputLib,sizeof(ts_XmountOutputLib));
+ XMOUNT_MALLOC(p_output_lib,pts_XmountOutputLib,sizeof(ts_XmountOutputLib));
// Initialize lib_functions structure to NULL
- memset(&(p_input_lib->lib_functions),
+ memset(&(p_output_lib->lib_functions),
0,
- sizeof(ts_LibXmountOutputFunctions));
+ sizeof(ts_LibXmountOutput_Functions));
// Set name and handle
- XMOUNT_STRSET(p_input_lib->p_name,p_lib_name);
- p_input_lib->p_lib=p_libxmount;
+ XMOUNT_STRSET(p_output_lib->p_name,p_lib_name);
+ p_output_lib->p_lib=p_libxmount;
// Get and set supported formats
- p_supported_formats=pfun_input_GetSupportedFormats();
+ p_supported_formats=pfun_output_GetSupportedFormats();
p_buf=p_supported_formats;
while(*p_buf!='\0') {
supported_formats_len+=(strlen(p_buf)+1);
p_buf+=(strlen(p_buf)+1);
}
supported_formats_len++;
- XMOUNT_MALLOC(p_input_lib->p_supported_input_types,
+ XMOUNT_MALLOC(p_output_lib->p_supported_output_formats,
char*,
supported_formats_len);
- memcpy(p_input_lib->p_supported_input_types,
+ memcpy(p_output_lib->p_supported_output_formats,
p_supported_formats,
supported_formats_len);
// Get, set and check lib_functions
- pfun_input_GetFunctions(&(p_input_lib->lib_functions));
- if(p_input_lib->lib_functions.CreateHandle==NULL ||
- p_input_lib->lib_functions.DestroyHandle==NULL ||
- p_input_lib->lib_functions.Open==NULL ||
- p_input_lib->lib_functions.Close==NULL ||
- p_input_lib->lib_functions.Size==NULL ||
- p_input_lib->lib_functions.Read==NULL ||
- p_input_lib->lib_functions.OptionsHelp==NULL ||
- p_input_lib->lib_functions.OptionsParse==NULL ||
- p_input_lib->lib_functions.GetInfofileContent==NULL ||
- p_input_lib->lib_functions.GetErrorMessage==NULL ||
- p_input_lib->lib_functions.FreeBuffer==NULL)
+ pfun_output_GetFunctions(&(p_output_lib->lib_functions));
+ if(p_output_lib->lib_functions.CreateHandle==NULL ||
+ p_output_lib->lib_functions.DestroyHandle==NULL ||
+ p_output_lib->lib_functions.Transform==NULL ||
+ p_output_lib->lib_functions.Size==NULL ||
+ p_output_lib->lib_functions.Read==NULL ||
+ p_output_lib->lib_functions.OptionsHelp==NULL ||
+ p_output_lib->lib_functions.OptionsParse==NULL ||
+ p_output_lib->lib_functions.GetInfofileContent==NULL ||
+ p_output_lib->lib_functions.GetErrorMessage==NULL ||
+ p_output_lib->lib_functions.FreeBuffer==NULL)
{
LOG_DEBUG("Missing implemention of one or more functions in lib %s!\n",
p_lib_name);
- XMOUNT_FREE(p_input_lib->p_supported_input_types);
- XMOUNT_FREE(p_input_lib->p_name);
- XMOUNT_FREE(p_input_lib);
+ XMOUNT_FREE(p_output_lib->p_supported_output_formats);
+ XMOUNT_FREE(p_output_lib->p_name);
+ XMOUNT_FREE(p_output_lib);
dlclose(p_libxmount);
return e_XmountOutputError_MissingLibraryFunction;
}
// Add entry to the input library list
XMOUNT_REALLOC(p_h->pp_libs,
pts_XmountOutputLib*,
sizeof(pts_XmountOutputLib)*(p_h->libs_count+1));
- p_h->pp_libs[p_h->libs_count++]=p_input_lib;
+ p_h->pp_libs[p_h->libs_count++]=p_output_lib;
LOG_DEBUG("Output library '%s' loaded successfully\n",p_lib_name);
-#undef XMOUNTINPUT_LOADLIBS__LOAD_SYMBOL
-*/
+#undef XMOUNTOUTPUT_LOADLIBS__LOAD_SYMBOL
+
return e_XmountOutputError_None;
}
te_XmountOutputError XmountOutput_GetLibraryCount(pts_XmountOutputHandle p_h,
uint32_t *p_count)
{
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(p_count==NULL) return e_XmountOutputError_InvalidBuffer;
// Return library count
*p_count=p_h->libs_count;
return e_XmountOutputError_None;
}
/*
* XmountOutput_GetSupportedFormats
*/
te_XmountOutputError
XmountOutput_GetSupportedFormats(pts_XmountOutputHandle p_h,
char **pp_formats)
{
char *p_buf=NULL;
char *p_formats=NULL;
uint32_t cur_len=0;
uint32_t vector_len=0;
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(pp_formats==NULL) return e_XmountOutputError_InvalidBuffer;
// Loop over all loaded libs, extract supported formats and add to our vector
// TODO: IMPROVEMENT: Final vector could be sorted
for(uint32_t i=0;i<p_h->libs_count;i++) {
p_buf=p_h->pp_libs[i]->p_supported_output_formats;
while(p_buf!=NULL && *p_buf!='\0') p_buf+=(strlen(p_buf)+1);
cur_len=(uint32_t)(p_buf-p_h->pp_libs[i]->p_supported_output_formats);
if(cur_len==0) continue;
p_formats=(char*)realloc(p_formats,vector_len+cur_len);
if(p_formats==NULL) return e_XmountOutputError_Alloc;
memcpy(p_formats+vector_len,
p_h->pp_libs[i]->p_supported_output_formats,
cur_len);
vector_len+=cur_len;
}
// Null-terminate vector
p_formats=(char*)realloc(p_formats,vector_len+1);
if(p_formats==NULL) return e_XmountOutputError_Alloc;
p_formats[vector_len]='\0';
*pp_formats=p_formats;
return e_XmountOutputError_None;
}
/*
* XmountOutput_SetOptions
*/
te_XmountOutputError XmountOutput_SetOptions(pts_XmountOutputHandle p_h,
char *p_options)
{
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(p_options==NULL) return e_XmountOutputError_InvalidString;
// Make sure library parameters haven't been set previously
if(p_h->pp_lib_params!=NULL) {
LOG_ERROR("Output library options already set!\n");
return e_XmountOutputError_LibOptionsAlreadySet;
}
// Save options
if(XmountLib_SplitLibParams(p_options,
&(p_h->lib_params_count),
&(p_h->pp_lib_params))!=0)
{
LOG_ERROR("Unable to parse input library options '%s'!\n",p_options);
return e_XmountOutputError_FailedParsingOptions;
}
return e_XmountOutputError_None;
}
/*
* XmountOutput_GetOptionsHelpText
*/
te_XmountOutputError XmountOutput_GetOptionsHelpText(pts_XmountOutputHandle p_h,
char **pp_help_text)
{
const char *p_buf=NULL;
char *p_help=NULL;
int ret=0;
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(pp_help_text==NULL) return e_XmountOutputError_InvalidBuffer;
// Loop over all loaded libs, extract help and add to our text buffer
// TODO: IMPROVEMENT: Final text should be sorted by lib's name
for(uint32_t i=0;i<p_h->libs_count;i++) {
ret=p_h->pp_libs[i]->lib_functions.OptionsHelp((const char**)&p_buf);
if(ret!=0) {
LOG_ERROR("Unable to get options help for library '%s': %s!\n",
p_h->pp_libs[i]->p_name,
p_h->pp_libs[i]->lib_functions.GetErrorMessage(ret));
}
if(p_buf==NULL) continue;
XMOUNT_STRAPP(p_help," - ");
XMOUNT_STRAPP(p_help,p_h->pp_libs[i]->p_name);
XMOUNT_STRAPP(p_help,"\n");
XMOUNT_STRAPP(p_help,p_buf);
XMOUNT_STRAPP(p_help,"\n");
- ret=p_h->pp_libs[i]->lib_functions.FreeBuffer(p_buf);
- if(ret!=0) {
- LOG_ERROR("Unable to free options help text from library '%s': %s!\n",
- p_h->pp_libs[i]->p_name,
- p_h->pp_libs[i]->lib_functions.GetErrorMessage(ret));
- }
+ p_h->pp_libs[i]->lib_functions.FreeBuffer(p_buf);
}
*pp_help_text=p_help;
return e_XmountOutputError_None;
}
/*
* XmountOutput_GetLibsInfoText
*/
te_XmountOutputError XmountOutput_GetLibsInfoText(pts_XmountOutputHandle p_h,
char **pp_info_text)
{
char *p_buf=NULL;
char *p_info_text=NULL;
uint8_t first=0;
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(pp_info_text==NULL) return e_XmountOutputError_InvalidBuffer;
// Loop over all loaded libs, extract name and supported formats and add to
// our text buffer
// TODO: IMPROVEMENT: Final text should be sorted by lib's name
for(uint32_t i=0;i<p_h->libs_count;i++) {
XMOUNT_STRAPP(p_info_text," - ");
XMOUNT_STRAPP(p_info_text,p_h->pp_libs[i]->p_name);
XMOUNT_STRAPP(p_info_text," supporting ");
XMOUNT_STRAPP(p_info_text," - ");
XMOUNT_STRAPP(p_info_text," - ");
- p_buf=p_h->pp_libs[i]->p_supported_output_types;
+ p_buf=p_h->pp_libs[i]->p_supported_output_formats;
first=1;
while(*p_buf!='\0') {
if(first==1) {
XMOUNT_STRAPP(p_info_text,"\"");
XMOUNT_STRAPP(p_info_text,p_buf);
XMOUNT_STRAPP(p_info_text,"\"");
first=0;
} else {
XMOUNT_STRAPP(p_info_text,", \"");
XMOUNT_STRAPP(p_info_text,p_buf);
XMOUNT_STRAPP(p_info_text,"\"");
}
p_buf+=(strlen(p_buf)+1);
}
XMOUNT_STRAPP(p_info_text,"\n");
}
*pp_info_text=p_info_text;
return e_XmountOutputError_None;
}
/*
- * XmountOutput_SetType
+ * XmountOutput_SetFormat
*/
-te_XmountOutputError XmountOutput_SetType(pts_XmountOutputHandle p_h,
- char *p_format)
+te_XmountOutputError XmountOutput_SetFormat(pts_XmountOutputHandle p_h,
+ char *p_format)
{
- // TODO: Implement
+ // Params check
+ if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
+ if(p_format==NULL) return e_XmountMorphError_InvalidString;
+
+ // Set output format
+ XMOUNT_STRSET(p_h->p_output_format,p_format);
+
return e_XmountOutputError_None;
}
/*
- * XmountOutput_Open
+ * XmountOutput_Transform
*/
-te_XmountOutputError XmountOutput_Open(pts_XmountOutputHandle p_h) {
- // TODO: Implement
- return e_XmountOutputError_None;
-}
+te_XmountOutputError XmountOutput_Transform(pts_XmountOutputHandle p_h) {
+ const char *p_err_msg=NULL;
+ int ret=0;
+ te_XmountOutputError output_ret=e_XmountOutputError_None;
+
+ // Params check
+ if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
+
+ // Set default output format if none was set previously
+ if(p_h->p_output_format==NULL) {
+ XMOUNT_STRSET(p_h->p_output_format,XMOUNT_OUTPUT_DEFAULT_OUTPUT_FORMAT);
+ }
+
+ // Find output lib
+ output_ret=XmountOutput_FindOutputLib(p_h);
+ if(output_ret!=e_XmountOutputError_None) {
+ LOG_ERROR("Unable to find a library supporting the output format '%s'!\n",
+ p_h->p_output_format);
+ return output_ret;
+ }
+ // Init output
+ ret=p_h->p_functions->CreateHandle(&p_h->p_handle,
+ p_h->p_output_format,
+ p_h->debug);
+ if(ret!=0) {
+ LOG_ERROR("Unable to create output handle: %s!\n",
+ p_h->p_functions->GetErrorMessage(ret));
+ return e_XmountOutputError_FailedCreatingOutputHandle;
+ }
+
+ // Parse output lib specific options
+ if(p_h->pp_lib_params!=NULL) {
+ p_err_msg=NULL;
+ ret=p_h->p_functions->OptionsParse(p_h->p_handle,
+ p_h->lib_params_count,
+ p_h->pp_lib_params,
+ &p_err_msg);
+ if(ret!=0) {
+ if(p_err_msg!=NULL) {
+ LOG_ERROR("Unable to parse output library specific options: %s: %s!\n",
+ p_h->p_functions->GetErrorMessage(ret),
+ p_err_msg);
+ p_h->p_functions->FreeBuffer(p_err_msg);
+ } else {
+ LOG_ERROR("Unable to parse output library specific options: %s!\n",
+ p_h->p_functions->GetErrorMessage(ret));
+ }
+ return e_XmountOutputError_FailedParsingLibParams;
+ }
+ }
+
+ // TODO: This has to be done somewhere!
/*
- * XmountOutput_Close
- */
-te_XmountOutputError XmountOutput_Close(pts_XmountOutputHandle p_h) {
- // TODO: Implement
+ if(!ExtractOutputFileNames(glob_xmount.p_first_input_image_name)) {
+ LOG_ERROR("Couldn't extract virtual file names!\n");
+ FreeResources();
+ return 1;
+ }
+ LOG_DEBUG("Virtual file names extracted successfully\n")
+*/
+
return e_XmountOutputError_None;
}
/*
* XmountOutput_GetOutputFilenames
*/
te_XmountOutputError
XmountOutput_GetOutputFilenames(pts_XmountOutputHandle p_h,
char ***ppp_output_files);
/*
* XmountOutput_GetSize
*/
te_XmountOutputError XmountOutput_GetSize(pts_XmountOutputHandle p_h,
const char *p_output_filename,
uint64_t *p_size)
{
/*
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(image_nr>=p_h->images_count) return e_XmountOutputError_NoSuchImage;
if(p_size==NULL) return e_XmountOutputError_InvalidBuffer;
*p_size=p_h->pp_images[image_nr]->size;
*/
// TODO: Implement
return e_XmountOutputError_None;
}
/*
* XmountOutput_ReadData
*/
te_XmountOutputError XmountOutput_ReadData(pts_XmountOutputHandle p_h,
const char *p_output_filename,
char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_read)
{
// TODO: Implement
/*
uint64_t to_read=0;
int ret=0;
int read_errno=0;
pts_XmountOutputImage p_image=NULL;
// Params check
if(p_h==NULL) return e_XmountOutputError_InvalidHandle;
if(image_nr>=p_h->images_count) return e_XmountOutputError_NoSuchImage;
if(p_buf==NULL) return e_XmountOutputError_InvalidBuffer;
p_image=p_h->pp_images[image_nr];
LOG_DEBUG("Reading %zu bytes at offset %zu from input image '%s'\n",
count,
offset,
p_image->pp_files[0]);
// Make sure we aren't reading past EOF of image file
if(offset>=p_image->size) {
// Offset is beyond image size
LOG_DEBUG("Offset %zu is at / beyond size of input image '%s'\n",
offset,
p_image->pp_files[0]);
*p_read=0;
return 0;
}
if(offset+count>p_image->size) {
// Attempt to read data past EOF of image file
to_read=p_image->size-offset;
LOG_DEBUG("Attempt to read data past EOF of input image '%s'. "
"Correcting size from %zu to %zu\n",
p_image->pp_files[0],
count,
to_read);
} else to_read=count;
// Read data from image file (adding input image offset if one was specified)
ret=p_image->p_functions->Read(p_image->p_handle,
p_buf,
offset+p_h->image_offset,
to_read,
p_read,
&read_errno);
if(ret!=0) {
LOG_ERROR("Couldn't read %zu bytes at offset %zu from input image "
"'%s': %s: Error code %u!\n",
to_read,
offset,
p_image->pp_files[0],
p_image->p_functions->GetErrorMessage(ret),
read_errno);
return e_XmountOutputError_FailedReadingData;
}
*/
return e_XmountOutputError_None;
}
/*
* XmountOutput_WriteData
*/
te_XmountOutputError XmountOutput_WriteData(pts_XmountOutputHandle p_h,
const char *p_output_filename,
const char *p_buf,
uint64_t offset,
- uint64_t count)
+ uint64_t count,
+ uint64_t *p_written)
{
// TODO: Implement
return e_XmountOutputError_None;
}
/*
* XmountOutput_GetInfoFileContent
*/
te_XmountOutputError XmountOutput_GetInfoFileContent(pts_XmountOutputHandle p_h,
char **pp_content)
{
char *p_content=NULL;
// TODO: Implement
*pp_content=p_content;
return e_XmountOutputError_None;
}
/*******************************************************************************
* Private functions implementations
******************************************************************************/
/*
* FindOutputLib
*/
-te_XmountOutputError XmountOutput_FindLib(pts_XmountOutputHandle p_h,
- pts_XmountOutputImage p_input_image)
-{
- // TODO: Implement
+te_XmountOutputError XmountOutput_FindLib(pts_XmountOutputHandle p_h) {
+ char *p_buf;
+
+ LOG_DEBUG("Trying to find suitable library for output format '%s'.\n",
+ p_h->p_output_format);
+
+ // Loop over all loaded output libs
+ for(uint32_t i=0;i<p_h->libs_count;i++) {
+ LOG_DEBUG("Checking output library %s\n",p_h->pp_libs[i]->p_name);
+ p_buf=p_h->pp_libs[i]->p_supported_output_formats;
+ while(*p_buf!='\0') {
+ if(strcmp(p_buf,p_h->p_output_format)==0) {
+ // Library supports output type, set lib functions
+ LOG_DEBUG("Output library '%s' pretends to handle that output format.\n",
+ p_h->pp_libs[i]->p_name);
+ p_h->p_functions=&(p_h->pp_libs[i]->lib_functions);
+ return e_XmountOutputError_None;
+ }
+ p_buf+=(strlen(p_buf)+1);
+ }
+ }
+
+ LOG_DEBUG("Couldn't find any suitable library.\n");
// No library supporting input type found
return e_XmountOutputError_UnsupportedFormat;
}
//! Get size of output image
/*!
* \param p_size Pointer to an uint64_t to which the size will be written to
* \return TRUE on success, FALSE on error
*/
/*
int GetOutputImageSize(uint64_t *p_size) {
int ret;
uint64_t output_image_size=0;
if(glob_xmount.output.image_size!=0) {
*p_size=glob_xmount.output.image_size;
return TRUE;
}
ret=glob_xmount.output.p_functions->Size(glob_xmount.output.p_handle,
&output_image_size);
if(ret!=0) {
LOG_ERROR("Couldn't get output image size!\n")
return FALSE;
}
glob_xmount.output.image_size=output_image_size;
*p_size=output_image_size;
return TRUE;
}
*/
//! Read data from output image
/*!
* \param p_buf Pointer to buffer to write read data to
* \param offset Offset at which data should be read
* \param size Size of data which should be read
* \return Number of read bytes on success or negated error code on error
*/
/*
int ReadOutputImageData(char *p_buf, off_t offset, size_t size) {
uint64_t output_image_size;
size_t read=0;
int ret;
// Get output image size
if(GetOutputImageSize(&output_image_size)!=TRUE) {
LOG_ERROR("Couldn't get size of output image!\n")
return -EIO;
}
// Make sure request is within output image
if(offset>=output_image_size) {
LOG_DEBUG("Offset %zu is at / beyond size of output image.\n",offset);
return 0;
}
if(offset+size>output_image_size) {
LOG_DEBUG("Attempt to read data past EOF of output image. Correcting size "
"from %zu to %zu.\n",
size,
output_image_size-offset);
size=output_image_size-offset;
}
// Read data
ret=glob_xmount.output.p_functions->Read(glob_xmount.output.p_handle,
p_buf,
offset,
size,
&read);
if(ret!=0) {
LOG_ERROR("Unable to read %zu bytes at offset %zu from output image!\n",
size,
offset)
return ret;
} else if(read!=size) {
LOG_WARNING("Unable to read all requested data from output image!\n")
return read;
}
return size;
}
*/
//! Write data to output image
/*!
* \param p_buf Buffer with data to write
* \param offset Offset to write to
* \param size Amount of bytes to write
* \return Number of written bytes on success or "-1" on error
*/
/*
int WriteOutputImageData(const char *p_buf, off_t offset, size_t size) {
uint64_t output_image_size;
int ret;
size_t written;
// Get output image size
if(!GetOutputImageSize(&output_image_size)) {
LOG_ERROR("Couldn't get output image size!\n")
return -1;
}
// Make sure write is within output image
if(offset>=output_image_size) {
LOG_ERROR("Attempt to write beyond EOF of output image file!\n")
return -1;
}
if(offset+size>output_image_size) {
LOG_DEBUG("Attempt to write past EOF of output image file. Correcting size "
"from %zu to %zu.\n",
size,
output_image_size-offset);
size=output_image_size-offset;
}
ret=glob_xmount.output.p_functions->Write(glob_xmount.output.p_handle,
p_buf,
offset,
size,
&written);
if(ret!=0) {
LOG_ERROR("Unable to write %zu bytes at offset %zu to output image!\n",
offset,
size)
return ret;
} else if(written!=size) {
LOG_WARNING("Unable to write all requested data to output image!\n")
}
return size;
}
*/
diff --git a/src/xmount_output.h b/src/xmount_output.h
index 6f7f3de..73705e4 100644
--- a/src/xmount_output.h
+++ b/src/xmount_output.h
@@ -1,353 +1,347 @@
/*******************************************************************************
* xmount Copyright (c) 2008-2016 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* This program is free software: you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the Free *
* Software Foundation, either version 3 of the License, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef XMOUNT_OUTPUT_H
#define XMOUNT_OUTPUT_H
/*******************************************************************************
* Public definitions / macros
******************************************************************************/
//! Naming scheme of morphing libraries
#define XMOUNT_OUTPUT_LIBRARY_NAMING_SCHEME "libxmount_output_"
+//! Default output format
+#define XMOUNT_OUTPUT_DEFAULT_OUTPUT_FORMAT "raw"
/*******************************************************************************
* Public types / structures / enums
******************************************************************************/
//! Output handle
typedef struct s_XmountOutputHandle *pts_XmountOutputHandle;
/*!
* \brief Function to get the size of the morphed data
*
* Function to get the size of the morphed data
*
* \param image Image number
* \param p_size Pointer to store input image's size to
* \return 0 on success
*/
typedef int (*tfun_XmountOutput_InputImageSize)(uint64_t image,
uint64_t *p_size);
//! Function to read data from input image
/*!
* \param image Image number
* \param p_buf Buffer to store read data to
* \param offset Position at which to start reading
* \param count Amount of bytes to read
* \param p_read Number of read bytes on success
* \return 0 on success or negated error code on error
*/
typedef int (*tfun_XmountOutput_InputImageRead)(uint64_t image,
char *p_buf,
off_t offset,
size_t count,
size_t *p_read);
//! Function to write data to input image
/*!
* \param image Image number
* \param p_buf Buffer to store read data to
* \param offset Position at which to start reading
* \param count Amount of bytes to read
* \param p_read Number of read bytes on success
* \return 0 on success or negated error code on error
*/
typedef int (*tfun_XmountOutput_InputImageWrite)(uint64_t image,
char *p_buf,
off_t offset,
size_t count,
size_t *p_written);
typedef enum e_XmountOutputError {
//! No error
e_XmountOutputError_None=0,
//! Error to allocate memory
e_XmountOutputError_Alloc,
//! Invalid morphing handle
e_XmountOutputError_InvalidHandle,
//! Invalid pointer to a morphing handle
e_XmountOutputError_InvalidHandlePointer,
//! A given buffer is invalid
e_XmountOutputError_InvalidBuffer,
//! A given string is invalid
e_XmountOutputError_InvalidString,
-/*
//! Library options have already been set
- e_XmountMorphError_LibOptionsAlreadySet,
+ e_XmountOutputError_LibOptionsAlreadySet,
//! Library options couldn't be parsed
- e_XmountMorphError_FailedParsingOptions,
+ e_XmountOutputError_FailedParsingOptions,
+/*
//! Unable to get info file content from library
e_XmountMorphError_FailedGettingInfoFileContent,
+*/
//! Unable to load library file
- e_XmountMorphError_FailedLoadingLibrary,
+ e_XmountOutputError_FailedLoadingLibrary,
//! Unable to load a library symbol
- e_XmountMorphError_FailedLoadingSymbol,
+ e_XmountOutputError_FailedLoadingSymbol,
//! Library has wrong API version
- e_XmountMorphError_WrongLibraryApiVersion,
+ e_XmountOutputError_WrongLibraryApiVersion,
//! Library is missing a function
- e_XmountMorphError_MissingLibraryFunction,
- //! Unsupported morphing type
- e_XmountMorphError_UnsupportedType,
- //! Unable to create morphing image handle
- e_XmountMorphError_FailedCreatingMorphHandle,
- //! Unable to parse morphing library options
- e_XmountMorphError_FailedParsingLibParams,
+ e_XmountOutputError_MissingLibraryFunction,
+ //! Unsupported output format
+ e_XmountOutputError_UnsupportedFormat,
+ //! Unable to create output library handle
+ e_XmountOutputError_FailedCreatingOutputHandle,
+ //! Unable to parse output library options
+ e_XmountOutputError_FailedParsingLibParams,
+/*
//! Unable to get image size
e_XmountMorphError_FailedGettingImageSize,
//! A specified offset is larger than the image
e_XmountMorphError_OffsetExceedsImageSize,
//! Unable to read data from morphed image
e_XmountMorphError_FailedReadingData
*/
} te_XmountOutputError;
/*******************************************************************************
* Public functions declarations
******************************************************************************/
/*!
* \brief Create new output handle
*
* Creates a new output handle.
*
* \param pp_h Pointer to output handle
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError
XmountOutput_CreateHandle(pts_XmountOutputHandle *pp_h,
tfun_XmountOutput_InputImageSize p_img_size,
tfun_XmountOutput_InputImageRead p_img_read,
tfun_XmountOutput_InputImageWrite p_img_write);
/*!
* \brief Destroy output handle
*
* Invalidates the given handle and frees all used resources.
*
* \param pp_h Pointer to output handle
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_DestroyHandle(pts_XmountOutputHandle *pp_h);
/*!
* \brief Enable internal debugging
*
* Enables the generation of intrernal debugging messages.
*
* \param p_h Output handle
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_EnableDebugging(pts_XmountOutputHandle p_h);
/*!
* \brief Load an output library
*
* Loads a given output library.
*
* \param p_h Output handle
* \param p_lib Library name (without path)
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_AddLibrary(pts_XmountOutputHandle p_h,
const char *p_lib_name);
/*!
* \brief Get loaded output library count
*
* Returns the number of successfully loaded output libraries.
*
* \param p_h Output handle
* \param p_count Library count is returned in this variable
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_GetLibraryCount(pts_XmountOutputHandle p_h,
uint32_t *p_count);
/*!
* \brief Return all supported output formats
*
* Returns a null-terminated vector of all supported output formats.
*
* The returned vector must be freed by the caller.
*
* \param p_h Output handle
* \param pp_types Supported formats vector is returned in this var
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError
XmountOutput_GetSupportedFormats(pts_XmountOutputHandle p_h,
char **pp_formats);
/*!
* \brief Set library options
*
* Parses the given library option string (as given after --outopts).
*
* \param p_h Output handle
* \param p_options Library option string
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_SetOptions(pts_XmountOutputHandle p_h,
char *p_options);
/*!
* \brief Return all library specific option help texts
*
* Returns a string containing help messages for all loaded output lib
* options. The string is pre-formated to be used in xmount's help output.
*
* The caller must free the returned string.
*
* \param p_h Output handle
* \param pp_help_text Help text is returned in this parameter
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_GetOptionsHelpText(pts_XmountOutputHandle p_h,
char **pp_help_text);
/*!
* \brief Returns a string containing infos about loaded libs
*
* Returns a string containing infos about loaded output libraries. The
* string is pre-formated to be used in xmount's info output.
*
* The caller must free the returned string.
*
* \param p_h Output handle
* \param pp_info_text Info text is returned in this parameter
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_GetLibsInfoText(pts_XmountOutputHandle p_h,
char **pp_info_text);
/*!
* \brief Set output format
*
* Set the output format.
*
* \param p_h Output handle
* \param p_type Output format string as specified with xmount's --out option.
* \return e_XmountMorphError_None on success
*/
-te_XmountOutputError XmountOutput_SetType(pts_XmountOutputHandle p_h,
- char *p_format);
+te_XmountOutputError XmountOutput_SetFormat(pts_XmountOutputHandle p_h,
+ char *p_format);
/*!
* \brief Generate output image
*
* Gets the output image ready for usage.
*
* \param p_h Output handle
* \return e_XmountMorphError_None on success
*/
-te_XmountOutputError XmountOutput_Open(pts_XmountOutputHandle p_h);
-
-/*!
- * \brief Destroy output image
- *
- * Frees what was necessary to use the output image.
- *
- * \param p_h Output handle
- * \return e_XmountMorphError_None on success
- */
-te_XmountOutputError XmountOutput_Close(pts_XmountOutputHandle p_h);
+te_XmountOutputError XmountOutput_Transform(pts_XmountOutputHandle p_h);
/*!
* \brief Returns an array containing all output files names
*
* TODO: Describe
*
* \param p_h Output handle
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError
XmountOutput_GetOutputFilenames(pts_XmountOutputHandle p_h,
char ***ppp_output_files);
/*!
* \brief Get the size of the output image
*
* Returns the size (in bytes) of the specified output image.
*
* \param p_h Output handle
* \param p_output_filename Output file for which to return the size
* \param p_size On success, size is returned in this variable
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_GetSize(pts_XmountOutputHandle p_h,
const char *p_output_filename,
uint64_t *p_size);
/*!
* \brief Read data from an output image
*
* Reads count bytes from the specified output image starting at given offset
* and copies the data into p_buf.
*
* The given buffer must be pre-allocated to hold as many bytes as should be
* read!
*
* \param p_h Output handle
* \param p_output_filename Output file for which to return the size
* \param p_buf Buffer into which to copy read data
* \param offset Offset at which to start reading
* \param count Amount of bytes to read
* \param p_read On success, amount of bytes read is returned in this variable
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_ReadData(pts_XmountOutputHandle p_h,
const char *p_output_filename,
char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_read);
/*!
* \brief Writes data to an output image
*
* Writes count bytes from p_buf to the specified output image starting at the
* given offset.
*
* \param p_h Output handle
* \param p_output_filename Output file for which to return the size
* \param p_buf Buffer with data to write
* \param offset Offset at which to start writing
* \param count Amount of bytes to write
* \param p_written On success, amount of bytes written is returned here
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_WriteData(pts_XmountOutputHandle p_h,
const char *p_output_filename,
const char *p_buf,
uint64_t offset,
uint64_t count,
uint64_t *p_written);
/*!
* \brief Get info text to be added to xmount's info file
*
* Generates a string containing informations about the output image.
*
* The caller must free the returned string.
*
* \param p_h Output handle
* \param pp_content Buffer in which text is returned
* \return e_XmountMorphError_None on success
*/
te_XmountOutputError XmountOutput_GetInfoFileContent(pts_XmountOutputHandle p_h,
char **pp_content);
#endif // XMOUNT_OUTPUT_H

File Metadata

Mime Type
text/x-diff
Expires
Mon, Dec 23, 1:17 PM (19 h, 5 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1176887
Default Alt Text
(195 KB)

Event Timeline