Add FreeBSD-specific file operation shims: pipe2, chflagsat, close_range, copy_file_range, and __specialfd. Also add the safe_copy_file_range and safe_ppoll syscall wrappers and the target_specialfd_eventfd type definitions.
Signed-off-by: Stacey Son <[email protected]> Signed-off-by: Warner Losh <[email protected]> Assisted-by: Claude Opus 4.6 (1M context) --- bsd-user/freebsd/os-file.h | 129 ++++++++++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 7 +++ 2 files changed, 136 insertions(+) diff --git a/bsd-user/freebsd/os-file.h b/bsd-user/freebsd/os-file.h new file mode 100644 index 0000000000..c1da52789a --- /dev/null +++ b/bsd-user/freebsd/os-file.h @@ -0,0 +1,129 @@ +/* + * FreeBSD file related system call shims and definitions + * + * Copyright (c) 2014 Stacey D. Son + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef FREEBSD_OS_FILE_H +#define FREEBSD_OS_FILE_H + +#include <sys/specialfd.h> + +/* + * Asynchronous I/O. + */ + +/* pipe2(2) */ +static abi_long do_bsd_pipe2(CPUArchState *env, abi_ulong pipedes, int flags) +{ + int host_pipe[2]; + int host_ret = pipe2(host_pipe, flags); + /* XXXss - flags should be translated from target to host. */ + + if (host_ret == -1) { + return get_errno(host_ret); + } + + /* + * pipe2() returns it's second FD by copying it back to userspace and not in + * a second register like pipe(2): set_second_rval(env, host_pipe[1]); + * + * Copy the FD's back to userspace: + */ + if (put_user_s32(host_pipe[0], pipedes) || + put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0]))) { + close(host_pipe[0]); + close(host_pipe[1]); + return -TARGET_EFAULT; + } + return 0; +} + +/* chflagsat(2) */ +static inline abi_long do_bsd_chflagsat(int fd, abi_ulong path, + abi_ulong flags, int atflags) +{ + abi_long ret; + void *p; + + LOCK_PATH(p, path); + ret = get_errno(chflagsat(fd, p, flags, atflags)); /* XXX path(p)? */ + UNLOCK_PATH(p, path); + + return ret; +} + +/* close_range(2) */ +static inline abi_long do_freebsd_close_range(unsigned int lowfd, + unsigned int highfd, int flags) +{ + + return get_errno(close_range(lowfd, highfd, flags)); +} + +ssize_t safe_copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int); + +/* copy_file_range(2) */ +static inline abi_long do_freebsd_copy_file_range(int infd, + abi_ulong inofftp, int outfd, abi_ulong outofftp, size_t len, + unsigned int flags) +{ + off_t inoff, outoff, *inp, *outp; + abi_long ret; + + inp = outp = NULL; + if (inofftp != 0 && !access_ok(VERIFY_WRITE, inofftp, sizeof(off_t))) { + return -TARGET_EFAULT; + } else if (inofftp != 0) { + inoff = tswap64(*(off_t *)g2h_untagged(inofftp)); + inp = &inoff; + } + if (outofftp != 0 && !access_ok(VERIFY_WRITE, outofftp, sizeof(off_t))) { + return -TARGET_EFAULT; + } else if (outofftp != 0) { + outoff = tswap64(*(off_t *)g2h_untagged(outofftp)); + outp = &outoff; + } + + ret = get_errno(safe_copy_file_range(infd, inp, outfd, outp, len, + flags)); + + if (!is_error(ret)) { + if (inofftp != 0) { + *(off_t *)g2h_untagged(inofftp) = tswap64(inoff); + } + if (outofftp != 0) { + *(off_t *)g2h_untagged(outofftp) = tswap64(outoff); + } + } + return ret; +} + +static inline abi_long do_freebsd___specialfd(int type, abi_ulong req, + size_t len) +{ + abi_long ret; + + ret = -TARGET_EINVAL; + switch (type) { + case TARGET_SPECIALFD_EVENT: { + struct specialfd_eventfd evfd; + struct target_specialfd_eventfd *target_eventfd; + + if (!lock_user_struct(VERIFY_READ, target_eventfd, req, 1)) { + return -TARGET_EFAULT; + } + + evfd.initval = tswap32(target_eventfd->initval); + evfd.flags = tswap32(target_eventfd->flags); + ret = get_errno(syscall(SYS___specialfd, type, &evfd, sizeof(evfd))); + unlock_user_struct(target_eventfd, req, 0); + break; + } + } + + return ret; +} + +#endif /* FREEBSD_OS_FILE_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index fc6273a780..8a25be4ac7 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -45,6 +45,7 @@ #include "os-stat.h" #include "os-proc.h" #include "os-signal.h" +#include "os-file.h" #include "os-misc.h" /* I/O */ @@ -66,6 +67,12 @@ safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt); safe_syscall4(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt, off_t, offset); +safe_syscall4(int, ppoll, struct pollfd *, fds, nfds_t, nfds, + const struct timespec *, restrict_timeout, const sigset_t *, + restrict_newsigmask); +safe_syscall6(ssize_t, copy_file_range, int, infd, off_t *, inoffp, int, outfd, + off_t *, outoffp, size_t, len, unsigned int, flags); + /* used in os-proc */ safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options, struct rusage *, rusage); -- 2.52.0
