@@ -34,6 +34,11 @@ SYSCALL_DEF(close, ARG_DEC);
#ifdef TARGET_NR_creat
SYSCALL_DEF(creat, ARG_STR, ARG_MODEFLAG);
#endif
+SYSCALL_DEF(dup, ARG_DEC);
+#ifdef TARGET_NR_dup2
+SYSCALL_DEF(dup2, ARG_DEC, ARG_DEC);
+#endif
+SYSCALL_DEF(dup3, ARG_DEC, ARG_DEC, ARG_OPENFLAG);
SYSCALL_DEF(exit, ARG_DEC);
SYSCALL_DEF(execve, ARG_STR, ARG_PTR, ARG_PTR);
SYSCALL_DEF(execveat, ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
@@ -94,6 +94,48 @@ SYSCALL_IMPL(creat)
}
#endif
+SYSCALL_IMPL(dup)
+{
+ abi_long ret = get_errno(dup(arg1));
+ if (ret >= 0) {
+ fd_trans_dup(arg1, ret);
+ }
+ return ret;
+}
+
+#ifdef TARGET_NR_dup2
+SYSCALL_IMPL(dup2)
+{
+ abi_long ret = get_errno(dup2(arg1, arg2));
+ if (ret >= 0) {
+ fd_trans_dup(arg1, arg2);
+ }
+ return ret;
+}
+#endif
+
+SYSCALL_IMPL(dup3)
+{
+ int ofd = arg1;
+ int nfd = arg2;
+ int host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
+ abi_long ret;
+
+#ifdef CONFIG_DUP3
+ ret = dup3(ofd, nfd, host_flags);
+#else
+ if (host_flags == 0) {
+ if (ofd == nfd) {
+ return -TARGET_EINVAL;
+ }
+ ret = dup2(ofd, nfd);
+ } else {
+ ret = syscall(__NR_dup3, ofd, nfd, host_flags);
+ }
+#endif
+ return get_errno(ret);
+}
+
SYSCALL_IMPL(faccessat)
{
return do_faccessat(arg1, arg2, arg3);
@@ -204,6 +204,9 @@ _syscall0(int, sys_gettid)
* Performing a bogus syscall is easier than boilerplating
* the replacement functions here in C.
*/
+#ifndef __NR_dup3
+#define __NR_dup3 -1
+#endif
#ifndef __NR_syncfs
#define __NR_syncfs -1
#endif
@@ -5373,12 +5376,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
void *p;
switch(num) {
- case TARGET_NR_dup:
- ret = get_errno(dup(arg1));
- if (ret >= 0) {
- fd_trans_dup(arg1, ret);
- }
- return ret;
#ifdef TARGET_NR_pipe
case TARGET_NR_pipe:
return do_pipe(cpu_env, arg1, 0, 0);
@@ -5433,30 +5430,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
ret = get_errno(chroot(p));
unlock_user(p, arg1, 0);
return ret;
-#ifdef TARGET_NR_dup2
- case TARGET_NR_dup2:
- ret = get_errno(dup2(arg1, arg2));
- if (ret >= 0) {
- fd_trans_dup(arg1, arg2);
- }
- return ret;
-#endif
-#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
- case TARGET_NR_dup3:
- {
- int host_flags;
-
- if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
- return -EINVAL;
- }
- host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
- ret = get_errno(dup3(arg1, arg2, host_flags));
- if (ret >= 0) {
- fd_trans_dup(arg1, arg2);
- }
- return ret;
- }
-#endif
#ifdef TARGET_NR_getpgrp
case TARGET_NR_getpgrp:
return get_errno(getpgrp());
@@ -91,12 +91,6 @@
#ifdef TARGET_NR_dipc
{ TARGET_NR_dipc, "dipc" , NULL, NULL, NULL },
#endif
-#ifdef TARGET_NR_dup
-{ TARGET_NR_dup, "dup" , NULL, NULL, NULL },
-#endif
-#ifdef TARGET_NR_dup2
-{ TARGET_NR_dup2, "dup2" , NULL, NULL, NULL },
-#endif
#ifdef TARGET_NR_epoll_create
{ TARGET_NR_epoll_create, "epoll_create" , NULL, NULL, NULL },
#endif
Note that dup3 is universally available for guests. Implement host support with syscall when !CONFIG_DUP3. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- linux-user/syscall-defs.h | 5 +++++ linux-user/syscall-file.inc.c | 42 +++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 33 +++------------------------ linux-user/strace.list | 6 ----- 4 files changed, 50 insertions(+), 36 deletions(-)