1 = Client Library = 2 3 The filesystem client library offers abstractions and a number of layers of 4 functionality to support interaction with [[Components|components]] and the 5 provision of higher-level mechanisms and abstractions for file access. In 6 particular, the client library is intended for use by a conventional C 7 library, with the functions in the C library invoking client library functions 8 and employing client library structures internally. 9 10 The client library is provided by [[Libraries#libfsclient|`libfsclient`]] 11 within the `departure` package. 12 13 <<TableOfContents(2,3)>> 14 15 == Header Files == 16 17 The following header files are pertinent to client library usage: 18 19 || '''File''' || '''Description''' || 20 || `fsclient/client.h` || Client functions and data structures || 21 || `systypes/fcntl.h` || Flag values for opening operations || 22 23 == File Data Structures == 24 25 Since files are accessed using file references, the `file_t` data structure is 26 used to wrap such references and other relevant state. Thus, such structures 27 can be broadly regarded as similar to the traditional `FILE` data structure. 28 29 The members of the `file_t` data structure are as follows: 30 31 || '''Member''' || '''Description''' || 32 || `ref` || A reference to the component providing file content || 33 || `memory` || The memory address of the exposed file region || 34 || `start_pos` || The start position of the region in the file || 35 || `end_pos` || The end position of the region in the file || 36 || `data_end` || The amount or extent of populated data in the region || 37 || `data_current` || The offset used to track client position in the region || 38 || `size` || The total size of the file || 39 || `object_flags` || Flags indicating support for certain file features || 40 || `can_block` || Notification flags for blocking access to the file || 41 || `notifications`|| Notification flags set for the file || 42 || `flags` || The flags used to open the file || 43 || `error` || Any failure or error condition on the file || 44 45 Generally, these members should not be accessed directly, mostly being 46 reserved for use by the client library itself. 47 48 == Client Programming Interface == 49 50 The client programming interface provides functions somewhat resembling the 51 traditional C library and low-level Unix interfaces for file access, and these 52 functions are intended to support such traditional interfaces. 53 54 === Files === 55 56 Files are opened using the following function returning a file data structure: 57 58 {{{ 59 file_t *client_open(const char *name, flags_t flags); 60 }}} 61 62 New instances of open files, employing potentially different flags, can be 63 obtained using the following function: 64 65 {{{ 66 file_t *client_reopen(file_t *file, flags_t flags); 67 }}} 68 69 To test whether the file was successfully open, the following function should 70 be invoked, this returning a true (non-zero) value if the file was 71 successfully opened: 72 73 {{{ 74 int client_opened(file_t *file); 75 }}} 76 77 Each file should be closed using `client_close` regardless of whether the file 78 was successfully opened. 79 80 ==== Example ==== 81 82 {{{ 83 file_t *file = client_open("somefile", O_RDONLY); 84 85 if (client_opened(file)) 86 { 87 /* Perform operations on file. */ 88 } 89 90 client_close(file); 91 }}} 92 93 === Pipes === 94 95 Pipes are opened using a special function returning an error code, setting the 96 supplied reader and writer endpoint parameters: 97 98 {{{ 99 long client_pipe(file_t **reader, file_t **writer, flags_t flags); 100 }}} 101 102 Each returned pipe endpoint may be closed using `client_close`. If an error 103 condition is reported using a non-zero value, the endpoints will not be 104 retained and will therefore not need to be closed: the error condition is 105 communicated purely via the return value. 106 107 ==== Example ==== 108 109 {{{ 110 file_t *reader, *writer; 111 112 if (!client_pipe(&reader, &writer, 0)) 113 { 114 /* Perform operations on pipe. */ 115 } 116 117 client_close(reader); 118 client_close(writer); 119 }}} 120 121 === Closing Files and Pipes === 122 123 Closing files and pipes involves a common operation: 124 125 {{{ 126 void client_close(file_t *file); 127 }}} 128 129 When client programs terminate, the freeing of their object capabilities 130 should cause the closure of files and pipes, but programs may choose to close 131 such resources explicitly. 132 133 === Reading and Writing === 134 135 Reading and writing files and pipes involves functions resembling the 136 traditional low-level `read` and `write` functions: 137 138 {{{ 139 offset_t client_read(file_t *file, void *buf, offset_t count); 140 offset_t client_write(file_t *file, const void *buf, offset_t count); 141 }}} 142 143 === Navigation in Files === 144 145 Support for navigation in files is provided using functions resembling the 146 traditional higher-level `fseek` and `ftell` functions: 147 148 {{{ 149 offset_t client_seek(file_t *file, offset_t offset, int whence); 150 long client_tell(file_t *file); 151 }}} 152 153 === Accessing Exposed Memory Regions === 154 155 Although the client library (and the provision of files) employs mapped 156 memory, a function can be used to explicitly reference memory for file access: 157 158 {{{ 159 void *client_mmap(file_t *file, offset_t position, offset_t length, 160 offset_t start_visible, offset_t end_visible, 161 l4re_rm_flags_t region_flags); 162 }}} 163 164 Here, a portion of the indicated `file` is exposed in a memory region, with 165 the memory region corresponding to the contents of the file starting at the 166 given `position` in the file and having a span of the given `length` in bytes. 167 168 Additional parameters control masking of the file content. If `start_visible` 169 and `end_visible` are both non-zero, then they indicate a visible span in the 170 file. Such limits are applied to the mapped region, with locations 171 corresponding to positions before `start_visible` and positions after 172 `end_visible` yielding zero byte values. 173 174 The `region_flags` indicate the memory access properties of the mapped region 175 in the task obtaining it. For example, where a region will be populated with 176 code, the `L4RE_DS_F_RX` flag would be appropriate, this indicating that the 177 region will be read and also have its contents run or executed. 178 179 '''Note:''' Currently, when masking is applied to a file, any write operations 180 will cause the modified memory to be copied and modified, as opposed to 181 causing modifications to the underlying file content. This behaviour may 182 eventually be more configurable. 183 184 === Accessing Pipe Content in Memory Regions === 185 186 Pipes support a different mechanism for navigation involving the following 187 functions: 188 189 {{{ 190 long client_current_region(file_t *file); 191 long client_next_region(file_t *file); 192 }}} 193 194 Such navigation functions for files and pipes do not need to be used where the 195 higher-level reading, writing and seeking functions are in use. 196 197 === Flushing and Synchronisation === 198 199 For synchronisation purposes, either with the filesystem itself or with other 200 users of the filesystem, a function resembling the traditional `fflush` 201 function is provided: 202 203 {{{ 204 long client_flush(file_t *file); 205 }}} 206 207 This updates the file data structure with new details of the file size, also 208 updating any altered details of the extent of the data in the currently 209 accessed region of the file. 210 211 === Notifications === 212 213 Since files and pipes may be accessed by multiple clients, this being of 214 particular significance for any real use of pipes, notifications can be 215 configured to communicate a change in state to other users of these resources 216 when they are accessed. Directories can also be monitored using notifications. 217 218 Notification types are specified using values encoding a number of flags, and 219 the following flags are available for this purpose: 220 221 || '''Flag''' || '''Notification Type''' || 222 || `NOTIFY_CONTENT_AVAILABLE` || Content available to read || 223 || `NOTIFY_FILE_OPENED` || File opened in directory || 224 || `NOTIFY_PEER_CLOSED` || Other party has closed their endpoint || 225 || `NOTIFY_SPACE_AVAILABLE` || Space available for writing || 226 227 The delivery of notifications is requested by subscribing to notifications for 228 a given resource via a notifier object: 229 230 {{{ 231 long client_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier); 232 }}} 233 234 A notifier object can be common throughout all threads in a task, being 235 obtained using the following function: 236 237 {{{ 238 file_notifier_t *client_notifier_task(); 239 }}} 240 241 Alternatively, a local notifier can be created for use within a thread: 242 243 {{{ 244 file_notifier_t *client_notifier_local(); 245 }}} 246 247 Local notifiers must be closed when they are no longer needed: 248 249 {{{ 250 void client_notifier_close(file_notifier_t *notifier); 251 }}} 252 253 When notifications are no longer needed, an unsubscribe operation can be 254 invoked: 255 256 {{{ 257 long client_unsubscribe(file_t *file, file_notifier_t *notifier); 258 }}} 259 260 ==== Example ==== 261 262 {{{ 263 file_notifier_t *notifier = client_notifier_local(); 264 file_t *directory = client_open(filename, O_DIRECTORY); 265 266 if (client_opened(directory)) 267 { 268 if (!client_subscribe(directory, NOTIFY_FILE_OPENED, notifier)) 269 { 270 if (!client_wait_file(directory, notifier)) 271 { 272 /* File opened in directory. */ 273 } 274 } 275 } 276 277 client_close(directory); 278 client_notifier_close(notifier); 279 }}} 280 281 === Blocking Operations === 282 283 Reading and writing operations can be configured to block if data cannot be 284 read or written respectively. The following function is provided for this 285 purpose: 286 287 {{{ 288 long client_set_blocking(file_t *file, notify_flags_t flags); 289 }}} 290 291 For pipes, blocking behaviour is the default and must be disabled explicitly, 292 either by opening using the `O_NONBLOCK` flag or by calling 293 `client_set_blocking` with no flags set. 294 295 Blocking behaviour is supported using the notification functionality. When 296 access to a file or pipe cannot be satisfied for a particular operation, such 297 as reading not being able to yield more content or writing not being able to 298 submit more content, the task-level notifier will be used to wait for 299 notifications applicable to the file or pipe involved. Consequently, the 300 access will effectively block until notifications are delivered indicating 301 that the state of the file or pipe has changed, and until it is determined 302 that the change of state will allow the operation to proceed successfully.