| /* | |
| * 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); | |
| } |