1.1 --- a/client/file.cc Thu Apr 08 23:55:47 2021 +0200
1.2 +++ b/client/file.cc Sun Apr 11 19:34:07 2021 +0200
1.3 @@ -36,6 +36,44 @@
1.4
1.5
1.6
1.7 +/* Update the extent of the file in a region using the region start and end
1.8 + positions and the file size. */
1.9 +
1.10 +static void _update_extent(file_t *file)
1.11 +{
1.12 + /* Handle files ending after or within the region. */
1.13 +
1.14 + if (file->size > file->start_pos)
1.15 + {
1.16 + if (file->size > file->end_pos)
1.17 + file->data_end = file->end_pos - file->start_pos;
1.18 + else
1.19 + file->data_end = file->size - file->start_pos;
1.20 + }
1.21 +
1.22 + /* Handle files ending before the region. */
1.23 +
1.24 + else
1.25 + file->data_end = 0;
1.26 +}
1.27 +
1.28 +
1.29 +
1.30 +/* Initialise the given file structure. */
1.31 +
1.32 +void file_init(file_t *file)
1.33 +{
1.34 + file->memory = NULL;
1.35 + file->ref = L4_INVALID_CAP;
1.36 + file->start_pos = 0;
1.37 + file->end_pos = 0;
1.38 + file->data_end = 0;
1.39 + file->data_current = 0;
1.40 + file->can_mmap = 1;
1.41 +}
1.42 +
1.43 +
1.44 +
1.45 /* Release resources for the given file. */
1.46
1.47 void file_close(file_t *file)
1.48 @@ -49,7 +87,36 @@
1.49 file_init(file);
1.50 }
1.51
1.52 -/* Initialise a file structure for a context obtained from the given server. */
1.53 +/* Open a file using the given structure, indicating the filename and
1.54 + filesystem server. The file_mmap function should be used to obtain access to
1.55 + memory providing file data. This is a convenience function invoking
1.56 + file_context and file_context_open. */
1.57 +
1.58 +long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server)
1.59 +{
1.60 + file_t context;
1.61 + long err;
1.62 +
1.63 + err = file_context(&context, server);
1.64 + if (err)
1.65 + return err;
1.66 +
1.67 + if (!file_string_set(&context, filename, 0, NULL))
1.68 + return -L4_ENOMEM;
1.69 +
1.70 + err = file_context_open(file, flags, &context);
1.71 +
1.72 + /* Close the context, although a separate mechanism could permit contexts to
1.73 + open several files. */
1.74 +
1.75 + file_close(&context);
1.76 + return err;
1.77 +}
1.78 +
1.79 +
1.80 +
1.81 +/* Initialise a file structure for a context obtained from the given server
1.82 + attaching memory to communicate filename information. */
1.83
1.84 long file_context(file_t *file, l4_cap_idx_t server)
1.85 {
1.86 @@ -87,54 +154,50 @@
1.87 return openercontext.open(flags, &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, flags_t flags, 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, flags, &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 +/* Flush populated data and obtain an updated file size and populated data
1.126 + details. */
1.127
1.128 -long file_mmap(file_t *file, offset_t position, offset_t length)
1.129 +long file_flush(file_t *file)
1.130 {
1.131 - client_MappedFile mapped_file(file->ref);
1.132 - long err = mapped_file.mmap(position, length, &file->start_pos, &file->end_pos, &file->data_end);
1.133 + client_File _file(file->ref);
1.134 + long err = _file.flush(file->data_current, &file->size);
1.135
1.136 if (err)
1.137 return err;
1.138
1.139 - return ipc_attach_dataspace(file->ref, file_span(file), (void **) &file->memory);
1.140 + _update_extent(file);
1.141 +
1.142 + return L4_EOK;
1.143 }
1.144
1.145 -/* Resize a file. */
1.146 +/* Map a region of the given file to a memory region, obtaining an updated file
1.147 + size and populated data details. Unmap any previously mapped region. */
1.148 +
1.149 +long file_mmap(file_t *file, offset_t position, offset_t length)
1.150 +{
1.151 + char *memory = file->memory;
1.152 + client_MappedFile mapped_file(file->ref);
1.153 + long err = mapped_file.mmap(position, length, &file->start_pos,
1.154 + &file->end_pos, &file->size);
1.155 +
1.156 + if (err)
1.157 + return err;
1.158 +
1.159 + _update_extent(file);
1.160 +
1.161 + err = ipc_attach_dataspace(file->ref, file_span(file), (void **) &file->memory);
1.162 + if (err)
1.163 + return err;
1.164 +
1.165 + if (memory != NULL)
1.166 + ipc_detach_dataspace(memory);
1.167 +
1.168 + return L4_EOK;
1.169 +}
1.170 +
1.171 +/* Resize a file, obtaining updated file size and populated data details. */
1.172
1.173 long file_resize(file_t *file, offset_t size)
1.174 {
1.175 @@ -142,21 +205,12 @@
1.176 offset_t file_size = size;
1.177 long err = _file.resize(&file_size);
1.178
1.179 - if (!err)
1.180 - {
1.181 - /* Determine the extent of the file in this region. */
1.182 + if (err)
1.183 + return err;
1.184
1.185 - if (file_size > file->end_pos)
1.186 - file->data_end = file_span(file);
1.187 - else
1.188 - file->data_end = file_size - file->start_pos;
1.189 -
1.190 - /* Update the file size locally. */
1.191 -
1.192 - file->size = file_size;
1.193 - }
1.194 -
1.195 - return err;
1.196 + file->size = file_size;
1.197 + _update_extent(file);
1.198 + return L4_EOK;
1.199 }
1.200
1.201
1.202 @@ -236,6 +290,72 @@
1.203
1.204
1.205
1.206 +/* Return the number of remaining populated bytes in the region. */
1.207 +
1.208 +offset_t file_data_available(file_t *file)
1.209 +{
1.210 + return file_populated_span(file) - file->data_current;
1.211 +}
1.212 +
1.213 +/* Return the current data offset in the region. */
1.214 +
1.215 +char *file_data_current(file_t *file)
1.216 +{
1.217 + return file->memory + file->data_current;
1.218 +}
1.219 +
1.220 +/* Return the current access position in the file. */
1.221 +
1.222 +offset_t file_data_current_position(file_t *file)
1.223 +{
1.224 + return file->start_pos + file->data_current;
1.225 +}
1.226 +
1.227 +/* Return the position of the end of the populated bytes in the region. */
1.228 +
1.229 +offset_t file_data_end_position(file_t *file)
1.230 +{
1.231 + return file->start_pos + file->data_end;
1.232 +}
1.233 +
1.234 +/* Return the amount of remaining space in the region. */
1.235 +
1.236 +offset_t file_data_space(file_t *file)
1.237 +{
1.238 + return file_span(file) - file->data_current;
1.239 +}
1.240 +
1.241 +
1.242 +
1.243 +/* Copy data to the given buffer from the current data position, updating the
1.244 + position. */
1.245 +
1.246 +void file_data_read(file_t *file, char *buf, size_t to_transfer)
1.247 +{
1.248 + memcpy(buf, file_data_current(file), to_transfer);
1.249 +
1.250 + /* Update position details. */
1.251 +
1.252 + file->data_current += to_transfer;
1.253 +}
1.254 +
1.255 +/* Copy data from the given buffer to the current data position, updating the
1.256 + position and the extent of populated data if this was exceeded. */
1.257 +
1.258 +void file_data_write(file_t *file, char *buf, size_t to_transfer)
1.259 +{
1.260 + memcpy(file_data_current(file), buf, to_transfer);
1.261 +
1.262 + /* Update position details. */
1.263 +
1.264 + file->data_current += to_transfer;
1.265 +
1.266 + if (file->data_current > file->data_end)
1.267 + file->data_end = file->data_current;
1.268 +}
1.269 +
1.270 +
1.271 +
1.272 /* Open two pipe endpoints using the given pipe server. */
1.273
1.274 long pipe_open(offset_t size, file_t *reader, file_t *writer, l4_cap_idx_t server)
1.275 @@ -248,6 +368,11 @@
1.276 file_init(reader);
1.277 file_init(writer);
1.278
1.279 + /* Pipes can usually only be accessed via region navigation. */
1.280 +
1.281 + reader->can_mmap = 0;
1.282 + writer->can_mmap = 0;
1.283 +
1.284 long err = opener.pipe(size, &reader->ref, &writer->ref);
1.285 if (err)
1.286 return err;