diff --git a/libc/calls/dup-nt.c b/libc/calls/dup-nt.c index f093326f3..4d54add88 100644 --- a/libc/calls/dup-nt.c +++ b/libc/calls/dup-nt.c @@ -24,9 +24,11 @@ #include "libc/calls/struct/sigset.internal.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/errno.h" +#include "libc/intrin/kprintf.h" #include "libc/intrin/weaken.h" #include "libc/nt/files.h" #include "libc/nt/runtime.h" +#include "libc/runtime/zipos.internal.h" #include "libc/sock/internal.h" #include "libc/str/str.h" #include "libc/sysv/consts/o.h" @@ -57,7 +59,11 @@ static textwindows int sys_dup_nt_impl(int oldfd, int newfd, int flags, return -1; } if (g_fds.p[newfd].kind) { - sys_close_nt(newfd, newfd); + if (g_fds.p[newfd].kind == kFdZip) { + _weaken(__zipos_close)(newfd); + } else { + sys_close_nt(newfd, newfd); + } } } diff --git a/libc/calls/dup2.c b/libc/calls/dup2.c index e1ddc7488..dbb5064a2 100644 --- a/libc/calls/dup2.c +++ b/libc/calls/dup2.c @@ -18,12 +18,15 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/state.internal.h" #include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" +#include "libc/runtime/zipos.internal.h" +#include "libc/str/str.h" #include "libc/sysv/errfuns.h" /** @@ -74,6 +77,11 @@ int dup2(int oldfd, int newfd) { #endif } else if (!IsWindows()) { rc = sys_dup2(oldfd, newfd, 0); + if (rc != -1 && oldfd != newfd && __isfdkind(newfd, kFdZip) && !__vforked) { + _weaken(__zipos_free)( + (struct ZiposHandle *)(intptr_t)g_fds.p[newfd].handle); + bzero(g_fds.p + newfd, sizeof(*g_fds.p)); + } } else if (newfd < 0) { rc = ebadf(); } else if (oldfd == newfd) { diff --git a/libc/calls/dup3.c b/libc/calls/dup3.c index eaea8757a..42a0573c9 100644 --- a/libc/calls/dup3.c +++ b/libc/calls/dup3.c @@ -18,12 +18,15 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/internal.h" +#include "libc/calls/state.internal.h" #include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" +#include "libc/runtime/zipos.internal.h" +#include "libc/str/str.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" @@ -71,6 +74,11 @@ int dup3(int oldfd, int newfd, int flags) { rc = enotsup(); } else if (!IsWindows()) { rc = sys_dup3(oldfd, newfd, flags); + if (rc != -1 && __isfdkind(newfd, kFdZip) && !__vforked) { + _weaken(__zipos_free)( + (struct ZiposHandle *)(intptr_t)g_fds.p[newfd].handle); + bzero(g_fds.p + newfd, sizeof(*g_fds.p)); + } } else { rc = sys_dup_nt(oldfd, newfd, flags, -1); } diff --git a/test/libc/calls/dup_test.c b/test/libc/calls/dup_test.c index 25556b522..fd3f79e65 100644 --- a/test/libc/calls/dup_test.c +++ b/test/libc/calls/dup_test.c @@ -33,6 +33,8 @@ #include "libc/testlib/testlib.h" #include "libc/x/xspawn.h" +__static_yoink("libc/testlib/hyperion.txt"); + void SetUpOnce(void) { testlib_enable_tmp_setup_teardown(); } @@ -50,7 +52,6 @@ static textstartup void TestInit(int argc, char **argv) { const void *const TestCtor[] initarray = {TestInit}; -#if 0 TEST(dup, ebadf) { ASSERT_SYS(EBADF, -1, dup(-1)); ASSERT_SYS(EBADF, -1, dup2(-1, 0)); @@ -72,7 +73,17 @@ TEST(dup, bigNumber) { ASSERT_SYS(0, 100, dup2(0, 100)); ASSERT_SYS(0, 0, close(100)); } -#endif + +TEST(dup2, zipos) { + ASSERT_SYS(0, 3, creat("real", 0644)); + ASSERT_SYS(0, 4, open("/zip/libc/testlib/hyperion.txt", O_RDONLY)); + ASSERT_SYS(0, 2, write(3, "hi", 2)); + ASSERT_SYS(EBADF, -1, write(4, "hi", 2)); + ASSERT_SYS(0, 4, dup2(3, 4)); + ASSERT_SYS(0, 2, write(4, "hi", 2)); + ASSERT_SYS(0, 0, close(4)); + ASSERT_SYS(0, 0, close(3)); +} #ifdef __x86_64__ TEST(dup, clearsCloexecFlag) {