1 = Files = 2 3 Access to files is provided by a number of programs acting as components. For 4 convenience, the component-level operations are wrapped up in a client library 5 that aims to provide simpler, more familiar mechanisms for opening, reading, 6 writing, and closing files, together with various other operations. 7 8 <<TableOfContents(2,3)>> 9 10 == Components == 11 12 At the lowest level in L4Re, files are accessed via a suite of components. 13 These components are principally of interest to library developers since they 14 only provide a limited level of abstraction. 15 16 === Filesystems === 17 18 Filesystems implement the `Filesystem` interface which provides the 19 `open_for_user` operation: 20 21 {{{ 22 open_for_user(in user_t user, out cap opener) 23 }}} 24 25 The operation yields a file opener appropriate for the given user credentials. 26 27 === File Openers === 28 29 File openers implement the `Opener` interface which provides the `context` 30 operation: 31 32 {{{ 33 context(out cap context) 34 }}} 35 36 Each client program, task or thread obtains its own context because it will 37 need its own dedicated channel for communication with the filesystem. 38 39 === Contexts === 40 41 A context acts as a dataspace, meaning that it can be attached to a task using 42 a region manager and provide a buffer via a region of mapped memory that the 43 task can write to. In the case of a context, the task will write a filesystem 44 path indicating the file to be opened. 45 46 Each context allows a client program to request access to individual files via 47 operations provided by the `OpenerContext` interface, of which the most 48 pertinent is the `open` operation: 49 50 {{{ 51 open(in flags_t flags, out offset_t size, out cap file, 52 out object_flags_t object_flags) 53 }}} 54 55 Using the path information written to the context's memory region, the `open` 56 operation will obtain a reference to a file-like object whose characteristics 57 are described by the accompanying `object_flags`, these helping the client to 58 distinguish between files that support arbitrary memory mapping operations and 59 pipes that mandate sequential region-by-region access. 60 61 Alongside regular files, directories may also be opened. Reading from them 62 yields a listing of directory entries. 63 64 === Files === 65 66 Files themselves act as dataspaces, meaning that they can be attached to a 67 task using a region manager and provide their content via a region of mapped 68 memory. Files implement the `MappedFile` interface. 69 70 Control over the region of the file provided via mapped memory occurs 71 using the `mmap` operation: 72 73 {{{ 74 mmap(in offset_t position, in offset_t length, 75 out offset_t start_pos, out offset_t end_pos, 76 out offset_t size) 77 }}} 78 79 Files also implement the more general `File` interface that provides the 80 `resize` operation: 81 82 {{{ 83 resize(inout offset_t size) 84 }}} 85 86 This allows the portion of the memory region dedicated to the file's contents 87 to be extended. 88 89 === Directories === 90 91 Directories are also meant to be accessed like files, meaning that it should 92 be possible to attach them to a task using a region manager and access the 93 provided content, this being a listing of directory entries, via the mapped 94 region. 95 96 However, unlike files which may support arbitrary mapping of their contents, 97 the provided content may be supplied by a pipe endpoint, thereby not 98 supporting precisely the same navigation mechanisms as those supported by 99 files. 100 101 === Pipe Openers === 102 103 Distinct from filesystems but potentially used by them, pipe openers provide a 104 means of obtaining pipes, which are channels that support unidirectional 105 communication via shared memory. 106 107 Pipe openers implement the `PipeOpener` interface and support the following 108 operation: 109 110 {{{ 111 pipe(in offset_t size, out cap reader, out cap writer) 112 }}} 113 114 The size is indicated to request pipe regions long enough for the needs of the 115 communicating parties, with both reader and writer endpoint capabilities being 116 returned. Such capabilities may be propagated to the eventual parties, these 117 typically being separate tasks. 118 119 === Pipes === 120 121 Although not generally obtained from filesystems, pipes may be involved in 122 providing content from some filesystem objects such as directories. However, 123 they are also obtained directly from an appropriate pipe server providing pipe 124 opening facilities. 125 126 Pipes expose single regions of shared memory to their endpoints, with the 127 writing endpoint populating one region while the reading endpoint accesses the 128 other. The reading endpoint may advance to the region being written, and this 129 will free up a new region for the writer when it has filled its region. When 130 the writer itself advances, it permits the reader to consume all data in the 131 fully populated region. Naturally, the reader may not advance ahead of the 132 writer. 133 134 Pipes implement the `Pipe` interface and a number of operations to support 135 this interaction mechanism. 136 137 The details of an endpoint's current region can be queried using the following 138 operation: 139 140 {{{ 141 current_region(out offset_t populated_size, out offset_t size) 142 }}} 143 144 This provides details of the populated size (or amount of written data) in a 145 region along with the size of the region. 146 147 Navigation to the next available region of the pipe is performed using the 148 following operation: 149 150 {{{ 151 next_region(inout offset_t populated_size, out offset_t size) 152 }}} 153 154 Here, the populated size may be specified by the writer so that the reader may 155 query the current region's properties using the appropriate operation. 156 157 The status of the pipe can be queried using the `closed` operation: 158 159 {{{ 160 closed(out int closed) 161 }}} 162 163 This indicates through a boolean-equivalent parameter whether one or both 164 endpoints have been closed. 165 166 == Libraries == 167 168 The filesystem client library offers abstractions and a number of layers of 169 functionality to support interaction with components and the provision of 170 higher-level mechanisms and abstractions for file access. 171 172 === Client Library === 173 174 The client library provides functions somewhat resembling the traditional C 175 library and low-level Unix interfaces for file access, and these functions are 176 intended to support such traditional interfaces. 177 178 Since files are accessed using file references, the `file_t` data structure is 179 used to wrap such references and other relevant state. Thus, such structures 180 can be broadly regarded as similar to the traditional `FILE` data structure. 181 182 Files are opened and closed using the following functions: 183 184 {{{ 185 file_t *client_open(const char *name, flags_t flags); 186 void client_close(file_t *file); 187 }}} 188 189 Pipes are opened using a special function: 190 191 {{{ 192 long client_pipe(file_t **reader, file_t **writer, flags_t flags); 193 }}} 194 195 Each pipe endpoint may be closed using `client_close`. 196 197 Reading and writing files and pipes involves functions resembling the 198 traditional low-level `read` and `write` functions: 199 200 {{{ 201 offset_t client_read(file_t *file, void *buf, offset_t count); 202 offset_t client_write(file_t *file, const void *buf, offset_t count); 203 }}} 204 205 Support for navigation in files is provided using functions resembling the 206 traditional higher-level `fseek` and `ftell` functions: 207 208 {{{ 209 offset_t client_seek(file_t *file, offset_t offset, int whence); 210 long client_tell(file_t *file); 211 }}} 212 213 Although the client library (and the provision of files) employs mapped 214 memory, a function can be used to explicitly reference memory for file access: 215 216 {{{ 217 void *client_mmap(file_t *file, offset_t position, offset_t length); 218 }}} 219 220 Pipes support a different mechanism for navigation involving the following 221 functions: 222 223 {{{ 224 long client_current_region(file_t *file); 225 long client_next_region(file_t *file); 226 }}} 227 228 Such navigation functions for files and pipes do not need to be used where the 229 higher-level reading, writing and seeking functions are in use. 230 231 For synchronisation purposes, either with the filesystem itself or with other 232 users of the filesystem, a function resembling the traditional `fflush` 233 function is provided: 234 235 {{{ 236 long client_flush(file_t *file); 237 }}}