Skip to content

Commit

Permalink
Support fcntl GET/SET_FL to file descriptor (#105)
Browse files Browse the repository at this point in the history
* Fix fcntl

* Update native flags (for fwrite, etc.). Handle O_APPEND in write

* Filter out file access flags

* Keep original flags as is
  • Loading branch information
isage authored Dec 20, 2024
1 parent b89e5bc commit 2d869fe
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 4 deletions.
42 changes: 38 additions & 4 deletions newlib/libc/sys/vita/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ DEALINGS IN THE SOFTWARE.
#include <fcntl.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>

#include <psp2/net/net.h>
#include <psp2/types.h>
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions newlib/libc/sys/vita/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
3 changes: 3 additions & 0 deletions newlib/libc/sys/vita/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions newlib/libc/sys/vita/vitadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef struct
DescriptorTypes type;
int ref_count;
char* filename;
int flags;
} DescriptorTranslation;

extern DescriptorTranslation *__vita_fdmap[];
Expand Down

0 comments on commit 2d869fe

Please sign in to comment.