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