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 <stdio.h>
# include <stdlib.h>
# 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
2015-12-04 16:51:08 +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
*/
/*
* Intentionally missing the ' devices ' mount .
* Co - mounting cpu & cpuacct controllers
* An anonymous controller for systemd
*/
2013-04-26 13:50:24 +04:00
const char * procmounts =
2013-03-28 18:36:52 +04:00
" rootfs / rootfs rw 0 0 \n "
" tmpfs /run tmpfs rw,seclabel,nosuid,nodev,mode=755 0 0 \n "
" tmpfs /not/really/sys/fs/cgroup tmpfs rw,seclabel,nosuid,nodev,noexec,mode=755 0 0 \n "
" cgroup /not/really/sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0 \n "
" cgroup /not/really/sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0 \n "
" cgroup /not/really/sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpuacct,cpu 0 0 \n "
" cgroup /not/really/sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0 \n "
" cgroup /not/really/sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0 \n "
" cgroup /not/really/sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0 \n "
" /dev/sda1 /boot ext4 rw,seclabel,relatime,data=ordered 0 0 \n "
" tmpfs /tmp tmpfs rw,seclabel,relatime,size=1024000k 0 0 \n " ;
2013-04-26 13:50:24 +04:00
const char * procselfcgroups =
2013-03-28 18:36:52 +04:00
" 115:memory:/ \n "
" 8:blkio:/ \n "
" 6:freezer:/ \n "
" 3:cpuacct,cpu:/system \n "
" 2:cpuset:/ \n "
" 1:name=systemd:/user/berrange/123 \n " ;
2013-04-26 13:50:24 +04:00
const char * proccgroups =
" #subsys_name hierarchy num_cgroups enabled \n "
" cpuset 2 4 1 \n "
" cpu 3 48 1 \n "
" cpuacct 3 48 1 \n "
" memory 4 4 1 \n "
" devices 5 4 1 \n "
" freezer 6 4 1 \n "
" blkio 8 4 1 \n " ;
2013-09-10 17:31:53 +04:00
const char * procmountsallinone =
" rootfs / rootfs rw 0 0 \n "
" sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 \n "
" proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 \n "
" udev /dev devtmpfs rw,relatime,size=16458560k,nr_inodes=4114640,mode=755 0 0 \n "
" devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 \n "
" nfsd /proc/fs/nfsd nfsd rw,relatime 0 0 \n "
" cgroup /not/really/sys/fs/cgroup cgroup rw,relatime,blkio,devices,memory,cpuacct,cpu,cpuset 0 0 \n " ;
const char * procselfcgroupsallinone =
" 6:blkio,devices,memory,cpuacct,cpu,cpuset:/ " ;
const char * proccgroupsallinone =
" #subsys_name hierarchy num_cgroups enabled \n "
" cpuset 6 1 1 \n "
" cpu 6 1 1 \n "
" cpuacct 6 1 1 \n "
" memory 6 1 1 \n "
" devices 6 1 1 \n "
" blkio 6 1 1 \n " ;
2013-09-11 22:15:52 +04:00
const char * procmountslogind =
" none /not/really/sys/fs/cgroup tmpfs rw,rootcontext=system_u:object_r:sysfs_t:s0,seclabel,relatime,size=4k,mode=755 0 0 \n "
" systemd /not/really/sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,name=systemd 0 0 \n " ;
const char * procselfcgroupslogind =
" 1:name=systemd:/ \n " ;
const char * proccgroupslogind =
" #subsys_name hierarchy num_cgroups enabled \n "
" cpuset 0 1 1 \n "
" cpu 0 1 1 \n "
" cpuacct 0 1 1 \n "
" memory 0 1 0 \n "
" devices 0 1 1 \n "
" freezer 0 1 1 \n "
" net_cls 0 1 1 \n "
" blkio 0 1 1 \n "
" perf_event 0 1 1 \n " ;
2013-03-28 18:36:52 +04:00
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 ;
# define MAKE_FILE(name, value) \
do { \
if ( make_file ( path , name , value ) < 0 ) \
goto cleanup ; \
} 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.rt_period_us " , " 1000000 \n " ) ;
MAKE_FILE ( " cpu.rt_runtime_us " , " 950000 \n " ) ;
MAKE_FILE ( " cpu.shares " , " 1024 \n " ) ;
MAKE_FILE ( " cpu.stat " ,
" nr_periods 0 \n "
" nr_throttled 0 \n "
" throttled_time 0 \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 " ) ) {
MAKE_FILE ( " cpuset.cpu_exclusive " , " 1 \n " ) ;
if ( STREQ ( controller , " cpuset " ) )
MAKE_FILE ( " cpuset.cpus " , " 0-1 " ) ;
else
MAKE_FILE ( " cpuset.cpus " , " " ) ; /* Values don't inherit */
MAKE_FILE ( " cpuset.mem_exclusive " , " 1 \n " ) ;
MAKE_FILE ( " cpuset.mem_hardwall " , " 0 \n " ) ;
MAKE_FILE ( " cpuset.memory_migrate " , " 0 \n " ) ;
MAKE_FILE ( " cpuset.memory_pressure " , " 0 \n " ) ;
MAKE_FILE ( " cpuset.memory_pressure_enabled " , " 0 \n " ) ;
MAKE_FILE ( " cpuset.memory_spread_page " , " 0 \n " ) ;
MAKE_FILE ( " cpuset.memory_spread_slab " , " 0 \n " ) ;
if ( STREQ ( controller , " cpuset " ) )
MAKE_FILE ( " cpuset.mems " , " 0 " ) ;
else
MAKE_FILE ( " cpuset.mems " , " " ) ; /* Values don't inherit */
MAKE_FILE ( " cpuset.sched_load_balance " , " 1 \n " ) ;
MAKE_FILE ( " cpuset.sched_relax_domain_level " , " -1 \n " ) ;
} else if ( STRPREFIX ( controller , " memory " ) ) {
MAKE_FILE ( " memory.failcnt " , " 0 \n " ) ;
MAKE_FILE ( " memory.force_empty " , " " ) ; /* Write only */
MAKE_FILE ( " memory.kmem.tcp.failcnt " , " 0 \n " ) ;
MAKE_FILE ( " memory.kmem.tcp.limit_in_bytes " , " 9223372036854775807 \n " ) ;
MAKE_FILE ( " memory.kmem.tcp.max_usage_in_bytes " , " 0 \n " ) ;
MAKE_FILE ( " memory.kmem.tcp.usage_in_bytes " , " 16384 \n " ) ;
MAKE_FILE ( " memory.limit_in_bytes " , " 9223372036854775807 \n " ) ;
MAKE_FILE ( " memory.max_usage_in_bytes " , " 0 \n " ) ;
MAKE_FILE ( " memory.memsw.failcnt " , " " ) ; /* Not supported */
MAKE_FILE ( " memory.memsw.limit_in_bytes " , " " ) ; /* Not supported */
MAKE_FILE ( " memory.memsw.max_usage_in_bytes " , " " ) ; /* Not supported */
MAKE_FILE ( " memory.memsw.usage_in_bytes " , " " ) ; /* Not supported */
MAKE_FILE ( " memory.move_charge_at_immigrate " , " 0 \n " ) ;
MAKE_FILE ( " memory.numa_stat " ,
" total=367664 N0=367664 \n "
" file=314764 N0=314764 \n "
" anon=51999 N0=51999 \n "
" unevictable=901 N0=901 \n " ) ;
MAKE_FILE ( " memory.oom_control " ,
" oom_kill_disable 0 \n "
" under_oom 0 \n " ) ;
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.swappiness " , " 60 \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.io_merged " ,
" 8:0 Read 1100949 \n "
" 8:0 Write 2248076 \n "
" 8:0 Sync 63063 \n "
" 8:0 Async 3285962 \n "
" 8:0 Total 3349025 \n " ) ;
MAKE_FILE ( " blkio.io_queued " ,
" 8:0 Read 0 \n "
" 8:0 Write 0 \n "
" 8:0 Sync 0 \n "
" 8:0 Async 0 \n "
" 8:0 Total 0 \n " ) ;
MAKE_FILE ( " blkio.io_service_bytes " ,
" 8:0 Read 59542078464 \n "
" 8:0 Write 397369182208 \n "
" 8:0 Sync 234080922624 \n "
" 8:0 Async 222830338048 \n "
" 8:0 Total 456911260672 \n " ) ;
MAKE_FILE ( " blkio.io_serviced " ,
" 8:0 Read 3402504 \n "
" 8:0 Write 14966516 \n "
" 8:0 Sync 12064031 \n "
" 8:0 Async 6304989 \n "
" 8:0 Total 18369020 \n " ) ;
MAKE_FILE ( " blkio.io_service_time " ,
" 8:0 Read 10747537542349 \n "
" 8:0 Write 9200028590575 \n "
" 8:0 Sync 6449319855381 \n "
" 8:0 Async 13498246277543 \n "
" 8:0 Total 19947566132924 \n " ) ;
MAKE_FILE ( " blkio.io_wait_time " ,
" 8:0 Read 14687514824889 \n "
" 8:0 Write 357748452187691 \n "
" 8:0 Sync 55296974349413 \n "
" 8:0 Async 317138992663167 \n "
" 8:0 Total 372435967012580 \n " ) ;
MAKE_FILE ( " blkio.reset_stats " , " " ) ; /* Write only */
MAKE_FILE ( " blkio.sectors " , " 8:0 892404806 \n " ) ;
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.time " , " 8:0 61019089 \n " ) ;
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 ( ) ;
}
2015-12-04 16:51:08 +03:00
# define MAKE_CONTROLLER(subpath) \
do { \
char * path ; \
if ( asprintf ( & path , " %s/%s " , fakesysfscgroupdir , subpath ) < 0 ) \
abort ( ) ; \
if ( make_controller ( path , 0755 ) < 0 ) { \
fprintf ( stderr , " Cannot initialize %s \n " , path ) ; \
2017-04-09 14:28:07 +03:00
free ( path ) ; \
2015-12-04 16:51:08 +03:00
abort ( ) ; \
} \
2017-04-09 14:28:07 +03:00
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 )
{
2013-09-10 17:31:53 +04:00
const char * mock ;
2013-09-11 22:15:52 +04:00
bool allinone = false , logind = false ;
2013-03-28 18:36:52 +04:00
init_syms ( ) ;
2013-09-10 17:31:53 +04:00
mock = getenv ( " VIR_CGROUP_MOCK_MODE " ) ;
2013-09-11 22:15:52 +04:00
if ( mock ) {
if ( STREQ ( mock , " allinone " ) )
allinone = true ;
else if ( STREQ ( mock , " logind " ) )
logind = true ;
}
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 " ) ) {
2013-09-10 17:31:53 +04:00
if ( allinone )
return fmemopen ( ( void * ) procmountsallinone ,
strlen ( procmountsallinone ) , mode ) ;
2013-09-11 22:15:52 +04:00
else if ( logind )
return fmemopen ( ( void * ) procmountslogind ,
strlen ( procmountslogind ) , mode ) ;
2013-09-10 17:31:53 +04:00
else
return fmemopen ( ( void * ) procmounts , strlen ( procmounts ) , mode ) ;
2013-04-26 13:50:24 +04:00
} else {
errno = EACCES ;
return NULL ;
}
}
if ( STREQ ( path , " /proc/cgroups " ) ) {
if ( STREQ ( mode , " r " ) ) {
2013-09-10 17:31:53 +04:00
if ( allinone )
return fmemopen ( ( void * ) proccgroupsallinone ,
strlen ( proccgroupsallinone ) , mode ) ;
2013-09-11 22:15:52 +04:00
else if ( logind )
return fmemopen ( ( void * ) proccgroupslogind ,
strlen ( proccgroupslogind ) , mode ) ;
2013-09-10 17:31:53 +04:00
else
return fmemopen ( ( void * ) proccgroups , strlen ( proccgroups ) , mode ) ;
2013-03-28 18:36:52 +04:00
} else {
errno = EACCES ;
return NULL ;
}
}
if ( STREQ ( path , " /proc/self/cgroup " ) ) {
if ( STREQ ( mode , " r " ) ) {
2013-09-10 17:31:53 +04:00
if ( allinone )
return fmemopen ( ( void * ) procselfcgroupsallinone ,
strlen ( procselfcgroupsallinone ) , mode ) ;
2013-09-11 22:15:52 +04:00
else if ( logind )
return fmemopen ( ( void * ) procselfcgroupslogind ,
strlen ( procselfcgroupslogind ) , mode ) ;
2013-09-10 17:31:53 +04:00
else
return fmemopen ( ( void * ) procselfcgroups , strlen ( procselfcgroups ) , mode ) ;
2013-03-28 18:36:52 +04:00
} else {
errno = EACCES ;
return NULL ;
}
}
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 ;
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 ;
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 ;
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 ;
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 ( ) ;
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 ;
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 ( ) ;
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 ) ;
mode = va_arg ( ap , mode_t ) ;
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