From b18cad15b9ea1b72436da4a96444012a360e5fc8 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Tue, 11 Jun 2024 10:30:58 -0400 Subject: [PATCH] posix: fd_mgmt: implement dup(), dup2(), fseeko(), and ftello() Implement the remaining functions from the POSIX_FD_MGMT Option Group that are part of POSIX, and add the CONFIG_REQUIRES_FULL_LIBC dependency to CONFIG_POSIX_FD_MGMT, to pull in the remaining C89 functions. The POSIX_FD_MGMT Option Group is required for PSE52, PSE53, and PSE54 Subprofiling Option Groups. Signed-off-by: Chris Friedt --- lib/os/fdtable.c | 40 +++++++++++++++++++++++++++++++ lib/posix/options/Kconfig.fd_mgmt | 2 ++ lib/posix/options/fd_mgmt.c | 37 ++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 0c9131d7c39d0b..52f62f69cd0e9f 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -424,6 +424,46 @@ int zvfs_fileno(FILE *file) return (struct fd_entry *)file - fdtable; } +int zvfs_dup(int fd, int *newfd) +{ + int ret; + + if (_check_fd(fd) < 0) { + return -1; + } + + (void)k_mutex_lock(&fdtable_lock, K_FOREVER); + + if (newfd == NULL) { + /* dup() - just find lowest-numbered fd */ + ret = _find_fd_entry(); + } else { + /* dup2() - check if newfd is valid */ + if (_check_fd(*newfd) < 0) { + ret = -1; + } else { + if (fdtable[fd].vtable->close) { + (void)fdtable[fd].vtable->close(fdtable[fd].obj); + } + ret = *newfd; + } + } + + if (ret >= 0) { + /* Mark entry as used and initialize fields */ + if (newfd == NULL) { + (void)z_fd_ref(ret); + } + fdtable[ret] = fdtable[fd]; + k_mutex_init(&fdtable[ret].lock); + k_condvar_init(&fdtable[ret].cond); + } + + k_mutex_unlock(&fdtable_lock); + + return ret; +} + int zvfs_fstat(int fd, struct stat *buf) { if (_check_fd(fd) < 0) { diff --git a/lib/posix/options/Kconfig.fd_mgmt b/lib/posix/options/Kconfig.fd_mgmt index 329036ffbf8915..fee6f17848f657 100644 --- a/lib/posix/options/Kconfig.fd_mgmt +++ b/lib/posix/options/Kconfig.fd_mgmt @@ -5,6 +5,8 @@ menuconfig POSIX_FD_MGMT bool "POSIX file descriptor management [EXPERIMENTAL]" select EXPERIMENTAL + select FDTABLE + select REQUIRES_FULL_LIBC help Select 'y' here and Zephyr will provide implementations for the POSIX_FD_MGMT Option Group. This includes support for dup(), dup2(), fcntl(), fseeko(), ftello(), ftruncate(), diff --git a/lib/posix/options/fd_mgmt.c b/lib/posix/options/fd_mgmt.c index c1f60aca8e490f..923a133cf1f5ac 100644 --- a/lib/posix/options/fd_mgmt.c +++ b/lib/posix/options/fd_mgmt.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -14,10 +15,22 @@ #include /* prototypes for external, not-yet-public, functions in fdtable.c or fs.c */ +int zvfs_dup(int fd, int *newfd); int zvfs_fcntl(int fd, int cmd, va_list arg); +int zvfs_fileno(FILE *file); int zvfs_ftruncate(int fd, off_t length); off_t zvfs_lseek(int fd, off_t offset, int whence); +int dup(int fd) +{ + return zvfs_dup(fd, NULL); +} + +int dup2(int oldfd, int newfd) +{ + return zvfs_dup(oldfd, &newfd); +} + int fcntl(int fd, int cmd, ...) { int ret; @@ -33,6 +46,30 @@ int fcntl(int fd, int cmd, ...) FUNC_ALIAS(fcntl, _fcntl, int); #endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FCNTL */ +int fseeko(FILE *file, off_t offset, int whence) +{ + int fd; + + fd = zvfs_fileno(file); + if (fd < 0) { + return -1; + } + + return zvfs_lseek(fd, offset, whence); +} + +off_t ftello(FILE *file) +{ + int fd; + + fd = zvfs_fileno(file); + if (fd < 0) { + return -1; + } + + return zvfs_lseek(fd, 0, SEEK_CUR); +} + int ftruncate(int fd, off_t length) { return zvfs_ftruncate(fd, length);