Ignore:
File:
1 edited

Legend:

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

    r4cac2d69 r08232ee  
    9292                }
    9393               
    94                 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
     94                rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
    9595                if (rc != EOK) {
    9696                        /* The lookup failed for some reason. */
     
    266266       
    267267        /* We want the client to send us the mount point. */
    268         char *mp;
    269         int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
    270             0, NULL);
    271         if (rc != EOK) {
    272                 ipc_answer_0(rid, rc);
    273                 return;
    274         }
     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';
    275299       
    276300        /* Now we expect to receive the mount options. */
    277         char *opts;
    278         rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
    279             0, NULL);
    280         if (rc != EOK) {
     301        if (!async_data_write_receive(&callid, &size)) {
     302                ipc_answer_0(callid, EINVAL);
     303                ipc_answer_0(rid, EINVAL);
    281304                free(mp);
    282                 ipc_answer_0(rid, rc);
    283                 return;
    284         }
     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';
    285334       
    286335        /*
     
    288337         * system.
    289338         */
    290         char *fs_name;
    291         rc = async_data_write_accept((void **) &fs_name, true, 0, FS_NAME_MAXLEN,
    292             0, NULL);
    293         if (rc != EOK) {
     339        if (!async_data_write_receive(&callid, &size)) {
     340                ipc_answer_0(callid, EINVAL);
     341                ipc_answer_0(rid, EINVAL);
    294342                free(mp);
    295343                free(opts);
    296                 ipc_answer_0(rid, rc);
    297                 return;
    298         }
    299        
     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
    300382        /*
    301383         * Wait for IPC_M_PING so that we can return an error if we don't know
     
    303385         */
    304386        ipc_call_t data;
    305         ipc_callid_t callid = async_get_call(&data);
     387        callid = async_get_call(&data);
    306388        if (IPC_GET_METHOD(data) != IPC_M_PING) {
    307389                ipc_answer_0(callid, ENOTSUP);
     
    347429}
    348430
    349 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request)
    350 {
    351         int rc;
    352         char *mp;
    353         vfs_lookup_res_t mp_res;
    354         vfs_lookup_res_t mr_res;
    355         vfs_node_t *mp_node;
    356         vfs_node_t *mr_node;
    357         int phone;
    358 
    359         /*
    360          * Receive the mount point path.
    361          */
    362         rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
    363             0, NULL);
    364         if (rc != EOK)
    365                 ipc_answer_0(rid, rc);
    366 
    367         /*
    368          * Taking the namespace lock will do two things for us. First, it will
    369          * prevent races with other lookup operations. Second, it will stop new
    370          * references to already existing VFS nodes and creation of new VFS
    371          * nodes. This is because new references are added as a result of some
    372          * lookup operation or at least of some operation which is protected by
    373          * the namespace lock.
    374          */
    375         fibril_rwlock_write_lock(&namespace_rwlock);
    376        
    377         /*
    378          * Lookup the mounted root and instantiate it.
    379          */
    380         rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL);
    381         if (rc != EOK) {
    382                 fibril_rwlock_write_unlock(&namespace_rwlock);
    383                 free(mp);
    384                 ipc_answer_0(rid, rc);
    385                 return;
    386         }
    387         mr_node = vfs_node_get(&mr_res);
    388         if (!mr_node) {
    389                 fibril_rwlock_write_unlock(&namespace_rwlock);
    390                 free(mp);
    391                 ipc_answer_0(rid, ENOMEM);
    392                 return;
    393         }
    394 
    395         /*
    396          * Count the total number of references for the mounted file system. We
    397          * are expecting at least two. One which we got above and one which we
    398          * got when the file system was mounted. If we find more, it means that
    399          * the file system cannot be gracefully unmounted at the moment because
    400          * someone is working with it.
    401          */
    402         if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
    403             mr_node->dev_handle) != 2) {
    404                 fibril_rwlock_write_unlock(&namespace_rwlock);
    405                 vfs_node_put(mr_node);
    406                 free(mp);
    407                 ipc_answer_0(rid, EBUSY);
    408                 return;
    409         }
    410 
    411         if (str_cmp(mp, "/") == 0) {
    412 
    413                 /*
    414                  * Unmounting the root file system.
    415                  *
    416                  * In this case, there is no mount point node and we send
    417                  * VFS_OUT_UNMOUNTED directly to the mounted file system.
    418                  */
    419 
    420                 free(mp);
    421                 phone = vfs_grab_phone(mr_node->fs_handle);
    422                 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
    423                     mr_node->dev_handle);
    424                 vfs_release_phone(phone);
    425                 if (rc != EOK) {
    426                         fibril_rwlock_write_unlock(&namespace_rwlock);
    427                         vfs_node_put(mr_node);
    428                         ipc_answer_0(rid, rc);
    429                         return;
    430                 }
    431                 rootfs.fs_handle = 0;
    432                 rootfs.dev_handle = 0;
    433         } else {
    434 
    435                 /*
    436                  * Unmounting a non-root file system.
    437                  *
    438                  * We have a regular mount point node representing the parent
    439                  * file system, so we delegate the operation to it.
    440                  */
    441 
    442                 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
    443                 free(mp);
    444                 if (rc != EOK) {
    445                         fibril_rwlock_write_unlock(&namespace_rwlock);
    446                         vfs_node_put(mr_node);
    447                         ipc_answer_0(rid, rc);
    448                         return;
    449                 }
    450                 vfs_node_t *mp_node = vfs_node_get(&mp_res);
    451                 if (!mp_node) {
    452                         fibril_rwlock_write_unlock(&namespace_rwlock);
    453                         vfs_node_put(mr_node);
    454                         ipc_answer_0(rid, ENOMEM);
    455                         return;
    456                 }
    457 
    458                 phone = vfs_grab_phone(mp_node->fs_handle);
    459                 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle,
    460                     mp_node->index);
    461                 vfs_release_phone(phone);
    462                 if (rc != EOK) {
    463                         fibril_rwlock_write_unlock(&namespace_rwlock);
    464                         vfs_node_put(mp_node);
    465                         vfs_node_put(mr_node);
    466                         ipc_answer_0(rid, rc);
    467                         return;
    468                 }
    469 
    470                 /* Drop the reference we got above. */
    471                 vfs_node_put(mp_node);
    472                 /* Drop the reference from when the file system was mounted. */
    473                 vfs_node_put(mp_node);
    474         }
    475 
    476 
    477         /*
    478          * All went well, the mounted file system was successfully unmounted.
    479          * The only thing left is to forget the unmounted root VFS node.
    480          */
    481         vfs_node_forget(mr_node);
    482 
    483         fibril_rwlock_write_unlock(&namespace_rwlock);
    484         ipc_answer_0(rid, EOK);
    485 }
    486 
    487431void vfs_open(ipc_callid_t rid, ipc_call_t *request)
    488432{
     
    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);
     
    1010982void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
    1011983{
    1012         char *path;
    1013         int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
    1014         if (rc != EOK) {
    1015                 ipc_answer_0(rid, rc);
    1016                 return;
    1017         }
    1018        
     984        size_t len;
    1019985        ipc_callid_t callid;
     986
     987        if (!async_data_write_receive(&callid, &len)) {
     988                ipc_answer_0(callid, EINVAL);
     989                ipc_answer_0(rid, EINVAL);
     990                return;
     991        }
     992        char *path = malloc(len + 1);
     993        if (!path) {
     994                ipc_answer_0(callid, ENOMEM);
     995                ipc_answer_0(rid, ENOMEM);
     996                return;
     997        }
     998        int rc;
     999        if ((rc = async_data_write_finalize(callid, path, len))) {
     1000                ipc_answer_0(rid, rc);
     1001                free(path);
     1002                return;
     1003        }
     1004        path[len] = '\0';
     1005
    10201006        if (!async_data_read_receive(&callid, NULL)) {
    10211007                free(path);
     
    10631049{
    10641050        int mode = IPC_GET_ARG1(*request);
    1065        
    1066         char *path;
    1067         int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
    1068         if (rc != EOK) {
    1069                 ipc_answer_0(rid, rc);
    1070                 return;
    1071         }
    1072        
     1051
     1052        size_t len;
     1053        ipc_callid_t callid;
     1054
     1055        if (!async_data_write_receive(&callid, &len)) {
     1056                ipc_answer_0(callid, EINVAL);
     1057                ipc_answer_0(rid, EINVAL);
     1058                return;
     1059        }
     1060        char *path = malloc(len + 1);
     1061        if (!path) {
     1062                ipc_answer_0(callid, ENOMEM);
     1063                ipc_answer_0(rid, ENOMEM);
     1064                return;
     1065        }
     1066        int rc;
     1067        if ((rc = async_data_write_finalize(callid, path, len))) {
     1068                ipc_answer_0(rid, rc);
     1069                free(path);
     1070                return;
     1071        }
     1072        path[len] = '\0';
     1073
    10731074        /* Ignore mode for now. */
    10741075        (void) mode;
     
    10851086{
    10861087        int lflag = IPC_GET_ARG1(*request);
    1087        
    1088         char *path;
    1089         int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
    1090         if (rc != EOK) {
    1091                 ipc_answer_0(rid, rc);
    1092                 return;
    1093         }
     1088
     1089        size_t len;
     1090        ipc_callid_t callid;
     1091
     1092        if (!async_data_write_receive(&callid, &len)) {
     1093                ipc_answer_0(callid, EINVAL);
     1094                ipc_answer_0(rid, EINVAL);
     1095                return;
     1096        }
     1097        char *path = malloc(len + 1);
     1098        if (!path) {
     1099                ipc_answer_0(callid, ENOMEM);
     1100                ipc_answer_0(rid, ENOMEM);
     1101                return;
     1102        }
     1103        int rc;
     1104        if ((rc = async_data_write_finalize(callid, path, len))) {
     1105                ipc_answer_0(rid, rc);
     1106                free(path);
     1107                return;
     1108        }
     1109        path[len] = '\0';
    10941110       
    10951111        fibril_rwlock_write_lock(&namespace_rwlock);
     
    11201136void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
    11211137{
     1138        size_t olen, nlen;
     1139        ipc_callid_t callid;
     1140        int rc;
     1141
    11221142        /* Retrieve the old path. */
    1123         char *old;
    1124         int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
    1125         if (rc != EOK) {
    1126                 ipc_answer_0(rid, rc);
    1127                 return;
    1128         }
     1143        if (!async_data_write_receive(&callid, &olen)) {
     1144                ipc_answer_0(callid, EINVAL);
     1145                ipc_answer_0(rid, EINVAL);
     1146                return;
     1147        }
     1148        char *old = malloc(olen + 1);
     1149        if (!old) {
     1150                ipc_answer_0(callid, ENOMEM);
     1151                ipc_answer_0(rid, ENOMEM);
     1152                return;
     1153        }
     1154        if ((rc = async_data_write_finalize(callid, old, olen))) {
     1155                ipc_answer_0(rid, rc);
     1156                free(old);
     1157                return;
     1158        }
     1159        old[olen] = '\0';
    11291160       
    11301161        /* Retrieve the new path. */
    1131         char *new;
    1132         rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
    1133         if (rc != EOK) {
     1162        if (!async_data_write_receive(&callid, &nlen)) {
     1163                ipc_answer_0(callid, EINVAL);
     1164                ipc_answer_0(rid, EINVAL);
    11341165                free(old);
    1135                 ipc_answer_0(rid, rc);
    1136                 return;
    1137         }
    1138        
    1139         size_t olen;
    1140         size_t nlen;
     1166                return;
     1167        }
     1168        char *new = malloc(nlen + 1);
     1169        if (!new) {
     1170                ipc_answer_0(callid, ENOMEM);
     1171                ipc_answer_0(rid, ENOMEM);
     1172                free(old);
     1173                return;
     1174        }
     1175        if ((rc = async_data_write_finalize(callid, new, nlen))) {
     1176                ipc_answer_0(rid, rc);
     1177                free(old);
     1178                free(new);
     1179                return;
     1180        }
     1181        new[nlen] = '\0';
     1182
    11411183        char *oldc = canonify(old, &olen);
    11421184        char *newc = canonify(new, &nlen);
    1143        
    1144         if ((!oldc) || (!newc)) {
     1185        if (!oldc || !newc) {
    11451186                ipc_answer_0(rid, EINVAL);
    11461187                free(old);
     
    11481189                return;
    11491190        }
    1150        
    11511191        oldc[olen] = '\0';
    11521192        newc[nlen] = '\0';
    1153        
    11541193        if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
    11551194            ((newc[str_length(oldc)] == '/') ||
     
    11721211        vfs_lookup_res_t new_par_lr;
    11731212        fibril_rwlock_write_lock(&namespace_rwlock);
    1174        
    11751213        /* Lookup the node belonging to the old file name. */
    11761214        rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
     
    11821220                return;
    11831221        }
    1184        
    11851222        vfs_node_t *old_node = vfs_node_get(&old_lr);
    11861223        if (!old_node) {
     
    11911228                return;
    11921229        }
    1193        
    11941230        /* Determine the path to the parent of the node with the new name. */
    11951231        char *parentc = str_dup(newc);
     
    12011237                return;
    12021238        }
    1203        
    12041239        char *lastsl = str_rchr(parentc + 1, '/');
    12051240        if (lastsl)
     
    12071242        else
    12081243                parentc[1] = '\0';
    1209        
    12101244        /* Lookup parent of the new file name. */
    12111245        rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
     
    12181252                return;
    12191253        }
    1220        
    12211254        /* Check whether linking to the same file system instance. */
    12221255        if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
     
    12281261                return;
    12291262        }
    1230        
    12311263        /* Destroy the old link for the new name. */
    12321264        vfs_node_t *new_node = NULL;
    12331265        rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
    1234        
    12351266        switch (rc) {
    12361267        case ENOENT:
     
    12571288                return;
    12581289        }
    1259        
    12601290        /* Create the new link for the new name. */
    12611291        rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
     
    12691299                return;
    12701300        }
    1271        
    12721301        fibril_mutex_lock(&nodes_mutex);
    12731302        old_node->lnkcnt++;
    12741303        fibril_mutex_unlock(&nodes_mutex);
    1275        
    12761304        /* Destroy the link for the old name. */
    12771305        rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
     
    12861314                return;
    12871315        }
    1288        
    12891316        fibril_mutex_lock(&nodes_mutex);
    12901317        old_node->lnkcnt--;
     
    12921319        fibril_rwlock_write_unlock(&namespace_rwlock);
    12931320        vfs_node_put(old_node);
    1294        
    12951321        if (new_node)
    12961322                vfs_node_put(new_node);
    1297        
    12981323        free(old);
    12991324        free(new);
Note: See TracChangeset for help on using the changeset viewer.