00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include "vfs.h"
00039 #include <macros.h>
00040 #include <stdint.h>
00041 #include <async.h>
00042 #include <errno.h>
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <str.h>
00046 #include <bool.h>
00047 #include <fibril_synch.h>
00048 #include <adt/list.h>
00049 #include <unistd.h>
00050 #include <ctype.h>
00051 #include <fcntl.h>
00052 #include <assert.h>
00053 #include <vfs/canonify.h>
00054
00055
00056 static int vfs_truncate_internal(fs_handle_t, devmap_handle_t, fs_index_t,
00057 aoff64_t);
00058
00063 FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
00064
00065 vfs_pair_t rootfs = {
00066 .fs_handle = 0,
00067 .devmap_handle = 0
00068 };
00069
00070 static void vfs_mount_internal(ipc_callid_t rid, devmap_handle_t devmap_handle,
00071 fs_handle_t fs_handle, char *mp, char *opts)
00072 {
00073 vfs_lookup_res_t mp_res;
00074 vfs_lookup_res_t mr_res;
00075 vfs_node_t *mp_node = NULL;
00076 vfs_node_t *mr_node;
00077 fs_index_t rindex;
00078 size_t rsize;
00079 unsigned rlnkcnt;
00080 sysarg_t rc;
00081 int phone;
00082 aid_t msg;
00083 ipc_call_t answer;
00084
00085
00086 fibril_rwlock_write_lock(&namespace_rwlock);
00087 if (rootfs.fs_handle) {
00088
00089 if (str_cmp(mp, "/") == 0) {
00090
00091 fibril_rwlock_write_unlock(&namespace_rwlock);
00092 async_answer_0(rid, EBUSY);
00093 return;
00094 }
00095
00096 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
00097 if (rc != EOK) {
00098
00099 fibril_rwlock_write_unlock(&namespace_rwlock);
00100 async_answer_0(rid, rc);
00101 return;
00102 }
00103
00104 mp_node = vfs_node_get(&mp_res);
00105 if (!mp_node) {
00106 fibril_rwlock_write_unlock(&namespace_rwlock);
00107 async_answer_0(rid, ENOMEM);
00108 return;
00109 }
00110
00111
00112
00113
00114
00115
00116 } else {
00117
00118 if (str_cmp(mp, "/") == 0) {
00119
00120
00121
00122
00123
00124
00125 phone = vfs_grab_phone(fs_handle);
00126 msg = async_send_1(phone, VFS_OUT_MOUNTED,
00127 (sysarg_t) devmap_handle, &answer);
00128
00129 rc = async_data_write_start(phone, (void *)opts,
00130 str_size(opts));
00131 if (rc != EOK) {
00132 async_wait_for(msg, NULL);
00133 vfs_release_phone(fs_handle, phone);
00134 fibril_rwlock_write_unlock(&namespace_rwlock);
00135 async_answer_0(rid, rc);
00136 return;
00137 }
00138 async_wait_for(msg, &rc);
00139 vfs_release_phone(fs_handle, phone);
00140
00141 if (rc != EOK) {
00142 fibril_rwlock_write_unlock(&namespace_rwlock);
00143 async_answer_0(rid, rc);
00144 return;
00145 }
00146
00147 rindex = (fs_index_t) IPC_GET_ARG1(answer);
00148 rsize = (size_t) IPC_GET_ARG2(answer);
00149 rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
00150
00151 mr_res.triplet.fs_handle = fs_handle;
00152 mr_res.triplet.devmap_handle = devmap_handle;
00153 mr_res.triplet.index = rindex;
00154 mr_res.size = rsize;
00155 mr_res.lnkcnt = rlnkcnt;
00156 mr_res.type = VFS_NODE_DIRECTORY;
00157
00158 rootfs.fs_handle = fs_handle;
00159 rootfs.devmap_handle = devmap_handle;
00160
00161
00162 mr_node = vfs_node_get(&mr_res);
00163 assert(mr_node);
00164
00165 fibril_rwlock_write_unlock(&namespace_rwlock);
00166 async_answer_0(rid, rc);
00167 return;
00168 } else {
00169
00170
00171
00172
00173 fibril_rwlock_write_unlock(&namespace_rwlock);
00174 async_answer_0(rid, ENOENT);
00175 return;
00176 }
00177 }
00178
00179
00180
00181
00182
00183
00184 int mountee_phone = vfs_grab_phone(fs_handle);
00185 assert(mountee_phone >= 0);
00186
00187 phone = vfs_grab_phone(mp_res.triplet.fs_handle);
00188 msg = async_send_4(phone, VFS_OUT_MOUNT,
00189 (sysarg_t) mp_res.triplet.devmap_handle,
00190 (sysarg_t) mp_res.triplet.index,
00191 (sysarg_t) fs_handle,
00192 (sysarg_t) devmap_handle, &answer);
00193
00194
00195 rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
00196 if (rc != EOK) {
00197 async_wait_for(msg, NULL);
00198 vfs_release_phone(fs_handle, mountee_phone);
00199 vfs_release_phone(mp_res.triplet.fs_handle, phone);
00200
00201 if (mp_node)
00202 vfs_node_put(mp_node);
00203 async_answer_0(rid, rc);
00204 fibril_rwlock_write_unlock(&namespace_rwlock);
00205 return;
00206 }
00207
00208 vfs_release_phone(fs_handle, mountee_phone);
00209
00210
00211 rc = async_data_write_start(phone, (void *)opts, str_size(opts));
00212 if (rc != EOK) {
00213 async_wait_for(msg, NULL);
00214 vfs_release_phone(mp_res.triplet.fs_handle, phone);
00215
00216 if (mp_node)
00217 vfs_node_put(mp_node);
00218 fibril_rwlock_write_unlock(&namespace_rwlock);
00219 async_answer_0(rid, rc);
00220 return;
00221 }
00222 async_wait_for(msg, &rc);
00223 vfs_release_phone(mp_res.triplet.fs_handle, phone);
00224
00225 if (rc == EOK) {
00226 rindex = (fs_index_t) IPC_GET_ARG1(answer);
00227 rsize = (size_t) IPC_GET_ARG2(answer);
00228 rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
00229
00230 mr_res.triplet.fs_handle = fs_handle;
00231 mr_res.triplet.devmap_handle = devmap_handle;
00232 mr_res.triplet.index = rindex;
00233 mr_res.size = rsize;
00234 mr_res.lnkcnt = rlnkcnt;
00235 mr_res.type = VFS_NODE_DIRECTORY;
00236
00237
00238 mr_node = vfs_node_get(&mr_res);
00239 assert(mr_node);
00240 } else {
00241
00242 if (mp_node)
00243 vfs_node_put(mp_node);
00244 }
00245
00246 async_answer_0(rid, rc);
00247 fibril_rwlock_write_unlock(&namespace_rwlock);
00248 }
00249
00250 void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
00251 {
00252 devmap_handle_t devmap_handle;
00253
00254
00255
00256
00257
00258
00259 devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
00260
00261
00262
00263
00264 unsigned int flags = (unsigned int) IPC_GET_ARG2(*request);
00265
00266
00267
00268
00269
00270
00271
00272 char *mp;
00273 int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
00274 0, NULL);
00275 if (rc != EOK) {
00276 async_answer_0(rid, rc);
00277 return;
00278 }
00279
00280
00281 char *opts;
00282 rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
00283 0, NULL);
00284 if (rc != EOK) {
00285 free(mp);
00286 async_answer_0(rid, rc);
00287 return;
00288 }
00289
00290
00291
00292
00293
00294 char *fs_name;
00295 rc = async_data_write_accept((void **) &fs_name, true, 0,
00296 FS_NAME_MAXLEN, 0, NULL);
00297 if (rc != EOK) {
00298 free(mp);
00299 free(opts);
00300 async_answer_0(rid, rc);
00301 return;
00302 }
00303
00304
00305
00306
00307
00308 ipc_call_t data;
00309 ipc_callid_t callid = async_get_call(&data);
00310 if (IPC_GET_IMETHOD(data) != IPC_M_PING) {
00311 async_answer_0(callid, ENOTSUP);
00312 async_answer_0(rid, ENOTSUP);
00313 free(mp);
00314 free(opts);
00315 free(fs_name);
00316 return;
00317 }
00318
00319
00320
00321
00322
00323 fibril_mutex_lock(&fs_head_lock);
00324 fs_handle_t fs_handle;
00325 recheck:
00326 fs_handle = fs_name_to_handle(fs_name, false);
00327 if (!fs_handle) {
00328 if (flags & IPC_FLAG_BLOCKING) {
00329 fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
00330 goto recheck;
00331 }
00332
00333 fibril_mutex_unlock(&fs_head_lock);
00334 async_answer_0(callid, ENOENT);
00335 async_answer_0(rid, ENOENT);
00336 free(mp);
00337 free(fs_name);
00338 free(opts);
00339 return;
00340 }
00341 fibril_mutex_unlock(&fs_head_lock);
00342
00343
00344 async_answer_0(callid, EOK);
00345
00346
00347 vfs_mount_internal(rid, devmap_handle, fs_handle, mp, opts);
00348 free(mp);
00349 free(fs_name);
00350 free(opts);
00351 }
00352
00353 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request)
00354 {
00355 int rc;
00356 char *mp;
00357 vfs_lookup_res_t mp_res;
00358 vfs_lookup_res_t mr_res;
00359 vfs_node_t *mr_node;
00360 int phone;
00361
00362
00363
00364
00365 rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
00366 0, NULL);
00367 if (rc != EOK)
00368 async_answer_0(rid, rc);
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 fibril_rwlock_write_lock(&namespace_rwlock);
00379
00380
00381
00382
00383 rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL);
00384 if (rc != EOK) {
00385 fibril_rwlock_write_unlock(&namespace_rwlock);
00386 free(mp);
00387 async_answer_0(rid, rc);
00388 return;
00389 }
00390 mr_node = vfs_node_get(&mr_res);
00391 if (!mr_node) {
00392 fibril_rwlock_write_unlock(&namespace_rwlock);
00393 free(mp);
00394 async_answer_0(rid, ENOMEM);
00395 return;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405 if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
00406 mr_node->devmap_handle) != 2) {
00407 fibril_rwlock_write_unlock(&namespace_rwlock);
00408 vfs_node_put(mr_node);
00409 free(mp);
00410 async_answer_0(rid, EBUSY);
00411 return;
00412 }
00413
00414 if (str_cmp(mp, "/") == 0) {
00415
00416
00417
00418
00419
00420
00421
00422
00423 free(mp);
00424 phone = vfs_grab_phone(mr_node->fs_handle);
00425 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
00426 mr_node->devmap_handle);
00427 vfs_release_phone(mr_node->fs_handle, phone);
00428 if (rc != EOK) {
00429 fibril_rwlock_write_unlock(&namespace_rwlock);
00430 vfs_node_put(mr_node);
00431 async_answer_0(rid, rc);
00432 return;
00433 }
00434 rootfs.fs_handle = 0;
00435 rootfs.devmap_handle = 0;
00436 } else {
00437
00438
00439
00440
00441
00442
00443
00444
00445 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
00446 free(mp);
00447 if (rc != EOK) {
00448 fibril_rwlock_write_unlock(&namespace_rwlock);
00449 vfs_node_put(mr_node);
00450 async_answer_0(rid, rc);
00451 return;
00452 }
00453 vfs_node_t *mp_node = vfs_node_get(&mp_res);
00454 if (!mp_node) {
00455 fibril_rwlock_write_unlock(&namespace_rwlock);
00456 vfs_node_put(mr_node);
00457 async_answer_0(rid, ENOMEM);
00458 return;
00459 }
00460
00461 phone = vfs_grab_phone(mp_node->fs_handle);
00462 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT,
00463 mp_node->devmap_handle, mp_node->index);
00464 vfs_release_phone(mp_node->fs_handle, phone);
00465 if (rc != EOK) {
00466 fibril_rwlock_write_unlock(&namespace_rwlock);
00467 vfs_node_put(mp_node);
00468 vfs_node_put(mr_node);
00469 async_answer_0(rid, rc);
00470 return;
00471 }
00472
00473
00474 vfs_node_put(mp_node);
00475
00476 vfs_node_put(mp_node);
00477 }
00478
00479
00480
00481
00482
00483
00484 vfs_node_forget(mr_node);
00485
00486 fibril_rwlock_write_unlock(&namespace_rwlock);
00487 async_answer_0(rid, EOK);
00488 }
00489
00490 void vfs_open(ipc_callid_t rid, ipc_call_t *request)
00491 {
00492
00493
00494
00495
00496
00497
00498
00499
00500 int lflag = IPC_GET_ARG1(*request);
00501 int oflag = IPC_GET_ARG2(*request);
00502 int mode = IPC_GET_ARG3(*request);
00503
00504
00505 (void) mode;
00506
00507
00508
00509
00510
00511
00512 if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
00513 ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
00514 (lflag & (L_OPEN | L_ROOT | L_MP))) {
00515 async_answer_0(rid, EINVAL);
00516 return;
00517 }
00518
00519 if (oflag & O_CREAT)
00520 lflag |= L_CREATE;
00521 if (oflag & O_EXCL)
00522 lflag |= L_EXCLUSIVE;
00523
00524 char *path;
00525 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
00526 if (rc != EOK) {
00527 async_answer_0(rid, rc);
00528 return;
00529 }
00530
00531
00532
00533
00534
00535
00536 if (lflag & L_CREATE)
00537 fibril_rwlock_write_lock(&namespace_rwlock);
00538 else
00539 fibril_rwlock_read_lock(&namespace_rwlock);
00540
00541
00542 vfs_lookup_res_t lr;
00543 rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
00544 if (rc != EOK) {
00545 if (lflag & L_CREATE)
00546 fibril_rwlock_write_unlock(&namespace_rwlock);
00547 else
00548 fibril_rwlock_read_unlock(&namespace_rwlock);
00549 async_answer_0(rid, rc);
00550 free(path);
00551 return;
00552 }
00553
00554
00555 free(path);
00556
00557 vfs_node_t *node = vfs_node_get(&lr);
00558 if (lflag & L_CREATE)
00559 fibril_rwlock_write_unlock(&namespace_rwlock);
00560 else
00561 fibril_rwlock_read_unlock(&namespace_rwlock);
00562
00563
00564 if (oflag & O_TRUNC) {
00565 fibril_rwlock_write_lock(&node->contents_rwlock);
00566 if (node->size) {
00567 rc = vfs_truncate_internal(node->fs_handle,
00568 node->devmap_handle, node->index, 0);
00569 if (rc) {
00570 fibril_rwlock_write_unlock(&node->contents_rwlock);
00571 vfs_node_put(node);
00572 async_answer_0(rid, rc);
00573 return;
00574 }
00575 node->size = 0;
00576 }
00577 fibril_rwlock_write_unlock(&node->contents_rwlock);
00578 }
00579
00580
00581
00582
00583
00584 int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
00585 if (fd < 0) {
00586 vfs_node_put(node);
00587 async_answer_0(rid, fd);
00588 return;
00589 }
00590 vfs_file_t *file = vfs_file_get(fd);
00591 assert(file);
00592 file->node = node;
00593 if (oflag & O_APPEND)
00594 file->append = true;
00595
00596
00597
00598
00599
00600
00601
00602
00603 vfs_node_addref(node);
00604 vfs_node_put(node);
00605 vfs_file_put(file);
00606
00607
00608 async_answer_1(rid, EOK, fd);
00609 }
00610
00611 void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
00612 {
00613
00614
00615
00616
00617
00618 vfs_lookup_res_t lr;
00619
00620 lr.triplet.fs_handle = IPC_GET_ARG1(*request);
00621 lr.triplet.devmap_handle = IPC_GET_ARG2(*request);
00622 lr.triplet.index = IPC_GET_ARG3(*request);
00623 int oflag = IPC_GET_ARG4(*request);
00624
00625 fibril_rwlock_read_lock(&namespace_rwlock);
00626
00627 int rc = vfs_open_node_internal(&lr);
00628 if (rc != EOK) {
00629 fibril_rwlock_read_unlock(&namespace_rwlock);
00630 async_answer_0(rid, rc);
00631 return;
00632 }
00633
00634 vfs_node_t *node = vfs_node_get(&lr);
00635 fibril_rwlock_read_unlock(&namespace_rwlock);
00636
00637
00638 if (oflag & O_TRUNC) {
00639 fibril_rwlock_write_lock(&node->contents_rwlock);
00640 if (node->size) {
00641 rc = vfs_truncate_internal(node->fs_handle,
00642 node->devmap_handle, node->index, 0);
00643 if (rc) {
00644 fibril_rwlock_write_unlock(&node->contents_rwlock);
00645 vfs_node_put(node);
00646 async_answer_0(rid, rc);
00647 return;
00648 }
00649 node->size = 0;
00650 }
00651 fibril_rwlock_write_unlock(&node->contents_rwlock);
00652 }
00653
00654
00655
00656
00657
00658 int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
00659 if (fd < 0) {
00660 vfs_node_put(node);
00661 async_answer_0(rid, fd);
00662 return;
00663 }
00664 vfs_file_t *file = vfs_file_get(fd);
00665 file->node = node;
00666 if (oflag & O_APPEND)
00667 file->append = true;
00668
00669
00670
00671
00672
00673
00674
00675
00676 vfs_node_addref(node);
00677 vfs_node_put(node);
00678 vfs_file_put(file);
00679
00680
00681 async_answer_1(rid, EOK, fd);
00682 }
00683
00684 void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
00685 {
00686 int fd = IPC_GET_ARG1(*request);
00687
00688
00689 vfs_file_t *file = vfs_file_get(fd);
00690 if (!file) {
00691 async_answer_0(rid, ENOENT);
00692 return;
00693 }
00694
00695
00696
00697
00698
00699 fibril_mutex_lock(&file->lock);
00700 int fs_phone = vfs_grab_phone(file->node->fs_handle);
00701
00702
00703 aid_t msg;
00704 ipc_call_t answer;
00705 msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->devmap_handle,
00706 file->node->index, &answer);
00707
00708
00709 sysarg_t rc;
00710 async_wait_for(msg, &rc);
00711
00712 vfs_release_phone(file->node->fs_handle, fs_phone);
00713 fibril_mutex_unlock(&file->lock);
00714
00715 vfs_file_put(file);
00716 async_answer_0(rid, rc);
00717 }
00718
00719 void vfs_close(ipc_callid_t rid, ipc_call_t *request)
00720 {
00721 int fd = IPC_GET_ARG1(*request);
00722 int ret;
00723
00724 ret = vfs_fd_free(fd);
00725 async_answer_0(rid, ret);
00726 }
00727
00728 static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
00729 {
00730 vfs_info_t *vi;
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 int fd = IPC_GET_ARG1(*request);
00743
00744
00745 vfs_file_t *file = vfs_file_get(fd);
00746 if (!file) {
00747 async_answer_0(rid, ENOENT);
00748 return;
00749 }
00750
00751
00752
00753
00754
00755 fibril_mutex_lock(&file->lock);
00756
00757 vi = fs_handle_to_info(file->node->fs_handle);
00758 assert(vi);
00759
00760
00761
00762
00763
00764
00765 if (read || (vi->concurrent_read_write && vi->write_retains_size))
00766 fibril_rwlock_read_lock(&file->node->contents_rwlock);
00767 else
00768 fibril_rwlock_write_lock(&file->node->contents_rwlock);
00769
00770 if (file->node->type == VFS_NODE_DIRECTORY) {
00771
00772
00773
00774
00775 assert(read);
00776 fibril_rwlock_read_lock(&namespace_rwlock);
00777 }
00778
00779 int fs_phone = vfs_grab_phone(file->node->fs_handle);
00780
00781
00782
00783
00784
00785
00786
00787
00788 sysarg_t rc;
00789 ipc_call_t answer;
00790 if (read) {
00791 rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
00792 file->node->devmap_handle, file->node->index, file->pos,
00793 &answer);
00794 } else {
00795 if (file->append)
00796 file->pos = file->node->size;
00797
00798 rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
00799 file->node->devmap_handle, file->node->index, file->pos,
00800 &answer);
00801 }
00802
00803 vfs_release_phone(file->node->fs_handle, fs_phone);
00804
00805 size_t bytes = IPC_GET_ARG1(answer);
00806
00807 if (file->node->type == VFS_NODE_DIRECTORY)
00808 fibril_rwlock_read_unlock(&namespace_rwlock);
00809
00810
00811 if (read || (vi->concurrent_read_write && vi->write_retains_size))
00812 fibril_rwlock_read_unlock(&file->node->contents_rwlock);
00813 else {
00814
00815 if (rc == EOK)
00816 file->node->size = IPC_GET_ARG2(answer);
00817 fibril_rwlock_write_unlock(&file->node->contents_rwlock);
00818 }
00819
00820
00821 if (rc == EOK)
00822 file->pos += bytes;
00823 fibril_mutex_unlock(&file->lock);
00824 vfs_file_put(file);
00825
00826
00827
00828
00829
00830 async_answer_1(rid, rc, bytes);
00831 }
00832
00833 void vfs_read(ipc_callid_t rid, ipc_call_t *request)
00834 {
00835 vfs_rdwr(rid, request, true);
00836 }
00837
00838 void vfs_write(ipc_callid_t rid, ipc_call_t *request)
00839 {
00840 vfs_rdwr(rid, request, false);
00841 }
00842
00843 void vfs_seek(ipc_callid_t rid, ipc_call_t *request)
00844 {
00845 int fd = (int) IPC_GET_ARG1(*request);
00846 off64_t off = (off64_t) MERGE_LOUP32(IPC_GET_ARG2(*request),
00847 IPC_GET_ARG3(*request));
00848 int whence = (int) IPC_GET_ARG4(*request);
00849
00850
00851 vfs_file_t *file = vfs_file_get(fd);
00852 if (!file) {
00853 async_answer_0(rid, ENOENT);
00854 return;
00855 }
00856
00857 fibril_mutex_lock(&file->lock);
00858
00859 off64_t newoff;
00860 switch (whence) {
00861 case SEEK_SET:
00862 if (off >= 0) {
00863 file->pos = (aoff64_t) off;
00864 fibril_mutex_unlock(&file->lock);
00865 vfs_file_put(file);
00866 async_answer_1(rid, EOK, off);
00867 return;
00868 }
00869 break;
00870 case SEEK_CUR:
00871 if ((off >= 0) && (file->pos + off < file->pos)) {
00872 fibril_mutex_unlock(&file->lock);
00873 vfs_file_put(file);
00874 async_answer_0(rid, EOVERFLOW);
00875 return;
00876 }
00877
00878 if ((off < 0) && (file->pos < (aoff64_t) -off)) {
00879 fibril_mutex_unlock(&file->lock);
00880 vfs_file_put(file);
00881 async_answer_0(rid, EOVERFLOW);
00882 return;
00883 }
00884
00885 file->pos += off;
00886 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos;
00887
00888 fibril_mutex_unlock(&file->lock);
00889 vfs_file_put(file);
00890 async_answer_2(rid, EOK, LOWER32(newoff),
00891 UPPER32(newoff));
00892 return;
00893 case SEEK_END:
00894 fibril_rwlock_read_lock(&file->node->contents_rwlock);
00895 aoff64_t size = file->node->size;
00896
00897 if ((off >= 0) && (size + off < size)) {
00898 fibril_rwlock_read_unlock(&file->node->contents_rwlock);
00899 fibril_mutex_unlock(&file->lock);
00900 vfs_file_put(file);
00901 async_answer_0(rid, EOVERFLOW);
00902 return;
00903 }
00904
00905 if ((off < 0) && (size < (aoff64_t) -off)) {
00906 fibril_rwlock_read_unlock(&file->node->contents_rwlock);
00907 fibril_mutex_unlock(&file->lock);
00908 vfs_file_put(file);
00909 async_answer_0(rid, EOVERFLOW);
00910 return;
00911 }
00912
00913 file->pos = size + off;
00914 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos;
00915
00916 fibril_rwlock_read_unlock(&file->node->contents_rwlock);
00917 fibril_mutex_unlock(&file->lock);
00918 vfs_file_put(file);
00919 async_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
00920 return;
00921 }
00922
00923 fibril_mutex_unlock(&file->lock);
00924 vfs_file_put(file);
00925 async_answer_0(rid, EINVAL);
00926 }
00927
00928 int vfs_truncate_internal(fs_handle_t fs_handle, devmap_handle_t devmap_handle,
00929 fs_index_t index, aoff64_t size)
00930 {
00931 sysarg_t rc;
00932 int fs_phone;
00933
00934 fs_phone = vfs_grab_phone(fs_handle);
00935 rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (sysarg_t) devmap_handle,
00936 (sysarg_t) index, LOWER32(size), UPPER32(size));
00937 vfs_release_phone(fs_handle, fs_phone);
00938 return (int)rc;
00939 }
00940
00941 void vfs_truncate(ipc_callid_t rid, ipc_call_t *request)
00942 {
00943 int fd = IPC_GET_ARG1(*request);
00944 aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(*request),
00945 IPC_GET_ARG3(*request));
00946 int rc;
00947
00948 vfs_file_t *file = vfs_file_get(fd);
00949 if (!file) {
00950 async_answer_0(rid, ENOENT);
00951 return;
00952 }
00953 fibril_mutex_lock(&file->lock);
00954
00955 fibril_rwlock_write_lock(&file->node->contents_rwlock);
00956 rc = vfs_truncate_internal(file->node->fs_handle,
00957 file->node->devmap_handle, file->node->index, size);
00958 if (rc == EOK)
00959 file->node->size = size;
00960 fibril_rwlock_write_unlock(&file->node->contents_rwlock);
00961
00962 fibril_mutex_unlock(&file->lock);
00963 vfs_file_put(file);
00964 async_answer_0(rid, (sysarg_t)rc);
00965 }
00966
00967 void vfs_fstat(ipc_callid_t rid, ipc_call_t *request)
00968 {
00969 int fd = IPC_GET_ARG1(*request);
00970 sysarg_t rc;
00971
00972 vfs_file_t *file = vfs_file_get(fd);
00973 if (!file) {
00974 async_answer_0(rid, ENOENT);
00975 return;
00976 }
00977
00978 ipc_callid_t callid;
00979 if (!async_data_read_receive(&callid, NULL)) {
00980 vfs_file_put(file);
00981 async_answer_0(callid, EINVAL);
00982 async_answer_0(rid, EINVAL);
00983 return;
00984 }
00985
00986 fibril_mutex_lock(&file->lock);
00987
00988 int fs_phone = vfs_grab_phone(file->node->fs_handle);
00989
00990 aid_t msg;
00991 msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle,
00992 file->node->index, true, NULL);
00993 async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
00994 async_wait_for(msg, &rc);
00995 vfs_release_phone(file->node->fs_handle, fs_phone);
00996
00997 fibril_mutex_unlock(&file->lock);
00998 vfs_file_put(file);
00999 async_answer_0(rid, rc);
01000 }
01001
01002 void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
01003 {
01004 char *path;
01005 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
01006 if (rc != EOK) {
01007 async_answer_0(rid, rc);
01008 return;
01009 }
01010
01011 ipc_callid_t callid;
01012 if (!async_data_read_receive(&callid, NULL)) {
01013 free(path);
01014 async_answer_0(callid, EINVAL);
01015 async_answer_0(rid, EINVAL);
01016 return;
01017 }
01018
01019 vfs_lookup_res_t lr;
01020 fibril_rwlock_read_lock(&namespace_rwlock);
01021 rc = vfs_lookup_internal(path, L_NONE, &lr, NULL);
01022 free(path);
01023 if (rc != EOK) {
01024 fibril_rwlock_read_unlock(&namespace_rwlock);
01025 async_answer_0(callid, rc);
01026 async_answer_0(rid, rc);
01027 return;
01028 }
01029 vfs_node_t *node = vfs_node_get(&lr);
01030 if (!node) {
01031 fibril_rwlock_read_unlock(&namespace_rwlock);
01032 async_answer_0(callid, ENOMEM);
01033 async_answer_0(rid, ENOMEM);
01034 return;
01035 }
01036
01037 fibril_rwlock_read_unlock(&namespace_rwlock);
01038
01039 int fs_phone = vfs_grab_phone(node->fs_handle);
01040 aid_t msg;
01041 msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle,
01042 node->index, false, NULL);
01043 async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
01044
01045 sysarg_t rv;
01046 async_wait_for(msg, &rv);
01047 vfs_release_phone(node->fs_handle, fs_phone);
01048
01049 async_answer_0(rid, rv);
01050
01051 vfs_node_put(node);
01052 }
01053
01054 void vfs_mkdir(ipc_callid_t rid, ipc_call_t *request)
01055 {
01056 int mode = IPC_GET_ARG1(*request);
01057
01058 char *path;
01059 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
01060 if (rc != EOK) {
01061 async_answer_0(rid, rc);
01062 return;
01063 }
01064
01065
01066 (void) mode;
01067
01068 fibril_rwlock_write_lock(&namespace_rwlock);
01069 int lflag = L_DIRECTORY | L_CREATE | L_EXCLUSIVE;
01070 rc = vfs_lookup_internal(path, lflag, NULL, NULL);
01071 fibril_rwlock_write_unlock(&namespace_rwlock);
01072 free(path);
01073 async_answer_0(rid, rc);
01074 }
01075
01076 void vfs_unlink(ipc_callid_t rid, ipc_call_t *request)
01077 {
01078 int lflag = IPC_GET_ARG1(*request);
01079
01080 char *path;
01081 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
01082 if (rc != EOK) {
01083 async_answer_0(rid, rc);
01084 return;
01085 }
01086
01087 fibril_rwlock_write_lock(&namespace_rwlock);
01088 lflag &= L_DIRECTORY;
01089 vfs_lookup_res_t lr;
01090 rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL);
01091 free(path);
01092 if (rc != EOK) {
01093 fibril_rwlock_write_unlock(&namespace_rwlock);
01094 async_answer_0(rid, rc);
01095 return;
01096 }
01097
01098
01099
01100
01101
01102
01103 vfs_node_t *node = vfs_node_get(&lr);
01104 fibril_mutex_lock(&nodes_mutex);
01105 node->lnkcnt--;
01106 fibril_mutex_unlock(&nodes_mutex);
01107 fibril_rwlock_write_unlock(&namespace_rwlock);
01108 vfs_node_put(node);
01109 async_answer_0(rid, EOK);
01110 }
01111
01112 void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
01113 {
01114
01115 char *old;
01116 int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
01117 if (rc != EOK) {
01118 async_answer_0(rid, rc);
01119 return;
01120 }
01121
01122
01123 char *new;
01124 rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
01125 if (rc != EOK) {
01126 free(old);
01127 async_answer_0(rid, rc);
01128 return;
01129 }
01130
01131 size_t olen;
01132 size_t nlen;
01133 char *oldc = canonify(old, &olen);
01134 char *newc = canonify(new, &nlen);
01135
01136 if ((!oldc) || (!newc)) {
01137 async_answer_0(rid, EINVAL);
01138 free(old);
01139 free(new);
01140 return;
01141 }
01142
01143 oldc[olen] = '\0';
01144 newc[nlen] = '\0';
01145
01146 if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
01147 ((newc[str_length(oldc)] == '/') ||
01148 (str_length(oldc) == 1) ||
01149 (str_length(oldc) == str_length(newc)))) {
01150
01151
01152
01153
01154
01155
01156 async_answer_0(rid, EINVAL);
01157 free(old);
01158 free(new);
01159 return;
01160 }
01161
01162 vfs_lookup_res_t old_lr;
01163 vfs_lookup_res_t new_lr;
01164 vfs_lookup_res_t new_par_lr;
01165 fibril_rwlock_write_lock(&namespace_rwlock);
01166
01167
01168 rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
01169 if (rc != EOK) {
01170 fibril_rwlock_write_unlock(&namespace_rwlock);
01171 async_answer_0(rid, rc);
01172 free(old);
01173 free(new);
01174 return;
01175 }
01176
01177 vfs_node_t *old_node = vfs_node_get(&old_lr);
01178 if (!old_node) {
01179 fibril_rwlock_write_unlock(&namespace_rwlock);
01180 async_answer_0(rid, ENOMEM);
01181 free(old);
01182 free(new);
01183 return;
01184 }
01185
01186
01187 char *parentc = str_dup(newc);
01188 if (!parentc) {
01189 fibril_rwlock_write_unlock(&namespace_rwlock);
01190 vfs_node_put(old_node);
01191 async_answer_0(rid, rc);
01192 free(old);
01193 free(new);
01194 return;
01195 }
01196
01197 char *lastsl = str_rchr(parentc + 1, '/');
01198 if (lastsl)
01199 *lastsl = '\0';
01200 else
01201 parentc[1] = '\0';
01202
01203
01204 rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
01205 free(parentc);
01206 if (rc != EOK) {
01207 fibril_rwlock_write_unlock(&namespace_rwlock);
01208 vfs_node_put(old_node);
01209 async_answer_0(rid, rc);
01210 free(old);
01211 free(new);
01212 return;
01213 }
01214
01215
01216 if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
01217 (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) {
01218 fibril_rwlock_write_unlock(&namespace_rwlock);
01219 vfs_node_put(old_node);
01220 async_answer_0(rid, EXDEV);
01221 free(old);
01222 free(new);
01223 return;
01224 }
01225
01226
01227 vfs_node_t *new_node = NULL;
01228 rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
01229
01230 switch (rc) {
01231 case ENOENT:
01232
01233 break;
01234 case EOK:
01235 new_node = vfs_node_get(&new_lr);
01236 if (!new_node) {
01237 fibril_rwlock_write_unlock(&namespace_rwlock);
01238 vfs_node_put(old_node);
01239 async_answer_0(rid, ENOMEM);
01240 free(old);
01241 free(new);
01242 return;
01243 }
01244 fibril_mutex_lock(&nodes_mutex);
01245 new_node->lnkcnt--;
01246 fibril_mutex_unlock(&nodes_mutex);
01247 break;
01248 default:
01249 fibril_rwlock_write_unlock(&namespace_rwlock);
01250 vfs_node_put(old_node);
01251 async_answer_0(rid, ENOTEMPTY);
01252 free(old);
01253 free(new);
01254 return;
01255 }
01256
01257
01258 rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
01259 if (rc != EOK) {
01260 fibril_rwlock_write_unlock(&namespace_rwlock);
01261 vfs_node_put(old_node);
01262 if (new_node)
01263 vfs_node_put(new_node);
01264 async_answer_0(rid, rc);
01265 free(old);
01266 free(new);
01267 return;
01268 }
01269
01270 fibril_mutex_lock(&nodes_mutex);
01271 old_node->lnkcnt++;
01272 fibril_mutex_unlock(&nodes_mutex);
01273
01274
01275 rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
01276 if (rc != EOK) {
01277 fibril_rwlock_write_unlock(&namespace_rwlock);
01278 vfs_node_put(old_node);
01279 if (new_node)
01280 vfs_node_put(new_node);
01281 async_answer_0(rid, rc);
01282 free(old);
01283 free(new);
01284 return;
01285 }
01286
01287 fibril_mutex_lock(&nodes_mutex);
01288 old_node->lnkcnt--;
01289 fibril_mutex_unlock(&nodes_mutex);
01290 fibril_rwlock_write_unlock(&namespace_rwlock);
01291 vfs_node_put(old_node);
01292
01293 if (new_node)
01294 vfs_node_put(new_node);
01295
01296 free(old);
01297 free(new);
01298 async_answer_0(rid, EOK);
01299 }
01300
01301 void vfs_dup(ipc_callid_t rid, ipc_call_t *request)
01302 {
01303 int oldfd = IPC_GET_ARG1(*request);
01304 int newfd = IPC_GET_ARG2(*request);
01305
01306
01307 if (oldfd == newfd) {
01308 async_answer_1(rid, EOK, newfd);
01309 return;
01310 }
01311
01312
01313 vfs_file_t *oldfile = vfs_file_get(oldfd);
01314 if (!oldfile) {
01315 async_answer_0(rid, EBADF);
01316 return;
01317 }
01318
01319
01320
01321
01322
01323 fibril_mutex_lock(&oldfile->lock);
01324
01325
01326 (void) vfs_fd_free(newfd);
01327
01328
01329 int ret = vfs_fd_assign(oldfile, newfd);
01330 fibril_mutex_unlock(&oldfile->lock);
01331 vfs_file_put(oldfile);
01332
01333 if (ret != EOK)
01334 async_answer_0(rid, ret);
01335 else
01336 async_answer_1(rid, EOK, newfd);
01337 }
01338