Changeset ca7506f in mainline
- Timestamp:
- 2017-04-03T20:17:21Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3ba431a
- Parents:
- 438f355
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/vfs/vfs.c
r438f355 rca7506f 51 51 #include <ipc/loc.h> 52 52 53 /* 54 * This file contains the implementation of the native HelenOS file system API. 55 * 56 * The API supports client-side file system roots, client-side IO cursors and 57 * uses file handles as a primary means to refer to files. In order to call the 58 * API functions, one just includes vfs/vfs.h. 59 * 60 * The API functions come in two main flavors: 61 * 62 * - functions that operate on integer file handles, such as: 63 * vfs_walk(), vfs_open(), vfs_read(), vfs_link(), ... 64 * 65 * - functions that operate on paths, such as: 66 * vfs_lookup(), vfs_link_path(), vfs_unlink_path(), vfs_rename_path(), ... 67 * 68 * There is usually a corresponding path function for each file handle function 69 * that exists mostly as a convenience wrapper, except for cases when only a 70 * path version exists due to file system consistency considerations (see 71 * vfs_rename_path()). Sometimes one of the versions does not make sense, in 72 * which case it is also omitted. 73 * 74 * Besides of that, the API provides some convenience wrappers for frequently 75 * performed pairs of operations, for example there is a combo API for 76 * vfs_lookup() and vfs_open(): vfs_lookup_open(). 77 * 78 * Some of the functions here return a file handle that can be passed to other 79 * functions. Note that a file handle does not automatically represent a file 80 * from which one can read or to which one can write. In order to do so, the 81 * file handle must be opened first for reading/writing using vfs_open(). 82 * 83 * All file handles, no matter whether opened or not, must be eventually 84 * returned to the system using vfs_put(). Non-returned file handles are in use 85 * and consume system resources. 86 * 87 * Functions that return int return a negative error code on error and do not 88 * set errno. Depending on function, success is signalled by returning either 89 * EOK or a non-negative file handle. 90 * 91 * An example life-cycle of a file handle is as follows: 92 * 93 * #include <vfs/vfs.h> 94 * 95 * int file = vfs_lookup("/foo/bar/foobar", WALK_REGULAR); 96 * if (file < 0) 97 * return file; 98 * int rc = vfs_open(file, MODE_READ); 99 * if (rc != EOK) { 100 * (void) vfs_put(file); 101 * return rc; 102 * } 103 * aoff64_t pos = 42; 104 * char buf[512]; 105 * ssize_t size = vfs_read(file, &pos, buf, sizeof(buf)); 106 * if (size < 0) { 107 * vfs_put(file); 108 * return size; 109 * } 110 * 111 * // buf is now filled with data from file 112 * 113 * vfs_put(file); 114 */ 115 53 116 static FIBRIL_MUTEX_INITIALIZE(vfs_mutex); 54 117 static async_sess_t *vfs_sess = NULL; … … 63 126 static int root_fd = -1; 64 127 128 /** Return a new file handle representing the local root 129 * 130 * @return A clone of the local root file handle or a negative error code 131 */ 65 132 int vfs_root(void) 66 133 { … … 75 142 } 76 143 144 /** Set a new local root 145 * 146 * Note that it is still possible to have file handles for other roots and pass 147 * them to the API functions. Functions like vfs_root() and vfs_lookup() will 148 * however consider the file set by this function to be the root. 149 * 150 * @param nroot The new local root file handle 151 */ 152 77 153 void vfs_root_set(int nroot) 78 154 { … … 84 160 } 85 161 86 /** Start an async exchange on the VFS session. 87 * 88 * @return New exchange. 89 * 162 /** Start an async exchange on the VFS session 163 * 164 * @return New exchange 90 165 */ 91 166 async_exch_t *vfs_exchange_begin(void) … … 103 178 } 104 179 105 /** Finish an async exchange on the VFS session. 106 * 107 * @param exch Exchange to be finished. 108 * 180 /** Finish an async exchange on the VFS session 181 * 182 * @param exch Exchange to be finished 109 183 */ 110 184 void vfs_exchange_end(async_exch_t *exch) … … 113 187 } 114 188 189 /** Walk a path starting in a parent node 190 * 191 * @param parent File handle of the parent node where the walk starts 192 * @param path Parent-relative path to be walked 193 * @param flags Flags influencing the walk 194 * 195 * @retrun File handle representing the result on success or 196 * a negative error code on error 197 */ 115 198 int vfs_walk(int parent, const char *path, int flags) 116 199 { … … 134 217 } 135 218 219 /** Lookup a path relative to the local root 220 * 221 * @param path Path to be looked up 222 * @param flags Walk flags 223 * 224 * @return File handle representing the result on success or a negative 225 * error code on error 226 */ 136 227 int vfs_lookup(const char *path, int flags) 137 228 { … … 151 242 } 152 243 244 /** Open a file handle for I/O 245 * 246 * @param file File handle to enable I/O on 247 * @param mode Mode in which to open file in 248 * 249 * @return EOK on success or a negative error code 250 */ 153 251 int vfs_open(int file, int mode) 154 252 { … … 160 258 } 161 259 260 /** Lookup a path relative to the local root and open the result 261 * 262 * This function is a convenience combo for vfs_lookup() and vfs_open(). 263 * 264 * @param path Path to be looked up 265 * @param flags Walk flags 266 * @param mode Mode in which to open file in 267 * 268 * @return EOK on success or a negative error code 269 */ 162 270 int vfs_lookup_open(const char *path, int flags, int mode) 163 271 { … … 175 283 } 176 284 285 /** Make a potentially relative path absolute 286 * 287 * This function coverts a current-working-directory-relative path into a 288 * well-formed, absolute path. The caller is responsible for deallocating the 289 * returned buffer. 290 * 291 * @param[in] path Path to be absolutized 292 * @param[out] retlen Length of the absolutized path 293 * 294 * @return New buffer holding the absolutized path or NULL 295 */ 177 296 char *vfs_absolutize(const char *path, size_t *retlen) 178 297 { … … 225 344 } 226 345 346 /** Mount a file system 347 * 348 * @param[in] mp File handle representing the mount-point 349 * @param[in] fs_name File system name 350 * @param[in] serv Service representing the mountee 351 * @param[in] opts Mount options for the endpoint file system 352 * @param[in] flags Mount flags 353 * @param[in] instance Instance number of the file system server 354 * @param[out] mountedfd File handle of the mounted root if not NULL 355 * 356 * @return EOK on success or a negative error code 357 */ 227 358 int vfs_mount(int mp, const char *fs_name, service_id_t serv, const char *opts, 228 359 unsigned int flags, unsigned int instance, int *mountedfd) … … 258 389 } 259 390 391 /** Unmount a file system 392 * 393 * @param mp File handle representing the mount-point 394 * 395 * @return EOK on success or a negative error code 396 */ 260 397 int vfs_unmount(int mp) 261 398 { … … 266 403 } 267 404 405 /** Mount a file system 406 * 407 * @param[in] mp Path representing the mount-point 408 * @param[in] fs_name File system name 409 * @param[in] fqsn Fully qualified service name of the mountee 410 * @param[in] opts Mount options for the endpoint file system 411 * @param[in] flags Mount flags 412 * @param[in] instance Instance number of the file system server 413 * 414 * @return EOK on success or a negative error code 415 */ 268 416 int vfs_mount_path(const char *mp, const char *fs_name, const char *fqsn, 269 417 const char *opts, unsigned int flags, unsigned int instance) … … 353 501 } 354 502 503 /** Unmount a file system 504 * 505 * @param mpp Mount-point path 506 * 507 * @return EOK on success or a negative error code 508 */ 355 509 int vfs_unmount_path(const char *mpp) 356 510 { … … 364 518 } 365 519 366 /** Close file. 367 * 368 * @param fildes File descriptor 369 * @return EOK on success or a negative error code otherwise. 370 */ 371 int vfs_put(int fildes) 372 { 373 sysarg_t rc; 374 375 async_exch_t *exch = vfs_exchange_begin(); 376 rc = async_req_1_0(exch, VFS_IN_PUT, fildes); 377 vfs_exchange_end(exch); 378 379 if (rc != EOK) { 380 errno = rc; 381 return -1; 382 } 383 384 return 0; 385 } 386 387 /** Read bytes from file. 520 /** Stop working with a file handle 521 * 522 * @param file File handle to put 523 * 524 * @return EOK on success or a negative error code 525 */ 526 int vfs_put(int file) 527 { 528 async_exch_t *exch = vfs_exchange_begin(); 529 int rc = async_req_1_0(exch, VFS_IN_PUT, file); 530 vfs_exchange_end(exch); 531 532 return rc; 533 } 534 535 /** Read bytes from a file 388 536 * 389 537 * Read up to @a nbyte bytes from file. The actual number of bytes read … … 392 540 * return success with zero bytes read. 393 541 * 394 * @param file File descriptor395 * @param posPosition to read from396 * @param buf Buffer397 * @param nbyte Maximum number of bytes to read398 * @param nread Place to store actual number of bytes read (0 or more)399 * 400 * @return EOK on success, non-zero error code on error.542 * @param file File handle to read from 543 * @param[in] pos Position to read from 544 * @param buf Buffer to read from 545 * @param nbyte Maximum number of bytes to read 546 * @param[out] nread Actual number of bytes read (0 or more) 547 * 548 * @return EOK on success or a negative error code 401 549 */ 402 550 int vfs_read_short(int file, aoff64_t pos, void *buf, size_t nbyte, … … 430 578 } 431 579 432 /** Write bytes to file.580 /** Write bytes to a file 433 581 * 434 582 * Write up to @a nbyte bytes from file. The actual number of bytes written 435 583 * may be lower, but greater than zero. 436 584 * 437 * @param file File descriptor438 * @param posPosition to write to439 * @param buf Buffer440 * @param nbyte Maximum number of bytes to write441 * @param nread Place to store actual number of bytes written (0 or more)442 * 443 * @return EOK on success, non-zero error code on error.585 * @param file File handle to write to 586 * @param[in] pos Position to write to 587 * @param buf Buffer to write to 588 * @param nbyte Maximum number of bytes to write 589 * @param[out] nread Actual number of bytes written (0 or more) 590 * 591 * @return EOK on success or a negative error code 444 592 */ 445 593 int vfs_write_short(int file, aoff64_t pos, const void *buf, size_t nbyte, … … 473 621 } 474 622 475 /** Read data .623 /** Read data 476 624 * 477 625 * Read up to @a nbytes bytes from file if available. This function always reads 478 626 * all the available bytes up to @a nbytes. 479 627 * 480 * @param fil des File descriptor481 * @param pos Pointer to position to read from628 * @param file File handle to read from 629 * @param[inout] pos Position to read from, updated by the actual bytes read 482 630 * @param buf Buffer, @a nbytes bytes long 483 631 * @param nbytes Number of bytes to read 484 632 * 485 * @return On success, non-negative number of bytes red.486 * On failure, a negative error code.633 * @return On success, non-negative number of bytes read 634 * @return On failure, a negative error code 487 635 */ 488 636 ssize_t vfs_read(int file, aoff64_t *pos, void *buf, size_t nbyte) … … 507 655 } 508 656 509 /** Write data .657 /** Write data 510 658 * 511 659 * This function fails if it cannot write exactly @a len bytes to the file. 512 660 * 513 * @param file File descriptor 514 * @param pos Pointer to position to write to 515 * @param buf Data, @a nbytes bytes long 516 * @param nbytes Number of bytes to write 517 * 518 * @return On success, non-negative number of bytes written. 519 * On failure, a negative error code. 661 * @param file File handle to write to 662 * @param[inout] pos Position to write to, updated by the actual bytes 663 * written 664 * @param buf Data, @a nbytes bytes long 665 * @param nbytes Number of bytes to write 666 * 667 * @return On success, non-negative number of bytes written 668 * @return On failure, a negative error code 520 669 */ 521 670 ssize_t vfs_write(int file, aoff64_t *pos, const void *buf, size_t nbyte) … … 540 689 } 541 690 542 /** Synchronize file. 543 * 544 * @param fildes File descriptor 545 * @return EOK on success or a negative error code otherwise. 691 /** Synchronize file 692 * 693 * @param file File handle to synchronize 694 * 695 * @return EOK on success or a negative error code 546 696 */ 547 697 int vfs_sync(int file) 548 698 { 549 699 async_exch_t *exch = vfs_exchange_begin(); 550 sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, file);551 vfs_exchange_end(exch); 552 553 return rc; 554 } 555 556 /** Truncate file to a specified length.557 * 558 * Truncate file so that its size is exactly @a length559 * 560 * @param fil des File descriptor561 * @param length Length562 * 563 * @return EOK on success or a negative erroc code otherwise.700 int rc = async_req_1_0(exch, VFS_IN_SYNC, file); 701 vfs_exchange_end(exch); 702 703 return rc; 704 } 705 706 /** Resize file to a specified length 707 * 708 * Resize file so that its size is exactly @a length. 709 * 710 * @param file File handle to resize 711 * @param length New length 712 * 713 * @return EOK on success or a negative error code 564 714 */ 565 715 int vfs_resize(int file, aoff64_t length) 566 716 { 567 sysarg_t rc; 568 569 async_exch_t *exch = vfs_exchange_begin(); 570 rc = async_req_3_0(exch, VFS_IN_RESIZE, file, LOWER32(length), 717 async_exch_t *exch = vfs_exchange_begin(); 718 int rc = async_req_3_0(exch, VFS_IN_RESIZE, file, LOWER32(length), 571 719 UPPER32(length)); 572 720 vfs_exchange_end(exch); … … 575 723 } 576 724 577 /** Get file status.578 * 579 * @param file File descriptor580 * @param statPlace to store file information581 * 582 * @return EOK on success or a negative error code otherwise.725 /** Get file information 726 * 727 * @param file File handle to get information about 728 * @param[out] stat Place to store file information 729 * 730 * @return EOK on success or a negative error code 583 731 */ 584 732 int vfs_stat(int file, struct stat *stat) … … 609 757 } 610 758 611 /** Get file status.612 * 613 * @param path Path to file614 * @param statPlace to store file information615 * 616 * @return EOK on success or a negative error code otherwise.759 /** Get file information 760 * 761 * @param path File path to get information about 762 * @param[out] stat Place to store file information 763 * 764 * @return EOK on success or a negative error code 617 765 */ 618 766 int vfs_stat_path(const char *path, struct stat *stat) … … 660 808 } 661 809 810 /** Link a file or directory 811 * 812 * Create a new name and an empty file or an empty directory in a parent 813 * directory. If child with the same name already exists, the function returns 814 * a failure, the existing file remains untouched and no file system object 815 * is created. 816 * 817 * @param parent File handle of the parent directory node 818 * @param child New name to be linked 819 * @param kind Kind of the object to be created: KIND_FILE or 820 * KIND_DIRECTORY 821 * @return EOK on success or a negative error code 822 */ 662 823 int vfs_link(int parent, const char *child, vfs_file_kind_t kind) 663 824 { … … 673 834 } 674 835 675 /** Link a file or directory. 676 * 677 * @param path Path 678 * @param kind Kind of the file to be created. 679 * @return EOK on success or a negative error code otherwise 836 /** Link a file or directory 837 * 838 * Create a new name and an empty file or an empty directory at given path. 839 * If a link with the same name already exists, the function returns 840 * a failure, the existing file remains untouched and no file system object 841 * is created. 842 * 843 * @param path New path to be linked 844 * @param kind Kind of the object to be created: KIND_FILE or 845 * KIND_DIRECTORY 846 * @return EOK on success or a negative error code 680 847 */ 681 848 int vfs_link_path(const char *path, vfs_file_kind_t kind) … … 693 860 } 694 861 862 /** Unlink a file or directory 863 * 864 * Unlink a name from a parent directory. The caller can supply the file handle 865 * of the unlinked child in order to detect a possible race with vfs_link() and 866 * avoid unlinking a wrong file. If the last link for a file or directory is 867 * removed, the FS implementation will deallocate its resources. 868 * 869 * @param parent File handle of the parent directory node 870 * @param child Old name to be unlinked 871 * @param expect File handle of the unlinked child 872 * 873 * @return EOK on success or a negative error code 874 */ 695 875 int vfs_unlink(int parent, const char *child, int expect) 696 876 { … … 713 893 } 714 894 715 /** Unlink a file or directory. 716 * 717 * @param path Path 718 * @return EOK on success or a negative error code otherwise 895 /** Unlink a file or directory 896 * 897 * Unlink a path. If the last link for a file or directory is removed, the FS 898 * implementation will deallocate its resources. 899 * 900 * @param path Old path to be unlinked 901 * 902 * @return EOK on success or a negative error code 719 903 */ 720 904 int vfs_unlink_path(const char *path) … … 739 923 } 740 924 741 /** Rename directory entry. 742 * 743 * @param old Old name 744 * @param new New name 745 * 746 * @return EOK on success or a negative error code otherwise. 925 /** Rename a file or directory 926 * 927 * There is no file-handle-based variant to disallow attempts to introduce loops 928 * and breakage in the directory tree when relinking eg. a node under its own 929 * descendant. The path-based variant is not susceptible because the VFS can 930 * prevent this lexically by comparing the paths. 931 * 932 * @param old Old path 933 * @param new New path 934 * 935 * @return EOK on success or a negative error code 747 936 */ 748 937 int vfs_rename_path(const char *old, const char *new) … … 804 993 } 805 994 806 /** Change working directory. 807 * 808 * @param path Path 809 * @return EOK on success or a negative error code otherwise. 995 /** Change working directory 996 * 997 * @param path Path of the new working directory 998 * 999 * @return EOK on success or a negative error code 810 1000 */ 811 1001 int vfs_cwd_set(const char *path) … … 838 1028 } 839 1029 840 /** Get current working directory path. 841 * 842 * @param buf Buffer 843 * @param size Size of @a buf 844 * @return EOK on success and a non-negative error code otherwise. 1030 /** Get current working directory path 1031 * 1032 * @param[out] buf Buffer 1033 * @param size Size of @a buf 1034 * 1035 * @return EOK on success or a non-negative error code 845 1036 */ 846 1037 int vfs_cwd_get(char *buf, size_t size) … … 859 1050 } 860 1051 861 /** Open session to service represented by a special file .862 * 863 * Given that the file referred to by @a fil desrepresents a service,1052 /** Open session to service represented by a special file 1053 * 1054 * Given that the file referred to by @a file represents a service, 864 1055 * open a session to that service. 865 1056 * 866 * @param fil des File descriptor1057 * @param file File handle representing a service 867 1058 * @param iface Interface to connect to (XXX Should be automatic) 868 * @return On success returns session pointer. On error returns @c NULL. 1059 * 1060 * @return Session pointer on success. 1061 * @return @c NULL or error. 869 1062 */ 870 1063 async_sess_t *vfs_fd_session(int file, iface_t iface) … … 881 1074 } 882 1075 883 /** Get filesystem statistics. 884 * 885 * @param file File located on the queried file system 886 * @param st Buffer for storing information 887 * @return EOK on success or a negative error code otherwise. 1076 /** Get filesystem statistics 1077 * 1078 * @param file File located on the queried file system 1079 * @param[out] st Buffer for storing information 1080 * 1081 * @return EOK on success or a negative error code 888 1082 */ 889 1083 int vfs_statfs(int file, struct statfs *st) … … 904 1098 return rc; 905 1099 } 906 /** Get filesystem statistics. 907 * 908 * @param path Mount point path 909 * @param st Buffer for storing information 910 * @return EOK on success or a negative error code otherwise. 1100 1101 /** Get filesystem statistics 1102 * 1103 * @param file Path pointing to the queried file system 1104 * @param[out] st Buffer for storing information 1105 * 1106 * @return EOK on success or a negative error code 911 1107 */ 912 1108 int vfs_statfs_path(const char *path, struct statfs *st) … … 923 1119 } 924 1120 1121 /** Pass a file handle to another VFS client 1122 * 1123 * @param vfs_exch Donor's VFS exchange 1124 * @param file Donor's file handle to pass 1125 * @param exch Exchange to the acceptor 1126 * 1127 * @return EOK on success or a negative error code 1128 */ 925 1129 int vfs_pass_handle(async_exch_t *vfs_exch, int file, async_exch_t *exch) 926 1130 { … … 929 1133 } 930 1134 931 int vfs_receive_handle(bool high_descriptor) 1135 /** Receive a file handle from another VFS client 1136 * 1137 * @param high If true, the received file handle will be allocated from high 1138 * indices 1139 * 1140 * @return EOK on success or a negative error code 1141 */ 1142 int vfs_receive_handle(bool high) 932 1143 { 933 1144 ipc_callid_t callid; … … 942 1153 943 1154 sysarg_t ret; 944 sysarg_t rc = async_req_1_1(vfs_exch, VFS_IN_WAIT_HANDLE, 945 high_descriptor, &ret); 1155 sysarg_t rc = async_req_1_1(vfs_exch, VFS_IN_WAIT_HANDLE, high, &ret); 946 1156 947 1157 async_exchange_end(vfs_exch); … … 952 1162 } 953 1163 954 int vfs_clone(int file_from, int file_to, bool high_descriptor) 1164 /** Clone a file handle 1165 * 1166 * The caller can choose whether to clone an existing file handle into another 1167 * already existing file handle (in which case it is first closed) or to a new 1168 * file handle allocated either from low or high indices. 1169 * 1170 * @param file_from Source file handle 1171 * @param file_to Destination file handle or -1 1172 * @param high If file_to is -1, high controls whether the new file 1173 * handle will be allocated from high indices 1174 * 1175 * @return New file handle on success or a negative error code 1176 */ 1177 int vfs_clone(int file_from, int file_to, bool high) 955 1178 { 956 1179 async_exch_t *vfs_exch = vfs_exchange_begin(); 957 1180 int rc = async_req_3_0(vfs_exch, VFS_IN_CLONE, (sysarg_t) file_from, 958 (sysarg_t) file_to, (sysarg_t) high _descriptor);1181 (sysarg_t) file_to, (sysarg_t) high); 959 1182 vfs_exchange_end(vfs_exch); 960 1183 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.