Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs_ops.c

    red903174 r1e4cada  
    3838#include "vfs.h"
    3939#include <ipc/ipc.h>
    40 #include <macros.h>
    41 #include <limits.h>
    4240#include <async.h>
    4341#include <errno.h>
     
    5553
    5654/* Forward declarations of static functions. */
    57 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, aoff64_t);
     55static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
    5856
    5957/**
     
    9492                }
    9593               
    96                 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
     94                rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
    9795                if (rc != EOK) {
    9896                        /* The lookup failed for some reason. */
     
    268266       
    269267        /* We want the client to send us the mount point. */
    270         char *mp;
    271         int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
    272             0, NULL);
    273         if (rc != EOK) {
    274                 ipc_answer_0(rid, rc);
    275                 return;
    276         }
     268        ipc_callid_t callid;
     269        size_t size;
     270        if (!async_data_write_receive(&callid, &size)) {
     271                ipc_answer_0(callid, EINVAL);
     272                ipc_answer_0(rid, EINVAL);
     273                return;
     274        }
     275       
     276        /* Check whether size is reasonable wrt. the mount point. */
     277        if ((size < 1) || (size > MAX_PATH_LEN)) {
     278                ipc_answer_0(callid, EINVAL);
     279                ipc_answer_0(rid, EINVAL);
     280                return;
     281        }
     282       
     283        /* Allocate buffer for the mount point data being received. */
     284        char *mp = malloc(size + 1);
     285        if (!mp) {
     286                ipc_answer_0(callid, ENOMEM);
     287                ipc_answer_0(rid, ENOMEM);
     288                return;
     289        }
     290       
     291        /* Deliver the mount point. */
     292        ipcarg_t retval = async_data_write_finalize(callid, mp, size);
     293        if (retval != EOK) {
     294                ipc_answer_0(rid, retval);
     295                free(mp);
     296                return;
     297        }
     298        mp[size] = '\0';
    277299       
    278300        /* Now we expect to receive the mount options. */
    279         char *opts;
    280         rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
    281             0, NULL);
    282         if (rc != EOK) {
     301        if (!async_data_write_receive(&callid, &size)) {
     302                ipc_answer_0(callid, EINVAL);
     303                ipc_answer_0(rid, EINVAL);
    283304                free(mp);
    284                 ipc_answer_0(rid, rc);
    285                 return;
    286         }
     305                return;
     306        }
     307
     308        /* Check the offered options size. */
     309        if (size > MAX_MNTOPTS_LEN) {
     310                ipc_answer_0(callid, EINVAL);
     311                ipc_answer_0(rid, EINVAL);
     312                free(mp);
     313                return;
     314        }
     315
     316        /* Allocate buffer for the mount options. */
     317        char *opts = (char *) malloc(size + 1);
     318        if (!opts) {
     319                ipc_answer_0(callid, ENOMEM);
     320                ipc_answer_0(rid, ENOMEM);
     321                free(mp);
     322                return;
     323        }
     324
     325        /* Deliver the mount options. */
     326        retval = async_data_write_finalize(callid, opts, size);
     327        if (retval != EOK) {
     328                ipc_answer_0(rid, retval);
     329                free(mp);
     330                free(opts);
     331                return;
     332        }
     333        opts[size] = '\0';
    287334       
    288335        /*
     
    290337         * system.
    291338         */
    292         char *fs_name;
    293         rc = async_data_write_accept((void **) &fs_name, true, 0, FS_NAME_MAXLEN,
    294             0, NULL);
    295         if (rc != EOK) {
     339        if (!async_data_write_receive(&callid, &size)) {
     340                ipc_answer_0(callid, EINVAL);
     341                ipc_answer_0(rid, EINVAL);
    296342                free(mp);
    297343                free(opts);
    298                 ipc_answer_0(rid, rc);
    299                 return;
    300         }
    301        
     344                return;
     345        }
     346       
     347        /*
     348         * Don't receive more than is necessary for storing a full file system
     349         * name.
     350         */
     351        if ((size < 1) || (size > FS_NAME_MAXLEN)) {
     352                ipc_answer_0(callid, EINVAL);
     353                ipc_answer_0(rid, EINVAL);
     354                free(mp);
     355                free(opts);
     356                return;
     357        }
     358       
     359        /*
     360         * Allocate buffer for file system name.
     361         */
     362        char *fs_name = (char *) malloc(size + 1);
     363        if (fs_name == NULL) {
     364                ipc_answer_0(callid, ENOMEM);
     365                ipc_answer_0(rid, ENOMEM);
     366                free(mp);
     367                free(opts);
     368                return;
     369        }
     370       
     371        /* Deliver the file system name. */
     372        retval = async_data_write_finalize(callid, fs_name, size);
     373        if (retval != EOK) {
     374                ipc_answer_0(rid, retval);
     375                free(mp);
     376                free(opts);
     377                free(fs_name);
     378                return;
     379        }
     380        fs_name[size] = '\0';
     381
    302382        /*
    303383         * Wait for IPC_M_PING so that we can return an error if we don't know
     
    305385         */
    306386        ipc_call_t data;
    307         ipc_callid_t callid = async_get_call(&data);
     387        callid = async_get_call(&data);
    308388        if (IPC_GET_METHOD(data) != IPC_M_PING) {
    309389                ipc_answer_0(callid, ENOTSUP);
     
    349429}
    350430
    351 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request)
    352 {
    353         int rc;
    354         char *mp;
    355         vfs_lookup_res_t mp_res;
    356         vfs_lookup_res_t mr_res;
    357         vfs_node_t *mr_node;
    358         int phone;
    359 
    360         /*
    361          * Receive the mount point path.
    362          */
    363         rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
    364             0, NULL);
    365         if (rc != EOK)
    366                 ipc_answer_0(rid, rc);
    367 
    368         /*
    369          * Taking the namespace lock will do two things for us. First, it will
    370          * prevent races with other lookup operations. Second, it will stop new
    371          * references to already existing VFS nodes and creation of new VFS
    372          * nodes. This is because new references are added as a result of some
    373          * lookup operation or at least of some operation which is protected by
    374          * the namespace lock.
    375          */
    376         fibril_rwlock_write_lock(&namespace_rwlock);
    377        
    378         /*
    379          * Lookup the mounted root and instantiate it.
    380          */
    381         rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL);
    382         if (rc != EOK) {
    383                 fibril_rwlock_write_unlock(&namespace_rwlock);
    384                 free(mp);
    385                 ipc_answer_0(rid, rc);
    386                 return;
    387         }
    388         mr_node = vfs_node_get(&mr_res);
    389         if (!mr_node) {
    390                 fibril_rwlock_write_unlock(&namespace_rwlock);
    391                 free(mp);
    392                 ipc_answer_0(rid, ENOMEM);
    393                 return;
    394         }
    395 
    396         /*
    397          * Count the total number of references for the mounted file system. We
    398          * are expecting at least two. One which we got above and one which we
    399          * got when the file system was mounted. If we find more, it means that
    400          * the file system cannot be gracefully unmounted at the moment because
    401          * someone is working with it.
    402          */
    403         if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
    404             mr_node->dev_handle) != 2) {
    405                 fibril_rwlock_write_unlock(&namespace_rwlock);
    406                 vfs_node_put(mr_node);
    407                 free(mp);
    408                 ipc_answer_0(rid, EBUSY);
    409                 return;
    410         }
    411 
    412         if (str_cmp(mp, "/") == 0) {
    413 
    414                 /*
    415                  * Unmounting the root file system.
    416                  *
    417                  * In this case, there is no mount point node and we send
    418                  * VFS_OUT_UNMOUNTED directly to the mounted file system.
    419                  */
    420 
    421                 free(mp);
    422                 phone = vfs_grab_phone(mr_node->fs_handle);
    423                 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
    424                     mr_node->dev_handle);
    425                 vfs_release_phone(phone);
    426                 if (rc != EOK) {
    427                         fibril_rwlock_write_unlock(&namespace_rwlock);
    428                         vfs_node_put(mr_node);
    429                         ipc_answer_0(rid, rc);
    430                         return;
    431                 }
    432                 rootfs.fs_handle = 0;
    433                 rootfs.dev_handle = 0;
    434         } else {
    435 
    436                 /*
    437                  * Unmounting a non-root file system.
    438                  *
    439                  * We have a regular mount point node representing the parent
    440                  * file system, so we delegate the operation to it.
    441                  */
    442 
    443                 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
    444                 free(mp);
    445                 if (rc != EOK) {
    446                         fibril_rwlock_write_unlock(&namespace_rwlock);
    447                         vfs_node_put(mr_node);
    448                         ipc_answer_0(rid, rc);
    449                         return;
    450                 }
    451                 vfs_node_t *mp_node = vfs_node_get(&mp_res);
    452                 if (!mp_node) {
    453                         fibril_rwlock_write_unlock(&namespace_rwlock);
    454                         vfs_node_put(mr_node);
    455                         ipc_answer_0(rid, ENOMEM);
    456                         return;
    457                 }
    458 
    459                 phone = vfs_grab_phone(mp_node->fs_handle);
    460                 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle,
    461                     mp_node->index);
    462                 vfs_release_phone(phone);
    463                 if (rc != EOK) {
    464                         fibril_rwlock_write_unlock(&namespace_rwlock);
    465                         vfs_node_put(mp_node);
    466                         vfs_node_put(mr_node);
    467                         ipc_answer_0(rid, rc);
    468                         return;
    469                 }
    470 
    471                 /* Drop the reference we got above. */
    472                 vfs_node_put(mp_node);
    473                 /* Drop the reference from when the file system was mounted. */
    474                 vfs_node_put(mp_node);
    475         }
    476 
    477 
    478         /*
    479          * All went well, the mounted file system was successfully unmounted.
    480          * The only thing left is to forget the unmounted root VFS node.
    481          */
    482         vfs_node_forget(mr_node);
    483 
    484         fibril_rwlock_write_unlock(&namespace_rwlock);
    485         ipc_answer_0(rid, EOK);
    486 }
    487 
    488431void vfs_open(ipc_callid_t rid, ipc_call_t *request)
    489432{
     
    504447        int oflag = IPC_GET_ARG2(*request);
    505448        int mode = IPC_GET_ARG3(*request);
     449        size_t len;
    506450
    507451        /* Ignore mode for now. */
     
    510454        /*
    511455         * Make sure that we are called with exactly one of L_FILE and
    512          * L_DIRECTORY. Make sure that the user does not pass L_OPEN,
    513          * L_ROOT or L_MP.
     456         * L_DIRECTORY. Make sure that the user does not pass L_OPEN.
    514457         */
    515458        if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
    516459            ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
    517             (lflag & (L_OPEN | L_ROOT | L_MP))) {
     460            ((lflag & L_OPEN) != 0)) {
    518461                ipc_answer_0(rid, EINVAL);
    519462                return;
     
    525468                lflag |= L_EXCLUSIVE;
    526469       
    527         char *path;
    528         int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
    529         if (rc != EOK) {
    530                 ipc_answer_0(rid, rc);
    531                 return;
    532         }
     470        ipc_callid_t callid;
     471        if (!async_data_write_receive(&callid, &len)) {
     472                ipc_answer_0(callid, EINVAL);
     473                ipc_answer_0(rid, EINVAL);
     474                return;
     475        }
     476       
     477        char *path = malloc(len + 1);
     478        if (!path) {
     479                ipc_answer_0(callid, ENOMEM);
     480                ipc_answer_0(rid, ENOMEM);
     481                return;
     482        }
     483       
     484        int rc;
     485        if ((rc = async_data_write_finalize(callid, path, len))) {
     486                ipc_answer_0(rid, rc);
     487                free(path);
     488                return;
     489        }
     490        path[len] = '\0';
    533491       
    534492        /*
     
    721679}
    722680
    723 int vfs_close_internal(vfs_file_t *file)
     681static int vfs_close_internal(vfs_file_t *file)
    724682{
    725683        /*
     
    798756       
    799757        /*
     758         * Now we need to receive a call with client's
     759         * IPC_M_DATA_READ/IPC_M_DATA_WRITE request.
     760         */
     761        ipc_callid_t callid;
     762        int res;
     763        if (read)
     764                res = async_data_read_receive(&callid, NULL);
     765        else
     766                res = async_data_write_receive(&callid, NULL);
     767        if (!res) {
     768                ipc_answer_0(callid, EINVAL);
     769                ipc_answer_0(rid, EINVAL);
     770                return;
     771        }
     772       
     773        /*
    800774         * Lock the open file structure so that no other thread can manipulate
    801775         * the same open file at a time.
     
    821795        }
    822796       
    823         int fs_phone = vfs_grab_phone(file->node->fs_handle);
    824        
    825         /*
    826          * Make a VFS_READ/VFS_WRITE request at the destination FS server
    827          * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
     797        int fs_phone = vfs_grab_phone(file->node->fs_handle);   
     798       
     799        /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
     800        aid_t msg;
     801        ipc_call_t answer;
     802        if (!read && file->append)
     803                file->pos = file->node->size;
     804        msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE,
     805            file->node->dev_handle, file->node->index, file->pos, &answer);
     806       
     807        /*
     808         * Forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
    828809         * destination FS server. The call will be routed as if sent by
    829810         * ourselves. Note that call arguments are immutable in this case so we
    830811         * don't have to bother.
    831812         */
     813        ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     814
     815        /* Wait for reply from the FS server. */
    832816        ipcarg_t rc;
    833         ipc_call_t answer;
    834         if (read) {
    835                 if (file->append)
    836                         file->pos = file->node->size;
    837                
    838                 rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
    839                     file->node->dev_handle, file->node->index, file->pos,
    840                     &answer);
    841         } else {
    842                 rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
    843                     file->node->dev_handle, file->node->index, file->pos,
    844                     &answer);
    845         }
     817        async_wait_for(msg, &rc);
    846818       
    847819        vfs_release_phone(fs_phone);
    848820       
    849821        size_t bytes = IPC_GET_ARG1(answer);
    850        
     822
    851823        if (file->node->type == VFS_NODE_DIRECTORY)
    852824                fibril_rwlock_read_unlock(&namespace_rwlock);
     
    887859{
    888860        int fd = (int) IPC_GET_ARG1(*request);
    889         off64_t off =
    890             (off64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request));
    891         int whence = (int) IPC_GET_ARG4(*request);
    892        
     861        off_t off = (off_t) IPC_GET_ARG2(*request);
     862        int whence = (int) IPC_GET_ARG3(*request);
     863
     864
    893865        /* Lookup the file structure corresponding to the file descriptor. */
    894866        vfs_file_t *file = vfs_file_get(fd);
     
    897869                return;
    898870        }
    899        
     871
     872        off_t newpos;
    900873        fibril_mutex_lock(&file->lock);
    901        
    902         off64_t newoff;
    903         switch (whence) {
    904                 case SEEK_SET:
    905                         if (off >= 0) {
    906                                 file->pos = (aoff64_t) off;
    907                                 fibril_mutex_unlock(&file->lock);
    908                                 ipc_answer_1(rid, EOK, off);
    909                                 return;
    910                         }
    911                         break;
    912                 case SEEK_CUR:
    913                         if ((off >= 0) && (file->pos + off < file->pos)) {
    914                                 fibril_mutex_unlock(&file->lock);
    915                                 ipc_answer_0(rid, EOVERFLOW);
    916                                 return;
    917                         }
    918                        
    919                         if ((off < 0) && (file->pos < (aoff64_t) -off)) {
    920                                 fibril_mutex_unlock(&file->lock);
    921                                 ipc_answer_0(rid, EOVERFLOW);
    922                                 return;
    923                         }
    924                        
    925                         file->pos += off;
    926                         newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos;
    927                        
     874        if (whence == SEEK_SET) {
     875                file->pos = off;
     876                fibril_mutex_unlock(&file->lock);
     877                ipc_answer_1(rid, EOK, off);
     878                return;
     879        }
     880        if (whence == SEEK_CUR) {
     881                if (file->pos + off < file->pos) {
    928882                        fibril_mutex_unlock(&file->lock);
    929                         ipc_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
     883                        ipc_answer_0(rid, EOVERFLOW);
    930884                        return;
    931                 case SEEK_END:
    932                         fibril_rwlock_read_lock(&file->node->contents_rwlock);
    933                         aoff64_t size = file->node->size;
    934                        
    935                         if ((off >= 0) && (size + off < size)) {
    936                                 fibril_rwlock_read_unlock(&file->node->contents_rwlock);
    937                                 fibril_mutex_unlock(&file->lock);
    938                                 ipc_answer_0(rid, EOVERFLOW);
    939                                 return;
    940                         }
    941                        
    942                         if ((off < 0) && (size < (aoff64_t) -off)) {
    943                                 fibril_rwlock_read_unlock(&file->node->contents_rwlock);
    944                                 fibril_mutex_unlock(&file->lock);
    945                                 ipc_answer_0(rid, EOVERFLOW);
    946                                 return;
    947                         }
    948                        
    949                         file->pos = size + off;
    950                         newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos;
    951                        
    952                         fibril_rwlock_read_unlock(&file->node->contents_rwlock);
     885                }
     886                file->pos += off;
     887                newpos = file->pos;
     888                fibril_mutex_unlock(&file->lock);
     889                ipc_answer_1(rid, EOK, newpos);
     890                return;
     891        }
     892        if (whence == SEEK_END) {
     893                fibril_rwlock_read_lock(&file->node->contents_rwlock);
     894                size_t size = file->node->size;
     895                fibril_rwlock_read_unlock(&file->node->contents_rwlock);
     896                if (size + off < size) {
    953897                        fibril_mutex_unlock(&file->lock);
    954                         ipc_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff));
     898                        ipc_answer_0(rid, EOVERFLOW);
    955899                        return;
    956         }
    957        
     900                }
     901                newpos = size + off;
     902                fibril_mutex_unlock(&file->lock);
     903                ipc_answer_1(rid, EOK, newpos);
     904                return;
     905        }
    958906        fibril_mutex_unlock(&file->lock);
    959907        ipc_answer_0(rid, EINVAL);
    960908}
    961909
    962 int vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,
    963     fs_index_t index, aoff64_t size)
     910int
     911vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,
     912    fs_index_t index, size_t size)
    964913{
    965914        ipcarg_t rc;
     
    967916       
    968917        fs_phone = vfs_grab_phone(fs_handle);
    969         rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t) dev_handle,
    970             (ipcarg_t) index, LOWER32(size), UPPER32(size));
     918        rc = async_req_3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,
     919            (ipcarg_t)index, (ipcarg_t)size);
    971920        vfs_release_phone(fs_phone);
    972921        return (int)rc;
     
    976925{
    977926        int fd = IPC_GET_ARG1(*request);
    978         aoff64_t size =
    979             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request));
     927        size_t size = IPC_GET_ARG2(*request);
    980928        int rc;
    981929
     
    1033981void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
    1034982{
    1035         char *path;
    1036         int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
    1037         if (rc != EOK) {
    1038                 ipc_answer_0(rid, rc);
    1039                 return;
    1040         }
    1041        
     983        size_t len;
    1042984        ipc_callid_t callid;
     985
     986        if (!async_data_write_receive(&callid, &len)) {
     987                ipc_answer_0(callid, EINVAL);
     988                ipc_answer_0(rid, EINVAL);
     989                return;
     990        }
     991        char *path = malloc(len + 1);
     992        if (!path) {
     993                ipc_answer_0(callid, ENOMEM);
     994                ipc_answer_0(rid, ENOMEM);
     995                return;
     996        }
     997        int rc;
     998        if ((rc = async_data_write_finalize(callid, path, len))) {
     999                ipc_answer_0(rid, rc);
     1000                free(path);
     1001                return;
     1002        }
     1003        path[len] = '\0';
     1004
    10431005        if (!async_data_read_receive(&callid, NULL)) {
    10441006                free(path);
     
    10861048{
    10871049        int mode = IPC_GET_ARG1(*request);
    1088        
    1089         char *path;
    1090         int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
    1091         if (rc != EOK) {
    1092                 ipc_answer_0(rid, rc);
    1093                 return;
    1094         }
    1095        
     1050
     1051        size_t len;
     1052        ipc_callid_t callid;
     1053
     1054        if (!async_data_write_receive(&callid, &len)) {
     1055                ipc_answer_0(callid, EINVAL);
     1056                ipc_answer_0(rid, EINVAL);
     1057                return;
     1058        }
     1059        char *path = malloc(len + 1);
     1060        if (!path) {
     1061                ipc_answer_0(callid, ENOMEM);
     1062                ipc_answer_0(rid, ENOMEM);
     1063                return;
     1064        }
     1065        int rc;
     1066        if ((rc = async_data_write_finalize(callid, path, len))) {
     1067                ipc_answer_0(rid, rc);
     1068                free(path);
     1069                return;
     1070        }
     1071        path[len] = '\0';
     1072
    10961073        /* Ignore mode for now. */
    10971074        (void) mode;
     
    11081085{
    11091086        int lflag = IPC_GET_ARG1(*request);
    1110        
    1111         char *path;
    1112         int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
    1113         if (rc != EOK) {
    1114                 ipc_answer_0(rid, rc);
    1115                 return;
    1116         }
     1087
     1088        size_t len;
     1089        ipc_callid_t callid;
     1090
     1091        if (!async_data_write_receive(&callid, &len)) {
     1092                ipc_answer_0(callid, EINVAL);
     1093                ipc_answer_0(rid, EINVAL);
     1094                return;
     1095        }
     1096        char *path = malloc(len + 1);
     1097        if (!path) {
     1098                ipc_answer_0(callid, ENOMEM);
     1099                ipc_answer_0(rid, ENOMEM);
     1100                return;
     1101        }
     1102        int rc;
     1103        if ((rc = async_data_write_finalize(callid, path, len))) {
     1104                ipc_answer_0(rid, rc);
     1105                free(path);
     1106                return;
     1107        }
     1108        path[len] = '\0';
    11171109       
    11181110        fibril_rwlock_write_lock(&namespace_rwlock);
     
    11431135void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
    11441136{
     1137        size_t olen, nlen;
     1138        ipc_callid_t callid;
     1139        int rc;
     1140
    11451141        /* Retrieve the old path. */
    1146         char *old;
    1147         int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
    1148         if (rc != EOK) {
    1149                 ipc_answer_0(rid, rc);
    1150                 return;
    1151         }
     1142        if (!async_data_write_receive(&callid, &olen)) {
     1143                ipc_answer_0(callid, EINVAL);
     1144                ipc_answer_0(rid, EINVAL);
     1145                return;
     1146        }
     1147        char *old = malloc(olen + 1);
     1148        if (!old) {
     1149                ipc_answer_0(callid, ENOMEM);
     1150                ipc_answer_0(rid, ENOMEM);
     1151                return;
     1152        }
     1153        if ((rc = async_data_write_finalize(callid, old, olen))) {
     1154                ipc_answer_0(rid, rc);
     1155                free(old);
     1156                return;
     1157        }
     1158        old[olen] = '\0';
    11521159       
    11531160        /* Retrieve the new path. */
    1154         char *new;
    1155         rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
    1156         if (rc != EOK) {
     1161        if (!async_data_write_receive(&callid, &nlen)) {
     1162                ipc_answer_0(callid, EINVAL);
     1163                ipc_answer_0(rid, EINVAL);
    11571164                free(old);
    1158                 ipc_answer_0(rid, rc);
    1159                 return;
    1160         }
    1161        
    1162         size_t olen;
    1163         size_t nlen;
     1165                return;
     1166        }
     1167        char *new = malloc(nlen + 1);
     1168        if (!new) {
     1169                ipc_answer_0(callid, ENOMEM);
     1170                ipc_answer_0(rid, ENOMEM);
     1171                free(old);
     1172                return;
     1173        }
     1174        if ((rc = async_data_write_finalize(callid, new, nlen))) {
     1175                ipc_answer_0(rid, rc);
     1176                free(old);
     1177                free(new);
     1178                return;
     1179        }
     1180        new[nlen] = '\0';
     1181
    11641182        char *oldc = canonify(old, &olen);
    11651183        char *newc = canonify(new, &nlen);
    1166        
    1167         if ((!oldc) || (!newc)) {
     1184        if (!oldc || !newc) {
    11681185                ipc_answer_0(rid, EINVAL);
    11691186                free(old);
     
    11711188                return;
    11721189        }
    1173        
    11741190        oldc[olen] = '\0';
    11751191        newc[nlen] = '\0';
    1176        
    11771192        if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
    11781193            ((newc[str_length(oldc)] == '/') ||
     
    11951210        vfs_lookup_res_t new_par_lr;
    11961211        fibril_rwlock_write_lock(&namespace_rwlock);
    1197        
    11981212        /* Lookup the node belonging to the old file name. */
    11991213        rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
     
    12051219                return;
    12061220        }
    1207        
    12081221        vfs_node_t *old_node = vfs_node_get(&old_lr);
    12091222        if (!old_node) {
     
    12141227                return;
    12151228        }
    1216        
    12171229        /* Determine the path to the parent of the node with the new name. */
    12181230        char *parentc = str_dup(newc);
     
    12241236                return;
    12251237        }
    1226        
    12271238        char *lastsl = str_rchr(parentc + 1, '/');
    12281239        if (lastsl)
     
    12301241        else
    12311242                parentc[1] = '\0';
    1232        
    12331243        /* Lookup parent of the new file name. */
    12341244        rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
     
    12411251                return;
    12421252        }
    1243        
    12441253        /* Check whether linking to the same file system instance. */
    12451254        if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
     
    12511260                return;
    12521261        }
    1253        
    12541262        /* Destroy the old link for the new name. */
    12551263        vfs_node_t *new_node = NULL;
    12561264        rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
    1257        
    12581265        switch (rc) {
    12591266        case ENOENT:
     
    12801287                return;
    12811288        }
    1282        
    12831289        /* Create the new link for the new name. */
    12841290        rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
     
    12921298                return;
    12931299        }
    1294        
    12951300        fibril_mutex_lock(&nodes_mutex);
    12961301        old_node->lnkcnt++;
    12971302        fibril_mutex_unlock(&nodes_mutex);
    1298        
    12991303        /* Destroy the link for the old name. */
    13001304        rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
     
    13091313                return;
    13101314        }
    1311        
    13121315        fibril_mutex_lock(&nodes_mutex);
    13131316        old_node->lnkcnt--;
     
    13151318        fibril_rwlock_write_unlock(&namespace_rwlock);
    13161319        vfs_node_put(old_node);
    1317        
    13181320        if (new_node)
    13191321                vfs_node_put(new_node);
    1320        
    13211322        free(old);
    13221323        free(new);
Note: See TracChangeset for help on using the changeset viewer.