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