1.1 --- a/client/client.cc Tue Apr 13 00:03:18 2021 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,390 +0,0 @@
1.4 -/*
1.5 - * Filesystem client functions.
1.6 - *
1.7 - * Copyright (C) 2018, 2019, 2020, 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 <l4/re/env.h>
1.26 -
1.27 -#include <stdio.h>
1.28 -#include <stdlib.h>
1.29 -
1.30 -#include "client.h"
1.31 -
1.32 -
1.33 -
1.34 -/* Default size of pipe regions. */
1.35 -
1.36 -const offset_t DEFAULT_PIPE_SIZE = 4096;
1.37 -
1.38 -
1.39 -
1.40 -/* Close a filesystem object. */
1.41 -
1.42 -void client_close(file_t *file)
1.43 -{
1.44 - if (file == NULL)
1.45 - return;
1.46 -
1.47 - file_close(file);
1.48 - free(file);
1.49 -}
1.50 -
1.51 -
1.52 -
1.53 -/* Open a filesystem object. */
1.54 -
1.55 -file_t *client_open(const char *name, flags_t flags)
1.56 -{
1.57 - file_t *file = (file_t *) malloc(sizeof(file_t));
1.58 -
1.59 - if (file == NULL)
1.60 - return NULL;
1.61 -
1.62 - l4_cap_idx_t server = l4re_env_get_cap("server");
1.63 -
1.64 - if (file_open(file, name, flags, server))
1.65 - {
1.66 - free(file);
1.67 - return NULL;
1.68 - }
1.69 -
1.70 - return file;
1.71 -}
1.72 -
1.73 -
1.74 -
1.75 -/* Open a pipe object. */
1.76 -
1.77 -long client_pipe(file_t **reader, file_t **writer)
1.78 -{
1.79 - *reader = (file_t *) malloc(sizeof(file_t));
1.80 -
1.81 - if (*reader == NULL)
1.82 - return -L4_ENOMEM;
1.83 -
1.84 - *writer = (file_t *) malloc(sizeof(file_t));
1.85 -
1.86 - if (*writer == NULL)
1.87 - {
1.88 - free(*reader);
1.89 - return -L4_ENOMEM;
1.90 - }
1.91 -
1.92 - l4_cap_idx_t server = l4re_env_get_cap("pipes");
1.93 -
1.94 - long err = pipe_open(DEFAULT_PIPE_SIZE, *reader, *writer, server);
1.95 -
1.96 - if (err)
1.97 - {
1.98 - free(*reader);
1.99 - free(*writer);
1.100 - }
1.101 -
1.102 - return err;
1.103 -}
1.104 -
1.105 -
1.106 -
1.107 -/* Flush data conditionally to the filesystem object. */
1.108 -
1.109 -static long _flush(file_t *file, offset_t position)
1.110 -{
1.111 - long err;
1.112 -
1.113 - /* Where the position is outside the current region, re-map. */
1.114 -
1.115 - if ((position < file->start_pos) || (position >= file->end_pos))
1.116 - {
1.117 - if (file->can_mmap)
1.118 - {
1.119 - if (file_mmap(file, position, file_span(file)))
1.120 - return -L4_EIO;
1.121 - }
1.122 -
1.123 - /* Strict conditions for region navigation in pipes. */
1.124 -
1.125 - else if ((position != file->end_pos) ||
1.126 - (client_next_region(file) == NULL))
1.127 - return -L4_EIO;
1.128 - }
1.129 -
1.130 - /* Otherwise, flush any written data in the current region and update the
1.131 - file size details. */
1.132 -
1.133 - else
1.134 - {
1.135 - err = client_flush(file);
1.136 -
1.137 - if (err)
1.138 - return err;
1.139 - }
1.140 -
1.141 - /* Update the current data offset. */
1.142 -
1.143 - file->data_current = position - file->start_pos;
1.144 - return L4_EOK;
1.145 -}
1.146 -
1.147 -
1.148 -
1.149 -/* Flush data explicitly to the filesystem object. */
1.150 -
1.151 -long client_flush(file_t *file)
1.152 -{
1.153 - if (file == NULL)
1.154 - return -L4_EINVAL;
1.155 -
1.156 - /* Flush and retain most buffer settings. */
1.157 -
1.158 - return file_flush(file);
1.159 -}
1.160 -
1.161 -
1.162 -
1.163 -/* Map a memory region to a file. */
1.164 -
1.165 -void *client_mmap(file_t *file, offset_t position, offset_t length)
1.166 -{
1.167 - if ((file == NULL) || (file_mmap(file, position, length)))
1.168 - return NULL;
1.169 -
1.170 - return file->memory;
1.171 -}
1.172 -
1.173 -
1.174 -
1.175 -/* Obtain the current region of a pipe. */
1.176 -
1.177 -void *client_current_region(file_t *file)
1.178 -{
1.179 - if ((file == NULL) || (pipe_current(file)))
1.180 - return NULL;
1.181 -
1.182 - return file->memory;
1.183 -}
1.184 -
1.185 -
1.186 -
1.187 -/* Obtain the next region of a pipe. */
1.188 -
1.189 -void *client_next_region(file_t *file)
1.190 -{
1.191 - if ((file == NULL) || (pipe_next(file)))
1.192 - return NULL;
1.193 -
1.194 - return file->memory;
1.195 -}
1.196 -
1.197 -
1.198 -
1.199 -/* Read from the filesystem object into the buffer provided. */
1.200 -
1.201 -offset_t client_read(file_t *file, void *buf, offset_t count)
1.202 -{
1.203 - if (file == NULL)
1.204 - return 0;
1.205 -
1.206 - /* Amount available in the descriptor buffer already. */
1.207 -
1.208 - offset_t available = file_data_available(file);
1.209 - offset_t to_transfer, total = 0;
1.210 -
1.211 - while (count > 0)
1.212 - {
1.213 - /* If there is no data, try and obtain more data. */
1.214 -
1.215 - if (!available)
1.216 - {
1.217 - /* Flush any unwritten data, preparing to read from the file position at
1.218 - the end of the data, and returning if no new data is available. */
1.219 -
1.220 - if (_flush(file, file_data_end_position(file)))
1.221 - break;
1.222 -
1.223 - available = file_data_available(file);
1.224 -
1.225 - if (!available)
1.226 - break;
1.227 - }
1.228 -
1.229 - /* Transfer data into the supplied buffer. */
1.230 -
1.231 - to_transfer = available <= count ? available : count;
1.232 -
1.233 - file_data_read(file, (char *) buf, to_transfer);
1.234 -
1.235 - /* Update counters. */
1.236 -
1.237 - available -= to_transfer;
1.238 -
1.239 - count -= to_transfer;
1.240 - total += to_transfer;
1.241 -
1.242 - buf = ((char *) buf + to_transfer);
1.243 - }
1.244 -
1.245 - return total;
1.246 -}
1.247 -
1.248 -
1.249 -
1.250 -/* Ensure that the buffer can provide the needed data. */
1.251 -
1.252 -offset_t client_seek(file_t *file, offset_t offset, int whence)
1.253 -{
1.254 - if (file == NULL)
1.255 - return 0;
1.256 -
1.257 - offset_t position, current = file_data_current_position(file), change;
1.258 -
1.259 - switch (whence)
1.260 - {
1.261 - case SEEK_SET:
1.262 - position = offset;
1.263 - break;
1.264 -
1.265 - case SEEK_CUR:
1.266 - position = current + offset;
1.267 - break;
1.268 -
1.269 - case SEEK_END:
1.270 - position = file->size + offset;
1.271 - break;
1.272 -
1.273 - default:
1.274 - /* NOTE: Set errno to EINVAL. */
1.275 - return -1;
1.276 - }
1.277 -
1.278 - /* Retain the current position if unchanged. */
1.279 -
1.280 - if (position == current)
1.281 - return position;
1.282 -
1.283 - /* Move forward in the file. */
1.284 -
1.285 - if (position > current)
1.286 - {
1.287 - change = position - current;
1.288 -
1.289 - /* Move towards the end of available data.
1.290 - Request new data if not enough is available. */
1.291 -
1.292 - if (change <= file_data_available(file))
1.293 - {
1.294 - file->data_current += change;
1.295 - return position;
1.296 - }
1.297 - }
1.298 -
1.299 - /* Move backward in the file. */
1.300 -
1.301 - else
1.302 - {
1.303 - change = current - position;
1.304 -
1.305 - /* Move towards the start of available data.
1.306 - Request new data if moving beyond the start of the data. */
1.307 -
1.308 - if (change <= file->data_current)
1.309 - {
1.310 - file->data_current -= change;
1.311 - return position;
1.312 - }
1.313 - }
1.314 -
1.315 - /* Handle unwritten data and reset the buffer for reading. */
1.316 -
1.317 - _flush(file, position);
1.318 - return position;
1.319 -}
1.320 -
1.321 -
1.322 -
1.323 -long client_tell(file_t *file)
1.324 -{
1.325 - if (file == NULL)
1.326 - return -L4_EINVAL;
1.327 -
1.328 - return file_data_current_position(file);
1.329 -}
1.330 -
1.331 -
1.332 -
1.333 -/* Write to the filesystem object from the buffer provided. */
1.334 -
1.335 -offset_t client_write(file_t *file, const void *buf, offset_t count)
1.336 -{
1.337 - if (file == NULL)
1.338 - return 0;
1.339 -
1.340 - /* Attempt to ensure that the file can accept the amount of data to be
1.341 - written. This may not resize to the needed amount if a file has a fixed
1.342 - size, but data will still be written to any available space. */
1.343 -
1.344 - offset_t needed_size = file_data_current_position(file) + count;
1.345 -
1.346 - if (file->size < needed_size)
1.347 - {
1.348 - file_resize(file, needed_size);
1.349 -
1.350 - if (file->size < needed_size)
1.351 - count = file->size - file_data_current_position(file);
1.352 - }
1.353 -
1.354 - /* Space remaining in the descriptor buffer. */
1.355 -
1.356 - offset_t space = file_data_space(file);
1.357 - offset_t to_transfer, total = 0;
1.358 -
1.359 - while (count > 0)
1.360 - {
1.361 - /* If no space is available, try and send data, reset the buffer. */
1.362 -
1.363 - if (!space)
1.364 - {
1.365 - /* Flush any unwritten data and continue writing from the current data
1.366 - position. */
1.367 -
1.368 - if (_flush(file, file_data_current_position(file)))
1.369 - break;
1.370 -
1.371 - space = file_data_space(file);
1.372 - }
1.373 -
1.374 - /* Transfer data into the supplied buffer. */
1.375 -
1.376 - to_transfer = space <= count ? space : count;
1.377 -
1.378 - file_data_write(file, (char *) buf, to_transfer);
1.379 -
1.380 - /* Update counters. */
1.381 -
1.382 - space -= to_transfer;
1.383 -
1.384 - count -= to_transfer;
1.385 - total += to_transfer;
1.386 -
1.387 - buf = ((char *) buf + to_transfer);
1.388 - }
1.389 -
1.390 - return total;
1.391 -}
1.392 -
1.393 -// vim: tabstop=2 expandtab shiftwidth=2