2013-03-28 18:36:52 +04:00
/*
* Copyright ( C ) 2013 Red Hat , Inc .
*
* 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/>.
*
* Author : Daniel P . Berrange < berrange @ redhat . com >
*/
# include <config.h>
# ifdef __linux__
2016-05-13 13:46:35 +03:00
# include "virmock.h"
2013-03-28 18:36:52 +04:00
# include <unistd.h>
# include <fcntl.h>
# include <sys / stat.h>
2016-04-14 16:11:45 +03:00
# ifdef MAJOR_IN_MKDEV
# include <sys / mkdev.h>
# elif MAJOR_IN_SYSMACROS
# include <sys / sysmacros.h>
# endif
2013-03-28 18:36:52 +04:00
# include <stdarg.h>
2014-02-14 21:49:05 +04:00
# include "testutilslxc.h"
2015-12-04 12:54:29 +03:00
# include "virstring.h"
# include "virfile.h"
2013-03-28 18:36:52 +04:00
2016-05-13 13:46:35 +03:00
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 ) ;
2013-05-13 15:43:08 +04:00
/* Don't make static, since it causes problems with clang
* when passed as an arg to asprintf ( )
* vircgroupmock . c : 462 : 22 : error : static variable ' fakesysfsdir ' is used in an inline function with external linkage [ - Werror , - Wstatic - in - inline ]
*/
2015-12-04 12:54:29 +03:00
char * fakerootdir ;
2015-12-04 16:51:08 +03:00
char * fakesysfscgroupdir ;
2014-02-14 21:49:05 +04:00
const char * fakedevicedir0 = FAKEDEVDIR0 ;
const char * fakedevicedir1 = FAKEDEVDIR1 ;
2013-03-28 18:36:52 +04:00
2018-09-18 10:28:54 +03:00
# define SYSFS_CGROUP_PREFIX " / not / really / sys / fs / cgroup"
2015-01-22 13:54:50 +03:00
# define SYSFS_CPU_PRESENT " / sys / devices / system / cpu / present"
# define SYSFS_CPU_PRESENT_MOCKED "devices_system_cpu_present"
2013-03-28 18:36:52 +04:00
/*
* The plan :
*
* We fake out / proc / mounts , so make it look as is cgroups
* are mounted on / not / really / sys / fs / cgroup . We don ' t
* use / sys / fs / cgroup , because we want to make it easy to
* detect places where we ' ve not mocked enough syscalls .
*
* In any open / acces / mkdir calls we look at path and if
* it starts with / not / really / sys / fs / cgroup , we rewrite
2015-12-04 15:38:16 +03:00
* the path to point at a subdirectory of the temporary
* directory referred to by LIBVIRT_FAKE_ROOT_DIR env
* variable that is set by the main test suite
2013-03-28 18:36:52 +04:00
*
* In mkdir ( ) calls , we simulate the cgroups behaviour
* whereby creating the directory auto - creates a bunch
* of files beneath it
*/
static int make_file ( const char * path ,
const char * name ,
const char * value )
{
int fd = - 1 ;
int ret = - 1 ;
char * filepath = NULL ;
if ( asprintf ( & filepath , " %s/%s " , path , name ) < 0 )
return - 1 ;
2016-05-13 13:46:35 +03:00
if ( ( fd = real_open ( filepath , O_CREAT | O_WRONLY , 0600 ) ) < 0 )
2013-03-28 18:36:52 +04:00
goto cleanup ;
if ( write ( fd , value , strlen ( value ) ) ! = strlen ( value ) )
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2013-03-28 18:36:52 +04:00
if ( fd ! = - 1 & & close ( fd ) < 0 )
ret = - 1 ;
free ( filepath ) ;
return ret ;
}
static int make_controller ( const char * path , mode_t mode )
{
int ret = - 1 ;
const char * controller ;
2015-12-04 16:51:08 +03:00
if ( ! STRPREFIX ( path , fakesysfscgroupdir ) ) {
2013-03-28 18:36:52 +04:00
errno = EINVAL ;
return - 1 ;
}
2015-12-04 16:51:08 +03:00
controller = path + strlen ( fakesysfscgroupdir ) + 1 ;
2013-03-28 18:36:52 +04:00
if ( STREQ ( controller , " cpu " ) )
return symlink ( " cpu,cpuacct " , path ) ;
if ( STREQ ( controller , " cpuacct " ) )
return symlink ( " cpu,cpuacct " , path ) ;
2016-05-13 13:46:35 +03:00
if ( real_mkdir ( path , mode ) < 0 )
2013-03-28 18:36:52 +04:00
goto cleanup ;
2017-11-03 15:09:47 +03:00
# define MAKE_FILE(name, value) \
do { \
if ( make_file ( path , name , value ) < 0 ) \
goto cleanup ; \
2013-03-28 18:36:52 +04:00
} while ( 0 )
if ( STRPREFIX ( controller , " cpu,cpuacct " ) ) {
MAKE_FILE ( " cpu.cfs_period_us " , " 100000 \n " ) ;
MAKE_FILE ( " cpu.cfs_quota_us " , " -1 \n " ) ;
MAKE_FILE ( " cpu.shares " , " 1024 \n " ) ;
MAKE_FILE ( " cpuacct.stat " ,
" user 216687025 \n "
" system 43421396 \n " ) ;
MAKE_FILE ( " cpuacct.usage " , " 2787788855799582 \n " ) ;
2015-01-22 13:54:50 +03:00
MAKE_FILE ( " cpuacct.usage_percpu " ,
" 7059492996 0 0 0 0 0 0 0 4180532496 0 0 0 0 0 0 0 "
" 1957541268 0 0 0 0 0 0 0 2065932204 0 0 0 0 0 0 0 "
" 18228689414 0 0 0 0 0 0 0 4245525148 0 0 0 0 0 0 0 "
" 2911161568 0 0 0 0 0 0 0 1407758136 0 0 0 0 0 0 0 "
" 1836807700 0 0 0 0 0 0 0 1065296618 0 0 0 0 0 0 0 "
" 2046213266 0 0 0 0 0 0 0 747889778 0 0 0 0 0 0 0 "
" 709566900 0 0 0 0 0 0 0 444777342 0 0 0 0 0 0 0 "
" 5683512916 0 0 0 0 0 0 0 635751356 0 0 0 0 0 0 0 \n " ) ;
2013-03-28 18:36:52 +04:00
} else if ( STRPREFIX ( controller , " cpuset " ) ) {
if ( STREQ ( controller , " cpuset " ) )
MAKE_FILE ( " cpuset.cpus " , " 0-1 " ) ;
else
MAKE_FILE ( " cpuset.cpus " , " " ) ; /* Values don't inherit */
MAKE_FILE ( " cpuset.memory_migrate " , " 0 \n " ) ;
if ( STREQ ( controller , " cpuset " ) )
MAKE_FILE ( " cpuset.mems " , " 0 " ) ;
else
MAKE_FILE ( " cpuset.mems " , " " ) ; /* Values don't inherit */
} else if ( STRPREFIX ( controller , " memory " ) ) {
MAKE_FILE ( " memory.limit_in_bytes " , " 9223372036854775807 \n " ) ;
MAKE_FILE ( " memory.memsw.limit_in_bytes " , " " ) ; /* Not supported */
MAKE_FILE ( " memory.memsw.usage_in_bytes " , " " ) ; /* Not supported */
MAKE_FILE ( " memory.soft_limit_in_bytes " , " 9223372036854775807 \n " ) ;
MAKE_FILE ( " memory.stat " ,
" cache 1336619008 \n "
" rss 97792000 \n "
" mapped_file 42090496 \n "
" pgpgin 13022605027 \n "
" pgpgout 13023820533 \n "
" pgfault 54429417056 \n "
" pgmajfault 315715 \n "
" inactive_anon 145887232 \n "
" active_anon 67100672 \n "
" inactive_file 627400704 \n "
" active_file 661872640 \n "
" unevictable 3690496 \n "
" hierarchical_memory_limit 9223372036854775807 \n "
" total_cache 1336635392 \n "
" total_rss 118689792 \n "
" total_mapped_file 42106880 \n "
" total_pgpgin 13022606816 \n "
" total_pgpgout 13023820793 \n "
" total_pgfault 54429422313 \n "
" total_pgmajfault 315715 \n "
" total_inactive_anon 145891328 \n "
" total_active_anon 88010752 \n "
" total_inactive_file 627400704 \n "
" total_active_file 661872640 \n "
" total_unevictable 3690496 \n "
" recent_rotated_anon 112807028 \n "
" recent_rotated_file 2547948 \n "
" recent_scanned_anon 113796164 \n "
" recent_scanned_file 8199863 \n " ) ;
MAKE_FILE ( " memory.usage_in_bytes " , " 1455321088 \n " ) ;
MAKE_FILE ( " memory.use_hierarchy " , " 0 \n " ) ;
} else if ( STRPREFIX ( controller , " freezer " ) ) {
MAKE_FILE ( " freezer.state " , " THAWED " ) ;
} else if ( STRPREFIX ( controller , " blkio " ) ) {
MAKE_FILE ( " blkio.throttle.io_service_bytes " ,
" 8:0 Read 59542107136 \n "
" 8:0 Write 411440480256 \n "
" 8:0 Sync 248486822912 \n "
" 8:0 Async 222495764480 \n "
2014-02-14 21:49:05 +04:00
" 8:0 Total 470982587392 \n "
" 9:0 Read 59542107137 \n "
" 9:0 Write 411440480257 \n "
" 9:0 Sync 248486822912 \n "
" 9:0 Async 222495764480 \n "
" 9:0 Total 470982587392 \n " ) ;
2013-03-28 18:36:52 +04:00
MAKE_FILE ( " blkio.throttle.io_serviced " ,
" 8:0 Read 4832583 \n "
" 8:0 Write 36641903 \n "
" 8:0 Sync 30723171 \n "
" 8:0 Async 10751315 \n "
2014-02-14 21:49:05 +04:00
" 8:0 Total 41474486 \n "
" 9:0 Read 4832584 \n "
" 9:0 Write 36641904 \n "
" 9:0 Sync 30723171 \n "
" 9:0 Async 10751315 \n "
" 9:0 Total 41474486 \n " ) ;
2013-03-28 18:36:52 +04:00
MAKE_FILE ( " blkio.throttle.read_bps_device " , " " ) ;
MAKE_FILE ( " blkio.throttle.read_iops_device " , " " ) ;
MAKE_FILE ( " blkio.throttle.write_bps_device " , " " ) ;
MAKE_FILE ( " blkio.throttle.write_iops_device " , " " ) ;
MAKE_FILE ( " blkio.weight " , " 1000 \n " ) ;
MAKE_FILE ( " blkio.weight_device " , " " ) ;
} else {
errno = EINVAL ;
goto cleanup ;
}
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2013-03-28 18:36:52 +04:00
return ret ;
}
static void init_syms ( void )
{
2016-05-13 13:46:35 +03:00
if ( real_fopen )
2013-03-28 18:36:52 +04:00
return ;
2016-05-13 13:46:35 +03:00
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 ) ;
2013-03-28 18:36:52 +04:00
}
static void init_sysfs ( void )
{
2015-12-04 16:51:08 +03:00
if ( fakerootdir & & fakesysfscgroupdir )
2013-03-28 18:36:52 +04:00
return ;
2015-12-04 15:38:16 +03:00
if ( ! ( fakerootdir = getenv ( " LIBVIRT_FAKE_ROOT_DIR " ) ) ) {
fprintf ( stderr , " Missing LIBVIRT_FAKE_ROOT_DIR env variable \n " ) ;
2013-03-28 18:36:52 +04:00
abort ( ) ;
}
2015-12-04 16:51:08 +03:00
if ( virAsprintfQuiet ( & fakesysfscgroupdir , " %s%s " ,
fakerootdir , SYSFS_CGROUP_PREFIX ) < 0 )
2015-12-04 12:54:29 +03:00
abort ( ) ;
2015-12-04 16:51:08 +03:00
if ( virFileMakePath ( fakesysfscgroupdir ) < 0 ) {
fprintf ( stderr , " Cannot create %s \n " , fakesysfscgroupdir ) ;
2015-12-04 12:54:29 +03:00
abort ( ) ;
}
2017-11-03 15:09:47 +03:00
# define MAKE_CONTROLLER(subpath) \
do { \
char * path ; \
2015-12-04 16:51:08 +03:00
if ( asprintf ( & path , " %s/%s " , fakesysfscgroupdir , subpath ) < 0 ) \
2017-11-03 15:09:47 +03:00
abort ( ) ; \
if ( make_controller ( path , 0755 ) < 0 ) { \
fprintf ( stderr , " Cannot initialize %s \n " , path ) ; \
free ( path ) ; \
abort ( ) ; \
} \
free ( path ) ; \
2013-03-28 18:36:52 +04:00
} while ( 0 )
MAKE_CONTROLLER ( " cpu " ) ;
MAKE_CONTROLLER ( " cpuacct " ) ;
MAKE_CONTROLLER ( " cpu,cpuacct " ) ;
MAKE_CONTROLLER ( " cpu,cpuacct/system " ) ;
MAKE_CONTROLLER ( " cpuset " ) ;
MAKE_CONTROLLER ( " blkio " ) ;
MAKE_CONTROLLER ( " memory " ) ;
MAKE_CONTROLLER ( " freezer " ) ;
2015-01-22 13:54:50 +03:00
2015-12-04 16:51:08 +03:00
if ( make_file ( fakesysfscgroupdir ,
SYSFS_CPU_PRESENT_MOCKED , " 8-23,48-159 \n " ) < 0 )
2015-01-22 13:54:50 +03:00
abort ( ) ;
2013-03-28 18:36:52 +04:00
}
FILE * fopen ( const char * path , const char * mode )
{
2018-09-24 18:17:00 +03:00
char * filepath = NULL ;
const char * type = NULL ;
FILE * rc = NULL ;
const char * filename = getenv ( " VIR_CGROUP_MOCK_FILENAME " ) ;
2013-03-28 18:36:52 +04:00
2018-09-24 18:17:00 +03:00
init_syms ( ) ;
2013-09-10 17:31:53 +04:00
2013-03-28 18:36:52 +04:00
if ( STREQ ( path , " /proc/mounts " ) ) {
if ( STREQ ( mode , " r " ) ) {
2018-09-24 18:17:00 +03:00
type = " mounts " ;
2013-04-26 13:50:24 +04:00
} else {
errno = EACCES ;
return NULL ;
}
}
if ( STREQ ( path , " /proc/cgroups " ) ) {
if ( STREQ ( mode , " r " ) ) {
2018-09-24 18:17:00 +03:00
type = " cgroups " ;
2013-03-28 18:36:52 +04:00
} else {
errno = EACCES ;
return NULL ;
}
}
if ( STREQ ( path , " /proc/self/cgroup " ) ) {
if ( STREQ ( mode , " r " ) ) {
2018-09-24 18:17:00 +03:00
type = " self.cgroup " ;
2013-03-28 18:36:52 +04:00
} else {
errno = EACCES ;
return NULL ;
}
}
2018-09-24 18:17:00 +03:00
if ( type ) {
if ( ! filename )
abort ( ) ;
if ( virAsprintfQuiet ( & filepath , " %s/vircgroupdata/%s.%s " ,
abs_srcdir , filename , type ) < 0 ) {
abort ( ) ;
}
rc = real_fopen ( filepath , mode ) ;
free ( filepath ) ;
return rc ;
}
2016-05-13 13:46:35 +03:00
return real_fopen ( path , mode ) ;
2013-03-28 18:36:52 +04:00
}
int access ( const char * path , int mode )
{
int ret ;
init_syms ( ) ;
2015-12-04 16:51:08 +03:00
if ( STRPREFIX ( path , SYSFS_CGROUP_PREFIX ) ) {
2013-03-28 18:36:52 +04:00
init_sysfs ( ) ;
char * newpath ;
2018-09-18 10:28:54 +03:00
if ( asprintf ( & newpath , " %s%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
path + strlen ( SYSFS_CGROUP_PREFIX ) ) < 0 ) {
2013-03-28 18:36:52 +04:00
errno = ENOMEM ;
return - 1 ;
}
2016-05-13 13:46:35 +03:00
ret = real_access ( newpath , mode ) ;
2013-03-28 18:36:52 +04:00
free ( newpath ) ;
2013-10-22 16:15:21 +04:00
} else if ( STREQ ( path , " /proc/cgroups " ) | |
2016-02-25 10:44:46 +03:00
STREQ ( path , " /proc/self/cgroup " ) | |
STREQ ( path , SYSFS_CPU_PRESENT ) ) {
2013-10-22 16:15:21 +04:00
/* These files are readable for all. */
ret = ( mode = = F_OK | | mode = = R_OK ) ? 0 : - 1 ;
} else if ( STREQ ( path , " /proc/mounts " ) ) {
/* This one is accessible anytime for anybody. In fact, it's just
* a symlink to / proc / self / mounts . */
ret = 0 ;
2013-03-28 18:36:52 +04:00
} else {
2016-05-13 13:46:35 +03:00
ret = real_access ( path , mode ) ;
2013-03-28 18:36:52 +04:00
}
return ret ;
}
2013-04-05 14:28:04 +04:00
int __lxstat ( int ver , const char * path , struct stat * sb )
{
int ret ;
init_syms ( ) ;
2015-12-04 16:51:08 +03:00
if ( STRPREFIX ( path , SYSFS_CGROUP_PREFIX ) ) {
2013-04-05 14:28:04 +04:00
init_sysfs ( ) ;
char * newpath ;
2018-09-18 10:28:54 +03:00
if ( asprintf ( & newpath , " %s%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
path + strlen ( SYSFS_CGROUP_PREFIX ) ) < 0 ) {
2013-04-05 14:28:04 +04:00
errno = ENOMEM ;
return - 1 ;
}
2016-05-16 18:15:46 +03:00
ret = real___lxstat ( ver , newpath , sb ) ;
2013-04-05 14:28:04 +04:00
free ( newpath ) ;
2014-02-14 21:49:05 +04:00
} else if ( STRPREFIX ( path , fakedevicedir0 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 8 , 0 ) ;
return 0 ;
} else if ( STRPREFIX ( path , fakedevicedir1 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 9 , 0 ) ;
return 0 ;
2013-04-05 14:28:04 +04:00
} else {
2016-05-16 18:15:46 +03:00
ret = real___lxstat ( ver , path , sb ) ;
2013-04-05 14:28:04 +04:00
}
return ret ;
}
int lstat ( const char * path , struct stat * sb )
{
int ret ;
init_syms ( ) ;
2015-12-04 16:51:08 +03:00
if ( STRPREFIX ( path , SYSFS_CGROUP_PREFIX ) ) {
2013-04-05 14:28:04 +04:00
init_sysfs ( ) ;
char * newpath ;
2018-09-18 10:28:54 +03:00
if ( asprintf ( & newpath , " %s%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
path + strlen ( SYSFS_CGROUP_PREFIX ) ) < 0 ) {
2013-04-05 14:28:04 +04:00
errno = ENOMEM ;
return - 1 ;
}
2016-05-16 18:15:46 +03:00
ret = real_lstat ( newpath , sb ) ;
2013-04-05 14:28:04 +04:00
free ( newpath ) ;
2014-02-14 21:49:05 +04:00
} else if ( STRPREFIX ( path , fakedevicedir0 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 8 , 0 ) ;
return 0 ;
} else if ( STRPREFIX ( path , fakedevicedir1 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 9 , 0 ) ;
return 0 ;
2013-04-05 14:28:04 +04:00
} else {
2016-05-16 18:15:46 +03:00
ret = real_lstat ( path , sb ) ;
2013-04-05 14:28:04 +04:00
}
return ret ;
}
2014-02-14 21:49:05 +04:00
int __xstat ( int ver , const char * path , struct stat * sb )
{
int ret ;
init_syms ( ) ;
2015-12-04 16:51:08 +03:00
if ( STRPREFIX ( path , SYSFS_CGROUP_PREFIX ) ) {
2014-02-14 21:49:05 +04:00
init_sysfs ( ) ;
char * newpath ;
2018-09-18 10:28:54 +03:00
if ( asprintf ( & newpath , " %s%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
path + strlen ( SYSFS_CGROUP_PREFIX ) ) < 0 ) {
2014-02-14 21:49:05 +04:00
errno = ENOMEM ;
return - 1 ;
}
2016-05-16 18:15:46 +03:00
ret = real___xstat ( ver , newpath , sb ) ;
2014-02-14 21:49:05 +04:00
free ( newpath ) ;
} else if ( STRPREFIX ( path , fakedevicedir0 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 8 , 0 ) ;
return 0 ;
} else if ( STRPREFIX ( path , fakedevicedir1 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 9 , 0 ) ;
return 0 ;
} else {
2016-05-16 18:15:46 +03:00
ret = real___xstat ( ver , path , sb ) ;
2014-02-14 21:49:05 +04:00
}
return ret ;
}
int stat ( const char * path , struct stat * sb )
{
2015-01-22 13:54:50 +03:00
char * newpath = NULL ;
2014-02-14 21:49:05 +04:00
int ret ;
init_syms ( ) ;
2015-01-22 13:54:50 +03:00
if ( STREQ ( path , SYSFS_CPU_PRESENT ) ) {
init_sysfs ( ) ;
if ( asprintf ( & newpath , " %s/%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
2015-01-22 13:54:50 +03:00
SYSFS_CPU_PRESENT_MOCKED ) < 0 ) {
errno = ENOMEM ;
return - 1 ;
}
2015-12-04 16:51:08 +03:00
} else if ( STRPREFIX ( path , SYSFS_CGROUP_PREFIX ) ) {
2014-02-14 21:49:05 +04:00
init_sysfs ( ) ;
2018-09-18 10:28:54 +03:00
if ( asprintf ( & newpath , " %s%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
path + strlen ( SYSFS_CGROUP_PREFIX ) ) < 0 ) {
2014-02-14 21:49:05 +04:00
errno = ENOMEM ;
return - 1 ;
}
} else if ( STRPREFIX ( path , fakedevicedir0 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 8 , 0 ) ;
return 0 ;
} else if ( STRPREFIX ( path , fakedevicedir1 ) ) {
sb - > st_mode = S_IFBLK ;
sb - > st_rdev = makedev ( 9 , 0 ) ;
return 0 ;
} else {
2015-01-22 13:54:50 +03:00
if ( ! ( newpath = strdup ( path ) ) )
return - 1 ;
2014-02-14 21:49:05 +04:00
}
2016-05-16 18:15:46 +03:00
ret = real_stat ( newpath , sb ) ;
2015-01-22 13:54:50 +03:00
free ( newpath ) ;
2014-02-14 21:49:05 +04:00
return ret ;
}
2013-03-28 18:36:52 +04:00
int mkdir ( const char * path , mode_t mode )
{
int ret ;
init_syms ( ) ;
2015-12-04 16:51:08 +03:00
if ( STRPREFIX ( path , SYSFS_CGROUP_PREFIX ) ) {
2013-03-28 18:36:52 +04:00
init_sysfs ( ) ;
char * newpath ;
2018-09-18 10:28:54 +03:00
if ( asprintf ( & newpath , " %s%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
path + strlen ( SYSFS_CGROUP_PREFIX ) ) < 0 ) {
2013-03-28 18:36:52 +04:00
errno = ENOMEM ;
return - 1 ;
}
ret = make_controller ( newpath , mode ) ;
free ( newpath ) ;
} else {
2016-05-13 13:46:35 +03:00
ret = real_mkdir ( path , mode ) ;
2013-03-28 18:36:52 +04:00
}
return ret ;
}
int open ( const char * path , int flags , . . . )
{
int ret ;
char * newpath = NULL ;
init_syms ( ) ;
2015-01-22 13:54:50 +03:00
if ( STREQ ( path , SYSFS_CPU_PRESENT ) ) {
init_sysfs ( ) ;
if ( asprintf ( & newpath , " %s/%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
2015-01-22 13:54:50 +03:00
SYSFS_CPU_PRESENT_MOCKED ) < 0 ) {
errno = ENOMEM ;
return - 1 ;
}
}
2015-12-04 16:51:08 +03:00
if ( STRPREFIX ( path , SYSFS_CGROUP_PREFIX ) ) {
2013-03-28 18:36:52 +04:00
init_sysfs ( ) ;
2018-09-18 10:28:54 +03:00
if ( asprintf ( & newpath , " %s%s " ,
2015-12-04 16:51:08 +03:00
fakesysfscgroupdir ,
path + strlen ( SYSFS_CGROUP_PREFIX ) ) < 0 ) {
2013-03-28 18:36:52 +04:00
errno = ENOMEM ;
return - 1 ;
}
}
if ( flags & O_CREAT ) {
va_list ap ;
mode_t mode ;
va_start ( ap , flags ) ;
2018-04-30 18:30:12 +03:00
mode = ( mode_t ) va_arg ( ap , int ) ;
2013-03-28 18:36:52 +04:00
va_end ( ap ) ;
2016-05-13 13:46:35 +03:00
ret = real_open ( newpath ? newpath : path , flags , mode ) ;
2013-03-28 18:36:52 +04:00
} else {
2016-05-13 13:46:35 +03:00
ret = real_open ( newpath ? newpath : path , flags ) ;
2013-03-28 18:36:52 +04:00
}
free ( newpath ) ;
return ret ;
}
# else
/* Nothing to override on non-__linux__ platforms */
# endif