Changes in uspace/lib/fs/libfs.c [f9b2cb4c:b8dbe2f] in mainline


Ignore:
File:
1 edited

Legend:

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

    rf9b2cb4c rb8dbe2f  
    3636
    3737#include "libfs.h"
    38 #include "../../srv/vfs/vfs.h"
    3938#include <macros.h>
    4039#include <errno.h>
     
    4544#include <mem.h>
    4645#include <sys/stat.h>
    47 #include <sys/statfs.h>
    4846#include <stdlib.h>
     47#include <fibril_synch.h>
    4948
    5049#define on_error(rc, action) \
     
    6362        } while (0)
    6463
     64#define DPRINTF(...)
     65
     66#define LOG_EXIT(rc) \
     67        DPRINTF("Exiting %s() with rc = %d at line %d\n", __FUNC__, rc, __LINE__);
     68
    6569static fs_reg_t reg;
    6670
     
    6872static libfs_ops_t *libfs_ops = NULL;
    6973
    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 *);
     74static void libfs_link(libfs_ops_t *, fs_handle_t, ipc_callid_t,
     75    ipc_call_t *);
    7276static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    7377    ipc_call_t *);
     
    7579static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    7680    ipc_call_t *);
    77 static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
    7881
    7982static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req)
     
    104107}
    105108
    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 
    111109static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
    112110{
     
    119117}
    120118
    121 static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
    122 {
    123                
    124         libfs_unmount(libfs_ops, rid, req);
     119static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req)
     120{
     121        libfs_link(libfs_ops, reg.fs_handle, rid, req);
    125122}
    126123
     
    193190        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
    194191        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
    195         int rc;
    196 
    197         rc = vfs_out_ops->destroy(service_id, index);
    198 
     192
     193        int rc;
     194        fs_node_t *node = NULL;
     195        rc = libfs_ops->node_get(&node, service_id, index);
     196        if (rc == EOK && node != NULL) {
     197                bool destroy = (libfs_ops->lnkcnt_get(node) == 0);
     198                libfs_ops->node_put(node);
     199                if (destroy) {
     200                        rc = vfs_out_ops->destroy(service_id, index);
     201                }
     202        }
    199203        async_answer_0(rid, rc);
    200204}
     
    221225}
    222226
    223 static void vfs_out_statfs(ipc_callid_t rid, ipc_call_t *req)
    224 {
    225         libfs_statfs(libfs_ops, reg.fs_handle, rid, req);
    226 }
     227static void vfs_out_get_size(ipc_callid_t rid, ipc_call_t *req)
     228{
     229        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
     230        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     231        int rc;
     232
     233        fs_node_t *node = NULL;
     234        rc = libfs_ops->node_get(&node, service_id, index);
     235        if (rc != EOK) {
     236                async_answer_0(rid, rc);
     237        }
     238        if (node == NULL) {
     239                async_answer_0(rid, EINVAL);
     240        }
     241       
     242        uint64_t size = libfs_ops->size_get(node);
     243        libfs_ops->node_put(node);
     244       
     245        async_answer_2(rid, EOK, LOWER32(size), UPPER32(size));
     246}
     247
     248static void vfs_out_is_empty(ipc_callid_t rid, ipc_call_t *req)
     249{
     250        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
     251        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     252        int rc;
     253
     254        fs_node_t *node = NULL;
     255        rc = libfs_ops->node_get(&node, service_id, index);
     256        if (rc != EOK) {
     257                async_answer_0(rid, rc);
     258        }
     259        if (node == NULL) {
     260                async_answer_0(rid, EINVAL);
     261        }
     262       
     263        bool children = false;
     264        rc = libfs_ops->has_children(&children, node);
     265        libfs_ops->node_put(node);
     266       
     267        if (rc != EOK) {
     268                async_answer_0(rid, rc);
     269        }
     270        async_answer_0(rid, children ? ENOTEMPTY : EOK);
     271}
     272
    227273static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    228274{
     
    247293                        vfs_out_mounted(callid, &call);
    248294                        break;
    249                 case VFS_OUT_MOUNT:
    250                         vfs_out_mount(callid, &call);
    251                         break;
    252295                case VFS_OUT_UNMOUNTED:
    253296                        vfs_out_unmounted(callid, &call);
    254297                        break;
    255                 case VFS_OUT_UNMOUNT:
    256                         vfs_out_unmount(callid, &call);
     298                case VFS_OUT_LINK:
     299                        vfs_out_link(callid, &call);
    257300                        break;
    258301                case VFS_OUT_LOOKUP:
     
    283326                        vfs_out_sync(callid, &call);
    284327                        break;
    285                 case VFS_OUT_STATFS:
    286                         vfs_out_statfs(callid, &call);
     328                case VFS_OUT_GET_SIZE:
     329                        vfs_out_get_size(callid, &call);
     330                        break;
     331                case VFS_OUT_IS_EMPTY:
     332                        vfs_out_is_empty(callid, &call);
    287333                        break;
    288334                default:
     
    342388         * Ask VFS for callback connection.
    343389         */
    344         port_id_t port;
    345         rc = async_create_callback_port(exch, INTERFACE_VFS_DRIVER_CB, 0, 0,
    346             vfs_connection, NULL, &port);
     390        async_connect_to_me(exch, 0, 0, 0, vfs_connection, NULL);
    347391       
    348392        /*
     
    373417         * the same connection fibril as well.
    374418         */
    375         async_set_fallback_port_handler(vfs_connection, NULL);
     419        async_set_client_connection(vfs_connection);
    376420       
    377421        return IPC_GET_RETVAL(answer);
     
    383427}
    384428
    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);
     429static char plb_get_char(unsigned pos)
     430{
     431        return reg.plb_ro[pos % PLB_SIZE];
     432}
     433
     434static int plb_get_component(char *dest, unsigned *sz, unsigned *ppos, unsigned last)
     435{
     436        unsigned pos = *ppos;
     437        unsigned size = 0;
     438       
     439        if (pos == last) {
     440                *sz = 0;
     441                return ERANGE;
     442        }
     443
     444        char c = plb_get_char(pos);
     445        if (c == '/') {
     446                pos++;
     447        }
     448       
     449        for (int i = 0; i <= NAME_MAX; i++) {
     450                c = plb_get_char(pos);
     451                if (pos == last || c == '/') {
     452                        dest[i] = 0;
     453                        *ppos = pos;
     454                        *sz = size;
     455                        return EOK;
     456                }
     457                dest[i] = c;
     458                pos++;
     459                size++;
     460        }
     461        return ENAMETOOLONG;
     462}
     463
     464static int receive_fname(char *buffer)
     465{
     466        size_t size;
     467        ipc_callid_t wcall;
     468       
     469        if (!async_data_write_receive(&wcall, &size)) {
     470                return ENOENT;
     471        }
     472        if (size > NAME_MAX + 1) {
     473                async_answer_0(wcall, ERANGE);
     474                return ERANGE;
     475        }
     476        return async_data_write_finalize(wcall, buffer, size);
     477}
     478
     479/** Link a file at a path.
     480 */
     481void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req)
     482{
     483        service_id_t parent_sid = IPC_GET_ARG1(*req);
     484        fs_index_t parent_index = IPC_GET_ARG2(*req);
     485        fs_index_t child_index = IPC_GET_ARG3(*req);
     486       
     487        char component[NAME_MAX + 1];
     488        int rc = receive_fname(component);
     489        if (rc != EOK) {
     490                async_answer_0(rid, rc);
    396491                return;
    397492        }
    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));
     493
     494        fs_node_t *parent = NULL;
     495        rc = ops->node_get(&parent, parent_sid, parent_index);
     496        if (parent == NULL) {
     497                async_answer_0(rid, rc == EOK ? EBADF : rc);
    405498                return;
    406499        }
    407500       
    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);
     501        fs_node_t *child = NULL;
     502        rc = ops->node_get(&child, parent_sid, child_index);
     503        if (child == NULL) {
     504                async_answer_0(rid, rc == EOK ? EBADF : rc);
     505                ops->node_put(parent);
    413506                return;
    414507        }
    415508       
    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];
     509        rc = ops->link(parent, child, component);
     510        ops->node_put(parent);
     511        ops->node_put(child);
     512        async_answer_0(rid, rc);
    497513}
    498514
     
    510526 *
    511527 */
    512 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    513     ipc_call_t *req)
    514 {
    515         unsigned int first = IPC_GET_ARG1(*req);
    516         unsigned int last = IPC_GET_ARG2(*req);
    517         unsigned int next = first;
     528void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid, ipc_call_t *req)
     529{
     530        unsigned first = IPC_GET_ARG1(*req);
     531        unsigned len = IPC_GET_ARG2(*req);
    518532        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);
     533        fs_index_t index = IPC_GET_ARG4(*req);
     534        int lflag = IPC_GET_ARG5(*req);
     535       
     536        assert((int) index != -1);
     537       
     538        DPRINTF("Entered libfs_lookup()\n");
     539       
     540        // TODO: Validate flags.
     541       
     542        unsigned next = first;
     543        unsigned last = first + len;
     544       
    521545        char component[NAME_MAX + 1];
    522         int len;
    523         int rc;
    524        
    525         if (last < next)
    526                 last += PLB_SIZE;
     546        int rc;
    527547       
    528548        fs_node_t *par = NULL;
    529549        fs_node_t *cur = NULL;
    530550        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);
     551        unsigned clen = 0;
     552       
     553        rc = ops->node_get(&cur, service_id, index);
     554        if (rc != EOK) {
     555                async_answer_0(rid, rc);
     556                LOG_EXIT(rc);
     557                goto out;
     558        }
     559       
     560        assert(cur != NULL);
     561       
     562        /* Find the file and its parent. */
     563       
     564        unsigned last_next = 0;
     565       
     566        while (next != last) {
     567                if (cur == NULL) {
     568                        assert(par != NULL);
     569                        goto out1;
     570                }
     571
     572                if (!ops->is_directory(cur)) {
     573                        async_answer_0(rid, ENOTDIR);
     574                        LOG_EXIT(ENOTDIR);
     575                        goto out;
     576                }
    541577               
    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;
     578                last_next = next;
     579                /* Collect the component */
     580                rc = plb_get_component(component, &clen, &next, last);
     581                assert(rc != ERANGE);
     582                if (rc != EOK) {
     583                        async_answer_0(rid, rc);
     584                        LOG_EXIT(rc);
     585                        goto out;
     586                }
    552587               
    553                 rc = ops->has_children(&has_children, cur);
    554                 on_error(rc, goto out_with_answer);
    555                 if (!has_children)
    556                         break;
     588                if (clen == 0) {
     589                        /* The path is just "/". */
     590                        break;
     591                }
    557592               
    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++;
     593                assert(component[clen] == 0);
    575594               
    576595                /* Match the component */
    577596                rc = ops->match(&tmp, cur, component);
    578                 on_error(rc, goto out_with_answer);
     597                if (rc != EOK) {
     598                        async_answer_0(rid, rc);
     599                        LOG_EXIT(rc);
     600                        goto out;
     601                }
    579602               
    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--;
     603                /* Descend one level */
     604                if (par) {
     605                        rc = ops->node_put(par);
     606                        if (rc != EOK) {
     607                                async_answer_0(rid, rc);
     608                                LOG_EXIT(rc);
     609                                goto out;
     610                        }
     611                }
     612               
     613                par = cur;
     614                cur = tmp;
     615                tmp = NULL;
     616        }
     617       
     618        /* At this point, par is either NULL or a directory.
     619         * If cur is NULL, the looked up file does not exist yet.
     620         */
     621         
     622        assert(par == NULL || ops->is_directory(par));
     623        assert(par != NULL || cur != NULL);
     624       
     625        /* Check for some error conditions. */
     626       
     627        if (cur && (lflag & L_FILE) && (ops->is_directory(cur))) {
     628                async_answer_0(rid, EISDIR);
     629                LOG_EXIT(EISDIR);
     630                goto out;
     631        }
     632       
     633        if (cur && (lflag & L_DIRECTORY) && (ops->is_file(cur))) {
     634                async_answer_0(rid, ENOTDIR);
     635                LOG_EXIT(ENOTDIR);
     636                goto out;
     637        }
     638       
     639        /* Unlink. */
     640       
     641        if (lflag & L_UNLINK) {
     642                if (!cur) {
     643                        async_answer_0(rid, ENOENT);
     644                        LOG_EXIT(ENOENT);
     645                        goto out;
     646                }
     647                if (!par) {
     648                        async_answer_0(rid, EINVAL);
     649                        LOG_EXIT(EINVAL);
     650                        goto out;
     651                }
     652               
     653                rc = ops->unlink(par, cur, component);
     654                if (rc == EOK) {
     655                        int64_t size = ops->size_get(cur);
     656                        int32_t lsize = LOWER32(size);
     657                        if (lsize != size) {
     658                                lsize = -1;
     659                        }
    596660                       
    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);
     661                        async_answer_5(rid, fs_handle, service_id,
     662                            ops->index_get(cur), last, lsize,
     663                            ops->is_directory(cur));
     664                        LOG_EXIT(EOK);
     665                } else {
     666                        async_answer_0(rid, rc);
     667                        LOG_EXIT(rc);
     668                }
     669                goto out;
     670        }
     671       
     672        /* Create. */
     673       
     674        if (lflag & L_CREATE) {
     675                if (cur && (lflag & L_EXCLUSIVE)) {
     676                        async_answer_0(rid, EEXIST);
     677                        LOG_EXIT(EEXIST);
     678                        goto out;
     679                }
     680       
     681                if (!cur) {
     682                        rc = ops->create(&cur, service_id, lflag & (L_FILE|L_DIRECTORY));
     683                        if (rc != EOK) {
     684                                async_answer_0(rid, rc);
     685                                LOG_EXIT(rc);
     686                                goto out;
     687                        }
     688                        if (!cur) {
     689                                async_answer_0(rid, ENOSPC);
     690                                LOG_EXIT(ENOSPC);
    615691                                goto out;
    616692                        }
    617693                       
    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                                
     694                        rc = ops->link(par, cur, component);
     695                        if (rc != EOK) {
     696                                (void) ops->destroy(cur);
     697                                cur = NULL;
     698                                async_answer_0(rid, rc);
     699                                LOG_EXIT(rc);
    651700                                goto out;
    652701                        }
    653                        
    654                         async_answer_0(rid, ENOENT);
     702                }
     703        }
     704       
     705        /* Return. */
     706out1:
     707        if (!cur) {
     708                async_answer_5(rid, fs_handle, service_id,
     709                        ops->index_get(par), last_next, -1, true);
     710                LOG_EXIT(EOK);
     711                goto out;
     712        }
     713       
     714        if (lflag & L_OPEN) {
     715                rc = ops->node_open(cur);
     716                if (rc != EOK) {
     717                        async_answer_0(rid, rc);
     718                        LOG_EXIT(rc);
    655719                        goto out;
    656720                }
    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        
     721        }
     722       
     723        int64_t size = ops->size_get(cur);
     724        int32_t lsize = LOWER32(size);
     725        if (lsize != size) {
     726                lsize = -1;
     727        }
     728       
     729        async_answer_5(rid, fs_handle, service_id,
     730                ops->index_get(cur), last, lsize,
     731                ops->is_directory(cur));
     732       
     733        LOG_EXIT(EOK);
    793734out:
    794        
    795         if (par)
     735        if (par) {
    796736                (void) ops->node_put(par);
    797        
    798         if (cur)
     737        }
     738       
     739        if (cur) {
    799740                (void) ops->node_put(cur);
    800        
    801         if (tmp)
     741        }
     742       
     743        if (tmp) {
    802744                (void) ops->node_put(tmp);
     745        }
    803746}
    804747
     
    808751        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
    809752        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    810 
     753       
    811754        fs_node_t *fn;
    812755        int rc = ops->node_get(&fn, service_id, index);
    813756        on_error(rc, answer_and_return(rid, rc));
    814 
     757       
    815758        ipc_callid_t callid;
    816759        size_t size;
     
    822765                return;
    823766        }
    824 
     767       
    825768        struct stat stat;
    826769        memset(&stat, 0, sizeof(struct stat));
    827 
     770       
    828771        stat.fs_handle = fs_handle;
    829772        stat.service_id = service_id;
     
    834777        stat.size = ops->size_get(fn);
    835778        stat.service = ops->service_get(fn);
    836 
     779       
    837780        ops->node_put(fn);
    838 
    839 
     781       
    840782        async_data_read_finalize(callid, &stat, sizeof(struct stat));
    841783        async_answer_0(rid, EOK);
    842784}
    843 
    844 void libfs_statfs(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    845     ipc_call_t *request)
    846 {
    847         service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
    848         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    849 
    850         fs_node_t *fn;
    851         int rc = ops->node_get(&fn, service_id, index);
    852         on_error(rc, answer_and_return(rid, rc));
    853 
    854         ipc_callid_t callid;
    855         size_t size;
    856         if ((!async_data_read_receive(&callid, &size)) ||
    857             (size != sizeof(struct statfs))) {
    858                 goto error;
    859         }
    860 
    861         struct statfs st;
    862         memset(&st, 0, sizeof(struct statfs));
    863 
    864         if (ops->size_block != NULL) {
    865                 rc = ops->size_block(service_id, &st.f_bsize);
    866                 if (rc != EOK)
    867                         goto error;
    868         }
    869 
    870         if (ops->total_block_count != NULL) {
    871                 rc = ops->total_block_count(service_id, &st.f_blocks);
    872                 if (rc != EOK)
    873                         goto error;
    874         }
    875 
    876         if (ops->free_block_count != NULL) {
    877                 rc = ops->free_block_count(service_id, &st.f_bfree);
    878                 if (rc != EOK)
    879                         goto error;
    880         }
    881 
    882         ops->node_put(fn);
    883         async_data_read_finalize(callid, &st, sizeof(struct statfs));
    884         async_answer_0(rid, EOK);
    885         return;
    886 
    887 error:
    888         ops->node_put(fn);
    889         async_answer_0(callid, EINVAL);
    890         async_answer_0(rid, EINVAL);
    891 }
    892 
    893785
    894786/** Open VFS triplet.
     
    944836
    945837        fibril_mutex_lock(&instances_mutex);
    946         list_foreach(instances_list, link, fs_instance_t, cur) {
     838        list_foreach(instances_list, link) {
     839                fs_instance_t *cur = list_get_instance(link, fs_instance_t,
     840                    link);
     841
    947842                if (cur->service_id == service_id) {
    948843                        fibril_mutex_unlock(&instances_mutex);
     
    967862{
    968863        fibril_mutex_lock(&instances_mutex);
    969         list_foreach(instances_list, link, fs_instance_t, inst) {
     864        list_foreach(instances_list, link) {
     865                fs_instance_t *inst = list_get_instance(link, fs_instance_t,
     866                    link);
     867
    970868                if (inst->service_id == service_id) {
    971869                        *idp = inst->data;
     
    981879{
    982880        fibril_mutex_lock(&instances_mutex);
    983         list_foreach(instances_list, link, fs_instance_t, inst) {
     881        list_foreach(instances_list, link) {
     882                fs_instance_t *inst = list_get_instance(link, fs_instance_t,
     883                    link);
     884
    984885                if (inst->service_id == service_id) {
    985886                        list_remove(&inst->link);
Note: See TracChangeset for help on using the changeset viewer.