1.1 --- a/docs/wiki/Files Sat Aug 28 00:27:23 2021 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,237 +0,0 @@
1.4 -= Files =
1.5 -
1.6 -Access to files is provided by a number of programs acting as components. For
1.7 -convenience, the component-level operations are wrapped up in a client library
1.8 -that aims to provide simpler, more familiar mechanisms for opening, reading,
1.9 -writing, and closing files, together with various other operations.
1.10 -
1.11 -<<TableOfContents(2,3)>>
1.12 -
1.13 -== Components ==
1.14 -
1.15 -At the lowest level in L4Re, files are accessed via a suite of components.
1.16 -These components are principally of interest to library developers since they
1.17 -only provide a limited level of abstraction.
1.18 -
1.19 -=== Filesystems ===
1.20 -
1.21 -Filesystems implement the `Filesystem` interface which provides the
1.22 -`open_for_user` operation:
1.23 -
1.24 -{{{
1.25 -open_for_user(in user_t user, out cap opener)
1.26 -}}}
1.27 -
1.28 -The operation yields a file opener appropriate for the given user credentials.
1.29 -
1.30 -=== File Openers ===
1.31 -
1.32 -File openers implement the `Opener` interface which provides the `context`
1.33 -operation:
1.34 -
1.35 -{{{
1.36 -context(out cap context)
1.37 -}}}
1.38 -
1.39 -Each client program, task or thread obtains its own context because it will
1.40 -need its own dedicated channel for communication with the filesystem.
1.41 -
1.42 -=== Contexts ===
1.43 -
1.44 -A context acts as a dataspace, meaning that it can be attached to a task using
1.45 -a region manager and provide a buffer via a region of mapped memory that the
1.46 -task can write to. In the case of a context, the task will write a filesystem
1.47 -path indicating the file to be opened.
1.48 -
1.49 -Each context allows a client program to request access to individual files via
1.50 -operations provided by the `OpenerContext` interface, of which the most
1.51 -pertinent is the `open` operation:
1.52 -
1.53 -{{{
1.54 -open(in flags_t flags, out offset_t size, out cap file,
1.55 - out object_flags_t object_flags)
1.56 -}}}
1.57 -
1.58 -Using the path information written to the context's memory region, the `open`
1.59 -operation will obtain a reference to a file-like object whose characteristics
1.60 -are described by the accompanying `object_flags`, these helping the client to
1.61 -distinguish between files that support arbitrary memory mapping operations and
1.62 -pipes that mandate sequential region-by-region access.
1.63 -
1.64 -Alongside regular files, directories may also be opened. Reading from them
1.65 -yields a listing of directory entries.
1.66 -
1.67 -=== Files ===
1.68 -
1.69 -Files themselves act as dataspaces, meaning that they can be attached to a
1.70 -task using a region manager and provide their content via a region of mapped
1.71 -memory. Files implement the `MappedFile` interface.
1.72 -
1.73 -Control over the region of the file provided via mapped memory occurs
1.74 -using the `mmap` operation:
1.75 -
1.76 -{{{
1.77 -mmap(in offset_t position, in offset_t length,
1.78 - out offset_t start_pos, out offset_t end_pos,
1.79 - out offset_t size)
1.80 -}}}
1.81 -
1.82 -Files also implement the more general `File` interface that provides the
1.83 -`resize` operation:
1.84 -
1.85 -{{{
1.86 -resize(inout offset_t size)
1.87 -}}}
1.88 -
1.89 -This allows the portion of the memory region dedicated to the file's contents
1.90 -to be extended.
1.91 -
1.92 -=== Directories ===
1.93 -
1.94 -Directories are also meant to be accessed like files, meaning that it should
1.95 -be possible to attach them to a task using a region manager and access the
1.96 -provided content, this being a listing of directory entries, via the mapped
1.97 -region.
1.98 -
1.99 -However, unlike files which may support arbitrary mapping of their contents,
1.100 -the provided content may be supplied by a pipe endpoint, thereby not
1.101 -supporting precisely the same navigation mechanisms as those supported by
1.102 -files.
1.103 -
1.104 -=== Pipe Openers ===
1.105 -
1.106 -Distinct from filesystems but potentially used by them, pipe openers provide a
1.107 -means of obtaining pipes, which are channels that support unidirectional
1.108 -communication via shared memory.
1.109 -
1.110 -Pipe openers implement the `PipeOpener` interface and support the following
1.111 -operation:
1.112 -
1.113 -{{{
1.114 -pipe(in offset_t size, out cap reader, out cap writer)
1.115 -}}}
1.116 -
1.117 -The size is indicated to request pipe regions long enough for the needs of the
1.118 -communicating parties, with both reader and writer endpoint capabilities being
1.119 -returned. Such capabilities may be propagated to the eventual parties, these
1.120 -typically being separate tasks.
1.121 -
1.122 -=== Pipes ===
1.123 -
1.124 -Although not generally obtained from filesystems, pipes may be involved in
1.125 -providing content from some filesystem objects such as directories. However,
1.126 -they are also obtained directly from an appropriate pipe server providing pipe
1.127 -opening facilities.
1.128 -
1.129 -Pipes expose single regions of shared memory to their endpoints, with the
1.130 -writing endpoint populating one region while the reading endpoint accesses the
1.131 -other. The reading endpoint may advance to the region being written, and this
1.132 -will free up a new region for the writer when it has filled its region. When
1.133 -the writer itself advances, it permits the reader to consume all data in the
1.134 -fully populated region. Naturally, the reader may not advance ahead of the
1.135 -writer.
1.136 -
1.137 -Pipes implement the `Pipe` interface and a number of operations to support
1.138 -this interaction mechanism.
1.139 -
1.140 -The details of an endpoint's current region can be queried using the following
1.141 -operation:
1.142 -
1.143 -{{{
1.144 -current_region(out offset_t populated_size, out offset_t size)
1.145 -}}}
1.146 -
1.147 -This provides details of the populated size (or amount of written data) in a
1.148 -region along with the size of the region.
1.149 -
1.150 -Navigation to the next available region of the pipe is performed using the
1.151 -following operation:
1.152 -
1.153 -{{{
1.154 -next_region(inout offset_t populated_size, out offset_t size)
1.155 -}}}
1.156 -
1.157 -Here, the populated size may be specified by the writer so that the reader may
1.158 -query the current region's properties using the appropriate operation.
1.159 -
1.160 -The status of the pipe can be queried using the `closed` operation:
1.161 -
1.162 -{{{
1.163 -closed(out int closed)
1.164 -}}}
1.165 -
1.166 -This indicates through a boolean-equivalent parameter whether one or both
1.167 -endpoints have been closed.
1.168 -
1.169 -== Libraries ==
1.170 -
1.171 -The filesystem client library offers abstractions and a number of layers of
1.172 -functionality to support interaction with components and the provision of
1.173 -higher-level mechanisms and abstractions for file access.
1.174 -
1.175 -=== Client Library ===
1.176 -
1.177 -The client library provides functions somewhat resembling the traditional C
1.178 -library and low-level Unix interfaces for file access, and these functions are
1.179 -intended to support such traditional interfaces.
1.180 -
1.181 -Since files are accessed using file references, the `file_t` data structure is
1.182 -used to wrap such references and other relevant state. Thus, such structures
1.183 -can be broadly regarded as similar to the traditional `FILE` data structure.
1.184 -
1.185 -Files are opened and closed using the following functions:
1.186 -
1.187 -{{{
1.188 -file_t *client_open(const char *name, flags_t flags);
1.189 -void client_close(file_t *file);
1.190 -}}}
1.191 -
1.192 -Pipes are opened using a special function:
1.193 -
1.194 -{{{
1.195 -long client_pipe(file_t **reader, file_t **writer, flags_t flags);
1.196 -}}}
1.197 -
1.198 -Each pipe endpoint may be closed using `client_close`.
1.199 -
1.200 -Reading and writing files and pipes involves functions resembling the
1.201 -traditional low-level `read` and `write` functions:
1.202 -
1.203 -{{{
1.204 -offset_t client_read(file_t *file, void *buf, offset_t count);
1.205 -offset_t client_write(file_t *file, const void *buf, offset_t count);
1.206 -}}}
1.207 -
1.208 -Support for navigation in files is provided using functions resembling the
1.209 -traditional higher-level `fseek` and `ftell` functions:
1.210 -
1.211 -{{{
1.212 -offset_t client_seek(file_t *file, offset_t offset, int whence);
1.213 -long client_tell(file_t *file);
1.214 -}}}
1.215 -
1.216 -Although the client library (and the provision of files) employs mapped
1.217 -memory, a function can be used to explicitly reference memory for file access:
1.218 -
1.219 -{{{
1.220 -void *client_mmap(file_t *file, offset_t position, offset_t length);
1.221 -}}}
1.222 -
1.223 -Pipes support a different mechanism for navigation involving the following
1.224 -functions:
1.225 -
1.226 -{{{
1.227 -long client_current_region(file_t *file);
1.228 -long client_next_region(file_t *file);
1.229 -}}}
1.230 -
1.231 -Such navigation functions for files and pipes do not need to be used where the
1.232 -higher-level reading, writing and seeking functions are in use.
1.233 -
1.234 -For synchronisation purposes, either with the filesystem itself or with other
1.235 -users of the filesystem, a function resembling the traditional `fflush`
1.236 -function is provided:
1.237 -
1.238 -{{{
1.239 -long client_flush(file_t *file);
1.240 -}}}