diff --git a/headers/posix/unistd.h b/headers/posix/unistd.h index a020c0d2d1..f67275f03b 100644 --- a/headers/posix/unistd.h +++ b/headers/posix/unistd.h @@ -344,6 +344,7 @@ extern int pipe(int fildes[2]); extern int pipe2(int fildes[2], int flags); extern int dup(int fd); extern int dup2(int fd1, int fd2); +extern int dup3(int fd1, int fd2, int flags); extern int close(int fd); extern int link(const char *toPath, const char *path); extern int linkat(int toFD, const char *toPath, int pathFD, diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index 8dad66f244..40618373e6 100644 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -250,7 +250,7 @@ ssize_t _user_read_dir(int fd, struct dirent *buffer, size_t bufferSize, status_t _user_rewind_dir(int fd); status_t _user_close(int fd); int _user_dup(int fd); -int _user_dup2(int ofd, int nfd); +int _user_dup2(int ofd, int nfd, int flags); status_t _user_lock_node(int fd); status_t _user_unlock_node(int fd); status_t _user_preallocate(int fd, off_t offset, off_t length); diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index f3dfb0d1e3..520de44fe6 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -349,7 +349,7 @@ extern status_t _kern_write_stat(int fd, const char *path, size_t statSize, int statMask); extern status_t _kern_close(int fd); extern int _kern_dup(int fd); -extern int _kern_dup2(int ofd, int nfd); +extern int _kern_dup2(int ofd, int nfd, int flags); extern status_t _kern_lock_node(int fd); extern status_t _kern_unlock_node(int fd); extern status_t _kern_get_next_fd_info(team_id team, uint32 *_cookie, diff --git a/src/bin/debug/strace/fcntl.cpp b/src/bin/debug/strace/fcntl.cpp index d7be346bd4..1569266d92 100644 --- a/src/bin/debug/strace/fcntl.cpp +++ b/src/bin/debug/strace/fcntl.cpp @@ -98,5 +98,9 @@ patch_fcntl() createPipe->ParameterAt(0)->SetOut(true); createPipe->ParameterAt(0)->SetCount(2); createPipe->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kOpenFlags)); + + Syscall *dup2 = get_syscall("_kern_dup2"); + dup2->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kOpenFlags)); + } diff --git a/src/system/kernel/fs/fd.cpp b/src/system/kernel/fs/fd.cpp index 7877655591..17f861652f 100644 --- a/src/system/kernel/fs/fd.cpp +++ b/src/system/kernel/fs/fd.cpp @@ -373,7 +373,7 @@ dup_fd(int fd, bool kernel) We do dup2() directly to be thread-safe. */ static int -dup2_fd(int oldfd, int newfd, bool kernel) +dup2_fd(int oldfd, int newfd, int flags, bool kernel) { struct file_descriptor* evicted = NULL; struct io_context* context; @@ -383,6 +383,8 @@ dup2_fd(int oldfd, int newfd, bool kernel) // quick check if (oldfd < 0 || newfd < 0) return B_FILE_ERROR; + if ((flags & ~O_CLOEXEC) != 0) + return B_BAD_VALUE; // Get current I/O context and lock it context = get_current_io_context(kernel); @@ -418,7 +420,7 @@ dup2_fd(int oldfd, int newfd, bool kernel) deselect_select_infos(evicted, selectInfos, true); } - fd_set_close_on_exec(context, newfd, false); + fd_set_close_on_exec(context, newfd, (flags & O_CLOEXEC) != 0); mutex_unlock(&context->io_mutex); @@ -1014,9 +1016,9 @@ _user_dup(int fd) int -_user_dup2(int ofd, int nfd) +_user_dup2(int ofd, int nfd, int flags) { - return dup2_fd(ofd, nfd, false); + return dup2_fd(ofd, nfd, flags, false); } @@ -1206,8 +1208,8 @@ _kern_dup(int fd) int -_kern_dup2(int ofd, int nfd) +_kern_dup2(int ofd, int nfd, int flags) { - return dup2_fd(ofd, nfd, true); + return dup2_fd(ofd, nfd, flags, true); } diff --git a/src/system/libroot/posix/unistd/dup.c b/src/system/libroot/posix/unistd/dup.c index d5ee4afdb3..c89dc77e4c 100644 --- a/src/system/libroot/posix/unistd/dup.c +++ b/src/system/libroot/posix/unistd/dup.c @@ -22,5 +22,12 @@ dup(int fd) int dup2(int oldFD, int newFD) { - RETURN_AND_SET_ERRNO(_kern_dup2(oldFD, newFD)); + return dup3(oldFD, newFD, 0); +} + + +int +dup3(int oldFD, int newFD, int flags) +{ + RETURN_AND_SET_ERRNO(_kern_dup2(oldFD, newFD, flags)); }