From 2d869fe47aaf02b8e52d04e9a2b79d5b210fd016 Mon Sep 17 00:00:00 2001 From: Epifanov Ivan Date: Fri, 20 Dec 2024 14:34:58 +0300 Subject: [PATCH] Support fcntl GET/SET_FL to file descriptor (#105) * Fix fcntl * Update native flags (for fwrite, etc.). Handle O_APPEND in write * Filter out file access flags * Keep original flags as is --- newlib/libc/sys/vita/fcntl.c | 42 ++++++++++++++++++++++++--- newlib/libc/sys/vita/io.c | 1 + newlib/libc/sys/vita/syscalls.c | 3 ++ newlib/libc/sys/vita/vitadescriptor.h | 1 + 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/newlib/libc/sys/vita/fcntl.c b/newlib/libc/sys/vita/fcntl.c index e6f167f02..2c55da534 100644 --- a/newlib/libc/sys/vita/fcntl.c +++ b/newlib/libc/sys/vita/fcntl.c @@ -26,6 +26,8 @@ DEALINGS IN THE SOFTWARE. #include #include #include +#include +#include #include #include @@ -34,6 +36,9 @@ DEALINGS IN THE SOFTWARE. #include "vitaerror.h" #include "vitanet.h" +extern FILE *__sfp (struct _reent *); +#define SETFL_FLAGS (O_NONBLOCK | O_APPEND | O_DIRECT | O_ASYNC | O_SYNC | O_DSYNC) + int _fcntl_r(struct _reent *reent, int fd, int cmd, ...) { int arg = 0; @@ -70,14 +75,13 @@ int _fcntl_r(struct _reent *reent, int fd, int cmd, ...) } // The only existing flag is FD_CLOEXEC, and it is unsupported, - // so F_GETFD always returns zero. - if (cmd == F_GETFD) + // so F_GETFD/F_SETFD always returns zero. + if (cmd == F_GETFD || cmd == F_SETFD) { __vita_fd_drop(fdmap); return 0; } - // Only net sockets are supported for F_GETFL/F_SETFL if (fdmap->type == VITA_DESCRIPTOR_SOCKET) { if (cmd == F_GETFL) @@ -114,7 +118,37 @@ int _fcntl_r(struct _reent *reent, int fd, int cmd, ...) } } + if (fdmap->type == VITA_DESCRIPTOR_FILE) + { + if (cmd == F_GETFL) + { + int flags = fdmap->flags; + __vita_fd_drop(fdmap); + return flags; + } + + if (cmd == F_SETFL) + { + // File access modes should be ignored + arg = arg & SETFL_FLAGS; + // But should be kept as is if they were set by open + arg |= (fdmap->flags & ~SETFL_FLAGS); + + fdmap->flags = arg; + __vita_fd_drop(fdmap); + // update native descriptor flags too + register FILE *fp; + if ((fp = __sfp (reent)) == 0) + { + errno = EINVAL; + return -1; + } + fp->_flags = arg; + return 0; + } + } + __vita_fd_drop(fdmap); - errno = ENOTSUP; + errno = EBADF; return -1; } diff --git a/newlib/libc/sys/vita/io.c b/newlib/libc/sys/vita/io.c index d6338a0f1..1137036b2 100644 --- a/newlib/libc/sys/vita/io.c +++ b/newlib/libc/sys/vita/io.c @@ -105,6 +105,7 @@ int __vita_acquire_descriptor(void) { __vita_fdmap[fd] = &__vita_fdmap_pool[i]; __vita_fdmap[fd]->ref_count = 1; + __vita_fdmap[fd]->flags = 0; sceKernelUnlockLwMutex(&_newlib_fd_mutex, 1); return fd; } diff --git a/newlib/libc/sys/vita/syscalls.c b/newlib/libc/sys/vita/syscalls.c index 3f3a5dd16..367d2bbc7 100755 --- a/newlib/libc/sys/vita/syscalls.c +++ b/newlib/libc/sys/vita/syscalls.c @@ -41,6 +41,8 @@ _write_r(struct _reent * reent, int fd, const void *buf, size_t nbytes) { case VITA_DESCRIPTOR_FILE: case VITA_DESCRIPTOR_TTY: + if (fdmap->flags & O_APPEND) + sceIoLseek(fdmap->sce_uid, 0, SCE_SEEK_END); ret = sceIoWrite(fdmap->sce_uid, buf, nbytes); break; case VITA_DESCRIPTOR_SOCKET: @@ -300,6 +302,7 @@ _open_r(struct _reent *reent, const char *file, int flags, int mode) __vita_fdmap[fd]->sce_uid = ret; __vita_fdmap[fd]->type = is_dir ? VITA_DESCRIPTOR_DIRECTORY : VITA_DESCRIPTOR_FILE; __vita_fdmap[fd]->filename = strdup(full_path); + __vita_fdmap[fd]->flags = flags; free(full_path); diff --git a/newlib/libc/sys/vita/vitadescriptor.h b/newlib/libc/sys/vita/vitadescriptor.h index aa5602db9..200781d70 100644 --- a/newlib/libc/sys/vita/vitadescriptor.h +++ b/newlib/libc/sys/vita/vitadescriptor.h @@ -43,6 +43,7 @@ typedef struct DescriptorTypes type; int ref_count; char* filename; + int flags; } DescriptorTranslation; extern DescriptorTranslation *__vita_fdmap[];