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 To test whether the file was successfully open, the following function should 63 be invoked, this returning a true (non-zero) value if the file was 64 successfully opened: 65 66 {{{ 67 int client_opened(file_t *file); 68 }}} 69 70 Each file should be closed using `client_close` regardless of whether the file 71 was successfully opened. 72 73 ==== Example ==== 74 75 {{{ 76 file_t *file = client_open("somefile", O_RDONLY); 77 78 if (client_opened(file)) 79 { 80 /* Perform operations on file. */ 81 } 82 83 client_close(file); 84 }}} 85 86 === Pipes === 87 88 Pipes are opened using a special function returning an error code, setting the 89 supplied reader and writer endpoint parameters: 90 91 {{{ 92 long client_pipe(file_t **reader, file_t **writer, flags_t flags); 93 }}} 94 95 Each returned pipe endpoint may be closed using `client_close`. If an error 96 condition is reported using a non-zero value, the endpoints will not be 97 retained and will therefore not need to be closed: the error condition is 98 communicated purely via the return value. 99 100 ==== Example ==== 101 102 {{{ 103 file_t *reader, *writer; 104 105 if (!client_pipe(&reader, &writer, 0)) 106 { 107 /* Perform operations on pipe. */ 108 } 109 110 client_close(reader); 111 client_close(writer); 112 }}} 113 114 === Closing Files and Pipes === 115 116 Closing files and pipes involves a common operation: 117 118 {{{ 119 void client_close(file_t *file); 120 }}} 121 122 When client programs terminate, the freeing of their object capabilities 123 should cause the closure of files and pipes, but programs may choose to close 124 such resources explicitly. 125 126 === Reading and Writing === 127 128 Reading and writing files and pipes involves functions resembling the 129 traditional low-level `read` and `write` functions: 130 131 {{{ 132 offset_t client_read(file_t *file, void *buf, offset_t count); 133 offset_t client_write(file_t *file, const void *buf, offset_t count); 134 }}} 135 136 === Navigation in Files === 137 138 Support for navigation in files is provided using functions resembling the 139 traditional higher-level `fseek` and `ftell` functions: 140 141 {{{ 142 offset_t client_seek(file_t *file, offset_t offset, int whence); 143 long client_tell(file_t *file); 144 }}} 145 146 === Accessing Exposed Memory Regions === 147 148 Although the client library (and the provision of files) employs mapped 149 memory, a function can be used to explicitly reference memory for file access: 150 151 {{{ 152 void *client_mmap(file_t *file, offset_t position, offset_t length, 153 offset_t start_visible, offset_t end_visible, 154 l4re_rm_flags_t region_flags); 155 }}} 156 157 Here, a portion of the indicated `file` is exposed in a memory region, with 158 the memory region corresponding to the contents of the file starting at the 159 given `position` in the file and having a span of the given `length` in bytes. 160 161 Additional parameters control masking of the file content. If `start_visible` 162 and `end_visible` are both non-zero, then they indicate a visible span in the 163 file. Such limits are applied to the mapped region, with locations 164 corresponding to positions before `start_visible` and positions after 165 `end_visible` yielding zero byte values. 166 167 The `region_flags` indicate the memory access properties of the mapped region 168 in the task obtaining it. For example, where a region will be populated with 169 code, the `L4RE_DS_F_RX` flag would be appropriate, this indicating that the 170 region will be read and also have its contents run or executed. 171 172 '''Note:''' Currently, when masking is applied to a file, any write operations 173 will cause the modified memory to be copied and modified, as opposed to 174 causing modifications to the underlying file content. This behaviour may 175 eventually be more configurable. 176 177 === Accessing Pipe Content in Memory Regions === 178 179 Pipes support a different mechanism for navigation involving the following 180 functions: 181 182 {{{ 183 long client_current_region(file_t *file); 184 long client_next_region(file_t *file); 185 }}} 186 187 Such navigation functions for files and pipes do not need to be used where the 188 higher-level reading, writing and seeking functions are in use. 189 190 === Flushing and Synchronisation === 191 192 For synchronisation purposes, either with the filesystem itself or with other 193 users of the filesystem, a function resembling the traditional `fflush` 194 function is provided: 195 196 {{{ 197 long client_flush(file_t *file); 198 }}} 199 200 This updates the file data structure with new details of the file size, also 201 updating any altered details of the extent of the data in the currently 202 accessed region of the file. 203 204 === Notifications === 205 206 Since files and pipes may be accessed by multiple clients, this being of 207 particular significance for any real use of pipes, notifications can be 208 configured to communicate a change in state to other users of these resources 209 when they are accessed. Directories can also be monitored using notifications. 210 211 Notification types are specified using values encoding a number of flags, and 212 the following flags are available for this purpose: 213 214 || '''Flag''' || '''Notification Type''' || 215 || `NOTIFY_CONTENT_AVAILABLE` || Content available to read || 216 || `NOTIFY_FILE_OPENED` || File opened in directory || 217 || `NOTIFY_PEER_CLOSED` || Other party has closed their endpoint || 218 || `NOTIFY_SPACE_AVAILABLE` || Space available for writing || 219 220 The delivery of notifications is requested by subscribing to notifications for 221 a given resource via a notifier object: 222 223 {{{ 224 long client_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier); 225 }}} 226 227 A notifier object can be common throughout all threads in a task, being 228 obtained using the following function: 229 230 {{{ 231 file_notifier_t *client_notifier_task(); 232 }}} 233 234 Alternatively, a local notifier can be created for use within a thread: 235 236 {{{ 237 file_notifier_t *client_notifier_local(); 238 }}} 239 240 Local notifiers must be closed when they are no longer needed: 241 242 {{{ 243 void client_notifier_close(file_notifier_t *notifier); 244 }}} 245 246 When notifications are no longer needed, an unsubscribe operation can be 247 invoked: 248 249 {{{ 250 long client_unsubscribe(file_t *file, file_notifier_t *notifier); 251 }}} 252 253 ==== Example ==== 254 255 {{{ 256 file_notifier_t *notifier = client_notifier_local(); 257 file_t *directory = client_open(filename, O_DIRECTORY); 258 259 if (client_opened(directory)) 260 { 261 if (!client_subscribe(directory, NOTIFY_FILE_OPENED, notifier)) 262 { 263 if (!client_wait_file(directory, notifier)) 264 { 265 /* File opened in directory. */ 266 } 267 } 268 } 269 270 client_close(directory); 271 client_notifier_close(notifier); 272 }}} 273 274 === Blocking Operations === 275 276 Reading and writing operations can be configured to block if data cannot be 277 read or written respectively. The following function is provided for this 278 purpose: 279 280 {{{ 281 long client_set_blocking(file_t *file, notify_flags_t flags); 282 }}} 283 284 For pipes, blocking behaviour is the default and must be disabled explicitly, 285 either by opening using the `O_NONBLOCK` flag or by calling 286 `client_set_blocking` with no flags set. 287 288 Blocking behaviour is supported using the notification functionality. When 289 access to a file or pipe cannot be satisfied for a particular operation, such 290 as reading not being able to yield more content or writing not being able to 291 submit more content, the task-level notifier will be used to wait for 292 notifications applicable to the file or pipe involved. Consequently, the 293 access will effectively block until notifications are delivered indicating 294 that the state of the file or pipe has changed, and until it is determined 295 that the change of state will allow the operation to proceed successfully.