blob: fe6953d99de562d47f7ef03c0e45c00165b05fef [file] [log] [blame] [edit]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <cpio/cpio.h>
#include <muslcsys/io.h>
#include <sel4/sel4.h>
#include <camkes.h>
seL4_Word fs_ctrl_get_sender_id(void);
void *fs_ctrl_buf(seL4_Word);
size_t fs_ctrl_buf_size(seL4_Word);
typedef struct cpio_file_data_wrap {
cpio_file_data_t data;
seL4_Word client;
} cpio_file_data_wrap_t;
extern char _cpio_archive[];
extern char _cpio_archive_end[];
void pre_init()
{
/* install the _cpio_archive */
unsigned long cpio_size = _cpio_archive_end - _cpio_archive;
muslcsys_install_cpio_interface(_cpio_archive, cpio_size, cpio_get_file);
}
bool validate_client_fd(int fd, seL4_Word client)
{
if (!valid_fd(fd)) {
ZF_LOGE("Client %zu attempted to use invalid fd %d", client, fd);
return false;
}
muslcsys_fd_t *fd_struct = get_fd_struct(fd);
if (fd_struct->filetype != FILE_TYPE_CPIO) {
ZF_LOGE("Client %zu attempted to use fd %d of a non-open file", client, fd);
return false;
}
cpio_file_data_wrap_t *data = (cpio_file_data_wrap_t *)fd_struct->data;
if (data->client != client) {
ZF_LOGE("Client %zu attempted to use fd %d that is for client %zu", client, fd, data->client);
return false;
}
return true;
}
int fs_ctrl_open(const char *name, int flags)
{
/* try the open and return early if we get an error */
int fd = open(name, flags);
if (fd < 0) {
return fd;
}
/* we make an assumption that we're still backed by the libsel4muslcsys
* implementation and we can extend its book keeping slightly to track
* the current client */
muslcsys_fd_t *fd_struct = get_fd_struct(fd);
assert(fd_struct);
cpio_file_data_wrap_t *newdata = realloc(fd_struct->data, sizeof(cpio_file_data_wrap_t));
if (!newdata) {
ZF_LOGE("Failed to allocate space for additional file metadata");
close(fd);
return -ENOMEM;
}
newdata->client = fs_ctrl_get_sender_id();
fd_struct->data = newdata;
return fd;
}
int64_t fs_ctrl_seek(int fd, int64_t offset, int whence)
{
seL4_Word client = fs_ctrl_get_sender_id();
if (!validate_client_fd(fd, client)) {
return -1;
}
return lseek(fd, offset, whence);
}
ssize_t fs_ctrl_read(int fd, size_t size)
{
seL4_Word client = fs_ctrl_get_sender_id();
if (!validate_client_fd(fd, client)) {
return -1;
}
void *dataport = fs_ctrl_buf(client);
assert(dataport);
size_t max = fs_ctrl_buf_size(client);
size = MIN(size, max);
return read(fd, dataport, size);
}
int fs_ctrl_close(int fd)
{
seL4_Word client = fs_ctrl_get_sender_id();
if (!validate_client_fd(fd, client)) {
return -EBADF;
}
return close(fd);
}