Changeset 1dff985 in mainline for uspace/lib
- Timestamp:
- 2017-03-03T21:32:38Z (9 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c577a9a
- Parents:
- 5b46ec8 (diff), b8dbe2f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib
- Files:
-
- 5 edited
-
c/generic/vfs/vfs.c (modified) (10 diffs)
-
c/include/ipc/vfs.h (modified) (6 diffs)
-
c/include/vfs/vfs.h (modified) (1 diff)
-
fs/libfs.c (modified) (12 diffs)
-
fs/libfs.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/vfs/vfs.c
r5b46ec8 r1dff985 93 93 } 94 94 95 int _vfs_walk(int parent, const char *path, int flags) 96 { 97 async_exch_t *exch = vfs_exchange_begin(); 98 99 ipc_call_t answer; 100 aid_t req = async_send_2(exch, VFS_IN_WALK, parent, flags, &answer); 101 sysarg_t rc = async_data_write_start(exch, path, str_size(path)); 102 vfs_exchange_end(exch); 103 104 sysarg_t rc_orig; 105 async_wait_for(req, &rc_orig); 106 107 if (rc_orig != EOK) { 108 return (int) rc_orig; 109 } 110 111 if (rc != EOK) { 112 return (int) rc; 113 } 114 115 return (int) IPC_GET_ARG1(answer); 116 } 117 118 int _vfs_open(int fildes, int mode) 119 { 120 async_exch_t *exch = vfs_exchange_begin(); 121 sysarg_t rc = async_req_2_0(exch, VFS_IN_OPEN2, fildes, mode); 122 vfs_exchange_end(exch); 123 124 return (int) rc; 125 } 126 95 127 char *vfs_absolutize(const char *path, size_t *retlen) 96 128 { … … 229 261 } 230 262 231 /* Ask VFS whether it likes fs_name. */232 rc = async_req_0_0(exch, VFS_IN_PING);233 if (rc != EOK) {234 vfs_exchange_end(exch);235 free(mpa);236 async_wait_for(req, &rc_orig);237 238 if (null_id != -1)239 loc_null_destroy(null_id);240 241 if (rc_orig == EOK)242 return (int) rc;243 else244 return (int) rc_orig;245 }246 247 263 vfs_exchange_end(exch); 248 264 free(mpa); … … 289 305 } 290 306 291 /** Open file (internal). 292 * 293 * @param abs Absolute path to file 294 * @param abs_size Size of @a abs string 295 * @param lflag L_xxx flags 296 * @param oflag O_xxx flags 297 * @param fd Place to store new file descriptor 298 * 299 * @return EOK on success, non-zero error code on error 300 */ 301 static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag, 302 int *fd) 303 { 304 async_exch_t *exch = vfs_exchange_begin(); 305 306 ipc_call_t answer; 307 aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer); 308 sysarg_t rc = async_data_write_start(exch, abs, abs_size); 309 310 if (rc != EOK) { 311 vfs_exchange_end(exch); 312 313 sysarg_t rc_orig; 314 async_wait_for(req, &rc_orig); 315 316 if (rc_orig == EOK) 317 return (int) rc; 318 else 319 return (int) rc_orig; 320 } 321 322 vfs_exchange_end(exch); 323 async_wait_for(req, &rc); 324 325 if (rc != EOK) 326 return (int) rc; 327 328 *fd = (int) IPC_GET_ARG1(answer); 329 return EOK; 307 static int walk_flags(int oflags) 308 { 309 int flags = 0; 310 if (oflags & O_CREAT) { 311 if (oflags & O_EXCL) { 312 flags |= WALK_MUST_CREATE; 313 } else { 314 flags |= WALK_MAY_CREATE; 315 } 316 } 317 return flags; 330 318 } 331 319 … … 341 329 int open(const char *path, int oflag, ...) 342 330 { 331 // FIXME: Some applications call this incorrectly. 332 if ((oflag & (O_RDONLY|O_WRONLY|O_RDWR)) == 0) { 333 oflag |= O_RDWR; 334 } 335 336 assert((((oflag & O_RDONLY) != 0) + ((oflag & O_WRONLY) != 0) + ((oflag & O_RDWR) != 0)) == 1); 337 343 338 size_t abs_size; 344 339 char *abs = vfs_absolutize(path, &abs_size); 345 int fd = -1; 346 347 if (abs == NULL) { 348 errno = ENOMEM; 349 return -1; 350 } 351 352 int rc = open_internal(abs, abs_size, L_FILE, oflag, &fd); 353 free(abs); 354 355 if (rc != EOK) { 356 errno = rc; 357 return -1; 358 } 359 360 return fd; 340 if (!abs) { 341 return ENOMEM; 342 } 343 344 int ret = _vfs_walk(-1, abs, walk_flags(oflag) | WALK_REGULAR); 345 if (ret < 0) { 346 return ret; 347 } 348 349 int mode = 350 ((oflag & O_RDWR) ? MODE_READ|MODE_WRITE : 0) | 351 ((oflag & O_RDONLY) ? MODE_READ : 0) | 352 ((oflag & O_WRONLY) ? MODE_WRITE : 0) | 353 ((oflag & O_APPEND) ? MODE_APPEND : 0); 354 355 int rc = _vfs_open(ret, mode); 356 if (rc < 0) { 357 // _vfs_put(ret); 358 close(ret); 359 return rc; 360 } 361 362 if (oflag & O_TRUNC) { 363 assert(oflag & O_WRONLY || oflag & O_RDWR); 364 assert(!(oflag & O_APPEND)); 365 366 // _vfs_resize 367 (void) ftruncate(ret, 0); 368 } 369 370 return ret; 361 371 } 362 372 … … 670 680 int stat(const char *path, struct stat *stat) 671 681 { 672 sysarg_t rc;673 sysarg_t rc_orig;674 aid_t req;675 676 682 size_t pa_size; 677 683 char *pa = vfs_absolutize(path, &pa_size); 678 if (pa == NULL) { 679 errno = ENOMEM; 680 return -1; 681 } 682 683 async_exch_t *exch = vfs_exchange_begin(); 684 685 req = async_send_0(exch, VFS_IN_STAT, NULL); 686 rc = async_data_write_start(exch, pa, pa_size); 687 if (rc != EOK) { 688 vfs_exchange_end(exch); 689 free(pa); 690 async_wait_for(req, &rc_orig); 691 if (rc_orig != EOK) 692 rc = rc_orig; 693 if (rc != EOK) { 694 errno = rc; 695 return -1; 696 } 697 } 698 rc = async_data_read_start(exch, stat, sizeof(struct stat)); 699 if (rc != EOK) { 700 vfs_exchange_end(exch); 701 free(pa); 702 async_wait_for(req, &rc_orig); 703 if (rc_orig != EOK) 704 rc = rc_orig; 705 if (rc != EOK) { 706 errno = rc; 707 return -1; 708 } 709 } 710 vfs_exchange_end(exch); 711 free(pa); 712 async_wait_for(req, &rc); 713 if (rc != EOK) { 714 errno = rc; 715 return -1; 716 } 717 return 0; 684 if (!pa) { 685 return ENOMEM; 686 } 687 688 int fd = _vfs_walk(-1, pa, 0); 689 if (fd < 0) { 690 return fd; 691 } 692 693 int rc = fstat(fd, stat); 694 close(fd); 695 return rc; 718 696 } 719 697 … … 727 705 { 728 706 DIR *dirp = malloc(sizeof(DIR)); 729 int fd = -1; 730 731 if (dirp == NULL) { 707 if (!dirp) { 732 708 errno = ENOMEM; 733 709 return NULL; … … 742 718 } 743 719 744 int r c = open_internal(abs, abs_size, L_DIRECTORY, 0, &fd);720 int ret = _vfs_walk(-1, abs, WALK_DIRECTORY); 745 721 free(abs); 746 722 747 if (r c !=EOK) {723 if (ret < EOK) { 748 724 free(dirp); 725 errno = ret; 726 return NULL; 727 } 728 729 int rc = _vfs_open(ret, MODE_READ); 730 if (rc < 0) { 731 free(dirp); 732 close(ret); 749 733 errno = rc; 750 734 return NULL; 751 735 } 752 736 753 dirp->fd = fd;737 dirp->fd = ret; 754 738 return dirp; 755 739 } … … 809 793 int mkdir(const char *path, mode_t mode) 810 794 { 795 size_t pa_size; 796 char *pa = vfs_absolutize(path, &pa_size); 797 if (!pa) { 798 return ENOMEM; 799 } 800 801 int ret = _vfs_walk(-1, pa, WALK_MUST_CREATE | WALK_DIRECTORY); 802 if (ret < 0) { 803 return ret; 804 } 805 806 close(ret); 807 return EOK; 808 } 809 810 static int _vfs_unlink2(int parent, const char *path, int expect, int wflag) 811 { 811 812 sysarg_t rc; 812 813 aid_t req; 813 814 815 async_exch_t *exch = vfs_exchange_begin(); 816 817 req = async_send_3(exch, VFS_IN_UNLINK2, parent, expect, wflag, NULL); 818 rc = async_data_write_start(exch, path, str_size(path)); 819 820 vfs_exchange_end(exch); 821 822 sysarg_t rc_orig; 823 async_wait_for(req, &rc_orig); 824 825 if (rc_orig != EOK) { 826 return (int) rc_orig; 827 } 828 return rc; 829 } 830 831 /** Unlink file or directory. 832 * 833 * @param path Path 834 * @return EOk on success, error code on error 835 */ 836 int unlink(const char *path) 837 { 814 838 size_t pa_size; 815 839 char *pa = vfs_absolutize(path, &pa_size); 816 if (pa == NULL) { 817 errno = ENOMEM; 818 return -1; 819 } 820 821 async_exch_t *exch = vfs_exchange_begin(); 822 823 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL); 824 rc = async_data_write_start(exch, pa, pa_size); 825 if (rc != EOK) { 826 vfs_exchange_end(exch); 827 free(pa); 828 829 sysarg_t rc_orig; 830 async_wait_for(req, &rc_orig); 831 832 if (rc_orig != EOK) 833 rc = rc_orig; 834 835 if (rc != EOK) { 836 errno = rc; 837 return -1; 838 } 839 840 return 0; 841 } 842 843 vfs_exchange_end(exch); 844 free(pa); 845 async_wait_for(req, &rc); 846 847 if (rc != EOK) { 848 errno = rc; 849 return -1; 850 } 851 852 return 0; 853 } 854 855 /** Unlink a file or directory. 856 * 857 * @param path Path to file or empty directory 858 * @param lflag L_xxx flag (L_NONE, L_FILE or L_DIRECTORY) 859 * @return EOK on success, non-zero error code on error 860 */ 861 static int _unlink(const char *path, int lflag) 862 { 863 sysarg_t rc; 864 aid_t req; 865 840 if (!pa) { 841 return ENOMEM; 842 } 843 844 return _vfs_unlink2(-1, pa, -1, 0); 845 } 846 847 /** Remove empty directory. 848 * 849 * @param path Path 850 * @return 0 on success. On error returns -1 and sets errno. 851 */ 852 int rmdir(const char *path) 853 { 866 854 size_t pa_size; 867 855 char *pa = vfs_absolutize(path, &pa_size); 868 if ( pa == NULL)856 if (!pa) { 869 857 return ENOMEM; 870 871 async_exch_t *exch = vfs_exchange_begin(); 872 873 req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL); 874 rc = async_data_write_start(exch, pa, pa_size); 875 if (rc != EOK) { 876 vfs_exchange_end(exch); 877 free(pa); 878 879 sysarg_t rc_orig; 880 async_wait_for(req, &rc_orig); 881 882 if (rc_orig == EOK) 883 return (int) rc; 884 else 885 return (int) rc_orig; 886 } 887 vfs_exchange_end(exch); 888 free(pa); 889 async_wait_for(req, &rc); 890 return rc; 891 } 892 893 /** Unlink file or directory. 894 * 895 * @param path Path 896 * @return EOk on success, error code on error 897 */ 898 int unlink(const char *path) 899 { 900 int rc; 901 902 rc = _unlink(path, L_NONE); 903 if (rc != EOK) { 904 errno = rc; 905 return -1; 906 } 907 908 return 0; 909 } 910 911 /** Remove empty directory. 912 * 913 * @param path Path 914 * @return 0 on success. On error returns -1 and sets errno. 915 */ 916 int rmdir(const char *path) 917 { 918 int rc; 919 920 rc = _unlink(path, L_DIRECTORY); 921 if (rc != EOK) { 922 errno = rc; 923 return -1; 924 } 925 926 return 0; 858 } 859 860 return _vfs_unlink2(-1, pa, -1, WALK_DIRECTORY); 927 861 } 928 862 … … 957 891 async_exch_t *exch = vfs_exchange_begin(); 958 892 959 req = async_send_ 0(exch, VFS_IN_RENAME, NULL);893 req = async_send_1(exch, VFS_IN_RENAME, -1, NULL); 960 894 rc = async_data_write_start(exch, olda, olda_size); 961 895 if (rc != EOK) { … … 1018 952 size_t abs_size; 1019 953 char *abs = vfs_absolutize(path, &abs_size); 1020 int fd = -1; 1021 1022 if (abs == NULL) { 1023 errno = ENOMEM; 1024 return -1; 1025 } 1026 1027 int rc = open_internal(abs, abs_size, L_DIRECTORY, O_DESC, &fd); 1028 1029 if (rc != EOK) { 954 if (!abs) 955 return ENOMEM; 956 957 int fd = _vfs_walk(-1, abs, WALK_DIRECTORY); 958 if (fd < 0) { 1030 959 free(abs); 1031 errno = rc;960 errno = fd; 1032 961 return -1; 1033 962 } -
uspace/lib/c/include/ipc/vfs.h
r5b46ec8 r1dff985 63 63 64 64 typedef enum { 65 VFS_IN_OPEN = IPC_FIRST_USER_METHOD, 66 VFS_IN_READ, 65 VFS_IN_READ = IPC_FIRST_USER_METHOD, 67 66 VFS_IN_WRITE, 68 67 VFS_IN_SEEK, … … 75 74 VFS_IN_SYNC, 76 75 VFS_IN_REGISTER, 77 VFS_IN_MKDIR,78 76 VFS_IN_UNLINK, 79 77 VFS_IN_RENAME, 80 VFS_IN_STAT,81 78 VFS_IN_DUP, 82 79 VFS_IN_WAIT_HANDLE, 83 80 VFS_IN_MTAB_GET, 84 VFS_IN_STATFS 81 VFS_IN_STATFS, 82 VFS_IN_WALK, 83 VFS_IN_OPEN2, 84 VFS_IN_UNLINK2, 85 85 } vfs_in_request_t; 86 86 … … 91 91 VFS_OUT_TRUNCATE, 92 92 VFS_OUT_CLOSE, 93 VFS_OUT_MOUNT,94 93 VFS_OUT_MOUNTED, 95 VFS_OUT_UNMOUNT,96 94 VFS_OUT_UNMOUNTED, 95 VFS_OUT_GET_SIZE, 96 VFS_OUT_IS_EMPTY, 97 97 VFS_OUT_SYNC, 98 98 VFS_OUT_STAT, 99 99 VFS_OUT_LOOKUP, 100 VFS_OUT_LINK, 100 101 VFS_OUT_DESTROY, 101 102 VFS_OUT_STATFS, … … 127 128 128 129 /** 129 * Lookup will succeed only if the object is a root directory. The flag is130 * mutually exclusive with L_FILE and L_MP.130 * Lookup will not cross any mount points. 131 * If the lookup would have to cross a mount point, it returns EXDEV instead. 131 132 */ 132 #define L_ ROOT4133 #define L_DISABLE_MOUNTS 4 133 134 134 135 /** … … 151 152 152 153 /** 153 * L_LINK is used for linking to an already existing nodes.154 */155 #define L_LINK 64156 157 /**158 154 * L_UNLINK is used to remove leaves from the file system namespace. This flag 159 155 * cannot be passed directly by the client, but will be set by VFS during … … 170 166 #define L_OPEN 256 171 167 168 /* 169 * Walk flags. 170 */ 171 enum { 172 /** 173 * WALK_PARTIAL requests that if the whole path cannot be traversed, 174 * the walk() operation should return the last visited file, along 175 * with an indication of how many directories have been traversed. 176 */ 177 //WALK_PARTIAL = (1 << 0), 178 179 WALK_MAY_CREATE = (1 << 1), 180 WALK_MUST_CREATE = (1 << 2), 181 182 WALK_REGULAR = (1 << 3), 183 WALK_DIRECTORY = (1 << 4), 184 185 WALK_ALL_FLAGS = WALK_MAY_CREATE | WALK_MUST_CREATE | WALK_REGULAR | WALK_DIRECTORY, 186 }; 187 188 enum { 189 MODE_READ = 1, 190 MODE_WRITE = 2, 191 MODE_APPEND = 4, 192 }; 193 172 194 #endif 173 195 -
uspace/lib/c/include/vfs/vfs.h
r5b46ec8 r1dff985 64 64 extern void vfs_exchange_end(async_exch_t *); 65 65 66 extern int _vfs_walk(int parent, const char *path, int flags); 67 extern int _vfs_open(int file, int mode); 68 66 69 #endif 67 70 -
uspace/lib/fs/libfs.c
r5b46ec8 r1dff985 36 36 37 37 #include "libfs.h" 38 #include "../../srv/vfs/vfs.h"39 38 #include <macros.h> 40 39 #include <errno.h> … … 47 46 #include <sys/statfs.h> 48 47 #include <stdlib.h> 48 #include <fibril_synch.h> 49 49 50 50 #define on_error(rc, action) \ … … 63 63 } while (0) 64 64 65 #define DPRINTF(...) 66 67 #define LOG_EXIT(rc) \ 68 DPRINTF("Exiting %s() with rc = %d at line %d\n", __FUNC__, rc, __LINE__); 69 65 70 static fs_reg_t reg; 66 71 … … 68 73 static libfs_ops_t *libfs_ops = NULL; 69 74 70 static void libfs_ mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);71 static void libfs_unmount(libfs_ops_t *, ipc_callid_t,ipc_call_t *);75 static void libfs_link(libfs_ops_t *, fs_handle_t, ipc_callid_t, 76 ipc_call_t *); 72 77 static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, 73 78 ipc_call_t *); … … 104 109 } 105 110 106 static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)107 {108 libfs_mount(libfs_ops, reg.fs_handle, rid, req);109 }110 111 111 static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req) 112 112 { … … 119 119 } 120 120 121 static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req) 122 { 123 124 libfs_unmount(libfs_ops, rid, req); 121 static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req) 122 { 123 libfs_link(libfs_ops, reg.fs_handle, rid, req); 125 124 } 126 125 … … 193 192 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 194 193 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 194 195 195 int rc; 196 197 rc = vfs_out_ops->destroy(service_id, index); 198 196 fs_node_t *node = NULL; 197 rc = libfs_ops->node_get(&node, service_id, index); 198 if (rc == EOK && node != NULL) { 199 bool destroy = (libfs_ops->lnkcnt_get(node) == 0); 200 libfs_ops->node_put(node); 201 if (destroy) { 202 rc = vfs_out_ops->destroy(service_id, index); 203 } 204 } 199 205 async_answer_0(rid, rc); 200 206 } … … 225 231 libfs_statfs(libfs_ops, reg.fs_handle, rid, req); 226 232 } 233 234 static void vfs_out_get_size(ipc_callid_t rid, ipc_call_t *req) 235 { 236 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 237 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 238 int rc; 239 240 fs_node_t *node = NULL; 241 rc = libfs_ops->node_get(&node, service_id, index); 242 if (rc != EOK) { 243 async_answer_0(rid, rc); 244 } 245 if (node == NULL) { 246 async_answer_0(rid, EINVAL); 247 } 248 249 uint64_t size = libfs_ops->size_get(node); 250 libfs_ops->node_put(node); 251 252 async_answer_2(rid, EOK, LOWER32(size), UPPER32(size)); 253 } 254 255 static void vfs_out_is_empty(ipc_callid_t rid, ipc_call_t *req) 256 { 257 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req); 258 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req); 259 int rc; 260 261 fs_node_t *node = NULL; 262 rc = libfs_ops->node_get(&node, service_id, index); 263 if (rc != EOK) { 264 async_answer_0(rid, rc); 265 } 266 if (node == NULL) { 267 async_answer_0(rid, EINVAL); 268 } 269 270 bool children = false; 271 rc = libfs_ops->has_children(&children, node); 272 libfs_ops->node_put(node); 273 274 if (rc != EOK) { 275 async_answer_0(rid, rc); 276 } 277 async_answer_0(rid, children ? ENOTEMPTY : EOK); 278 } 279 227 280 static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 228 281 { … … 247 300 vfs_out_mounted(callid, &call); 248 301 break; 249 case VFS_OUT_MOUNT:250 vfs_out_mount(callid, &call);251 break;252 302 case VFS_OUT_UNMOUNTED: 253 303 vfs_out_unmounted(callid, &call); 254 304 break; 255 case VFS_OUT_ UNMOUNT:256 vfs_out_ unmount(callid, &call);305 case VFS_OUT_LINK: 306 vfs_out_link(callid, &call); 257 307 break; 258 308 case VFS_OUT_LOOKUP: … … 285 335 case VFS_OUT_STATFS: 286 336 vfs_out_statfs(callid, &call); 337 break; 338 case VFS_OUT_GET_SIZE: 339 vfs_out_get_size(callid, &call); 340 break; 341 case VFS_OUT_IS_EMPTY: 342 vfs_out_is_empty(callid, &call); 287 343 break; 288 344 default: … … 383 439 } 384 440 385 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, 386 ipc_call_t *req) 387 { 388 service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req); 389 fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req); 390 fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req); 391 service_id_t mr_service_id = (service_id_t) IPC_GET_ARG4(*req); 392 393 async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL); 394 if (mountee_sess == NULL) { 395 async_answer_0(rid, EINVAL); 441 static char plb_get_char(unsigned pos) 442 { 443 return reg.plb_ro[pos % PLB_SIZE]; 444 } 445 446 static int plb_get_component(char *dest, unsigned *sz, unsigned *ppos, unsigned last) 447 { 448 unsigned pos = *ppos; 449 unsigned size = 0; 450 451 if (pos == last) { 452 *sz = 0; 453 return ERANGE; 454 } 455 456 char c = plb_get_char(pos); 457 if (c == '/') { 458 pos++; 459 } 460 461 for (int i = 0; i <= NAME_MAX; i++) { 462 c = plb_get_char(pos); 463 if (pos == last || c == '/') { 464 dest[i] = 0; 465 *ppos = pos; 466 *sz = size; 467 return EOK; 468 } 469 dest[i] = c; 470 pos++; 471 size++; 472 } 473 return ENAMETOOLONG; 474 } 475 476 static int receive_fname(char *buffer) 477 { 478 size_t size; 479 ipc_callid_t wcall; 480 481 if (!async_data_write_receive(&wcall, &size)) { 482 return ENOENT; 483 } 484 if (size > NAME_MAX + 1) { 485 async_answer_0(wcall, ERANGE); 486 return ERANGE; 487 } 488 return async_data_write_finalize(wcall, buffer, size); 489 } 490 491 /** Link a file at a path. 492 */ 493 void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req) 494 { 495 service_id_t parent_sid = IPC_GET_ARG1(*req); 496 fs_index_t parent_index = IPC_GET_ARG2(*req); 497 fs_index_t child_index = IPC_GET_ARG3(*req); 498 499 char component[NAME_MAX + 1]; 500 int rc = receive_fname(component); 501 if (rc != EOK) { 502 async_answer_0(rid, rc); 396 503 return; 397 504 } 398 399 fs_node_t *fn; 400 int res = ops->node_get(&fn, mp_service_id, mp_fs_index); 401 if ((res != EOK) || (!fn)) { 402 async_hangup(mountee_sess); 403 async_data_write_void(combine_rc(res, ENOENT)); 404 async_answer_0(rid, combine_rc(res, ENOENT)); 505 506 fs_node_t *parent = NULL; 507 rc = ops->node_get(&parent, parent_sid, parent_index); 508 if (parent == NULL) { 509 async_answer_0(rid, rc == EOK ? EBADF : rc); 405 510 return; 406 511 } 407 512 408 if (fn->mp_data.mp_active) {409 async_hangup(mountee_sess);410 (void) ops->node_put(fn);411 async_ data_write_void(EBUSY);412 async_answer_0(rid, EBUSY);513 fs_node_t *child = NULL; 514 rc = ops->node_get(&child, parent_sid, child_index); 515 if (child == NULL) { 516 async_answer_0(rid, rc == EOK ? EBADF : rc); 517 ops->node_put(parent); 413 518 return; 414 519 } 415 520 416 async_exch_t *exch = async_exchange_begin(mountee_sess); 417 async_sess_t *sess = async_clone_establish(EXCHANGE_PARALLEL, exch); 418 419 if (!sess) { 420 async_exchange_end(exch); 421 async_hangup(mountee_sess); 422 (void) ops->node_put(fn); 423 async_data_write_void(errno); 424 async_answer_0(rid, errno); 425 return; 426 } 427 428 ipc_call_t answer; 429 int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED, 430 mr_service_id, &answer); 431 async_exchange_end(exch); 432 433 if (rc == EOK) { 434 fn->mp_data.mp_active = true; 435 fn->mp_data.fs_handle = mr_fs_handle; 436 fn->mp_data.service_id = mr_service_id; 437 fn->mp_data.sess = mountee_sess; 438 } 439 440 /* 441 * Do not release the FS node so that it stays in memory. 442 */ 443 async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), 444 IPC_GET_ARG3(answer), IPC_GET_ARG4(answer)); 445 } 446 447 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req) 448 { 449 service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req); 450 fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req); 451 fs_node_t *fn; 452 int res; 453 454 res = ops->node_get(&fn, mp_service_id, mp_fs_index); 455 if ((res != EOK) || (!fn)) { 456 async_answer_0(rid, combine_rc(res, ENOENT)); 457 return; 458 } 459 460 /* 461 * We are clearly expecting to find the mount point active. 462 */ 463 if (!fn->mp_data.mp_active) { 464 (void) ops->node_put(fn); 465 async_answer_0(rid, EINVAL); 466 return; 467 } 468 469 /* 470 * Tell the mounted file system to unmount. 471 */ 472 async_exch_t *exch = async_exchange_begin(fn->mp_data.sess); 473 res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.service_id); 474 async_exchange_end(exch); 475 476 /* 477 * If everything went well, perform the clean-up on our side. 478 */ 479 if (res == EOK) { 480 async_hangup(fn->mp_data.sess); 481 fn->mp_data.mp_active = false; 482 fn->mp_data.fs_handle = 0; 483 fn->mp_data.service_id = 0; 484 fn->mp_data.sess = NULL; 485 486 /* Drop the reference created in libfs_mount(). */ 487 (void) ops->node_put(fn); 488 } 489 490 (void) ops->node_put(fn); 491 async_answer_0(rid, res); 492 } 493 494 static char plb_get_char(unsigned pos) 495 { 496 return reg.plb_ro[pos % PLB_SIZE]; 521 rc = ops->link(parent, child, component); 522 ops->node_put(parent); 523 ops->node_put(child); 524 async_answer_0(rid, rc); 497 525 } 498 526 … … 513 541 ipc_call_t *req) 514 542 { 515 unsigned int first = IPC_GET_ARG1(*req); 516 unsigned int last = IPC_GET_ARG2(*req); 517 unsigned int next = first; 543 unsigned first = IPC_GET_ARG1(*req); 544 unsigned len = IPC_GET_ARG2(*req); 518 545 service_id_t service_id = IPC_GET_ARG3(*req); 519 int lflag = IPC_GET_ARG4(*req); 520 fs_index_t index = IPC_GET_ARG5(*req); 546 fs_index_t index = IPC_GET_ARG4(*req); 547 int lflag = IPC_GET_ARG5(*req); 548 549 assert((int) index != -1); 550 551 DPRINTF("Entered libfs_lookup()\n"); 552 553 // TODO: Validate flags. 554 555 unsigned next = first; 556 unsigned last = first + len; 557 521 558 char component[NAME_MAX + 1]; 522 int len;523 559 int rc; 524 525 if (last < next)526 last += PLB_SIZE;527 560 528 561 fs_node_t *par = NULL; 529 562 fs_node_t *cur = NULL; 530 563 fs_node_t *tmp = NULL; 531 532 rc = ops->root_get(&cur, service_id); 533 on_error(rc, goto out_with_answer); 534 535 if (cur->mp_data.mp_active) { 536 async_exch_t *exch = async_exchange_begin(cur->mp_data.sess); 537 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last, 538 cur->mp_data.service_id, lflag, index, 539 IPC_FF_ROUTE_FROM_ME); 540 async_exchange_end(exch); 564 unsigned clen = 0; 565 566 rc = ops->node_get(&cur, service_id, index); 567 if (rc != EOK) { 568 async_answer_0(rid, rc); 569 LOG_EXIT(rc); 570 goto out; 571 } 572 573 assert(cur != NULL); 574 575 /* Find the file and its parent. */ 576 577 unsigned last_next = 0; 578 579 while (next != last) { 580 if (cur == NULL) { 581 assert(par != NULL); 582 goto out1; 583 } 584 585 if (!ops->is_directory(cur)) { 586 async_answer_0(rid, ENOTDIR); 587 LOG_EXIT(ENOTDIR); 588 goto out; 589 } 541 590 542 (void) ops->node_put(cur); 543 return; 544 } 545 546 /* Eat slash */ 547 if (plb_get_char(next) == '/') 548 next++; 549 550 while (next <= last) { 551 bool has_children; 591 last_next = next; 592 /* Collect the component */ 593 rc = plb_get_component(component, &clen, &next, last); 594 assert(rc != ERANGE); 595 if (rc != EOK) { 596 async_answer_0(rid, rc); 597 LOG_EXIT(rc); 598 goto out; 599 } 552 600 553 rc = ops->has_children(&has_children, cur);554 on_error(rc, goto out_with_answer);555 if (!has_children)556 break;601 if (clen == 0) { 602 /* The path is just "/". */ 603 break; 604 } 557 605 558 /* Collect the component */ 559 len = 0; 560 while ((next <= last) && (plb_get_char(next) != '/')) { 561 if (len + 1 == NAME_MAX) { 562 /* Component length overflow */ 563 async_answer_0(rid, ENAMETOOLONG); 564 goto out; 565 } 566 component[len++] = plb_get_char(next); 567 /* Process next character */ 568 next++; 569 } 570 571 assert(len); 572 component[len] = '\0'; 573 /* Eat slash */ 574 next++; 606 assert(component[clen] == 0); 575 607 576 608 /* Match the component */ 577 609 rc = ops->match(&tmp, cur, component); 578 on_error(rc, goto out_with_answer); 610 if (rc != EOK) { 611 async_answer_0(rid, rc); 612 LOG_EXIT(rc); 613 goto out; 614 } 579 615 580 /* 581 * If the matching component is a mount point, there are two 582 * legitimate semantics of the lookup operation. The first is 583 * the commonly used one in which the lookup crosses each mount 584 * point into the mounted file system. The second semantics is 585 * used mostly during unmount() and differs from the first one 586 * only in that the last mount point in the looked up path, 587 * which is also its last component, is not crossed. 588 */ 589 590 if ((tmp) && (tmp->mp_data.mp_active) && 591 (!(lflag & L_MP) || (next <= last))) { 592 if (next > last) 593 next = last = first; 594 else 595 next--; 616 /* Descend one level */ 617 if (par) { 618 rc = ops->node_put(par); 619 if (rc != EOK) { 620 async_answer_0(rid, rc); 621 LOG_EXIT(rc); 622 goto out; 623 } 624 } 625 626 par = cur; 627 cur = tmp; 628 tmp = NULL; 629 } 630 631 /* At this point, par is either NULL or a directory. 632 * If cur is NULL, the looked up file does not exist yet. 633 */ 634 635 assert(par == NULL || ops->is_directory(par)); 636 assert(par != NULL || cur != NULL); 637 638 /* Check for some error conditions. */ 639 640 if (cur && (lflag & L_FILE) && (ops->is_directory(cur))) { 641 async_answer_0(rid, EISDIR); 642 LOG_EXIT(EISDIR); 643 goto out; 644 } 645 646 if (cur && (lflag & L_DIRECTORY) && (ops->is_file(cur))) { 647 async_answer_0(rid, ENOTDIR); 648 LOG_EXIT(ENOTDIR); 649 goto out; 650 } 651 652 /* Unlink. */ 653 654 if (lflag & L_UNLINK) { 655 if (!cur) { 656 async_answer_0(rid, ENOENT); 657 LOG_EXIT(ENOENT); 658 goto out; 659 } 660 if (!par) { 661 async_answer_0(rid, EINVAL); 662 LOG_EXIT(EINVAL); 663 goto out; 664 } 665 666 rc = ops->unlink(par, cur, component); 667 if (rc == EOK) { 668 int64_t size = ops->size_get(cur); 669 int32_t lsize = LOWER32(size); 670 if (lsize != size) { 671 lsize = -1; 672 } 596 673 597 async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess); 598 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, 599 last, tmp->mp_data.service_id, lflag, index, 600 IPC_FF_ROUTE_FROM_ME); 601 async_exchange_end(exch); 602 603 (void) ops->node_put(cur); 604 (void) ops->node_put(tmp); 605 if (par) 606 (void) ops->node_put(par); 607 return; 608 } 609 610 /* Handle miss: match amongst siblings */ 611 if (!tmp) { 612 if (next <= last) { 613 /* There are unprocessed components */ 614 async_answer_0(rid, ENOENT); 674 async_answer_5(rid, fs_handle, service_id, 675 ops->index_get(cur), last, lsize, 676 ops->is_directory(cur)); 677 LOG_EXIT(EOK); 678 } else { 679 async_answer_0(rid, rc); 680 LOG_EXIT(rc); 681 } 682 goto out; 683 } 684 685 /* Create. */ 686 687 if (lflag & L_CREATE) { 688 if (cur && (lflag & L_EXCLUSIVE)) { 689 async_answer_0(rid, EEXIST); 690 LOG_EXIT(EEXIST); 691 goto out; 692 } 693 694 if (!cur) { 695 rc = ops->create(&cur, service_id, lflag & (L_FILE|L_DIRECTORY)); 696 if (rc != EOK) { 697 async_answer_0(rid, rc); 698 LOG_EXIT(rc); 699 goto out; 700 } 701 if (!cur) { 702 async_answer_0(rid, ENOSPC); 703 LOG_EXIT(ENOSPC); 615 704 goto out; 616 705 } 617 706 618 /* Miss in the last component */ 619 if (lflag & (L_CREATE | L_LINK)) { 620 /* Request to create a new link */ 621 if (!ops->is_directory(cur)) { 622 async_answer_0(rid, ENOTDIR); 623 goto out; 624 } 625 626 fs_node_t *fn; 627 if (lflag & L_CREATE) 628 rc = ops->create(&fn, service_id, 629 lflag); 630 else 631 rc = ops->node_get(&fn, service_id, 632 index); 633 on_error(rc, goto out_with_answer); 634 635 if (fn) { 636 rc = ops->link(cur, fn, component); 637 if (rc != EOK) { 638 if (lflag & L_CREATE) 639 (void) ops->destroy(fn); 640 else 641 (void) ops->node_put(fn); 642 async_answer_0(rid, rc); 643 } else { 644 (void) ops->node_put(cur); 645 cur = fn; 646 goto out_with_answer; 647 } 648 } else 649 async_answer_0(rid, ENOSPC); 650 707 rc = ops->link(par, cur, component); 708 if (rc != EOK) { 709 (void) ops->destroy(cur); 710 cur = NULL; 711 async_answer_0(rid, rc); 712 LOG_EXIT(rc); 651 713 goto out; 652 714 } 653 654 async_answer_0(rid, ENOENT); 715 } 716 } 717 718 /* Return. */ 719 out1: 720 if (!cur) { 721 async_answer_5(rid, fs_handle, service_id, 722 ops->index_get(par), last_next, -1, true); 723 LOG_EXIT(EOK); 724 goto out; 725 } 726 727 if (lflag & L_OPEN) { 728 rc = ops->node_open(cur); 729 if (rc != EOK) { 730 async_answer_0(rid, rc); 731 LOG_EXIT(rc); 655 732 goto out; 656 733 } 657 658 if (par) { 659 rc = ops->node_put(par); 660 on_error(rc, goto out_with_answer); 661 } 662 663 /* Descend one level */ 664 par = cur; 665 cur = tmp; 666 tmp = NULL; 667 } 668 669 /* Handle miss: excessive components */ 670 if (next <= last) { 671 bool has_children; 672 rc = ops->has_children(&has_children, cur); 673 on_error(rc, goto out_with_answer); 674 675 if (has_children) 676 goto skip_miss; 677 678 if (lflag & (L_CREATE | L_LINK)) { 679 if (!ops->is_directory(cur)) { 680 async_answer_0(rid, ENOTDIR); 681 goto out; 682 } 683 684 /* Collect next component */ 685 len = 0; 686 while (next <= last) { 687 if (plb_get_char(next) == '/') { 688 /* More than one component */ 689 async_answer_0(rid, ENOENT); 690 goto out; 691 } 692 693 if (len + 1 == NAME_MAX) { 694 /* Component length overflow */ 695 async_answer_0(rid, ENAMETOOLONG); 696 goto out; 697 } 698 699 component[len++] = plb_get_char(next); 700 /* Process next character */ 701 next++; 702 } 703 704 assert(len); 705 component[len] = '\0'; 706 707 fs_node_t *fn; 708 if (lflag & L_CREATE) 709 rc = ops->create(&fn, service_id, lflag); 710 else 711 rc = ops->node_get(&fn, service_id, index); 712 on_error(rc, goto out_with_answer); 713 714 if (fn) { 715 rc = ops->link(cur, fn, component); 716 if (rc != EOK) { 717 if (lflag & L_CREATE) 718 (void) ops->destroy(fn); 719 else 720 (void) ops->node_put(fn); 721 async_answer_0(rid, rc); 722 } else { 723 (void) ops->node_put(cur); 724 cur = fn; 725 goto out_with_answer; 726 } 727 } else 728 async_answer_0(rid, ENOSPC); 729 730 goto out; 731 } 732 733 async_answer_0(rid, ENOENT); 734 goto out; 735 } 736 737 skip_miss: 738 739 /* Handle hit */ 740 if (lflag & L_UNLINK) { 741 unsigned int old_lnkcnt = ops->lnkcnt_get(cur); 742 rc = ops->unlink(par, cur, component); 743 744 if (rc == EOK) { 745 aoff64_t size = ops->size_get(cur); 746 async_answer_5(rid, fs_handle, service_id, 747 ops->index_get(cur), LOWER32(size), UPPER32(size), 748 old_lnkcnt); 749 } else 750 async_answer_0(rid, rc); 751 752 goto out; 753 } 754 755 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 756 (lflag & L_LINK)) { 757 async_answer_0(rid, EEXIST); 758 goto out; 759 } 760 761 if ((lflag & L_FILE) && (ops->is_directory(cur))) { 762 async_answer_0(rid, EISDIR); 763 goto out; 764 } 765 766 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { 767 async_answer_0(rid, ENOTDIR); 768 goto out; 769 } 770 771 if ((lflag & L_ROOT) && par) { 772 async_answer_0(rid, EINVAL); 773 goto out; 774 } 775 776 out_with_answer: 777 778 if (rc == EOK) { 779 if (lflag & L_OPEN) 780 rc = ops->node_open(cur); 781 782 if (rc == EOK) { 783 aoff64_t size = ops->size_get(cur); 784 async_answer_5(rid, fs_handle, service_id, 785 ops->index_get(cur), LOWER32(size), UPPER32(size), 786 ops->lnkcnt_get(cur)); 787 } else 788 async_answer_0(rid, rc); 789 790 } else 791 async_answer_0(rid, rc); 792 734 } 735 736 int64_t size = ops->size_get(cur); 737 int32_t lsize = LOWER32(size); 738 if (lsize != size) { 739 lsize = -1; 740 } 741 742 async_answer_5(rid, fs_handle, service_id, ops->index_get(cur), last, 743 lsize, ops->is_directory(cur)); 744 745 LOG_EXIT(EOK); 793 746 out: 794 795 if (par) 747 if (par) { 796 748 (void) ops->node_put(par); 797 798 if (cur) 749 } 750 751 if (cur) { 799 752 (void) ops->node_put(cur); 800 801 if (tmp) 753 } 754 755 if (tmp) { 802 756 (void) ops->node_put(tmp); 757 } 803 758 } 804 759 -
uspace/lib/fs/libfs.h
r5b46ec8 r1dff985 56 56 57 57 typedef struct { 58 bool mp_active;59 async_sess_t *sess;60 fs_handle_t fs_handle;61 service_id_t service_id;62 } mp_data_t;63 64 typedef struct {65 mp_data_t mp_data; /**< Mount point info. */66 58 void *data; /**< Data of the file system implementation. */ 67 59 } fs_node_t;
Note:
See TracChangeset
for help on using the changeset viewer.
