2017-04-03 15:29:45 +03:00
/*
* virfilewrapper . c : Wrapper for universal file access
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library 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
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
2017-05-11 13:42:14 +03:00
# ifndef WIN32
2017-04-03 15:29:45 +03:00
2017-05-11 13:42:14 +03:00
# include <fcntl.h>
# include "viralloc.h"
# include "virfile.h"
# include "virfilewrapper.h"
# include "virmock.h"
# include "virstring.h"
2017-04-03 15:29:45 +03:00
/* Mapping for prefix overrides */
static size_t noverrides ;
static const char * * overrides ;
/* nprefixes == noverrides, but two variables make it easier to use
* VIR_ * _ELEMENT macros */
static size_t nprefixes ;
static const char * * prefixes ;
/* TODO: callbacks */
static int ( * real_open ) ( const char * path , int flags , . . . ) ;
static FILE * ( * real_fopen ) ( const char * path , const char * mode ) ;
static int ( * real_access ) ( const char * path , int mode ) ;
static int ( * real_stat ) ( const char * path , struct stat * sb ) ;
static int ( * real___xstat ) ( int ver , const char * path , struct stat * sb ) ;
static int ( * real_lstat ) ( const char * path , struct stat * sb ) ;
static int ( * real___lxstat ) ( int ver , const char * path , struct stat * sb ) ;
static int ( * real_mkdir ) ( const char * path , mode_t mode ) ;
static DIR * ( * real_opendir ) ( const char * path ) ;
static void init_syms ( void )
{
if ( real_fopen )
return ;
VIR_MOCK_REAL_INIT ( fopen ) ;
VIR_MOCK_REAL_INIT ( access ) ;
VIR_MOCK_REAL_INIT_ALT ( lstat , __lxstat ) ;
VIR_MOCK_REAL_INIT_ALT ( stat , __xstat ) ;
VIR_MOCK_REAL_INIT ( mkdir ) ;
VIR_MOCK_REAL_INIT ( open ) ;
VIR_MOCK_REAL_INIT ( opendir ) ;
}
int
virFileWrapperAddPrefix ( const char * prefix ,
2017-07-25 12:43:33 +03:00
const char * override )
2017-04-03 15:29:45 +03:00
{
/* Both parameters are mandatory */
if ( ! prefix | | ! override )
return - 1 ;
init_syms ( ) ;
if ( VIR_APPEND_ELEMENT_QUIET ( prefixes , nprefixes , prefix ) < 0 | |
VIR_APPEND_ELEMENT_QUIET ( overrides , noverrides , override ) < 0 ) {
VIR_FREE ( prefixes ) ;
VIR_FREE ( overrides ) ;
return - 1 ;
}
return 0 ;
}
void
virFileWrapperRemovePrefix ( const char * prefix )
{
size_t i = 0 ;
for ( i = 0 ; i < noverrides ; i + + ) {
if ( STREQ ( prefixes [ i ] , prefix ) )
break ;
}
if ( i = = noverrides )
return ;
VIR_DELETE_ELEMENT ( overrides , i , noverrides ) ;
VIR_DELETE_ELEMENT ( prefixes , i , nprefixes ) ;
}
void
virFileWrapperClearPrefixes ( void )
{
nprefixes = 0 ;
noverrides = 0 ;
VIR_FREE ( prefixes ) ;
VIR_FREE ( overrides ) ;
}
static char *
virFileWrapperOverridePrefix ( const char * path )
{
char * ret = NULL ;
size_t i = 0 ;
for ( i = 0 ; i < noverrides ; i + + ) {
const char * tmp = STRSKIP ( path , prefixes [ i ] ) ;
if ( ! tmp )
continue ;
if ( virAsprintfQuiet ( & ret , " %s%s " , overrides [ i ] , tmp ) < 0 )
return NULL ;
break ;
}
if ( ! ret )
ignore_value ( VIR_STRDUP_QUIET ( ret , path ) ) ;
return ret ;
}
2017-11-03 15:09:47 +03:00
# define PATH_OVERRIDE(newpath, path) \
do { \
init_syms ( ) ; \
\
newpath = virFileWrapperOverridePrefix ( path ) ; \
if ( ! newpath ) \
abort ( ) ; \
2017-04-03 15:29:45 +03:00
} while ( 0 )
FILE * fopen ( const char * path , const char * mode )
{
FILE * ret = NULL ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real_fopen ( newpath , mode ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
int access ( const char * path , int mode )
{
int ret = - 1 ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real_access ( newpath , mode ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
2017-05-11 13:42:14 +03:00
# ifdef HAVE___LXSTAT
2017-04-03 15:29:45 +03:00
int __lxstat ( int ver , const char * path , struct stat * sb )
{
int ret = - 1 ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real___lxstat ( ver , newpath , sb ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
2017-05-11 13:42:14 +03:00
# endif /* HAVE___LXSTAT */
2017-04-03 15:29:45 +03:00
int lstat ( const char * path , struct stat * sb )
{
int ret = - 1 ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real_lstat ( newpath , sb ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
2017-05-11 13:42:14 +03:00
# ifdef HAVE___XSTAT
2017-04-03 15:29:45 +03:00
int __xstat ( int ver , const char * path , struct stat * sb )
{
int ret = - 1 ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real___xstat ( ver , newpath , sb ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
2017-05-11 13:42:14 +03:00
# endif /* HAVE___XSTAT */
2017-04-03 15:29:45 +03:00
int stat ( const char * path , struct stat * sb )
{
int ret = - 1 ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real_stat ( newpath , sb ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
int mkdir ( const char * path , mode_t mode )
{
int ret = - 1 ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real_mkdir ( newpath , mode ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
int open ( const char * path , int flags , . . . )
{
int ret = - 1 ;
char * newpath = NULL ;
2017-09-25 21:27:07 +03:00
va_list ap ;
mode_t mode = 0 ;
2017-04-03 15:29:45 +03:00
PATH_OVERRIDE ( newpath , path ) ;
2017-09-25 21:27:07 +03:00
/* The mode argument is mandatory when O_CREAT is set in flags,
* otherwise the argument is ignored .
*/
if ( flags & O_CREAT ) {
va_start ( ap , flags ) ;
2017-10-05 10:06:03 +03:00
mode = ( mode_t ) va_arg ( ap , int ) ;
2017-09-25 21:27:07 +03:00
va_end ( ap ) ;
}
ret = real_open ( newpath , flags , mode ) ;
2017-04-03 15:29:45 +03:00
VIR_FREE ( newpath ) ;
return ret ;
}
DIR * opendir ( const char * path )
{
DIR * ret = NULL ;
char * newpath = NULL ;
PATH_OVERRIDE ( newpath , path ) ;
ret = real_opendir ( newpath ) ;
VIR_FREE ( newpath ) ;
return ret ;
}
2017-05-11 13:42:14 +03:00
# endif