Changeset 1dff985 in mainline for uspace/lib/fs/libfs.c


Ignore:
Timestamp:
2017-03-03T21:32:38Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade
Children:
c577a9a
Parents:
5b46ec8 (diff), b8dbe2f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~zarevucky-jiri/helenos/vfs-2.5 up to revision 1926

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/fs/libfs.c

    r5b46ec8 r1dff985  
    3636
    3737#include "libfs.h"
    38 #include "../../srv/vfs/vfs.h"
    3938#include <macros.h>
    4039#include <errno.h>
     
    4746#include <sys/statfs.h>
    4847#include <stdlib.h>
     48#include <fibril_synch.h>
    4949
    5050#define on_error(rc, action) \
     
    6363        } while (0)
    6464
     65#define DPRINTF(...)
     66
     67#define LOG_EXIT(rc) \
     68        DPRINTF("Exiting %s() with rc = %d at line %d\n", __FUNC__, rc, __LINE__);
     69
    6570static fs_reg_t reg;
    6671
     
    6873static libfs_ops_t *libfs_ops = NULL;
    6974
    70 static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
    71 static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
     75static void libfs_link(libfs_ops_t *, fs_handle_t, ipc_callid_t,
     76    ipc_call_t *);
    7277static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    7378    ipc_call_t *);
     
    104109}
    105110
    106 static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)
    107 {
    108         libfs_mount(libfs_ops, reg.fs_handle, rid, req);
    109 }
    110 
    111111static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
    112112{
     
    119119}
    120120
    121 static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
    122 {
    123                
    124         libfs_unmount(libfs_ops, rid, req);
     121static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req)
     122{
     123        libfs_link(libfs_ops, reg.fs_handle, rid, req);
    125124}
    126125
     
    193192        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
    194193        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     194
    195195        int rc;
    196 
    197         rc = vfs_out_ops->destroy(service_id, index);
    198 
     196        fs_node_t *node = NULL;
     197        rc = libfs_ops->node_get(&node, service_id, index);
     198        if (rc == EOK && node != NULL) {
     199                bool destroy = (libfs_ops->lnkcnt_get(node) == 0);
     200                libfs_ops->node_put(node);
     201                if (destroy) {
     202                        rc = vfs_out_ops->destroy(service_id, index);
     203                }
     204        }
    199205        async_answer_0(rid, rc);
    200206}
     
    225231        libfs_statfs(libfs_ops, reg.fs_handle, rid, req);
    226232}
     233
     234static void vfs_out_get_size(ipc_callid_t rid, ipc_call_t *req)
     235{
     236        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
     237        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     238        int rc;
     239
     240        fs_node_t *node = NULL;
     241        rc = libfs_ops->node_get(&node, service_id, index);
     242        if (rc != EOK) {
     243                async_answer_0(rid, rc);
     244        }
     245        if (node == NULL) {
     246                async_answer_0(rid, EINVAL);
     247        }
     248       
     249        uint64_t size = libfs_ops->size_get(node);
     250        libfs_ops->node_put(node);
     251       
     252        async_answer_2(rid, EOK, LOWER32(size), UPPER32(size));
     253}
     254
     255static void vfs_out_is_empty(ipc_callid_t rid, ipc_call_t *req)
     256{
     257        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
     258        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     259        int rc;
     260
     261        fs_node_t *node = NULL;
     262        rc = libfs_ops->node_get(&node, service_id, index);
     263        if (rc != EOK) {
     264                async_answer_0(rid, rc);
     265        }
     266        if (node == NULL) {
     267                async_answer_0(rid, EINVAL);
     268        }
     269       
     270        bool children = false;
     271        rc = libfs_ops->has_children(&children, node);
     272        libfs_ops->node_put(node);
     273       
     274        if (rc != EOK) {
     275                async_answer_0(rid, rc);
     276        }
     277        async_answer_0(rid, children ? ENOTEMPTY : EOK);
     278}
     279
    227280static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    228281{
     
    247300                        vfs_out_mounted(callid, &call);
    248301                        break;
    249                 case VFS_OUT_MOUNT:
    250                         vfs_out_mount(callid, &call);
    251                         break;
    252302                case VFS_OUT_UNMOUNTED:
    253303                        vfs_out_unmounted(callid, &call);
    254304                        break;
    255                 case VFS_OUT_UNMOUNT:
    256                         vfs_out_unmount(callid, &call);
     305                case VFS_OUT_LINK:
     306                        vfs_out_link(callid, &call);
    257307                        break;
    258308                case VFS_OUT_LOOKUP:
     
    285335                case VFS_OUT_STATFS:
    286336                        vfs_out_statfs(callid, &call);
     337                        break;
     338                case VFS_OUT_GET_SIZE:
     339                        vfs_out_get_size(callid, &call);
     340                        break;
     341                case VFS_OUT_IS_EMPTY:
     342                        vfs_out_is_empty(callid, &call);
    287343                        break;
    288344                default:
     
    383439}
    384440
    385 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    386     ipc_call_t *req)
    387 {
    388         service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req);
    389         fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
    390         fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req);
    391         service_id_t mr_service_id = (service_id_t) IPC_GET_ARG4(*req);
    392        
    393         async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL);
    394         if (mountee_sess == NULL) {
    395                 async_answer_0(rid, EINVAL);
     441static char plb_get_char(unsigned pos)
     442{
     443        return reg.plb_ro[pos % PLB_SIZE];
     444}
     445
     446static int plb_get_component(char *dest, unsigned *sz, unsigned *ppos, unsigned last)
     447{
     448        unsigned pos = *ppos;
     449        unsigned size = 0;
     450       
     451        if (pos == last) {
     452                *sz = 0;
     453                return ERANGE;
     454        }
     455
     456        char c = plb_get_char(pos);
     457        if (c == '/') {
     458                pos++;
     459        }
     460       
     461        for (int i = 0; i <= NAME_MAX; i++) {
     462                c = plb_get_char(pos);
     463                if (pos == last || c == '/') {
     464                        dest[i] = 0;
     465                        *ppos = pos;
     466                        *sz = size;
     467                        return EOK;
     468                }
     469                dest[i] = c;
     470                pos++;
     471                size++;
     472        }
     473        return ENAMETOOLONG;
     474}
     475
     476static int receive_fname(char *buffer)
     477{
     478        size_t size;
     479        ipc_callid_t wcall;
     480       
     481        if (!async_data_write_receive(&wcall, &size)) {
     482                return ENOENT;
     483        }
     484        if (size > NAME_MAX + 1) {
     485                async_answer_0(wcall, ERANGE);
     486                return ERANGE;
     487        }
     488        return async_data_write_finalize(wcall, buffer, size);
     489}
     490
     491/** Link a file at a path.
     492 */
     493void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req)
     494{
     495        service_id_t parent_sid = IPC_GET_ARG1(*req);
     496        fs_index_t parent_index = IPC_GET_ARG2(*req);
     497        fs_index_t child_index = IPC_GET_ARG3(*req);
     498       
     499        char component[NAME_MAX + 1];
     500        int rc = receive_fname(component);
     501        if (rc != EOK) {
     502                async_answer_0(rid, rc);
    396503                return;
    397504        }
    398        
    399         fs_node_t *fn;
    400         int res = ops->node_get(&fn, mp_service_id, mp_fs_index);
    401         if ((res != EOK) || (!fn)) {
    402                 async_hangup(mountee_sess);
    403                 async_data_write_void(combine_rc(res, ENOENT));
    404                 async_answer_0(rid, combine_rc(res, ENOENT));
     505
     506        fs_node_t *parent = NULL;
     507        rc = ops->node_get(&parent, parent_sid, parent_index);
     508        if (parent == NULL) {
     509                async_answer_0(rid, rc == EOK ? EBADF : rc);
    405510                return;
    406511        }
    407512       
    408         if (fn->mp_data.mp_active) {
    409                 async_hangup(mountee_sess);
    410                 (void) ops->node_put(fn);
    411                 async_data_write_void(EBUSY);
    412                 async_answer_0(rid, EBUSY);
     513        fs_node_t *child = NULL;
     514        rc = ops->node_get(&child, parent_sid, child_index);
     515        if (child == NULL) {
     516                async_answer_0(rid, rc == EOK ? EBADF : rc);
     517                ops->node_put(parent);
    413518                return;
    414519        }
    415520       
    416         async_exch_t *exch = async_exchange_begin(mountee_sess);
    417         async_sess_t *sess = async_clone_establish(EXCHANGE_PARALLEL, exch);
    418        
    419         if (!sess) {
    420                 async_exchange_end(exch);
    421                 async_hangup(mountee_sess);
    422                 (void) ops->node_put(fn);
    423                 async_data_write_void(errno);
    424                 async_answer_0(rid, errno);
    425                 return;
    426         }
    427        
    428         ipc_call_t answer;
    429         int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED,
    430             mr_service_id, &answer);
    431         async_exchange_end(exch);
    432        
    433         if (rc == EOK) {
    434                 fn->mp_data.mp_active = true;
    435                 fn->mp_data.fs_handle = mr_fs_handle;
    436                 fn->mp_data.service_id = mr_service_id;
    437                 fn->mp_data.sess = mountee_sess;
    438         }
    439        
    440         /*
    441          * Do not release the FS node so that it stays in memory.
    442          */
    443         async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
    444             IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
    445 }
    446 
    447 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req)
    448 {
    449         service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req);
    450         fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
    451         fs_node_t *fn;
    452         int res;
    453 
    454         res = ops->node_get(&fn, mp_service_id, mp_fs_index);
    455         if ((res != EOK) || (!fn)) {
    456                 async_answer_0(rid, combine_rc(res, ENOENT));
    457                 return;
    458         }
    459 
    460         /*
    461          * We are clearly expecting to find the mount point active.
    462          */
    463         if (!fn->mp_data.mp_active) {
    464                 (void) ops->node_put(fn);
    465                 async_answer_0(rid, EINVAL);
    466                 return;
    467         }
    468 
    469         /*
    470          * Tell the mounted file system to unmount.
    471          */
    472         async_exch_t *exch = async_exchange_begin(fn->mp_data.sess);
    473         res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.service_id);
    474         async_exchange_end(exch);
    475 
    476         /*
    477          * If everything went well, perform the clean-up on our side.
    478          */
    479         if (res == EOK) {
    480                 async_hangup(fn->mp_data.sess);
    481                 fn->mp_data.mp_active = false;
    482                 fn->mp_data.fs_handle = 0;
    483                 fn->mp_data.service_id = 0;
    484                 fn->mp_data.sess = NULL;
    485                
    486                 /* Drop the reference created in libfs_mount(). */
    487                 (void) ops->node_put(fn);
    488         }
    489 
    490         (void) ops->node_put(fn);
    491         async_answer_0(rid, res);
    492 }
    493 
    494 static char plb_get_char(unsigned pos)
    495 {
    496         return reg.plb_ro[pos % PLB_SIZE];
     521        rc = ops->link(parent, child, component);
     522        ops->node_put(parent);
     523        ops->node_put(child);
     524        async_answer_0(rid, rc);
    497525}
    498526
     
    513541    ipc_call_t *req)
    514542{
    515         unsigned int first = IPC_GET_ARG1(*req);
    516         unsigned int last = IPC_GET_ARG2(*req);
    517         unsigned int next = first;
     543        unsigned first = IPC_GET_ARG1(*req);
     544        unsigned len = IPC_GET_ARG2(*req);
    518545        service_id_t service_id = IPC_GET_ARG3(*req);
    519         int lflag = IPC_GET_ARG4(*req);
    520         fs_index_t index = IPC_GET_ARG5(*req);
     546        fs_index_t index = IPC_GET_ARG4(*req);
     547        int lflag = IPC_GET_ARG5(*req);
     548       
     549        assert((int) index != -1);
     550       
     551        DPRINTF("Entered libfs_lookup()\n");
     552       
     553        // TODO: Validate flags.
     554       
     555        unsigned next = first;
     556        unsigned last = first + len;
     557       
    521558        char component[NAME_MAX + 1];
    522         int len;
    523559        int rc;
    524        
    525         if (last < next)
    526                 last += PLB_SIZE;
    527560       
    528561        fs_node_t *par = NULL;
    529562        fs_node_t *cur = NULL;
    530563        fs_node_t *tmp = NULL;
    531        
    532         rc = ops->root_get(&cur, service_id);
    533         on_error(rc, goto out_with_answer);
    534        
    535         if (cur->mp_data.mp_active) {
    536                 async_exch_t *exch = async_exchange_begin(cur->mp_data.sess);
    537                 async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
    538                     cur->mp_data.service_id, lflag, index,
    539                     IPC_FF_ROUTE_FROM_ME);
    540                 async_exchange_end(exch);
     564        unsigned clen = 0;
     565       
     566        rc = ops->node_get(&cur, service_id, index);
     567        if (rc != EOK) {
     568                async_answer_0(rid, rc);
     569                LOG_EXIT(rc);
     570                goto out;
     571        }
     572       
     573        assert(cur != NULL);
     574       
     575        /* Find the file and its parent. */
     576       
     577        unsigned last_next = 0;
     578       
     579        while (next != last) {
     580                if (cur == NULL) {
     581                        assert(par != NULL);
     582                        goto out1;
     583                }
     584
     585                if (!ops->is_directory(cur)) {
     586                        async_answer_0(rid, ENOTDIR);
     587                        LOG_EXIT(ENOTDIR);
     588                        goto out;
     589                }
    541590               
    542                 (void) ops->node_put(cur);
    543                 return;
    544         }
    545        
    546         /* Eat slash */
    547         if (plb_get_char(next) == '/')
    548                 next++;
    549        
    550         while (next <= last) {
    551                 bool has_children;
     591                last_next = next;
     592                /* Collect the component */
     593                rc = plb_get_component(component, &clen, &next, last);
     594                assert(rc != ERANGE);
     595                if (rc != EOK) {
     596                        async_answer_0(rid, rc);
     597                        LOG_EXIT(rc);
     598                        goto out;
     599                }
    552600               
    553                 rc = ops->has_children(&has_children, cur);
    554                 on_error(rc, goto out_with_answer);
    555                 if (!has_children)
    556                         break;
     601                if (clen == 0) {
     602                        /* The path is just "/". */
     603                        break;
     604                }
    557605               
    558                 /* Collect the component */
    559                 len = 0;
    560                 while ((next <= last) && (plb_get_char(next) != '/')) {
    561                         if (len + 1 == NAME_MAX) {
    562                                 /* Component length overflow */
    563                                 async_answer_0(rid, ENAMETOOLONG);
    564                                 goto out;
    565                         }
    566                         component[len++] = plb_get_char(next);
    567                         /* Process next character */
    568                         next++;
    569                 }
    570                
    571                 assert(len);
    572                 component[len] = '\0';
    573                 /* Eat slash */
    574                 next++;
     606                assert(component[clen] == 0);
    575607               
    576608                /* Match the component */
    577609                rc = ops->match(&tmp, cur, component);
    578                 on_error(rc, goto out_with_answer);
     610                if (rc != EOK) {
     611                        async_answer_0(rid, rc);
     612                        LOG_EXIT(rc);
     613                        goto out;
     614                }
    579615               
    580                 /*
    581                  * If the matching component is a mount point, there are two
    582                  * legitimate semantics of the lookup operation. The first is
    583                  * the commonly used one in which the lookup crosses each mount
    584                  * point into the mounted file system. The second semantics is
    585                  * used mostly during unmount() and differs from the first one
    586                  * only in that the last mount point in the looked up path,
    587                  * which is also its last component, is not crossed.
    588                  */
    589 
    590                 if ((tmp) && (tmp->mp_data.mp_active) &&
    591                     (!(lflag & L_MP) || (next <= last))) {
    592                         if (next > last)
    593                                 next = last = first;
    594                         else
    595                                 next--;
     616                /* Descend one level */
     617                if (par) {
     618                        rc = ops->node_put(par);
     619                        if (rc != EOK) {
     620                                async_answer_0(rid, rc);
     621                                LOG_EXIT(rc);
     622                                goto out;
     623                        }
     624                }
     625               
     626                par = cur;
     627                cur = tmp;
     628                tmp = NULL;
     629        }
     630       
     631        /* At this point, par is either NULL or a directory.
     632         * If cur is NULL, the looked up file does not exist yet.
     633         */
     634         
     635        assert(par == NULL || ops->is_directory(par));
     636        assert(par != NULL || cur != NULL);
     637       
     638        /* Check for some error conditions. */
     639       
     640        if (cur && (lflag & L_FILE) && (ops->is_directory(cur))) {
     641                async_answer_0(rid, EISDIR);
     642                LOG_EXIT(EISDIR);
     643                goto out;
     644        }
     645       
     646        if (cur && (lflag & L_DIRECTORY) && (ops->is_file(cur))) {
     647                async_answer_0(rid, ENOTDIR);
     648                LOG_EXIT(ENOTDIR);
     649                goto out;
     650        }
     651       
     652        /* Unlink. */
     653       
     654        if (lflag & L_UNLINK) {
     655                if (!cur) {
     656                        async_answer_0(rid, ENOENT);
     657                        LOG_EXIT(ENOENT);
     658                        goto out;
     659                }
     660                if (!par) {
     661                        async_answer_0(rid, EINVAL);
     662                        LOG_EXIT(EINVAL);
     663                        goto out;
     664                }
     665               
     666                rc = ops->unlink(par, cur, component);
     667                if (rc == EOK) {
     668                        int64_t size = ops->size_get(cur);
     669                        int32_t lsize = LOWER32(size);
     670                        if (lsize != size) {
     671                                lsize = -1;
     672                        }
    596673                       
    597                         async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess);
    598                         async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next,
    599                             last, tmp->mp_data.service_id, lflag, index,
    600                             IPC_FF_ROUTE_FROM_ME);
    601                         async_exchange_end(exch);
    602                        
    603                         (void) ops->node_put(cur);
    604                         (void) ops->node_put(tmp);
    605                         if (par)
    606                                 (void) ops->node_put(par);
    607                         return;
    608                 }
    609                
    610                 /* Handle miss: match amongst siblings */
    611                 if (!tmp) {
    612                         if (next <= last) {
    613                                 /* There are unprocessed components */
    614                                 async_answer_0(rid, ENOENT);
     674                        async_answer_5(rid, fs_handle, service_id,
     675                            ops->index_get(cur), last, lsize,
     676                            ops->is_directory(cur));
     677                        LOG_EXIT(EOK);
     678                } else {
     679                        async_answer_0(rid, rc);
     680                        LOG_EXIT(rc);
     681                }
     682                goto out;
     683        }
     684       
     685        /* Create. */
     686       
     687        if (lflag & L_CREATE) {
     688                if (cur && (lflag & L_EXCLUSIVE)) {
     689                        async_answer_0(rid, EEXIST);
     690                        LOG_EXIT(EEXIST);
     691                        goto out;
     692                }
     693       
     694                if (!cur) {
     695                        rc = ops->create(&cur, service_id, lflag & (L_FILE|L_DIRECTORY));
     696                        if (rc != EOK) {
     697                                async_answer_0(rid, rc);
     698                                LOG_EXIT(rc);
     699                                goto out;
     700                        }
     701                        if (!cur) {
     702                                async_answer_0(rid, ENOSPC);
     703                                LOG_EXIT(ENOSPC);
    615704                                goto out;
    616705                        }
    617706                       
    618                         /* Miss in the last component */
    619                         if (lflag & (L_CREATE | L_LINK)) {
    620                                 /* Request to create a new link */
    621                                 if (!ops->is_directory(cur)) {
    622                                         async_answer_0(rid, ENOTDIR);
    623                                         goto out;
    624                                 }
    625                                
    626                                 fs_node_t *fn;
    627                                 if (lflag & L_CREATE)
    628                                         rc = ops->create(&fn, service_id,
    629                                             lflag);
    630                                 else
    631                                         rc = ops->node_get(&fn, service_id,
    632                                             index);
    633                                 on_error(rc, goto out_with_answer);
    634                                
    635                                 if (fn) {
    636                                         rc = ops->link(cur, fn, component);
    637                                         if (rc != EOK) {
    638                                                 if (lflag & L_CREATE)
    639                                                         (void) ops->destroy(fn);
    640                                                 else
    641                                                         (void) ops->node_put(fn);
    642                                                 async_answer_0(rid, rc);
    643                                         } else {
    644                                                 (void) ops->node_put(cur);
    645                                                 cur = fn;
    646                                                 goto out_with_answer;
    647                                         }
    648                                 } else
    649                                         async_answer_0(rid, ENOSPC);
    650                                
     707                        rc = ops->link(par, cur, component);
     708                        if (rc != EOK) {
     709                                (void) ops->destroy(cur);
     710                                cur = NULL;
     711                                async_answer_0(rid, rc);
     712                                LOG_EXIT(rc);
    651713                                goto out;
    652714                        }
    653                        
    654                         async_answer_0(rid, ENOENT);
     715                }
     716        }
     717       
     718        /* Return. */
     719out1:
     720        if (!cur) {
     721                async_answer_5(rid, fs_handle, service_id,
     722                        ops->index_get(par), last_next, -1, true);
     723                LOG_EXIT(EOK);
     724                goto out;
     725        }
     726       
     727        if (lflag & L_OPEN) {
     728                rc = ops->node_open(cur);
     729                if (rc != EOK) {
     730                        async_answer_0(rid, rc);
     731                        LOG_EXIT(rc);
    655732                        goto out;
    656733                }
    657                
    658                 if (par) {
    659                         rc = ops->node_put(par);
    660                         on_error(rc, goto out_with_answer);
    661                 }
    662                
    663                 /* Descend one level */
    664                 par = cur;
    665                 cur = tmp;
    666                 tmp = NULL;
    667         }
    668        
    669         /* Handle miss: excessive components */
    670         if (next <= last) {
    671                 bool has_children;
    672                 rc = ops->has_children(&has_children, cur);
    673                 on_error(rc, goto out_with_answer);
    674                
    675                 if (has_children)
    676                         goto skip_miss;
    677                
    678                 if (lflag & (L_CREATE | L_LINK)) {
    679                         if (!ops->is_directory(cur)) {
    680                                 async_answer_0(rid, ENOTDIR);
    681                                 goto out;
    682                         }
    683                        
    684                         /* Collect next component */
    685                         len = 0;
    686                         while (next <= last) {
    687                                 if (plb_get_char(next) == '/') {
    688                                         /* More than one component */
    689                                         async_answer_0(rid, ENOENT);
    690                                         goto out;
    691                                 }
    692                                
    693                                 if (len + 1 == NAME_MAX) {
    694                                         /* Component length overflow */
    695                                         async_answer_0(rid, ENAMETOOLONG);
    696                                         goto out;
    697                                 }
    698                                
    699                                 component[len++] = plb_get_char(next);
    700                                 /* Process next character */
    701                                 next++;
    702                         }
    703                        
    704                         assert(len);
    705                         component[len] = '\0';
    706                        
    707                         fs_node_t *fn;
    708                         if (lflag & L_CREATE)
    709                                 rc = ops->create(&fn, service_id, lflag);
    710                         else
    711                                 rc = ops->node_get(&fn, service_id, index);
    712                         on_error(rc, goto out_with_answer);
    713                        
    714                         if (fn) {
    715                                 rc = ops->link(cur, fn, component);
    716                                 if (rc != EOK) {
    717                                         if (lflag & L_CREATE)
    718                                                 (void) ops->destroy(fn);
    719                                         else
    720                                                 (void) ops->node_put(fn);
    721                                         async_answer_0(rid, rc);
    722                                 } else {
    723                                         (void) ops->node_put(cur);
    724                                         cur = fn;
    725                                         goto out_with_answer;
    726                                 }
    727                         } else
    728                                 async_answer_0(rid, ENOSPC);
    729                        
    730                         goto out;
    731                 }
    732                
    733                 async_answer_0(rid, ENOENT);
    734                 goto out;
    735         }
    736        
    737 skip_miss:
    738        
    739         /* Handle hit */
    740         if (lflag & L_UNLINK) {
    741                 unsigned int old_lnkcnt = ops->lnkcnt_get(cur);
    742                 rc = ops->unlink(par, cur, component);
    743                
    744                 if (rc == EOK) {
    745                         aoff64_t size = ops->size_get(cur);
    746                         async_answer_5(rid, fs_handle, service_id,
    747                             ops->index_get(cur), LOWER32(size), UPPER32(size),
    748                             old_lnkcnt);
    749                 } else
    750                         async_answer_0(rid, rc);
    751                
    752                 goto out;
    753         }
    754        
    755         if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) ||
    756             (lflag & L_LINK)) {
    757                 async_answer_0(rid, EEXIST);
    758                 goto out;
    759         }
    760        
    761         if ((lflag & L_FILE) && (ops->is_directory(cur))) {
    762                 async_answer_0(rid, EISDIR);
    763                 goto out;
    764         }
    765        
    766         if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) {
    767                 async_answer_0(rid, ENOTDIR);
    768                 goto out;
    769         }
    770 
    771         if ((lflag & L_ROOT) && par) {
    772                 async_answer_0(rid, EINVAL);
    773                 goto out;
    774         }
    775        
    776 out_with_answer:
    777        
    778         if (rc == EOK) {
    779                 if (lflag & L_OPEN)
    780                         rc = ops->node_open(cur);
    781                
    782                 if (rc == EOK) {
    783                         aoff64_t size = ops->size_get(cur);
    784                         async_answer_5(rid, fs_handle, service_id,
    785                             ops->index_get(cur), LOWER32(size), UPPER32(size),
    786                             ops->lnkcnt_get(cur));
    787                 } else
    788                         async_answer_0(rid, rc);
    789                
    790         } else
    791                 async_answer_0(rid, rc);
    792        
     734        }
     735       
     736        int64_t size = ops->size_get(cur);
     737        int32_t lsize = LOWER32(size);
     738        if (lsize != size) {
     739                lsize = -1;
     740        }
     741       
     742        async_answer_5(rid, fs_handle, service_id, ops->index_get(cur), last,
     743            lsize, ops->is_directory(cur));
     744       
     745        LOG_EXIT(EOK);
    793746out:
    794        
    795         if (par)
     747        if (par) {
    796748                (void) ops->node_put(par);
    797        
    798         if (cur)
     749        }
     750       
     751        if (cur) {
    799752                (void) ops->node_put(cur);
    800        
    801         if (tmp)
     753        }
     754       
     755        if (tmp) {
    802756                (void) ops->node_put(tmp);
     757        }
    803758}
    804759
Note: See TracChangeset for help on using the changeset viewer.