1 /* 2 * File access convenience functions. 3 * 4 * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <ipc/cap_alloc.h> 23 #include <ipc/mem_ipc.h> 24 25 #include <string.h> 26 27 #include "dataspace_client.h" 28 #include "opener_client.h" 29 #include "opener_context_client.h" 30 #include "mapped_file_client.h" 31 32 #include "file.h" 33 34 35 36 /* Release resources for the given file. */ 37 38 void file_close(file_t *file) 39 { 40 if (l4_is_valid_cap(file->ref)) 41 ipc_cap_free_um(file->ref); 42 43 if (file->memory != NULL) 44 ipc_detach_dataspace(file->memory); 45 46 file_init(file); 47 } 48 49 /* Initialise a file structure for a context obtained from the given server. */ 50 51 long file_context(file_t *file, l4_cap_idx_t server) 52 { 53 client_Opener opener(server); 54 unsigned long size, flags; 55 long err; 56 57 file_init(file); 58 err = opener.context(&file->ref); 59 60 if (err) 61 return err; 62 63 client_Dataspace context_ds(file->ref); 64 65 err = context_ds.info(&size, &flags); 66 67 if (err) 68 return err; 69 70 return ipc_attach_dataspace(file->ref, size, (void **) &file->memory); 71 } 72 73 /* Initialise the given file structure. */ 74 75 void file_init(file_t *file) 76 { 77 file->memory = NULL; 78 file->ref = L4_INVALID_CAP; 79 } 80 81 /* Open a file using the given structure and context. */ 82 83 long file_open(file_t *file, file_t *context) 84 { 85 client_OpenerContext openercontext(context->ref); 86 file_init(file); 87 return openercontext.open(L4_FPAGE_RW, &file->size, &file->ref); 88 } 89 90 91 92 /* Map a region of the given file to a memory region. */ 93 94 long file_mmap(file_t *file, offset_t position, offset_t length) 95 { 96 client_MappedFile mapped_file(file->ref); 97 long err = mapped_file.mmap(position, length, &file->start_pos, &file->end_pos, &file->data_end); 98 99 if (err) 100 return err; 101 102 return ipc_attach_dataspace(file->ref, file_span(file), (void **) &file->memory); 103 } 104 105 /* Return the amount of data in the mapped region for the given file. */ 106 107 offset_t file_populated_span(file_t *file) 108 { 109 offset_t size = file_span(file); 110 return (file->data_end < size) ? file->data_end : size; 111 } 112 113 /* Return the size of the mapped region for the given file. */ 114 115 offset_t file_span(file_t *file) 116 { 117 return file->end_pos - file->start_pos; 118 } 119 120 121 122 /* Get a pointer to any terminated string at the given offset or NULL if the 123 data from offset is not terminated. */ 124 125 char *file_string_get(file_t *file, offset_t offset) 126 { 127 offset_t limit = file_span(file) - offset; 128 129 if (strnlen(file->memory + offset, limit) < limit) 130 return file->memory + offset; 131 else 132 return NULL; 133 } 134 135 /* Copy a string to the mapped region at the given offset, returning the number 136 of copied characters excluding the zero terminator. */ 137 138 offset_t file_string_set(file_t *file, const char *data, offset_t offset) 139 { 140 offset_t i, pos, limit = file_span(file) - 1; 141 142 /* Do not attempt to copy data with an invalid offset. */ 143 144 if (offset > limit) 145 return 0; 146 147 /* Copy the data to the given offset, stopping before the final byte of the 148 region. */ 149 150 for (i = 0, pos = offset; pos < limit; i++, pos++) 151 { 152 file->memory[pos] = data[i]; 153 154 /* Terminator written, can return immediately. */ 155 156 if (!data[i]) 157 return pos - offset - 1; 158 } 159 160 /* Terminate the incomplete string at the end of the region. */ 161 162 file->memory[limit] = '\0'; 163 return limit - offset; 164 } 165 166 // vim: tabstop=2 expandtab shiftwidth=2