diff options
| author | kx <kx@radix-linux.su> | 2026-10-09 18:00:15 +0300 |
|---|---|---|
| committer | kx <kx@radix-linux.su> | 2026-10-09 18:00:15 +0300 |
| commit | 065da3509019b15dd0e678072e6be629e5330bef (patch) | |
| tree | 69c934c9e786ac048b4fbe8f4c4c5571661521f4 /cpu/cpu-syscalls.c | |
| parent | d130fe27fa753be02ed76fd9b277aa3c3d928eb9 (diff) | |
| download | libmcpu-0.4.0.tar.xz | |
Version 0.4.00.4.0
Diffstat (limited to 'cpu/cpu-syscalls.c')
| -rw-r--r-- | cpu/cpu-syscalls.c | 2174 |
1 files changed, 2174 insertions, 0 deletions
diff --git a/cpu/cpu-syscalls.c b/cpu/cpu-syscalls.c new file mode 100644 index 0000000..f12e729 --- /dev/null +++ b/cpu/cpu-syscalls.c @@ -0,0 +1,2174 @@ +/*************************************************************** + __CPU_SYSCALLS.C + + This file contains source code of MCPU system calls. + + PART OF : CPU - library . + + USAGE : Internal only . + + NOTE : NONE . + + Copyright (C) 2026 by Andrew V.Kosteltsev. + All Rights Reserved. + ***************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#include <libmcpu.h> +#include <cpu-context.h> +#include <cpu-syscalls.h> +#include <cpu-sysdeps.h> + + +#define __NR_brk 10 +#define __NR_gettimeofday 0x01c +#define __NR_clock_getres 0x021 +#define __NR_clock_gettime 0x022 +#define __NR_nanosleep 0x030 +#define __NR_clock_nanosleep 0x031 + +#define __NR_read 0x100 +#define __NR_write 0x101 +#define __NR_lseek 0x102 +#define __NR_open 0x103 +#define __NR_creat 0x104 +#define __NR_close 0x105 +#define __NR_link 0x106 +#define __NR_unlink 0x107 +#define __NR_chdir 0x108 +#define __NR_mkdir 0x109 +#define __NR_chmod 0x10b +#define __NR_chown 0x10c +#define __NR_access 0x10f +#define __NR_rename 0x111 +#define __NR_rmdir 0x112 +#define __NR_symlink 0x113 +#define __NR_readlink 0x114 +#define __NR_stat 0x115 +#define __NR_fstat 0x116 +#define __NR_lstat 0x117 +#define __NR_fcntl 0x119 +#define __NR_pipe2 0x11a +#define __NR_getdents 0x11d +#define __NR_select 0x11e +#define __NR_fsync 0x120 +#define __NR_truncate 0x121 +#define __NR_ftruncate 0x122 +#define __NR_fchmod 0x123 +#define __NR_fchown 0x124 +#define __NR_fchdir 0x125 +#define __NR_dup 0x126 +#define __NR_dup2 0x127 + +#define CPU_PATH_MAX 4096U + + +static __mpu_uint64_t +__cpu_syscall_error( int error ) +{ + __mpu_int64_t ret = -(__mpu_int64_t)error; + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_syscall_error() */ + + +static __mpu_uint32_t +__cpu_syscall_nargs( void ) +{ + return( __cpu_data_get_u32( __cpu_reg_ptr( 32, CPU_SYSCALL_NARGS_ADDR ) ) ); + +} /* End of __cpu_syscall_nargs() */ + + +static __mpu_uint64_t +__cpu_syscall_arg( unsigned int n ) +{ + static const __mpu_uint32_t address[CPU_SYSCALL_MAX_ARGS] = + { + CPU_SYSCALL_ARG0_ADDR, + CPU_SYSCALL_ARG1_ADDR, + CPU_SYSCALL_ARG2_ADDR, + CPU_SYSCALL_ARG3_ADDR, + CPU_SYSCALL_ARG4_ADDR, + CPU_SYSCALL_ARG5_ADDR + }; + + if( n >= CPU_SYSCALL_MAX_ARGS ) return( 0 ); + + return( __cpu_data_get_u64( __cpu_reg_ptr( 64, address[n] ) ) ); + +} /* End of __cpu_syscall_arg() */ + + +static int +__cpu_memory_resolve( __mpu_uint64_t ptr, __mpu_uint64_t size, int write, + __mpu_UNIT_t **memory ) +{ + __mpu_UNIT_t *base = (__mpu_UNIT_t *)0; + __mpu_uint64_t limit = 0; + __mpu_uint64_t offset; + unsigned int segment; + + if( !memory ) return( __MCPU_EFAULT ); + *memory = (__mpu_UNIT_t *)0; + + if( ptr == CPU_NULL_PTR ) return( __MCPU_EFAULT ); + + segment = __cpu_ptr_segment( ptr ); + offset = __cpu_ptr_offset( ptr ); + + switch( segment ) + { + case CPU_PTR_SEG_DATA: + base = __DATA; + limit = __DSIZE; + break; + case CPU_PTR_SEG_STACK: + base = __STACK; + limit = __SSIZE; + break; + case CPU_PTR_SEG_PROGRAM: + if( write ) return( __MCPU_EFAULT ); + base = __PROGRAM; + limit = __PSIZE; + break; + case CPU_PTR_SEG_CONTROL: + if( write ) return( __MCPU_EFAULT ); + base = __CONTROL; + limit = __CSIZE; + break; + case CPU_PTR_SEG_INPUT: + if( write ) return( __MCPU_EFAULT ); + base = __INPUT; + limit = __ISIZE; + break; + case CPU_PTR_SEG_OUTPUT: + base = __OUTPUT; + limit = __OSIZE; + break; + case CPU_PTR_SEG_TRACE: + base = __TRACE; + limit = __TSIZE; + break; + case CPU_PTR_SEG_HEAP: + base = __HEAP; + limit = __HBRK; + if( offset < CPU_HEAP_BEGIN ) return( __MCPU_EFAULT ); + break; + default: + return( __MCPU_EFAULT ); + } + + if( !base || offset > limit || size > limit - offset ) return( __MCPU_EFAULT ); + + *memory = base + offset; + return( 0 ); + +} /* End of __cpu_memory_resolve() */ + + +static int +__cpu_copyin( void *dst, __mpu_uint64_t src, __mpu_uint64_t size ) +{ + __mpu_UNIT_t *memory; + int error; + + if( !size ) return( 0 ); + if( !dst ) return( __MCPU_EFAULT ); + + error = __cpu_memory_resolve( src, size, 0, &memory ); + if( error ) return( error ); + + memcpy( dst, memory, (size_t)size ); + return( 0 ); + +} /* End of __cpu_copyin() */ + + +static int +__cpu_copyout( __mpu_uint64_t dst, const void *src, __mpu_uint64_t size ) +{ + __mpu_UNIT_t *memory; + int error; + + if( !size ) return( 0 ); + if( !src ) return( __MCPU_EFAULT ); + + error = __cpu_memory_resolve( dst, size, 1, &memory ); + if( error ) return( error ); + + memcpy( memory, src, (size_t)size ); + return( 0 ); + +} /* End of __cpu_copyout() */ + + +static int +__cpu_utf8_valid( const unsigned char *s, size_t n ) +{ + size_t i = 0; + + while( i < n ) + { + unsigned int c = s[i++]; + + if( c < 0x80U ) continue; + + if( c >= 0xc2U && c <= 0xdfU ) + { + if( i >= n || ( s[i] & 0xc0U ) != 0x80U ) return( 0 ); + ++i; + continue; + } + + if( c == 0xe0U ) + { + if( i + 1 >= n || s[i] < 0xa0U || s[i] > 0xbfU || + ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 ); + i += 2; + continue; + } + + if( c >= 0xe1U && c <= 0xecU ) + { + if( i + 1 >= n || ( s[i] & 0xc0U ) != 0x80U || + ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 ); + i += 2; + continue; + } + + if( c == 0xedU ) + { + if( i + 1 >= n || s[i] < 0x80U || s[i] > 0x9fU || + ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 ); + i += 2; + continue; + } + + if( c >= 0xeeU && c <= 0xefU ) + { + if( i + 1 >= n || ( s[i] & 0xc0U ) != 0x80U || + ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 ); + i += 2; + continue; + } + + if( c == 0xf0U ) + { + if( i + 2 >= n || s[i] < 0x90U || s[i] > 0xbfU || + ( s[i + 1] & 0xc0U ) != 0x80U || + ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 ); + i += 3; + continue; + } + + if( c >= 0xf1U && c <= 0xf3U ) + { + if( i + 2 >= n || ( s[i] & 0xc0U ) != 0x80U || + ( s[i + 1] & 0xc0U ) != 0x80U || + ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 ); + i += 3; + continue; + } + + if( c == 0xf4U ) + { + if( i + 2 >= n || s[i] < 0x80U || s[i] > 0x8fU || + ( s[i + 1] & 0xc0U ) != 0x80U || + ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 ); + i += 3; + continue; + } + + return( 0 ); + } + + return( 1 ); + +} /* End of __cpu_utf8_valid() */ + + +static int +__cpu_copyinstr( char **dst, __mpu_uint64_t src ) +{ + __mpu_UNIT_t *memory; + __mpu_uint64_t offset; + __mpu_uint64_t limit; + __mpu_uint64_t n; + unsigned int segment; + char *s; + + if( !dst ) return( __MCPU_EFAULT ); + *dst = (char *)0; + + if( src == CPU_NULL_PTR ) return( __MCPU_EFAULT ); + + segment = __cpu_ptr_segment( src ); + offset = __cpu_ptr_offset( src ); + + if( __cpu_memory_resolve( src, 1, 0, &memory ) != 0 ) return( __MCPU_EFAULT ); + + switch( segment ) + { + case CPU_PTR_SEG_DATA: limit = __DSIZE; break; + case CPU_PTR_SEG_STACK: limit = __SSIZE; break; + case CPU_PTR_SEG_PROGRAM: limit = __PSIZE; break; + case CPU_PTR_SEG_CONTROL: limit = __CSIZE; break; + case CPU_PTR_SEG_INPUT: limit = __ISIZE; break; + case CPU_PTR_SEG_OUTPUT: limit = __OSIZE; break; + case CPU_PTR_SEG_TRACE: limit = __TSIZE; break; + case CPU_PTR_SEG_HEAP: limit = __HBRK; break; + default: return( __MCPU_EFAULT ); + } + + n = 0; + while( offset + n < limit && n < CPU_PATH_MAX ) + { + if( memory[n] == 0 ) break; + ++n; + } + + if( offset + n >= limit || n >= CPU_PATH_MAX ) return( __MCPU_ENAMETOOLONG ); + if( !__cpu_utf8_valid( memory, (size_t)n ) ) return( __MCPU_EILSEQ ); + + s = (char *)malloc( (size_t)n + 1U ); + if( !s ) return( __MCPU_ENOMEM ); + memcpy( s, memory, (size_t)n ); + s[n] = '\0'; + *dst = s; + + return( 0 ); + +} /* End of __cpu_copyinstr() */ + + +void +__cpu_fd_context_init( void ) +{ + unsigned int i; + + if( !pcctx ) return; + + for( i = 0; i < CPU_GUEST_FD_MAX; ++i ) + { + pcctx->_fd[i].host_fd = -1; + pcctx->_fd[i].owned = 0; + pcctx->_fd[i].flags = 0; + } + + pcctx->_fd[0].host_fd = 0; + pcctx->_fd[1].host_fd = 1; + pcctx->_fd[2].host_fd = 2; + pcctx->_fd[0].flags = 0; + pcctx->_fd[1].flags = 0; + pcctx->_fd[2].flags = 0; + pcctx->_fd_initialized = 1; + +} /* End of __cpu_fd_context_init() */ + + +void +__cpu_fd_context_free( void ) +{ + unsigned int i; + + if( !pcctx || !pcctx->_fd_initialized ) return; + + for( i = 0; i < CPU_GUEST_FD_MAX; ++i ) + { + if( pcctx->_fd[i].host_fd >= 0 && pcctx->_fd[i].owned ) + (void)__cpu_sys_close( pcctx->_fd[i].host_fd ); + + pcctx->_fd[i].host_fd = -1; + pcctx->_fd[i].owned = 0; + pcctx->_fd[i].flags = 0; + } + + pcctx->_fd_initialized = 0; + +} /* End of __cpu_fd_context_free() */ + + +void +__cpu_cwd_context_init( void ) +{ + __mpu_int64_t ret; + + if( !pcctx ) return; + + pcctx->_cwd_fd = -1; + pcctx->_cwd_initialized = 0; + + ret = __cpu_sys_cwd_init(); + if( ret < 0 ) return; + + pcctx->_cwd_fd = (int)ret; + pcctx->_cwd_initialized = 1; + +} /* End of __cpu_cwd_context_init() */ + + +void +__cpu_cwd_context_free( void ) +{ + if( !pcctx || !pcctx->_cwd_initialized ) return; + + if( pcctx->_cwd_fd >= 0 ) + (void)__cpu_sys_close( pcctx->_cwd_fd ); + + pcctx->_cwd_fd = -1; + pcctx->_cwd_initialized = 0; + +} /* End of __cpu_cwd_context_free() */ + + +static int +__cpu_fd_get( __mpu_uint64_t fd, int *host_fd ) +{ + if( !pcctx || !pcctx->_fd_initialized || fd >= CPU_GUEST_FD_MAX || + pcctx->_fd[fd].host_fd < 0 ) return( __MCPU_EBADF ); + + if( host_fd ) *host_fd = pcctx->_fd[fd].host_fd; + return( 0 ); + +} /* End of __cpu_fd_get() */ + + +static int +__cpu_fd_find_from( __mpu_uint64_t minimum ) +{ + unsigned int fd; + + if( !pcctx || !pcctx->_fd_initialized || minimum >= CPU_GUEST_FD_MAX ) + return( -1 ); + + for( fd = (unsigned int)minimum; fd < CPU_GUEST_FD_MAX; ++fd ) + if( pcctx->_fd[fd].host_fd < 0 ) return( (int)fd ); + + return( -1 ); + +} /* End of __cpu_fd_find_from() */ + + +static int +__cpu_fd_install_from( int host_fd, __mpu_uint64_t minimum, unsigned int flags ) +{ + int fd; + + if( host_fd < 0 ) return( -1 ); + + fd = __cpu_fd_find_from( minimum ); + if( fd < 0 ) return( -1 ); + + pcctx->_fd[fd].host_fd = host_fd; + pcctx->_fd[fd].owned = 1; + pcctx->_fd[fd].flags = flags; + + return( fd ); + +} /* End of __cpu_fd_install_from() */ + + +static int +__cpu_fd_install( int host_fd ) +{ + return( __cpu_fd_install_from( host_fd, 3, 0 ) ); + +} /* End of __cpu_fd_install() */ + + + + +static __mpu_uint64_t +__cpu_stat_i64_bits( __mpu_int64_t value ) +{ + __mpu_uint64_t bits; + + memcpy( &bits, &value, sizeof( bits ) ); + return( bits ); + +} /* End of __cpu_stat_i64_bits() */ + + +static int +__cpu_stat_copyout( __mpu_uint64_t ptr, const struct __cpu_stat *st ) +{ + __mpu_UNIT_t data[__CPU_STAT_SIZE]; + + if( !st ) return( __MCPU_EFAULT ); + + memset( data, 0, sizeof( data ) ); + + __cpu_data_put_u64( data + __CPU_STAT_ST_DEV, st->st_dev ); + __cpu_data_put_u64( data + __CPU_STAT_ST_INO, st->st_ino ); + __cpu_data_put_u64( data + __CPU_STAT_ST_MODE, st->st_mode ); + __cpu_data_put_u64( data + __CPU_STAT_ST_NLINK, st->st_nlink ); + __cpu_data_put_u64( data + __CPU_STAT_ST_UID, st->st_uid ); + __cpu_data_put_u64( data + __CPU_STAT_ST_GID, st->st_gid ); + __cpu_data_put_u64( data + __CPU_STAT_ST_RDEV, st->st_rdev ); + __cpu_data_put_u64( data + __CPU_STAT_ST_SIZE, __cpu_stat_i64_bits( st->st_size ) ); + __cpu_data_put_u64( data + __CPU_STAT_ST_BLKSIZE, __cpu_stat_i64_bits( st->st_blksize ) ); + __cpu_data_put_u64( data + __CPU_STAT_ST_BLOCKS, __cpu_stat_i64_bits( st->st_blocks ) ); + __cpu_data_put_u64( data + __CPU_STAT_ST_ATIME_SEC, __cpu_stat_i64_bits( st->st_atime_sec ) ); + __cpu_data_put_u64( data + __CPU_STAT_ST_ATIME_NSEC, st->st_atime_nsec ); + __cpu_data_put_u64( data + __CPU_STAT_ST_MTIME_SEC, __cpu_stat_i64_bits( st->st_mtime_sec ) ); + __cpu_data_put_u64( data + __CPU_STAT_ST_MTIME_NSEC, st->st_mtime_nsec ); + __cpu_data_put_u64( data + __CPU_STAT_ST_CTIME_SEC, __cpu_stat_i64_bits( st->st_ctime_sec ) ); + __cpu_data_put_u64( data + __CPU_STAT_ST_CTIME_NSEC, st->st_ctime_nsec ); + + return( __cpu_copyout( ptr, data, sizeof( data ) ) ); + +} /* End of __cpu_stat_copyout() */ + + +static __mpu_uint64_t +__cpu_dirent_i64_bits( __mpu_int64_t value ) +{ + __mpu_uint64_t bits; + + memcpy( &bits, &value, sizeof( bits ) ); + return( bits ); + +} /* End of __cpu_dirent_i64_bits() */ + + +static int +__cpu_dirent_copyout( __mpu_uint64_t ptr, const struct __cpu_dirent *de, + __mpu_uint64_t count ) +{ + __mpu_UNIT_t *data; + __mpu_uint64_t nrecords; + __mpu_uint64_t i; + int error; + + if( !de && count ) return( __MCPU_EFAULT ); + if( count % __CPU_DIRENT_SIZE != 0 ) return( __MCPU_EINVAL ); + if( count > (__mpu_uint64_t)(size_t)-1 ) return( __MCPU_EINVAL ); + + if( !count ) return( 0 ); + data = (__mpu_UNIT_t *)calloc( 1, (size_t)count ); + if( !data ) return( __MCPU_ENOMEM ); + + nrecords = count / __CPU_DIRENT_SIZE; + for( i = 0; i < nrecords; ++i ) + { + __mpu_UNIT_t *record = data + i * __CPU_DIRENT_SIZE; + + __cpu_data_put_u64( record + __CPU_DIRENT_D_INO, de[i].d_ino ); + __cpu_data_put_u64( record + __CPU_DIRENT_D_OFF, + __cpu_dirent_i64_bits( de[i].d_off ) ); + __cpu_data_put_u64( record + __CPU_DIRENT_D_RECLEN, de[i].d_reclen ); + __cpu_data_put_u64( record + __CPU_DIRENT_D_TYPE, de[i].d_type ); + memcpy( record + __CPU_DIRENT_D_NAME, de[i].d_name, + __CPU_DIRENT_NAME_SIZE ); + } + + error = __cpu_copyout( ptr, data, count ); + free( data ); + return( error ); + +} /* End of __cpu_dirent_copyout() */ + + +static __mpu_int64_t +__cpu_select_i64_from_bits( __mpu_uint64_t bits ) +{ + __mpu_int64_t value; + + memcpy( &value, &bits, sizeof( value ) ); + return( value ); + +} /* End of __cpu_select_i64_from_bits() */ + + +static int +__cpu_fdset_load( __mpu_uint64_t ptr, __mpu_uint64_t words[__CPU_FD_SET_WORDS] ) +{ + __mpu_UNIT_t data[__CPU_FD_SET_SIZE]; + __mpu_UNIT_t *memory; + unsigned int i; + int error; + + error = __cpu_memory_resolve( ptr, __CPU_FD_SET_SIZE, 1, &memory ); + if( error ) return( error ); + (void)memory; + + error = __cpu_copyin( data, ptr, sizeof( data ) ); + if( error ) return( error ); + + for( i = 0; i < __CPU_FD_SET_WORDS; ++i ) + words[i] = __cpu_data_get_u64( data + i * 8U ); + + return( 0 ); + +} /* End of __cpu_fdset_load() */ + + +static int +__cpu_fdset_store( __mpu_uint64_t ptr, + const __mpu_uint64_t words[__CPU_FD_SET_WORDS] ) +{ + __mpu_UNIT_t data[__CPU_FD_SET_SIZE]; + unsigned int i; + + memset( data, 0, sizeof( data ) ); + for( i = 0; i < __CPU_FD_SET_WORDS; ++i ) + __cpu_data_put_u64( data + i * 8U, words[i] ); + + return( __cpu_copyout( ptr, data, sizeof( data ) ) ); + +} /* End of __cpu_fdset_store() */ + + +static int +__cpu_fdset_isset( const __mpu_uint64_t words[__CPU_FD_SET_WORDS], + unsigned int fd ) +{ + unsigned int word = fd / 64U; + unsigned int bit = fd % 64U; + + return( ( words[word] & ( (__mpu_uint64_t)1U << bit ) ) != 0 ); + +} /* End of __cpu_fdset_isset() */ + + +static void +__cpu_fdset_set( __mpu_uint64_t words[__CPU_FD_SET_WORDS], unsigned int fd ) +{ + unsigned int word = fd / 64U; + unsigned int bit = fd % 64U; + + words[word] |= ( (__mpu_uint64_t)1U << bit ); + +} /* End of __cpu_fdset_set() */ + + +static int +__cpu_timeval_load( __mpu_uint64_t ptr, struct __cpu_timeval *timeout ) +{ + __mpu_UNIT_t data[__CPU_TIMEVAL_SIZE]; + int error; + + if( !timeout ) return( __MCPU_EFAULT ); + + error = __cpu_copyin( data, ptr, sizeof( data ) ); + if( error ) return( error ); + + timeout->tv_sec = __cpu_select_i64_from_bits( + __cpu_data_get_u64( data + __CPU_TIMEVAL_TV_SEC ) ); + timeout->tv_usec = __cpu_select_i64_from_bits( + __cpu_data_get_u64( data + __CPU_TIMEVAL_TV_USEC ) ); + + if( timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999 ) + return( __MCPU_EINVAL ); + + return( 0 ); + +} /* End of __cpu_timeval_load() */ + + +static int +__cpu_timespec_load( __mpu_uint64_t ptr, struct __cpu_timespec *ts ) +{ + __mpu_UNIT_t data[__CPU_TIMESPEC_SIZE]; + int error; + + if( !ts ) return( __MCPU_EFAULT ); + + error = __cpu_copyin( data, ptr, sizeof( data ) ); + if( error ) return( error ); + + ts->tv_sec = __cpu_select_i64_from_bits( + __cpu_data_get_u64( data + __CPU_TIMESPEC_TV_SEC ) ); + ts->tv_nsec = __cpu_select_i64_from_bits( + __cpu_data_get_u64( data + __CPU_TIMESPEC_TV_NSEC ) ); + + if( ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec > 999999999 ) + return( __MCPU_EINVAL ); + + return( 0 ); + +} /* End of __cpu_timespec_load() */ + + +static __mpu_uint64_t +__cpu_time_i64_bits( __mpu_int64_t value ) +{ + __mpu_uint64_t bits; + + memcpy( &bits, &value, sizeof( bits ) ); + return( bits ); + +} /* End of __cpu_time_i64_bits() */ + + +static int +__cpu_timeval_copyout( __mpu_uint64_t ptr, const struct __cpu_timeval *tv ) +{ + __mpu_UNIT_t data[__CPU_TIMEVAL_SIZE]; + + if( !tv ) return( __MCPU_EFAULT ); + + memset( data, 0, sizeof( data ) ); + __cpu_data_put_u64( data + __CPU_TIMEVAL_TV_SEC, + __cpu_time_i64_bits( tv->tv_sec ) ); + __cpu_data_put_u64( data + __CPU_TIMEVAL_TV_USEC, + __cpu_time_i64_bits( tv->tv_usec ) ); + + return( __cpu_copyout( ptr, data, sizeof( data ) ) ); + +} /* End of __cpu_timeval_copyout() */ + + +static int +__cpu_timespec_copyout( __mpu_uint64_t ptr, const struct __cpu_timespec *ts ) +{ + __mpu_UNIT_t data[__CPU_TIMESPEC_SIZE]; + + if( !ts ) return( __MCPU_EFAULT ); + + memset( data, 0, sizeof( data ) ); + __cpu_data_put_u64( data + __CPU_TIMESPEC_TV_SEC, + __cpu_time_i64_bits( ts->tv_sec ) ); + __cpu_data_put_u64( data + __CPU_TIMESPEC_TV_NSEC, + __cpu_time_i64_bits( ts->tv_nsec ) ); + + return( __cpu_copyout( ptr, data, sizeof( data ) ) ); + +} /* End of __cpu_timespec_copyout() */ + + +static __mpu_uint64_t +__cpu_current_brk( void ) +{ + __mpu_uint64_t ptr = CPU_NULL_PTR; + + if( !__HEAP || __HLIMIT < CPU_HEAP_BEGIN || __HBRK < CPU_HEAP_BEGIN ) + return( CPU_NULL_PTR ); + + if( __cpu_ptr_make( &ptr, CPU_PTR_SEG_HEAP, __HBRK ) != 0 ) + return( CPU_NULL_PTR ); + + return( ptr ); + +} /* End of __cpu_current_brk() */ + + +__mpu_uint64_t +__cpu_SYS_brk( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t arg; + __mpu_uint64_t brk; + __mpu_uint64_t ptr = CPU_NULL_PTR; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_current_brk() ); + + arg = __cpu_syscall_arg( 0 ); + + if( arg == CPU_NULL_PTR ) return( __cpu_current_brk() ); + + if( __cpu_ptr_segment( arg ) != CPU_PTR_SEG_HEAP ) + return( __cpu_current_brk() ); + + brk = __cpu_heap_brk( __cpu_ptr_offset( arg ) ); + + if( brk < CPU_HEAP_BEGIN || __cpu_ptr_make( &ptr, CPU_PTR_SEG_HEAP, brk ) != 0 ) + return( CPU_NULL_PTR ); + + return( ptr ); + +} /* End of __cpu_SYS_brk() */ + + +__mpu_uint64_t +__cpu_SYS_close( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + if( pcctx->_fd[fd].owned ) + { + ret = __cpu_sys_close( host_fd ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + } + + pcctx->_fd[fd].host_fd = -1; + pcctx->_fd[fd].owned = 0; + pcctx->_fd[fd].flags = 0; + + return( 0 ); + +} /* End of __cpu_SYS_close() */ + + +__mpu_uint64_t +__cpu_SYS_dup( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_int64_t ret; + int host_fd; + int new_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + new_fd = __cpu_fd_find_from( 0 ); + if( new_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) ); + + ret = __cpu_sys_dup( host_fd ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + pcctx->_fd[new_fd].host_fd = (int)ret; + pcctx->_fd[new_fd].owned = 1; + pcctx->_fd[new_fd].flags = 0; + + return( (__mpu_uint64_t)new_fd ); + +} /* End of __cpu_SYS_dup() */ + + +__mpu_uint64_t +__cpu_SYS_dup2( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t old_fd; + __mpu_uint64_t new_fd; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + old_fd = __cpu_syscall_arg( 0 ); + new_fd = __cpu_syscall_arg( 1 ); + + error = __cpu_fd_get( old_fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + if( new_fd >= CPU_GUEST_FD_MAX ) return( __cpu_syscall_error( __MCPU_EBADF ) ); + + if( old_fd == new_fd ) return( new_fd ); + + ret = __cpu_sys_dup( host_fd ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + if( pcctx->_fd[new_fd].host_fd >= 0 && pcctx->_fd[new_fd].owned ) + (void)__cpu_sys_close( pcctx->_fd[new_fd].host_fd ); + + pcctx->_fd[new_fd].host_fd = (int)ret; + pcctx->_fd[new_fd].owned = 1; + pcctx->_fd[new_fd].flags = 0; + + return( new_fd ); + +} /* End of __cpu_SYS_dup2() */ + + +__mpu_uint64_t +__cpu_SYS_write( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_uint64_t ptr; + __mpu_uint64_t count; + __mpu_int64_t ret; + unsigned char *buf = (unsigned char *)0; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + ptr = __cpu_syscall_arg( 1 ); + count = __cpu_syscall_arg( 2 ); + + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + if( count ) + { + if( count > (__mpu_uint64_t)(size_t)-1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + buf = (unsigned char *)malloc( (size_t)count ); + if( !buf ) return( __cpu_syscall_error( __MCPU_ENOMEM ) ); + error = __cpu_copyin( buf, ptr, count ); + if( error ) + { + free( buf ); + return( __cpu_syscall_error( error ) ); + } + } + + ret = __cpu_sys_write( host_fd, buf, count ); + free( buf ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_write() */ + + +__mpu_uint64_t +__cpu_SYS_read( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_uint64_t ptr; + __mpu_uint64_t count; + __mpu_int64_t ret; + unsigned char *buf = (unsigned char *)0; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + ptr = __cpu_syscall_arg( 1 ); + count = __cpu_syscall_arg( 2 ); + + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + if( count ) + { + __mpu_UNIT_t *memory; + + if( count > (__mpu_uint64_t)(size_t)-1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + error = __cpu_memory_resolve( ptr, count, 1, &memory ); + if( error ) return( __cpu_syscall_error( error ) ); + + buf = (unsigned char *)malloc( (size_t)count ); + if( !buf ) return( __cpu_syscall_error( __MCPU_ENOMEM ) ); + } + + ret = __cpu_sys_read( host_fd, buf, count ); + if( ret > 0 ) + { + error = __cpu_copyout( ptr, buf, (__mpu_uint64_t)ret ); + if( error ) ret = -(__mpu_int64_t)error; + } + + free( buf ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_read() */ + + +__mpu_uint64_t +__cpu_SYS_lseek( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_uint64_t bits; + __mpu_int64_t offset; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + bits = __cpu_syscall_arg( 1 ); + memcpy( &offset, &bits, sizeof( offset ) ); + + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_lseek( host_fd, offset, __cpu_syscall_arg( 2 ) ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_lseek() */ + + +__mpu_uint64_t +__cpu_SYS_open( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_open( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ), + __cpu_syscall_arg( 2 ) ); + free( path ); + + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + fd = __cpu_fd_install( (int)ret ); + if( fd < 0 ) + { + (void)__cpu_sys_close( (int)ret ); + return( __cpu_syscall_error( __MCPU_EMFILE ) ); + } + + return( (__mpu_uint64_t)fd ); + +} /* End of __cpu_SYS_open() */ + + +__mpu_uint64_t +__cpu_SYS_creat( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_creat( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) ); + free( path ); + + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + fd = __cpu_fd_install( (int)ret ); + if( fd < 0 ) + { + (void)__cpu_sys_close( (int)ret ); + return( __cpu_syscall_error( __MCPU_EMFILE ) ); + } + + return( (__mpu_uint64_t)fd ); + +} /* End of __cpu_SYS_creat() */ + + +__mpu_uint64_t +__cpu_SYS_link( __mpu_uint32_t sysno ) +{ + char *oldpath = (char *)0; + char *newpath = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &oldpath, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + error = __cpu_copyinstr( &newpath, __cpu_syscall_arg( 1 ) ); + if( error ) + { + free( oldpath ); + return( __cpu_syscall_error( error ) ); + } + + ret = __cpu_sys_link( pcctx->_cwd_fd, oldpath, newpath ); + free( newpath ); + free( oldpath ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_link() */ + + +__mpu_uint64_t +__cpu_SYS_unlink( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_unlink( pcctx->_cwd_fd, path ); + free( path ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_unlink() */ + + +__mpu_uint64_t +__cpu_SYS_chdir( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int old_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_chdir( pcctx->_cwd_fd, path ); + free( path ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + old_fd = pcctx->_cwd_fd; + pcctx->_cwd_fd = (int)ret; + pcctx->_cwd_initialized = 1; + if( old_fd >= 0 ) (void)__cpu_sys_close( old_fd ); + + return( 0 ); + +} /* End of __cpu_SYS_chdir() */ + + +__mpu_uint64_t +__cpu_SYS_fchdir( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_int64_t ret; + int host_fd; + int old_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_fchdir( host_fd ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + old_fd = pcctx->_cwd_fd; + pcctx->_cwd_fd = (int)ret; + pcctx->_cwd_initialized = 1; + if( old_fd >= 0 ) (void)__cpu_sys_close( old_fd ); + + return( 0 ); + +} /* End of __cpu_SYS_fchdir() */ + + +__mpu_uint64_t +__cpu_SYS_rename( __mpu_uint32_t sysno ) +{ + char *oldpath = (char *)0; + char *newpath = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &oldpath, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + error = __cpu_copyinstr( &newpath, __cpu_syscall_arg( 1 ) ); + if( error ) + { + free( oldpath ); + return( __cpu_syscall_error( error ) ); + } + + ret = __cpu_sys_rename( pcctx->_cwd_fd, oldpath, newpath ); + free( newpath ); + free( oldpath ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_rename() */ + + +__mpu_uint64_t +__cpu_SYS_mkdir( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_mkdir( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) ); + free( path ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_mkdir() */ + + +__mpu_uint64_t +__cpu_SYS_chmod( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_chmod( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) ); + free( path ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_chmod() */ + + +__mpu_uint64_t +__cpu_SYS_chown( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_chown( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ), + __cpu_syscall_arg( 2 ) ); + free( path ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_chown() */ + + +__mpu_uint64_t +__cpu_SYS_access( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_access( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) ); + free( path ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_access() */ + + +__mpu_uint64_t +__cpu_SYS_rmdir( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_rmdir( pcctx->_cwd_fd, path ); + free( path ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_rmdir() */ + + +__mpu_uint64_t +__cpu_SYS_symlink( __mpu_uint32_t sysno ) +{ + char *target = (char *)0; + char *linkpath = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &target, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + error = __cpu_copyinstr( &linkpath, __cpu_syscall_arg( 1 ) ); + if( error ) + { + free( target ); + return( __cpu_syscall_error( error ) ); + } + + ret = __cpu_sys_symlink( pcctx->_cwd_fd, target, linkpath ); + free( linkpath ); + free( target ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_symlink() */ + + +__mpu_uint64_t +__cpu_SYS_readlink( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_uint64_t ptr; + __mpu_uint64_t count; + __mpu_int64_t ret; + unsigned char *buf = (unsigned char *)0; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ptr = __cpu_syscall_arg( 1 ); + count = __cpu_syscall_arg( 2 ); + + if( count ) + { + __mpu_UNIT_t *memory; + + if( count > (__mpu_uint64_t)(size_t)-1 ) + { + free( path ); + return( __cpu_syscall_error( __MCPU_EINVAL ) ); + } + + error = __cpu_memory_resolve( ptr, count, 1, &memory ); + if( error ) + { + free( path ); + return( __cpu_syscall_error( error ) ); + } + + buf = (unsigned char *)malloc( (size_t)count ); + if( !buf ) + { + free( path ); + return( __cpu_syscall_error( __MCPU_ENOMEM ) ); + } + } + + ret = __cpu_sys_readlink( pcctx->_cwd_fd, path, buf, count ); + free( path ); + + if( ret > 0 ) + { + error = __cpu_copyout( ptr, buf, (__mpu_uint64_t)ret ); + if( error ) ret = -(__mpu_int64_t)error; + } + + free( buf ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_readlink() */ + + +__mpu_uint64_t +__cpu_SYS_stat( __mpu_uint32_t sysno ) +{ + struct __cpu_stat st; + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_stat( pcctx->_cwd_fd, path, &st ); + free( path ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + error = __cpu_stat_copyout( __cpu_syscall_arg( 1 ), &st ); + if( error ) return( __cpu_syscall_error( error ) ); + + return( 0 ); + +} /* End of __cpu_SYS_stat() */ + + +__mpu_uint64_t +__cpu_SYS_fstat( __mpu_uint32_t sysno ) +{ + struct __cpu_stat st; + __mpu_uint64_t fd; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_fstat( host_fd, &st ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + error = __cpu_stat_copyout( __cpu_syscall_arg( 1 ), &st ); + if( error ) return( __cpu_syscall_error( error ) ); + + return( 0 ); + +} /* End of __cpu_SYS_fstat() */ + + +__mpu_uint64_t +__cpu_SYS_lstat( __mpu_uint32_t sysno ) +{ + struct __cpu_stat st; + char *path = (char *)0; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_lstat( pcctx->_cwd_fd, path, &st ); + free( path ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + error = __cpu_stat_copyout( __cpu_syscall_arg( 1 ), &st ); + if( error ) return( __cpu_syscall_error( error ) ); + + return( 0 ); + +} /* End of __cpu_SYS_lstat() */ + + +__mpu_uint64_t +__cpu_SYS_getdents( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_uint64_t ptr; + __mpu_uint64_t count; + __mpu_uint64_t usable; + __mpu_int64_t ret; + struct __cpu_dirent *buf = (struct __cpu_dirent *)0; + __mpu_UNIT_t *memory; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + ptr = __cpu_syscall_arg( 1 ); + count = __cpu_syscall_arg( 2 ); + + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + if( count < __CPU_DIRENT_SIZE ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + if( count > (__mpu_uint64_t)(size_t)-1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_memory_resolve( ptr, count, 1, &memory ); + if( error ) return( __cpu_syscall_error( error ) ); + + usable = ( count / __CPU_DIRENT_SIZE ) * __CPU_DIRENT_SIZE; + buf = (struct __cpu_dirent *)calloc( (size_t)( usable / __CPU_DIRENT_SIZE ), + sizeof( *buf ) ); + if( !buf ) return( __cpu_syscall_error( __MCPU_ENOMEM ) ); + + ret = __cpu_sys_getdents( host_fd, buf, usable ); + if( ret > 0 ) + { + error = __cpu_dirent_copyout( ptr, buf, (__mpu_uint64_t)ret ); + if( error ) ret = -(__mpu_int64_t)error; + } + + free( buf ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_getdents() */ + + +__mpu_uint64_t +__cpu_SYS_fcntl( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_uint64_t cmd; + __mpu_uint64_t arg; + __mpu_int64_t ret; + int host_fd; + int new_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + cmd = __cpu_syscall_arg( 1 ); + arg = __cpu_syscall_arg( 2 ); + + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + switch( cmd ) + { + case __CPU_F_DUPFD: + if( arg >= CPU_GUEST_FD_MAX ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + new_fd = __cpu_fd_find_from( arg ); + if( new_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) ); + + ret = __cpu_sys_fcntl( host_fd, cmd, 0 ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + pcctx->_fd[new_fd].host_fd = (int)ret; + pcctx->_fd[new_fd].owned = 1; + pcctx->_fd[new_fd].flags = 0; + return( (__mpu_uint64_t)new_fd ); + + case __CPU_F_GETFD: + if( arg != 0 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + return( (__mpu_uint64_t)( pcctx->_fd[fd].flags & __CPU_FD_SUPPORTED ) ); + + case __CPU_F_SETFD: + if( arg & ~(__mpu_uint64_t)__CPU_FD_SUPPORTED ) + return( __cpu_syscall_error( __MCPU_EINVAL ) ); + pcctx->_fd[fd].flags = (unsigned int)arg; + return( 0 ); + + case __CPU_F_GETFL: + if( arg != 0 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + ret = __cpu_sys_fcntl( host_fd, cmd, 0 ); + return( (__mpu_uint64_t)ret ); + + case __CPU_F_SETFL: + ret = __cpu_sys_fcntl( host_fd, cmd, arg ); + return( (__mpu_uint64_t)ret ); + + default: + return( __cpu_syscall_error( __MCPU_EINVAL ) ); + } + +} /* End of __cpu_SYS_fcntl() */ + + +__mpu_uint64_t +__cpu_SYS_pipe2( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t ptr; + __mpu_uint64_t flags; + __mpu_UNIT_t data[__CPU_PIPEFD_SIZE]; + __mpu_UNIT_t *memory; + __mpu_int64_t ret; + unsigned int fd_flags; + int host_pipe[2] = { -1, -1 }; + int read_fd; + int write_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + ptr = __cpu_syscall_arg( 0 ); + flags = __cpu_syscall_arg( 1 ); + + if( flags & ~(__mpu_uint64_t)__CPU_PIPE2_SUPPORTED ) + return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_memory_resolve( ptr, __CPU_PIPEFD_SIZE, 1, &memory ); + if( error ) return( __cpu_syscall_error( error ) ); + (void)memory; + + read_fd = __cpu_fd_find_from( 3 ); + if( read_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) ); + + write_fd = __cpu_fd_find_from( (__mpu_uint64_t)read_fd + 1U ); + if( write_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) ); + + ret = __cpu_sys_pipe2( host_pipe, flags & __CPU_O_NONBLOCK ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + memset( data, 0, sizeof( data ) ); + __cpu_data_put_u64( data + __CPU_PIPEFD_READ, (__mpu_uint64_t)read_fd ); + __cpu_data_put_u64( data + __CPU_PIPEFD_WRITE, (__mpu_uint64_t)write_fd ); + + error = __cpu_copyout( ptr, data, sizeof( data ) ); + if( error ) + { + (void)__cpu_sys_close( host_pipe[0] ); + (void)__cpu_sys_close( host_pipe[1] ); + return( __cpu_syscall_error( error ) ); + } + + fd_flags = ( flags & __CPU_O_CLOEXEC ) ? __CPU_FD_CLOEXEC : 0U; + + pcctx->_fd[read_fd].host_fd = host_pipe[0]; + pcctx->_fd[read_fd].owned = 1; + pcctx->_fd[read_fd].flags = fd_flags; + + pcctx->_fd[write_fd].host_fd = host_pipe[1]; + pcctx->_fd[write_fd].owned = 1; + pcctx->_fd[write_fd].flags = fd_flags; + + return( 0 ); + +} /* End of __cpu_SYS_pipe2() */ + + + +__mpu_uint64_t +__cpu_SYS_select( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t nfds; + __mpu_uint64_t read_ptr; + __mpu_uint64_t write_ptr; + __mpu_uint64_t except_ptr; + __mpu_uint64_t timeout_ptr; + __mpu_uint64_t read_in[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 }; + __mpu_uint64_t write_in[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 }; + __mpu_uint64_t except_in[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 }; + __mpu_uint64_t read_out[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 }; + __mpu_uint64_t write_out[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 }; + __mpu_uint64_t except_out[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 }; + struct __cpu_select_entry entries[CPU_GUEST_FD_MAX]; + struct __cpu_timeval timeout; + const struct __cpu_timeval *ptimeout = (const struct __cpu_timeval *)0; + __mpu_int64_t ret; + __mpu_uint64_t nentries = 0; + __mpu_uint64_t ready = 0; + unsigned int fd; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 5 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + nfds = __cpu_syscall_arg( 0 ); + read_ptr = __cpu_syscall_arg( 1 ); + write_ptr = __cpu_syscall_arg( 2 ); + except_ptr = __cpu_syscall_arg( 3 ); + timeout_ptr = __cpu_syscall_arg( 4 ); + + if( nfds > CPU_GUEST_FD_MAX ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + if( read_ptr != CPU_NULL_PTR ) + { + error = __cpu_fdset_load( read_ptr, read_in ); + if( error ) return( __cpu_syscall_error( error ) ); + } + if( write_ptr != CPU_NULL_PTR ) + { + error = __cpu_fdset_load( write_ptr, write_in ); + if( error ) return( __cpu_syscall_error( error ) ); + } + if( except_ptr != CPU_NULL_PTR ) + { + error = __cpu_fdset_load( except_ptr, except_in ); + if( error ) return( __cpu_syscall_error( error ) ); + } + if( timeout_ptr != CPU_NULL_PTR ) + { + error = __cpu_timeval_load( timeout_ptr, &timeout ); + if( error ) return( __cpu_syscall_error( error ) ); + ptimeout = &timeout; + } + + memset( entries, 0, sizeof( entries ) ); + + for( fd = 0; fd < (unsigned int)nfds; ++fd ) + { + unsigned int events = 0; + + if( read_ptr != CPU_NULL_PTR && __cpu_fdset_isset( read_in, fd ) ) + events |= __CPU_SELECT_READ; + if( write_ptr != CPU_NULL_PTR && __cpu_fdset_isset( write_in, fd ) ) + events |= __CPU_SELECT_WRITE; + if( except_ptr != CPU_NULL_PTR && __cpu_fdset_isset( except_in, fd ) ) + events |= __CPU_SELECT_EXCEPT; + + if( !events ) continue; + + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + entries[nentries].guest_fd = fd; + entries[nentries].host_fd = host_fd; + entries[nentries].events = events; + entries[nentries].revents = 0; + ++nentries; + } + + ret = __cpu_sys_select( entries, nentries, ptimeout ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + for( nfds = 0; nfds < nentries; ++nfds ) + { + fd = entries[nfds].guest_fd; + + if( ( entries[nfds].revents & __CPU_SELECT_READ ) && read_ptr != CPU_NULL_PTR ) + { + __cpu_fdset_set( read_out, fd ); + ++ready; + } + if( ( entries[nfds].revents & __CPU_SELECT_WRITE ) && write_ptr != CPU_NULL_PTR ) + { + __cpu_fdset_set( write_out, fd ); + ++ready; + } + if( ( entries[nfds].revents & __CPU_SELECT_EXCEPT ) && except_ptr != CPU_NULL_PTR ) + { + __cpu_fdset_set( except_out, fd ); + ++ready; + } + } + + if( read_ptr != CPU_NULL_PTR ) + { + error = __cpu_fdset_store( read_ptr, read_out ); + if( error ) return( __cpu_syscall_error( error ) ); + } + if( write_ptr != CPU_NULL_PTR ) + { + error = __cpu_fdset_store( write_ptr, write_out ); + if( error ) return( __cpu_syscall_error( error ) ); + } + if( except_ptr != CPU_NULL_PTR ) + { + error = __cpu_fdset_store( except_ptr, except_out ); + if( error ) return( __cpu_syscall_error( error ) ); + } + + return( ready ); + +} /* End of __cpu_SYS_select() */ + +__mpu_uint64_t +__cpu_SYS_gettimeofday( __mpu_uint32_t sysno ) +{ + struct __cpu_timespec ts; + struct __cpu_timeval tv; + __mpu_uint64_t tv_ptr; + __mpu_uint64_t tz_ptr; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + tv_ptr = __cpu_syscall_arg( 0 ); + tz_ptr = __cpu_syscall_arg( 1 ); + + if( tv_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) ); + if( tz_ptr != CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + ret = __cpu_sys_clock_gettime( __CPU_CLOCK_REALTIME, &ts ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + + error = __cpu_timeval_copyout( tv_ptr, &tv ); + if( error ) return( __cpu_syscall_error( error ) ); + + return( 0 ); + +} /* End of __cpu_SYS_gettimeofday() */ + + +__mpu_uint64_t +__cpu_SYS_clock_getres( __mpu_uint32_t sysno ) +{ + struct __cpu_timespec res; + __mpu_uint64_t clockid; + __mpu_uint64_t res_ptr; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + clockid = __cpu_syscall_arg( 0 ); + res_ptr = __cpu_syscall_arg( 1 ); + + ret = __cpu_sys_clock_getres( clockid, + res_ptr == CPU_NULL_PTR ? (struct __cpu_timespec *)0 : &res ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + if( res_ptr != CPU_NULL_PTR ) + { + error = __cpu_timespec_copyout( res_ptr, &res ); + if( error ) return( __cpu_syscall_error( error ) ); + } + + return( 0 ); + +} /* End of __cpu_SYS_clock_getres() */ + + +__mpu_uint64_t +__cpu_SYS_clock_gettime( __mpu_uint32_t sysno ) +{ + struct __cpu_timespec ts; + __mpu_uint64_t clockid; + __mpu_uint64_t tp_ptr; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + clockid = __cpu_syscall_arg( 0 ); + tp_ptr = __cpu_syscall_arg( 1 ); + + if( tp_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) ); + + ret = __cpu_sys_clock_gettime( clockid, &ts ); + if( ret < 0 ) return( (__mpu_uint64_t)ret ); + + error = __cpu_timespec_copyout( tp_ptr, &ts ); + if( error ) return( __cpu_syscall_error( error ) ); + + return( 0 ); + +} /* End of __cpu_SYS_clock_gettime() */ + + +__mpu_uint64_t +__cpu_SYS_nanosleep( __mpu_uint32_t sysno ) +{ + struct __cpu_timespec req; + struct __cpu_timespec rem; + __mpu_uint64_t req_ptr; + __mpu_uint64_t rem_ptr; + __mpu_UNIT_t *memory; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + req_ptr = __cpu_syscall_arg( 0 ); + rem_ptr = __cpu_syscall_arg( 1 ); + + if( req_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) ); + + error = __cpu_timespec_load( req_ptr, &req ); + if( error ) return( __cpu_syscall_error( error ) ); + + if( rem_ptr != CPU_NULL_PTR ) + { + error = __cpu_memory_resolve( rem_ptr, __CPU_TIMESPEC_SIZE, 1, &memory ); + if( error ) return( __cpu_syscall_error( error ) ); + (void)memory; + } + + ret = __cpu_sys_clock_nanosleep( __CPU_CLOCK_MONOTONIC, 0, &req, + rem_ptr == CPU_NULL_PTR ? (struct __cpu_timespec *)0 : &rem ); + + if( ret == -(__mpu_int64_t)__MCPU_EINTR && rem_ptr != CPU_NULL_PTR ) + { + error = __cpu_timespec_copyout( rem_ptr, &rem ); + if( error ) return( __cpu_syscall_error( error ) ); + } + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_nanosleep() */ + + +__mpu_uint64_t +__cpu_SYS_clock_nanosleep( __mpu_uint32_t sysno ) +{ + struct __cpu_timespec req; + struct __cpu_timespec rem; + __mpu_uint64_t clockid; + __mpu_uint64_t flags; + __mpu_uint64_t req_ptr; + __mpu_uint64_t rem_ptr; + __mpu_UNIT_t *memory; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 4 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + clockid = __cpu_syscall_arg( 0 ); + flags = __cpu_syscall_arg( 1 ); + req_ptr = __cpu_syscall_arg( 2 ); + rem_ptr = __cpu_syscall_arg( 3 ); + + if( flags & ~(__mpu_uint64_t)__CPU_TIMER_ABSTIME ) + return( __cpu_syscall_error( __MCPU_EINVAL ) ); + if( req_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) ); + + error = __cpu_timespec_load( req_ptr, &req ); + if( error ) return( __cpu_syscall_error( error ) ); + + if( !( flags & __CPU_TIMER_ABSTIME ) && rem_ptr != CPU_NULL_PTR ) + { + error = __cpu_memory_resolve( rem_ptr, __CPU_TIMESPEC_SIZE, 1, &memory ); + if( error ) return( __cpu_syscall_error( error ) ); + (void)memory; + } + + ret = __cpu_sys_clock_nanosleep( clockid, flags, &req, + ( flags & __CPU_TIMER_ABSTIME ) || rem_ptr == CPU_NULL_PTR ? + (struct __cpu_timespec *)0 : &rem ); + + if( ret == -(__mpu_int64_t)__MCPU_EINTR && !( flags & __CPU_TIMER_ABSTIME ) && + rem_ptr != CPU_NULL_PTR ) + { + error = __cpu_timespec_copyout( rem_ptr, &rem ); + if( error ) return( __cpu_syscall_error( error ) ); + } + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_clock_nanosleep() */ + + +__mpu_uint64_t +__cpu_SYS_fsync( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_fsync( host_fd ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_fsync() */ + + +__mpu_uint64_t +__cpu_SYS_truncate( __mpu_uint32_t sysno ) +{ + char *path = (char *)0; + __mpu_uint64_t bits; + __mpu_int64_t length; + __mpu_int64_t ret; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) ); + if( error ) return( __cpu_syscall_error( error ) ); + + bits = __cpu_syscall_arg( 1 ); + memcpy( &length, &bits, sizeof( length ) ); + + ret = __cpu_sys_truncate( pcctx->_cwd_fd, path, length ); + free( path ); + + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_truncate() */ + + +__mpu_uint64_t +__cpu_SYS_ftruncate( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_uint64_t bits; + __mpu_int64_t length; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + bits = __cpu_syscall_arg( 1 ); + memcpy( &length, &bits, sizeof( length ) ); + + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_ftruncate( host_fd, length ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_ftruncate() */ + + +__mpu_uint64_t +__cpu_SYS_fchmod( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_fchmod( host_fd, __cpu_syscall_arg( 1 ) ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_fchmod() */ + + +__mpu_uint64_t +__cpu_SYS_fchown( __mpu_uint32_t sysno ) +{ + __mpu_uint64_t fd; + __mpu_int64_t ret; + int host_fd; + int error; + + (void)sysno; + + if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + fd = __cpu_syscall_arg( 0 ); + error = __cpu_fd_get( fd, &host_fd ); + if( error ) return( __cpu_syscall_error( error ) ); + + ret = __cpu_sys_fchown( host_fd, __cpu_syscall_arg( 1 ), + __cpu_syscall_arg( 2 ) ); + return( (__mpu_uint64_t)ret ); + +} /* End of __cpu_SYS_fchown() */ + + +static const __cpu_syscall_handler_t __syscalls[] = +{ + [__NR_brk] = __cpu_SYS_brk, + [__NR_gettimeofday] = __cpu_SYS_gettimeofday, + [__NR_clock_getres] = __cpu_SYS_clock_getres, + [__NR_clock_gettime] = __cpu_SYS_clock_gettime, + [__NR_nanosleep] = __cpu_SYS_nanosleep, + [__NR_clock_nanosleep] = __cpu_SYS_clock_nanosleep, + [__NR_read] = __cpu_SYS_read, + [__NR_write] = __cpu_SYS_write, + [__NR_lseek] = __cpu_SYS_lseek, + [__NR_open] = __cpu_SYS_open, + [__NR_creat] = __cpu_SYS_creat, + [__NR_close] = __cpu_SYS_close, + [__NR_link] = __cpu_SYS_link, + [__NR_unlink] = __cpu_SYS_unlink, + [__NR_chdir] = __cpu_SYS_chdir, + [__NR_mkdir] = __cpu_SYS_mkdir, + [__NR_chmod] = __cpu_SYS_chmod, + [__NR_chown] = __cpu_SYS_chown, + [__NR_access] = __cpu_SYS_access, + [__NR_rename] = __cpu_SYS_rename, + [__NR_rmdir] = __cpu_SYS_rmdir, + [__NR_symlink] = __cpu_SYS_symlink, + [__NR_readlink] = __cpu_SYS_readlink, + [__NR_stat] = __cpu_SYS_stat, + [__NR_fstat] = __cpu_SYS_fstat, + [__NR_lstat] = __cpu_SYS_lstat, + [__NR_fcntl] = __cpu_SYS_fcntl, + [__NR_pipe2] = __cpu_SYS_pipe2, + [__NR_getdents] = __cpu_SYS_getdents, + [__NR_select] = __cpu_SYS_select, + [__NR_fsync] = __cpu_SYS_fsync, + [__NR_truncate] = __cpu_SYS_truncate, + [__NR_ftruncate] = __cpu_SYS_ftruncate, + [__NR_fchmod] = __cpu_SYS_fchmod, + [__NR_fchown] = __cpu_SYS_fchown, + [__NR_fchdir] = __cpu_SYS_fchdir, + [__NR_dup] = __cpu_SYS_dup, + [__NR_dup2] = __cpu_SYS_dup2, +}; + + +__mpu_uint64_t +__cpu_syscall_dispatch( void ) +{ + __mpu_uint32_t sysno; + + sysno = __cpu_data_get_u32( __cpu_reg_ptr( 32, CPU_SYSCALL_SYSNO_ADDR ) ); + + if( __cpu_syscall_nargs() > CPU_SYSCALL_MAX_ARGS ) + return( __cpu_syscall_error( __MCPU_EINVAL ) ); + + if( sysno >= sizeof( __syscalls ) / sizeof( __syscalls[0] ) || + __syscalls[sysno] == (__cpu_syscall_handler_t)0 ) + return( __cpu_syscall_error( __MCPU_ENOSYS ) ); + + return( __syscalls[sysno]( sysno ) ); + +} /* End of __cpu_syscall_dispatch() */ |
