summaryrefslogtreecommitdiff
path: root/cpu/cpu-syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/cpu-syscalls.c')
-rw-r--r--cpu/cpu-syscalls.c2174
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() */