1.1 --- a/file.cc Thu Apr 01 00:57:43 2021 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,320 +0,0 @@
1.4 -/*
1.5 - * File access convenience functions.
1.6 - *
1.7 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
1.8 - *
1.9 - * This program is free software; you can redistribute it and/or
1.10 - * modify it under the terms of the GNU General Public License as
1.11 - * published by the Free Software Foundation; either version 2 of
1.12 - * the License, or (at your option) any later version.
1.13 - *
1.14 - * This program is distributed in the hope that it will be useful,
1.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 - * GNU General Public License for more details.
1.18 - *
1.19 - * You should have received a copy of the GNU General Public License
1.20 - * along with this program; if not, write to the Free Software
1.21 - * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 - * Boston, MA 02110-1301, USA
1.23 - */
1.24 -
1.25 -#include <ipc/cap_alloc.h>
1.26 -#include <ipc/mem_ipc.h>
1.27 -
1.28 -#include <string.h>
1.29 -
1.30 -#include "dataspace_client.h"
1.31 -#include "file_client.h"
1.32 -#include "opener_client.h"
1.33 -#include "opener_context_client.h"
1.34 -#include "pipe_client.h"
1.35 -#include "pipe_opener_client.h"
1.36 -#include "mapped_file_client.h"
1.37 -
1.38 -#include "file.h"
1.39 -
1.40 -
1.41 -
1.42 -/* Release resources for the given file. */
1.43 -
1.44 -void file_close(file_t *file)
1.45 -{
1.46 - if (l4_is_valid_cap(file->ref))
1.47 - ipc_cap_free_um(file->ref);
1.48 -
1.49 - if (file->memory != NULL)
1.50 - ipc_detach_dataspace(file->memory);
1.51 -
1.52 - file_init(file);
1.53 -}
1.54 -
1.55 -/* Initialise a file structure for a context obtained from the given server. */
1.56 -
1.57 -long file_context(file_t *file, l4_cap_idx_t server)
1.58 -{
1.59 - client_Opener opener(server);
1.60 - unsigned long size, flags;
1.61 - long err;
1.62 -
1.63 - file_init(file);
1.64 -
1.65 - err = opener.context(&file->ref);
1.66 - if (err)
1.67 - return err;
1.68 -
1.69 - client_Dataspace context_ds(file->ref);
1.70 -
1.71 - err = context_ds.info(&size, &flags);
1.72 - if (err)
1.73 - return err;
1.74 -
1.75 - file->start_pos = 0;
1.76 - file->end_pos = size;
1.77 -
1.78 - return ipc_attach_dataspace(file->ref, size, (void **) &file->memory);
1.79 -}
1.80 -
1.81 -/* Open a file using the given structure and context. */
1.82 -
1.83 -long file_context_open(file_t *file, file_t *context)
1.84 -{
1.85 - client_OpenerContext openercontext(context->ref);
1.86 - file_init(file);
1.87 - return openercontext.open(L4_FPAGE_RW, &file->size, &file->ref);
1.88 -}
1.89 -
1.90 -/* Initialise the given file structure. */
1.91 -
1.92 -void file_init(file_t *file)
1.93 -{
1.94 - file->memory = NULL;
1.95 - file->ref = L4_INVALID_CAP;
1.96 - file->start_pos = 0;
1.97 - file->end_pos = 0;
1.98 - file->data_end = 0;
1.99 -}
1.100 -
1.101 -/* Open a file using the given structure, indicating the filename and
1.102 - filesystem server. This is a convenience function invoking file_context and
1.103 - file_context_open. */
1.104 -
1.105 -long file_open(file_t *file, const char *filename, l4_cap_idx_t server)
1.106 -{
1.107 - file_t context;
1.108 - long err;
1.109 -
1.110 - err = file_context(&context, server);
1.111 - if (err)
1.112 - return err;
1.113 -
1.114 - if (!file_string_set(&context, filename, 0, NULL))
1.115 - return -L4_ENOMEM;
1.116 -
1.117 - err = file_context_open(file, &context);
1.118 - file_close(&context);
1.119 - return err;
1.120 -}
1.121 -
1.122 -
1.123 -
1.124 -/* Map a region of the given file to a memory region. */
1.125 -
1.126 -long file_mmap(file_t *file, offset_t position, offset_t length)
1.127 -{
1.128 - client_MappedFile mapped_file(file->ref);
1.129 - long err = mapped_file.mmap(position, length, &file->start_pos, &file->end_pos, &file->data_end);
1.130 -
1.131 - if (err)
1.132 - return err;
1.133 -
1.134 - return ipc_attach_dataspace(file->ref, file_span(file), (void **) &file->memory);
1.135 -}
1.136 -
1.137 -/* Resize a file. */
1.138 -
1.139 -long file_resize(file_t *file, offset_t size)
1.140 -{
1.141 - client_File _file(file->ref);
1.142 - offset_t file_size = size;
1.143 - long err = _file.resize(&file_size);
1.144 -
1.145 - if (!err)
1.146 - {
1.147 - /* Determine the extent of the file in this region. */
1.148 -
1.149 - if (file_size > file->end_pos)
1.150 - file->data_end = file_span(file);
1.151 - else
1.152 - file->data_end = file_size - file->start_pos;
1.153 -
1.154 - /* Update the file size locally. */
1.155 -
1.156 - file->size = file_size;
1.157 - }
1.158 -
1.159 - return err;
1.160 -}
1.161 -
1.162 -
1.163 -
1.164 -/* Return the amount of data in the mapped region for the given file. */
1.165 -
1.166 -offset_t file_populated_span(file_t *file)
1.167 -{
1.168 - offset_t size = file_span(file);
1.169 - return (file->data_end < size) ? file->data_end : size;
1.170 -}
1.171 -
1.172 -/* Return the size of the mapped region for the given file. */
1.173 -
1.174 -offset_t file_span(file_t *file)
1.175 -{
1.176 - return file->end_pos - file->start_pos;
1.177 -}
1.178 -
1.179 -
1.180 -
1.181 -/* Get a pointer to any terminated string at the given offset or NULL if the
1.182 - data from offset is not terminated. */
1.183 -
1.184 -char *file_string_get(file_t *file, offset_t offset)
1.185 -{
1.186 - offset_t limit = file_span(file) - offset;
1.187 -
1.188 - if (strnlen(file->memory + offset, limit) < limit)
1.189 - return file->memory + offset;
1.190 - else
1.191 - return NULL;
1.192 -}
1.193 -
1.194 -/* Copy a string to the mapped region at the given offset, returning 1 (true)
1.195 - where all characters were copied, 0 (false) otherwise. The precise number of
1.196 - characters copied, excluding the zero terminator is provided via the written
1.197 - parameter if it is not specified as NULL. */
1.198 -
1.199 -int file_string_set(file_t *file, const char *data, offset_t offset,
1.200 - offset_t *written)
1.201 -{
1.202 - offset_t i, pos, limit = file_span(file);
1.203 -
1.204 - /* Do not attempt to copy data with an invalid offset. */
1.205 -
1.206 - if (offset >= limit)
1.207 - {
1.208 - if (written != NULL)
1.209 - *written = 0;
1.210 - return 0;
1.211 - }
1.212 -
1.213 - /* Copy the data to the given offset, stopping at the end of the region. */
1.214 -
1.215 - for (i = 0, pos = offset; pos < limit; i++, pos++)
1.216 - {
1.217 - file->memory[pos] = data[i];
1.218 -
1.219 - /* Terminator written, can return immediately. */
1.220 -
1.221 - if (!data[i])
1.222 - {
1.223 - if (written != NULL)
1.224 - *written = pos - offset;
1.225 - return 1;
1.226 - }
1.227 - }
1.228 -
1.229 - /* Terminate the incomplete string at the end of the region. */
1.230 -
1.231 - file->memory[limit - 1] = '\0';
1.232 - if (written != NULL)
1.233 - *written = limit - 1 - offset;
1.234 - return 0;
1.235 -}
1.236 -
1.237 -
1.238 -
1.239 -/* Open two pipe endpoints using the given pipe server. */
1.240 -
1.241 -long pipe_open(offset_t size, file_t *reader, file_t *writer, l4_cap_idx_t server)
1.242 -{
1.243 - client_PipeOpener opener(server);
1.244 -
1.245 - file_init(reader);
1.246 - file_init(writer);
1.247 -
1.248 - long err = opener.pipe(size, &reader->ref, &writer->ref);
1.249 - if (err)
1.250 - return err;
1.251 -
1.252 - err = pipe_next(writer) || pipe_next(reader);
1.253 -
1.254 - if (err)
1.255 - {
1.256 - file_close(reader);
1.257 - file_close(writer);
1.258 - }
1.259 -
1.260 - return err;
1.261 -}
1.262 -
1.263 -/* Access the current region for a pipe endpoint. */
1.264 -
1.265 -long pipe_current(file_t *pipe)
1.266 -{
1.267 - client_Pipe _pipe(pipe->ref);
1.268 - long err = _pipe.current_region(&pipe->data_end, &pipe->size);
1.269 - char *memory = pipe->memory;
1.270 -
1.271 - if (err)
1.272 - return err;
1.273 -
1.274 - pipe->end_pos = pipe->size;
1.275 -
1.276 - err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory);
1.277 - if (err)
1.278 - return err;
1.279 -
1.280 - if (memory != NULL)
1.281 - ipc_detach_dataspace(memory);
1.282 -
1.283 - return L4_EOK;
1.284 -}
1.285 -
1.286 -/* Access the next region for a pipe endpoint, updating the eventual size of
1.287 - the current region. */
1.288 -
1.289 -long pipe_next(file_t *pipe)
1.290 -{
1.291 - client_Pipe _pipe(pipe->ref);
1.292 - long err = _pipe.next_region(&pipe->data_end, &pipe->size);
1.293 - char *memory = pipe->memory;
1.294 -
1.295 - if (err)
1.296 - return err;
1.297 -
1.298 - pipe->end_pos = pipe->size;
1.299 -
1.300 - err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory);
1.301 - if (err)
1.302 - return err;
1.303 -
1.304 - if (memory != NULL)
1.305 - ipc_detach_dataspace(memory);
1.306 -
1.307 - return L4_EOK;
1.308 -}
1.309 -
1.310 -/* Set the size of the written region. */
1.311 -
1.312 -long pipe_written(file_t *pipe, offset_t size)
1.313 -{
1.314 - if (size <= pipe->size)
1.315 - {
1.316 - pipe->data_end = size;
1.317 - return L4_EOK;
1.318 - }
1.319 - else
1.320 - return -L4_EINVAL;
1.321 -}
1.322 -
1.323 -// vim: tabstop=2 expandtab shiftwidth=2