1 /* 2 * This file Copyright (C) 2013-2017 Mnemosyne LLC 3 * 4 * It may be used under the GNU GPL versions 2 or 3 5 * or any future license endorsed by Mnemosyne LLC. 6 * 7 */ 8 9 #pragma once 10 11 #include <inttypes.h> 12 #include <time.h> 13 14 #ifdef _WIN32 15 #include <windows.h> 16 #endif 17 18 #ifdef __cplusplus 19 extern "C" 20 { 21 #endif 22 23 struct tr_error; 24 25 /** 26 * @addtogroup file_io File IO 27 * @{ 28 */ 29 30 #ifndef _WIN32 31 32 /** @brief Platform-specific file descriptor type. */ 33 typedef int tr_sys_file_t; 34 /** @brief Platform-specific invalid file descriptor constant. */ 35 #define TR_BAD_SYS_FILE (-1) 36 /** @brief Platform-specific directory descriptor type. */ 37 typedef void* tr_sys_dir_t; 38 /** @brief Platform-specific end-of-line sequence. */ 39 #define TR_NATIVE_EOL_STR "\n" 40 /** @brief Platform-specific end-of-line sequence length. */ 41 #define TR_NATIVE_EOL_STR_SIZE 1 42 43 #else 44 45 typedef HANDLE tr_sys_file_t; 46 #define TR_BAD_SYS_FILE INVALID_HANDLE_VALUE 47 typedef struct tr_sys_dir_win32* tr_sys_dir_t; 48 #define TR_NATIVE_EOL_STR "\r\n" 49 #define TR_NATIVE_EOL_STR_SIZE 2 50 51 #endif 52 53 /** @brief Platform-specific invalid directory descriptor constant. */ 54 #define TR_BAD_SYS_DIR ((tr_sys_dir_t)NULL) 55 56 typedef enum 57 { 58 TR_STD_SYS_FILE_IN, 59 TR_STD_SYS_FILE_OUT, 60 TR_STD_SYS_FILE_ERR 61 } 62 tr_std_sys_file_t; 63 64 typedef enum 65 { 66 TR_SYS_FILE_READ = (1 << 0), 67 TR_SYS_FILE_WRITE = (1 << 1), 68 TR_SYS_FILE_CREATE = (1 << 2), 69 TR_SYS_FILE_CREATE_NEW = (1 << 3), 70 TR_SYS_FILE_APPEND = (1 << 4), 71 TR_SYS_FILE_TRUNCATE = (1 << 5), 72 TR_SYS_FILE_SEQUENTIAL = (1 << 6) 73 } 74 tr_sys_file_open_flags_t; 75 76 typedef enum 77 { 78 TR_SEEK_SET, 79 TR_SEEK_CUR, 80 TR_SEEK_END 81 } 82 tr_seek_origin_t; 83 84 typedef enum 85 { 86 TR_SYS_FILE_LOCK_SH = (1 << 0), 87 TR_SYS_FILE_LOCK_EX = (1 << 1), 88 TR_SYS_FILE_LOCK_NB = (1 << 2), 89 TR_SYS_FILE_LOCK_UN = (1 << 3) 90 } 91 tr_sys_file_lock_flags_t; 92 93 typedef enum 94 { 95 TR_SYS_PATH_NO_FOLLOW = (1 << 0) 96 } 97 tr_sys_path_get_info_flags_t; 98 99 typedef enum 100 { 101 TR_SYS_FILE_ADVICE_WILL_NEED, 102 TR_SYS_FILE_ADVICE_DONT_NEED 103 } 104 tr_sys_file_advice_t; 105 106 typedef enum 107 { 108 TR_SYS_FILE_PREALLOC_SPARSE = (1 << 0) 109 } 110 tr_sys_file_preallocate_flags_t; 111 112 typedef enum 113 { 114 TR_SYS_DIR_CREATE_PARENTS = (1 << 0) 115 } 116 tr_sys_dir_create_flags_t; 117 118 typedef enum 119 { 120 TR_SYS_PATH_IS_FILE, 121 TR_SYS_PATH_IS_DIRECTORY, 122 TR_SYS_PATH_IS_OTHER 123 } 124 tr_sys_path_type_t; 125 126 typedef struct tr_sys_path_info 127 { 128 tr_sys_path_type_t type; 129 uint64_t size; 130 time_t last_modified_at; 131 } 132 tr_sys_path_info; 133 134 /** 135 * @name Platform-specific wrapper functions 136 * 137 * Following functions accept paths in UTF-8 encoding and convert them to native 138 * encoding internally if needed. 139 * Descriptors returned (@ref tr_sys_file_t and @ref tr_sys_dir_t) may have 140 * different type depending on platform and should generally not be passed to 141 * native functions, but to wrapper functions instead. 142 * 143 * @{ 144 */ 145 146 /* Path-related wrappers */ 147 148 /** 149 * @brief Portability wrapper for `stat()`. 150 * 151 * @param[in] path Path to file or directory. 152 * @param[in] flags Combination of @ref tr_sys_path_get_info_flags_t values. 153 * @param[out] info Result buffer. 154 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 155 * not interested in error details. 156 * 157 * @return `True` on success, `false` otherwise (with `error` set accordingly). 158 */ 159 bool tr_sys_path_get_info(char const* path, int flags, tr_sys_path_info* info, struct tr_error** error); 160 161 /** 162 * @brief Portability wrapper for `access()`. 163 * 164 * @param[in] path Path to file or directory. 165 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 166 * not interested in error details. 167 * 168 * @return `True` if path exists, `false` otherwise. Note that `false` will also 169 * be returned in case of error; if you need to distinguish the two, 170 * check if `error` is `NULL` afterwards. 171 */ 172 bool tr_sys_path_exists(char const* path, struct tr_error** error); 173 174 /** 175 * @brief Check whether path is relative. 176 * 177 * This function only analyzes the string, so no error reporting is needed. 178 * 179 * @param[in] path Path to file or directory. 180 * 181 * @return `True` if path is relative, `false` otherwise 182 */ 183 bool tr_sys_path_is_relative(char const* path); 184 185 /** 186 * @brief Test to see if the two filenames point to the same file. 187 * 188 * @param[in] path1 Path to first file or directory. 189 * @param[in] path2 Path to second file or directory. 190 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 191 * not interested in error details. 192 * 193 * @return `True` if two paths point to the same file or directory, `false` 194 * otherwise. Note that `false` will also be returned in case of error; 195 * if you need to distinguish the two, check if `error` is `NULL` 196 * afterwards. 197 */ 198 bool tr_sys_path_is_same(char const* path1, char const* path2, struct tr_error** error); 199 200 /** 201 * @brief Portability wrapper for `realpath()`. 202 * 203 * @param[in] path Path to file or directory. 204 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 205 * not interested in error details. 206 * 207 * @return Pointer to newly allocated buffer containing full path (with symbolic 208 * links, `.` and `..` resolved) on success (use @ref tr_free to free it 209 * when no longer needed), `NULL` otherwise (with `error` set 210 * accordingly). 211 */ 212 char* tr_sys_path_resolve(char const* path, struct tr_error** error); 213 214 /** 215 * @brief Portability wrapper for `basename()`. 216 * 217 * @param[in] path Path to file or directory. 218 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 219 * not interested in error details. 220 * 221 * @return Pointer to newly allocated buffer containing base name (last path 222 * component; parent path removed) on success (use @ref tr_free to free 223 * it when no longer needed), `NULL` otherwise (with `error` set 224 * accordingly). 225 */ 226 char* tr_sys_path_basename(char const* path, struct tr_error** error); 227 228 /** 229 * @brief Portability wrapper for `dirname()`. 230 * 231 * @param[in] path Path to file or directory. 232 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 233 * not interested in error details. 234 * 235 * @return Pointer to newly allocated buffer containing directory (parent path; 236 * last path component removed) on success (use @ref tr_free to free it 237 * when no longer needed), `NULL` otherwise (with `error` set 238 * accordingly). 239 */ 240 char* tr_sys_path_dirname(char const* path, struct tr_error** error); 241 242 /** 243 * @brief Portability wrapper for `rename()`. 244 * 245 * @param[in] src_path Path to source file or directory. 246 * @param[in] dst_path Path to destination file or directory. 247 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 248 * are not interested in error details. 249 * 250 * @return `True` on success, `false` otherwise (with `error` set accordingly). 251 * Rename will generally only succeed if both source and destination are 252 * on the same partition. 253 */ 254 bool tr_sys_path_rename(char const* src_path, char const* dst_path, struct tr_error** error); 255 256 /** 257 * @brief Portability wrapper for `remove()`. 258 * 259 * @param[in] path Path to file or directory. 260 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 261 * not interested in error details. 262 * 263 * @return `True` on success, `false` otherwise (with `error` set accordingly). 264 * Directory removal will only succeed if it is empty (contains no other 265 * files and directories). 266 */ 267 bool tr_sys_path_remove(char const* path, struct tr_error** error); 268 269 /** 270 * @brief Transform path separators to native ones, in-place. 271 * 272 * @param[in,out] path Path to transform. 273 * 274 * @return Same path but with native (and uniform) separators. 275 */ 276 char* tr_sys_path_native_separators(char* path); 277 278 /* File-related wrappers */ 279 280 /** 281 * @brief Get handle to one of standard I/O files. 282 * 283 * @param[in] std_file Standard file identifier. 284 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 285 * are not interested in error details. 286 * 287 * @return Opened file descriptor on success, `TR_BAD_SYS_FILE` otherwise (with 288 * `error` set accordingly). DO NOT pass this descriptor to 289 * @ref tr_sys_file_close (unless you know what you are doing). 290 */ 291 tr_sys_file_t tr_sys_file_get_std(tr_std_sys_file_t std_file, struct tr_error** error); 292 293 /** 294 * @brief Portability wrapper for `open()`. 295 * 296 * @param[in] path Path to file. 297 * @param[in] flags Combination of @ref tr_sys_file_open_flags_t values. 298 * @param[in] permissions Permissions to create file with (in case 299 @ref TR_SYS_FILE_CREATE is used). Not used on Windows. 300 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 301 * are not interested in error details. 302 * 303 * @return Opened file descriptor on success, `TR_BAD_SYS_FILE` otherwise (with 304 * `error` set accordingly). 305 */ 306 tr_sys_file_t tr_sys_file_open(char const* path, int flags, int permissions, struct tr_error** error); 307 308 /** 309 * @brief Portability wrapper for `mkstemp()`. 310 * 311 * @param[in,out] path_template Template path to file. Should end with at least 312 * six 'X' characters. Upon success, trailing 'X' 313 * characters are replaced with actual random 314 * characters used to form a unique path to 315 * temporary file. 316 * @param[out] error Pointer to error object. Optional, pass `NULL` 317 * if you are not interested in error details. 318 * 319 * @return Opened file descriptor on success, `TR_BAD_SYS_FILE` otherwise (with 320 * `error` set accordingly). 321 */ 322 tr_sys_file_t tr_sys_file_open_temp(char* path_template, struct tr_error** error); 323 324 /** 325 * @brief Portability wrapper for `close()`. 326 * 327 * @param[in] handle Valid file descriptor. 328 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 329 * not interested in error details. 330 * 331 * @return `True` on success, `false` otherwise (with `error` set accordingly). 332 */ 333 bool tr_sys_file_close(tr_sys_file_t handle, struct tr_error** error); 334 335 /** 336 * @brief Portability wrapper for `fstat()`. 337 * 338 * @param[in] handle Valid file descriptor. 339 * @param[out] info Result buffer. 340 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 341 * not interested in error details. 342 * 343 * @return `True` on success, `false` otherwise (with `error` set accordingly). 344 */ 345 bool tr_sys_file_get_info(tr_sys_file_t handle, tr_sys_path_info* info, struct tr_error** error); 346 347 /** 348 * @brief Portability wrapper for `lseek()`. 349 * 350 * @param[in] handle Valid file descriptor. 351 * @param[in] offset Relative file offset in bytes to seek to. 352 * @param[in] origin Offset origin. 353 * @param[out] new_offset New offset in bytes from beginning of file. Optional, 354 * pass `NULL` if you are not interested. 355 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 356 * are not interested in error details. 357 * 358 * @return `True` on success, `false` otherwise (with `error` set accordingly). 359 */ 360 bool tr_sys_file_seek(tr_sys_file_t handle, int64_t offset, tr_seek_origin_t origin, uint64_t* new_offset, 361 struct tr_error** error); 362 363 /** 364 * @brief Portability wrapper for `read()`. 365 * 366 * @param[in] handle Valid file descriptor. 367 * @param[out] buffer Buffer to store read data to. 368 * @param[in] size Number of bytes to read. 369 * @param[out] bytes_read Number of bytes actually read. Optional, pass `NULL` 370 * if you are not interested. 371 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 372 * are not interested in error details. 373 * 374 * @return `True` on success, `false` otherwise (with `error` set accordingly). 375 */ 376 bool tr_sys_file_read(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_t* bytes_read, struct tr_error** error); 377 378 /** 379 * @brief Like `pread()`, except that the position is undefined afterwards. 380 * Not thread-safe. 381 * 382 * @param[in] handle Valid file descriptor. 383 * @param[out] buffer Buffer to store read data to. 384 * @param[in] size Number of bytes to read. 385 * @param[in] offset File offset in bytes to start reading from. 386 * @param[out] bytes_read Number of bytes actually read. Optional, pass `NULL` 387 * if you are not interested. 388 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 389 * are not interested in error details. 390 * 391 * @return `True` on success, `false` otherwise (with `error` set accordingly). 392 */ 393 bool tr_sys_file_read_at(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_read, 394 struct tr_error** error); 395 396 /** 397 * @brief Portability wrapper for `write()`. 398 * 399 * @param[in] handle Valid file descriptor. 400 * @param[in] buffer Buffer to get data being written from. 401 * @param[in] size Number of bytes to write. 402 * @param[out] bytes_written Number of bytes actually written. Optional, pass 403 * `NULL` if you are not interested. 404 * @param[out] error Pointer to error object. Optional, pass `NULL` if 405 * you are not interested in error details. 406 * 407 * @return `True` on success, `false` otherwise (with `error` set accordingly). 408 */ 409 bool tr_sys_file_write(tr_sys_file_t handle, void const* buffer, uint64_t size, uint64_t* bytes_written, 410 struct tr_error** error); 411 412 /** 413 * @brief Like `pwrite()`, except that the position is undefined afterwards. 414 * Not thread-safe. 415 * 416 * @param[in] handle Valid file descriptor. 417 * @param[in] buffer Buffer to get data being written from. 418 * @param[in] size Number of bytes to write. 419 * @param[in] offset File offset in bytes to start writing from. 420 * @param[out] bytes_written Number of bytes actually written. Optional, pass 421 * `NULL` if you are not interested. 422 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 423 * are not interested in error details. 424 * 425 * @return `True` on success, `false` otherwise (with `error` set accordingly). 426 */ 427 bool tr_sys_file_write_at(tr_sys_file_t handle, void const* buffer, uint64_t size, uint64_t offset, uint64_t* bytes_written, 428 struct tr_error** error); 429 430 /** 431 * @brief Portability wrapper for `fsync()`. 432 * 433 * @param[in] handle Valid file descriptor. 434 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 435 * not interested in error details. 436 * 437 * @return `True` on success, `false` otherwise (with `error` set accordingly). 438 */ 439 bool tr_sys_file_flush(tr_sys_file_t handle, struct tr_error** error); 440 441 /** 442 * @brief Portability wrapper for `ftruncate()`. 443 * 444 * @param[in] handle Valid file descriptor. 445 * @param[in] size Number of bytes to truncate (or extend) file to. 446 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 447 * not interested in error details. 448 * 449 * @return `True` on success, `false` otherwise (with `error` set accordingly). 450 */ 451 bool tr_sys_file_truncate(tr_sys_file_t handle, uint64_t size, struct tr_error** error); 452 453 /** 454 * @brief Tell system to prefetch or discard some part of file which is [not] to be read soon. 455 * 456 * @param[in] handle Valid file descriptor. 457 * @param[in] offset Offset in file to prefetch from. 458 * @param[in] size Number of bytes to prefetch. 459 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 460 * not interested in error details. 461 * 462 * @return `True` on success, `false` otherwise (with `error` set accordingly). 463 */ 464 bool tr_sys_file_advise(tr_sys_file_t handle, uint64_t offset, uint64_t size, tr_sys_file_advice_t advice, 465 struct tr_error** error); 466 467 /** 468 * @brief Preallocate file to specified size in full or sparse mode. 469 * 470 * @param[in] handle Valid file descriptor. 471 * @param[in] size Number of bytes to preallocate file to. 472 * @param[in] flags Combination of @ref tr_sys_file_preallocate_flags_t values. 473 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 474 * not interested in error details. 475 * 476 * @return `True` on success, `false` otherwise (with `error` set accordingly). 477 */ 478 bool tr_sys_file_preallocate(tr_sys_file_t handle, uint64_t size, int flags, struct tr_error** error); 479 480 /** 481 * @brief Portability wrapper for `mmap()` for files. 482 * 483 * @param[in] handle Valid file descriptor. 484 * @param[in] offset Offset in file to map from. 485 * @param[in] size Number of bytes to map. 486 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 487 * not interested in error details. 488 * 489 * @return Pointer to mapped file data on success, `NULL` otherwise (with 490 * `error` set accordingly). 491 */ 492 void* tr_sys_file_map_for_reading(tr_sys_file_t handle, uint64_t offset, uint64_t size, struct tr_error** error); 493 494 /** 495 * @brief Portability wrapper for `munmap()` for files. 496 * 497 * @param[in] address Pointer to mapped file data. 498 * @param[in] size Size of mapped data in bytes. 499 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 500 * not interested in error details. 501 * 502 * @return `True` on success, `false` otherwise (with `error` set accordingly). 503 */ 504 bool tr_sys_file_unmap(void const* address, uint64_t size, struct tr_error** error); 505 506 /** 507 * @brief Portability wrapper for `flock()`. 508 * 509 * Don't try to upgrade or downgrade the lock unless you know what you are 510 * doing, as behavior varies a bit between platforms. 511 * 512 * @param[in] handle Valid file descriptor. 513 * @param[in] operation Combination of @ref tr_sys_file_lock_flags_t values. 514 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 515 * are not interested in error details. 516 * 517 * @return `True` on success, `false` otherwise (with `error` set accordingly). 518 */ 519 bool tr_sys_file_lock(tr_sys_file_t handle, int operation, struct tr_error** error); 520 521 /* File-related wrappers (utility) */ 522 523 /** 524 * @brief Portability wrapper for `fgets()`, removing EOL internally. 525 * 526 * Special care should be taken when reading from one of standard input streams 527 * (@ref tr_std_sys_file_t) since no UTF-8 conversion is currently being made. 528 * 529 * Reading from other streams (files, pipes) also leaves data untouched, so it 530 * should already be in UTF-8 encoding, or whichever else you expect. 531 * 532 * @param[in] handle Valid file descriptor. 533 * @param[out] buffer Buffer to store read zero-terminated string to. 534 * @param[in] buffer_size Buffer size in bytes, taking '\0' character into 535 * account. 536 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 537 * are not interested in error details. 538 * 539 * @return `True` on success, `false` otherwise (with `error` set accordingly). 540 * Note that `false` will also be returned in case of end of file; if 541 * you need to distinguish the two, check if `error` is `NULL` 542 * afterwards. 543 */ 544 bool tr_sys_file_read_line(tr_sys_file_t handle, char* buffer, size_t buffer_size, struct tr_error** error); 545 546 /** 547 * @brief Portability wrapper for `fputs()`, appending EOL internally. 548 * 549 * Special care should be taken when writing to one of standard output streams 550 * (@ref tr_std_sys_file_t) since no UTF-8 conversion is currently being made. 551 * 552 * Writing to other streams (files, pipes) also leaves data untouched, so it 553 * should already be in UTF-8 encoding, or whichever else you expect. 554 * 555 * @param[in] handle Valid file descriptor. 556 * @param[in] buffer Zero-terminated string to write. 557 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 558 * not interested in error details. 559 * 560 * @return `True` on success, `false` otherwise (with `error` set accordingly). 561 */ 562 bool tr_sys_file_write_line(tr_sys_file_t handle, char const* buffer, struct tr_error** error); 563 564 /** 565 * @brief Portability wrapper for `fprintf()`. 566 * 567 * Special care should be taken when writing to one of standard output streams 568 * (@ref tr_std_sys_file_t) since no UTF-8 conversion is currently being made. 569 * 570 * Writing to other streams (files, pipes) also leaves data untouched, so it 571 * should already be in UTF-8 encoding, or whichever else you expect. 572 * 573 * @param[in] handle Valid file descriptor. 574 * @param[in] format String format to write. 575 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 576 * not interested in error details. 577 * @param[in] ... Format arguments. 578 * 579 * @return `True` on success, `false` otherwise (with `error` set accordingly). 580 */ 581 bool tr_sys_file_write_fmt(tr_sys_file_t handle, char const* format, struct tr_error** error, ...) TR_GNUC_PRINTF(2, 4); 582 583 /* Directory-related wrappers */ 584 585 /** 586 * @brief Portability wrapper for `getcwd()`. 587 * 588 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 589 * not interested in error details. 590 * 591 * @return Pointer to newly allocated buffer containing path to current 592 * directory (use @ref tr_free to free it when no longer needed) on 593 * success, `NULL` otherwise (with `error` set accordingly). 594 */ 595 char* tr_sys_dir_get_current(struct tr_error** error); 596 597 /** 598 * @brief Like `mkdir()`, but makes parent directories if needed. 599 * 600 * @param[in] path Path to directory. 601 * @param[in] flags Combination of @ref tr_sys_dir_create_flags_t values. 602 * @param[in] permissions Permissions to create directory with. Not used on 603 Windows. 604 * @param[out] error Pointer to error object. Optional, pass `NULL` if you 605 * are not interested in error details. 606 * 607 * @return `True` on success, `false` otherwise (with `error` set accordingly). 608 */ 609 bool tr_sys_dir_create(char const* path, int flags, int permissions, struct tr_error** error); 610 611 /** 612 * @brief Portability wrapper for `mkdtemp()`. 613 * 614 * @param[in,out] path_template Template path to directory. Should end with at 615 * least six 'X' characters. Upon success, trailing 616 * 'X' characters are replaced with actual random 617 * characters used to form a unique path to 618 * temporary directory. 619 * @param[out] error Pointer to error object. Optional, pass `NULL` 620 * if you are not interested in error details. 621 * 622 * @return `True` on success, `false` otherwise (with `error` set accordingly). 623 */ 624 bool tr_sys_dir_create_temp(char* path_template, struct tr_error** error); 625 626 /** 627 * @brief Portability wrapper for `opendir()`. 628 * 629 * @param[in] path Path to directory. 630 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 631 * not interested in error details. 632 * 633 * @return Opened directory descriptor on success, `TR_BAD_SYS_DIR` otherwise 634 * (with `error` set accordingly). 635 */ 636 tr_sys_dir_t tr_sys_dir_open(char const* path, struct tr_error** error); 637 638 /** 639 * @brief Portability wrapper for `readdir()`. 640 * 641 * @param[in] handle Valid directory descriptor. 642 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 643 * not interested in error details. 644 * 645 * @return Pointer to next directory entry name (stored internally, DO NOT pass 646 * it to @ref tr_free) on success, `NULL` otherwise (with `error` set 647 * accordingly). Note that `NULL` will also be returned in case of end 648 * of directory; if you need to distinguish the two, check if `error` 649 * is `NULL` afterwards. 650 */ 651 char const* tr_sys_dir_read_name(tr_sys_dir_t handle, struct tr_error** error); 652 653 /** 654 * @brief Portability wrapper for `closedir()`. 655 * 656 * @param[in] handle Valid directory descriptor. 657 * @param[out] error Pointer to error object. Optional, pass `NULL` if you are 658 * not interested in error details. 659 * 660 * @return `True` on success, `false` otherwise (with `error` set accordingly). 661 */ 662 bool tr_sys_dir_close(tr_sys_dir_t handle, struct tr_error** error); 663 664 /** @} */ 665 /** @} */ 666 667 #ifdef __cplusplus 668 } 669 #endif 670