blob: d789e35413137357fb0ef2fddc831df2061af384 [file] [log] [blame] [edit]
/*
* 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
}