Changeset 368ee04 in mainline for uspace/lib/fs/libfs.c


Ignore:
Timestamp:
2017-04-05T18:10:39Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
93ad8166
Parents:
39f892a9 (diff), 2166728 (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:~jakub/helenos/vfs-2.5-cherrypick

This merge cherry-picks some of the changesets from Jiri Zarevucky's:

lp:~zarevucky-jiri/helenos/vfs-2.5

and then continues independently, yet sometime in a similar vein.

Roughly speaking, Jiri's branch is merged entirely up to its revision
1926 and then cherry-picked on and off until its revision 1965. Among
these changes are:

  • relativization of the API,
  • client-side roots,
  • server-side mounts,
  • inbox for passing arbitrary files from parent to child,
  • some streamlining and cleanup.

Additional changes include:

  • addressing issues introduced by the above changes,
  • client-side I/O cursors (file positions),
  • all HelenOS file system APIs begin with the vfs_ prefix and can be used after including vfs/vfs.h,
  • removal of some POSIX-ish headers and definitions,
  • additional cleanup.
File:
1 edited

Legend:

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

    r39f892a9 r368ee04  
    3636
    3737#include "libfs.h"
    38 #include "../../srv/vfs/vfs.h"
    3938#include <macros.h>
    4039#include <errno.h>
     
    4443#include <dirent.h>
    4544#include <mem.h>
    46 #include <sys/stat.h>
    47 #include <sys/statfs.h>
     45#include <str.h>
    4846#include <stdlib.h>
     47#include <fibril_synch.h>
     48#include <ipc/vfs.h>
     49#include <vfs/vfs.h>
    4950
    5051#define on_error(rc, action) \
     
    6869static libfs_ops_t *libfs_ops = NULL;
    6970
    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 *);
     71static char fs_name[FS_NAME_MAXLEN + 1];
     72
     73static void libfs_link(libfs_ops_t *, fs_handle_t, ipc_callid_t,
     74    ipc_call_t *);
    7275static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    7376    ipc_call_t *);
     
    7578static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    7679    ipc_call_t *);
    77 static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
     80static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t,
     81    ipc_call_t *);
    7882
    7983static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req)
     
    104108}
    105109
    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 
    111110static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
    112111{
     
    119118}
    120119
    121 static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
    122 {
    123                
    124         libfs_unmount(libfs_ops, rid, req);
     120static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req)
     121{
     122        libfs_link(libfs_ops, reg.fs_handle, rid, req);
    125123}
    126124
     
    159157        rc = vfs_out_ops->write(service_id, index, pos, &wbytes, &nsize);
    160158
    161         if (rc == EOK)
    162                 async_answer_3(rid, EOK, wbytes, LOWER32(nsize), UPPER32(nsize));
    163         else
     159        if (rc == EOK) {
     160                async_answer_3(rid, EOK, wbytes, LOWER32(nsize),
     161                    UPPER32(nsize));
     162        } else
    164163                async_answer_0(rid, rc);
    165164}
     
    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        }
    199204        async_answer_0(rid, rc);
    200205}
     
    225230        libfs_statfs(libfs_ops, reg.fs_handle, rid, req);
    226231}
     232
     233static void vfs_out_is_empty(ipc_callid_t rid, ipc_call_t *req)
     234{
     235        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
     236        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     237        int rc;
     238
     239        fs_node_t *node = NULL;
     240        rc = libfs_ops->node_get(&node, service_id, index);
     241        if (rc != EOK)
     242                async_answer_0(rid, rc);
     243        if (node == NULL)
     244                async_answer_0(rid, EINVAL);
     245       
     246        bool children = false;
     247        rc = libfs_ops->has_children(&children, node);
     248        libfs_ops->node_put(node);
     249       
     250        if (rc != EOK)
     251                async_answer_0(rid, rc);
     252        async_answer_0(rid, children ? ENOTEMPTY : EOK);
     253}
     254
    227255static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    228256{
     
    247275                        vfs_out_mounted(callid, &call);
    248276                        break;
    249                 case VFS_OUT_MOUNT:
    250                         vfs_out_mount(callid, &call);
    251                         break;
    252277                case VFS_OUT_UNMOUNTED:
    253278                        vfs_out_unmounted(callid, &call);
    254279                        break;
    255                 case VFS_OUT_UNMOUNT:
    256                         vfs_out_unmount(callid, &call);
     280                case VFS_OUT_LINK:
     281                        vfs_out_link(callid, &call);
    257282                        break;
    258283                case VFS_OUT_LOOKUP:
     
    285310                case VFS_OUT_STATFS:
    286311                        vfs_out_statfs(callid, &call);
     312                        break;
     313                case VFS_OUT_IS_EMPTY:
     314                        vfs_out_is_empty(callid, &call);
    287315                        break;
    288316                default:
     
    338366        vfs_out_ops = vops;
    339367        libfs_ops = lops;
     368
     369        str_cpy(fs_name, sizeof(fs_name), info->name);
    340370
    341371        /*
     
    383413}
    384414
    385 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
     415static char plb_get_char(unsigned pos)
     416{
     417        return reg.plb_ro[pos % PLB_SIZE];
     418}
     419
     420static int plb_get_component(char *dest, unsigned *sz, unsigned *ppos,
     421    unsigned last)
     422{
     423        unsigned pos = *ppos;
     424        unsigned size = 0;
     425       
     426        if (pos == last) {
     427                *sz = 0;
     428                return ERANGE;
     429        }
     430
     431        char c = plb_get_char(pos);
     432        if (c == '/')
     433                pos++;
     434       
     435        for (int i = 0; i <= NAME_MAX; i++) {
     436                c = plb_get_char(pos);
     437                if (pos == last || c == '/') {
     438                        dest[i] = 0;
     439                        *ppos = pos;
     440                        *sz = size;
     441                        return EOK;
     442                }
     443                dest[i] = c;
     444                pos++;
     445                size++;
     446        }
     447        return ENAMETOOLONG;
     448}
     449
     450static int receive_fname(char *buffer)
     451{
     452        size_t size;
     453        ipc_callid_t wcall;
     454       
     455        if (!async_data_write_receive(&wcall, &size))
     456                return ENOENT;
     457        if (size > NAME_MAX + 1) {
     458                async_answer_0(wcall, ERANGE);
     459                return ERANGE;
     460        }
     461        return async_data_write_finalize(wcall, buffer, size);
     462}
     463
     464/** Link a file at a path.
     465 */
     466void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    386467    ipc_call_t *req)
    387468{
    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);
     469        service_id_t parent_sid = IPC_GET_ARG1(*req);
     470        fs_index_t parent_index = IPC_GET_ARG2(*req);
     471        fs_index_t child_index = IPC_GET_ARG3(*req);
     472       
     473        char component[NAME_MAX + 1];
     474        int rc = receive_fname(component);
     475        if (rc != EOK) {
     476                async_answer_0(rid, rc);
    396477                return;
    397478        }
    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));
     479
     480        fs_node_t *parent = NULL;
     481        rc = ops->node_get(&parent, parent_sid, parent_index);
     482        if (parent == NULL) {
     483                async_answer_0(rid, rc == EOK ? EBADF : rc);
    405484                return;
    406485        }
    407486       
    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);
     487        fs_node_t *child = NULL;
     488        rc = ops->node_get(&child, parent_sid, child_index);
     489        if (child == NULL) {
     490                async_answer_0(rid, rc == EOK ? EBADF : rc);
     491                ops->node_put(parent);
    413492                return;
    414493        }
    415494       
    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];
     495        rc = ops->link(parent, child, component);
     496        ops->node_put(parent);
     497        ops->node_put(child);
     498        async_answer_0(rid, rc);
    497499}
    498500
     
    513515    ipc_call_t *req)
    514516{
    515         unsigned int first = IPC_GET_ARG1(*req);
    516         unsigned int last = IPC_GET_ARG2(*req);
    517         unsigned int next = first;
     517        unsigned first = IPC_GET_ARG1(*req);
     518        unsigned len = IPC_GET_ARG2(*req);
    518519        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);
     520        fs_index_t index = IPC_GET_ARG4(*req);
     521        int lflag = IPC_GET_ARG5(*req);
     522       
     523        // TODO: Validate flags.
     524       
     525        unsigned next = first;
     526        unsigned last = first + len;
     527       
    521528        char component[NAME_MAX + 1];
    522         int len;
    523529        int rc;
    524        
    525         if (last < next)
    526                 last += PLB_SIZE;
    527530       
    528531        fs_node_t *par = NULL;
    529532        fs_node_t *cur = NULL;
    530533        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);
     534        unsigned clen = 0;
     535       
     536        rc = ops->node_get(&cur, service_id, index);
     537        if (rc != EOK) {
     538                async_answer_0(rid, rc);
     539                goto out;
     540        }
     541       
     542        assert(cur != NULL);
     543       
     544        /* Find the file and its parent. */
     545       
     546        unsigned last_next = 0;
     547       
     548        while (next != last) {
     549                if (cur == NULL) {
     550                        assert(par != NULL);
     551                        goto out1;
     552                }
     553
     554                if (!ops->is_directory(cur)) {
     555                        async_answer_0(rid, ENOTDIR);
     556                        goto out;
     557                }
    541558               
    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;
     559                last_next = next;
     560                /* Collect the component */
     561                rc = plb_get_component(component, &clen, &next, last);
     562                assert(rc != ERANGE);
     563                if (rc != EOK) {
     564                        async_answer_0(rid, rc);
     565                        goto out;
     566                }
    552567               
    553                 rc = ops->has_children(&has_children, cur);
    554                 on_error(rc, goto out_with_answer);
    555                 if (!has_children)
    556                         break;
     568                if (clen == 0) {
     569                        /* The path is just "/". */
     570                        break;
     571                }
    557572               
    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++;
     573                assert(component[clen] == 0);
    575574               
    576575                /* Match the component */
    577576                rc = ops->match(&tmp, cur, component);
    578                 on_error(rc, goto out_with_answer);
     577                if (rc != EOK) {
     578                        async_answer_0(rid, rc);
     579                        goto out;
     580                }
    579581               
    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--;
    596                        
    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;
     582                /* Descend one level */
     583                if (par) {
     584                        rc = ops->node_put(par);
     585                        if (rc != EOK) {
     586                                async_answer_0(rid, rc);
     587                                goto out;
     588                        }
    608589                }
    609590               
    610                 /* Handle miss: match amongst siblings */
    611                 if (!tmp) {
    612                         if (next <= last) {
    613                                 /* There are unprocessed components */
    614                                 async_answer_0(rid, ENOENT);
     591                par = cur;
     592                cur = tmp;
     593                tmp = NULL;
     594        }
     595       
     596        /* At this point, par is either NULL or a directory.
     597         * If cur is NULL, the looked up file does not exist yet.
     598         */
     599         
     600        assert(par == NULL || ops->is_directory(par));
     601        assert(par != NULL || cur != NULL);
     602       
     603        /* Check for some error conditions. */
     604       
     605        if (cur && (lflag & L_FILE) && (ops->is_directory(cur))) {
     606                async_answer_0(rid, EISDIR);
     607                goto out;
     608        }
     609       
     610        if (cur && (lflag & L_DIRECTORY) && (ops->is_file(cur))) {
     611                async_answer_0(rid, ENOTDIR);
     612                goto out;
     613        }
     614       
     615        /* Unlink. */
     616       
     617        if (lflag & L_UNLINK) {
     618                if (!cur) {
     619                        async_answer_0(rid, ENOENT);
     620                        goto out;
     621                }
     622                if (!par) {
     623                        async_answer_0(rid, EINVAL);
     624                        goto out;
     625                }
     626               
     627                rc = ops->unlink(par, cur, component);
     628                if (rc == EOK) {
     629                        aoff64_t size = ops->size_get(cur);
     630                        async_answer_5(rid, fs_handle, service_id,
     631                            ops->index_get(cur),
     632                            (ops->is_directory(cur) << 16) | last,
     633                            LOWER32(size), UPPER32(size));
     634                } else {
     635                        async_answer_0(rid, rc);
     636                }
     637                goto out;
     638        }
     639       
     640        /* Create. */
     641       
     642        if (lflag & L_CREATE) {
     643                if (cur && (lflag & L_EXCLUSIVE)) {
     644                        async_answer_0(rid, EEXIST);
     645                        goto out;
     646                }
     647       
     648                if (!cur) {
     649                        rc = ops->create(&cur, service_id,
     650                            lflag & (L_FILE | L_DIRECTORY));
     651                        if (rc != EOK) {
     652                                async_answer_0(rid, rc);
     653                                goto out;
     654                        }
     655                        if (!cur) {
     656                                async_answer_0(rid, ENOSPC);
    615657                                goto out;
    616658                        }
    617659                       
    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                                
     660                        rc = ops->link(par, cur, component);
     661                        if (rc != EOK) {
     662                                (void) ops->destroy(cur);
     663                                cur = NULL;
     664                                async_answer_0(rid, rc);
    651665                                goto out;
    652666                        }
    653                        
    654                         async_answer_0(rid, ENOENT);
    655                         goto out;
    656                 }
    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);
     667                }
     668        }
     669       
     670        /* Return. */
     671out1:
     672        if (!cur) {
     673                async_answer_5(rid, fs_handle, service_id, ops->index_get(par),
     674                    last_next, -1, true);
    734675                goto out;
    735676        }
    736677       
    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);
     678        aoff64_t size = ops->size_get(cur);
     679        async_answer_5(rid, fs_handle, service_id, ops->index_get(cur),
     680            (ops->is_directory(cur) << 16) | last, LOWER32(size),
     681            UPPER32(size));
    792682       
    793683out:
    794        
    795684        if (par)
    796685                (void) ops->node_put(par);
     
    862751        memset(&st, 0, sizeof(struct statfs));
    863752
     753        str_cpy(st.fs_name, sizeof(st.fs_name), fs_name);
     754
    864755        if (ops->size_block != NULL) {
    865756                rc = ops->size_block(service_id, &st.f_bsize);
     
    919810        async_answer_4(rid, rc, LOWER32(size), UPPER32(size),
    920811            ops->lnkcnt_get(fn),
    921             (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
     812            (ops->is_file(fn) ? L_FILE : 0) |
     813            (ops->is_directory(fn) ? L_DIRECTORY : 0));
    922814       
    923815        (void) ops->node_put(fn);
Note: See TracChangeset for help on using the changeset viewer.