| /* | |
| * Copyright 2018, Data61, CSIRO (ABN 41 687 119 230) | |
| * | |
| * SPDX-License-Identifier: BSD-2-Clause | |
| */ | |
| #include <stdint.h> | |
| #include <string.h> | |
| #include <fcntl.h> | |
| #include <errno.h> | |
| #include <sys/uio.h> | |
| #include <utils/util.h> | |
| #include <muslcsys/vsyscall.h> | |
| #include "fsclient.h" | |
| static void *ext_buf; | |
| static int (*ext_open)(const char *name, int flags); | |
| static ssize_t (*ext_read)(int fd, size_t size); | |
| static int64_t (*ext_seek)(int fd, int64_t offset, int whence); | |
| static int (*ext_close)(int fd); | |
| static long fileserver_open(va_list ap) | |
| { | |
| const char *pathname = va_arg(ap, const char *); | |
| int flags = va_arg(ap, int); | |
| return ext_open(pathname, flags); | |
| } | |
| static long fileserver_openat(va_list ap) | |
| { | |
| int dirfd = va_arg(ap, int); | |
| const char *pathname = va_arg(ap, const char *); | |
| int flags = va_arg(ap, int); | |
| if (dirfd != AT_FDCWD) { | |
| ZF_LOGE("Openat only supports relative path to the current working directory\n"); | |
| return -EINVAL; | |
| } | |
| return ext_open(pathname, flags); | |
| } | |
| static long fileserver_close(va_list ap) | |
| { | |
| int fd = va_arg(ap, int); | |
| return ext_close(fd); | |
| } | |
| static long fileserver_read(va_list ap) | |
| { | |
| int fd = va_arg(ap, int); | |
| void *buf = va_arg(ap, void *); | |
| size_t count = va_arg(ap, size_t); | |
| ssize_t total = 0; | |
| size_t remain = count; | |
| while (total < count) { | |
| ssize_t result = ext_read(fd, remain); | |
| if (result <= 0) { | |
| return total; | |
| } | |
| memcpy(buf + total, ext_buf, result); | |
| total += result; | |
| remain -= result; | |
| } | |
| return total; | |
| } | |
| static long fileserver_readv(va_list ap) | |
| { | |
| int fd = va_arg(ap, int); | |
| struct iovec *iov = va_arg(ap, struct iovec *); | |
| int iovcnt = va_arg(ap, int); | |
| ssize_t total = 0; | |
| int i; | |
| for (i = 0; i < iovcnt; i++) { | |
| long iov_offset = 0; | |
| while (iov_offset < iov[i].iov_len) { | |
| long read = ext_read(fd, iov[i].iov_len - iov_offset); | |
| if (read <= 0) { | |
| return total; | |
| } | |
| memcpy(iov[i].iov_base + iov_offset, ext_buf, read); | |
| iov_offset += read; | |
| total += read; | |
| } | |
| } | |
| return total; | |
| } | |
| static long fileserver_lseek(va_list ap) | |
| { | |
| int fd = va_arg(ap, int); | |
| off_t offset = va_arg(ap, off_t); | |
| int whence = va_arg(ap, int); | |
| return ext_seek(fd, offset, whence); | |
| } | |
| static long fileserver_llseek(va_list ap) | |
| { | |
| int fd = va_arg(ap, int); | |
| uint32_t offset_high = va_arg(ap, uint32_t); | |
| uint32_t offset_low = va_arg(ap, uint32_t); | |
| off_t *result = va_arg(ap, off_t *); | |
| int whence = va_arg(ap, int); | |
| *result = ext_seek(fd, (((uint64_t)offset_high) << 32) | offset_low, whence); | |
| return 0; | |
| } | |
| void install_fileserver(file_server_interface_t fs_interface) | |
| { | |
| ext_buf = fs_interface.ext_buf; | |
| ext_open = fs_interface.ext_open; | |
| ext_read = fs_interface.ext_read; | |
| ext_seek = fs_interface.ext_seek; | |
| ext_close = fs_interface.ext_close; | |
| #ifdef __NR_open | |
| muslcsys_install_syscall(__NR_open, fileserver_open); | |
| #endif | |
| #ifdef __NR_openat | |
| muslcsys_install_syscall(__NR_openat, fileserver_openat); | |
| #endif | |
| muslcsys_install_syscall(__NR_close, fileserver_close); | |
| muslcsys_install_syscall(__NR_read, fileserver_read); | |
| muslcsys_install_syscall(__NR_readv, fileserver_readv); | |
| muslcsys_install_syscall(__NR_lseek, fileserver_lseek); | |
| #ifdef __NR__llseek | |
| muslcsys_install_syscall(__NR__llseek, fileserver_llseek); | |
| #endif | |
| } |