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


Ignore:
File:
1 edited

Legend:

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

    r2166728 rf9b2cb4c  
    3636
    3737#include "libfs.h"
     38#include "../../srv/vfs/vfs.h"
    3839#include <macros.h>
    3940#include <errno.h>
     
    4344#include <dirent.h>
    4445#include <mem.h>
    45 #include <str.h>
     46#include <sys/stat.h>
     47#include <sys/statfs.h>
    4648#include <stdlib.h>
    47 #include <fibril_synch.h>
    48 #include <ipc/vfs.h>
    49 #include <vfs/vfs.h>
    5049
    5150#define on_error(rc, action) \
     
    6968static libfs_ops_t *libfs_ops = NULL;
    7069
    71 static char fs_name[FS_NAME_MAXLEN + 1];
    72 
    73 static void libfs_link(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    74     ipc_call_t *);
     70static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
     71static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
    7572static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    7673    ipc_call_t *);
     
    7875static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    7976    ipc_call_t *);
    80 static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t,
    81     ipc_call_t *);
     77static void libfs_statfs(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
    8278
    8379static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req)
     
    108104}
    109105
     106static 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
    110111static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
    111112{
     
    118119}
    119120
    120 static void vfs_out_link(ipc_callid_t rid, ipc_call_t *req)
    121 {
    122         libfs_link(libfs_ops, reg.fs_handle, rid, req);
     121static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
     122{
     123               
     124        libfs_unmount(libfs_ops, rid, req);
    123125}
    124126
     
    157159        rc = vfs_out_ops->write(service_id, index, pos, &wbytes, &nsize);
    158160
    159         if (rc == EOK) {
    160                 async_answer_3(rid, EOK, wbytes, LOWER32(nsize),
    161                     UPPER32(nsize));
    162         } else
     161        if (rc == EOK)
     162                async_answer_3(rid, EOK, wbytes, LOWER32(nsize), UPPER32(nsize));
     163        else
    163164                async_answer_0(rid, rc);
    164165}
     
    192193        service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
    193194        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
    194 
    195195        int rc;
    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         }
     196
     197        rc = vfs_out_ops->destroy(service_id, index);
     198
    204199        async_answer_0(rid, rc);
    205200}
     
    230225        libfs_statfs(libfs_ops, reg.fs_handle, rid, req);
    231226}
    232 
    233 static 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 
    255227static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    256228{
     
    275247                        vfs_out_mounted(callid, &call);
    276248                        break;
     249                case VFS_OUT_MOUNT:
     250                        vfs_out_mount(callid, &call);
     251                        break;
    277252                case VFS_OUT_UNMOUNTED:
    278253                        vfs_out_unmounted(callid, &call);
    279254                        break;
    280                 case VFS_OUT_LINK:
    281                         vfs_out_link(callid, &call);
     255                case VFS_OUT_UNMOUNT:
     256                        vfs_out_unmount(callid, &call);
    282257                        break;
    283258                case VFS_OUT_LOOKUP:
     
    310285                case VFS_OUT_STATFS:
    311286                        vfs_out_statfs(callid, &call);
    312                         break;
    313                 case VFS_OUT_IS_EMPTY:
    314                         vfs_out_is_empty(callid, &call);
    315287                        break;
    316288                default:
     
    367339        libfs_ops = lops;
    368340
    369         str_cpy(fs_name, sizeof(fs_name), info->name);
    370 
    371341        /*
    372342         * Ask VFS for callback connection.
     
    413383}
    414384
     385void 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);
     396                return;
     397        }
     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));
     405                return;
     406        }
     407       
     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);
     413                return;
     414        }
     415       
     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
     447void 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
    415494static char plb_get_char(unsigned pos)
    416495{
    417496        return reg.plb_ro[pos % PLB_SIZE];
    418 }
    419 
    420 static 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 
    450 static 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  */
    466 void libfs_link(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    467     ipc_call_t *req)
    468 {
    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);
    477                 return;
    478         }
    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);
    484                 return;
    485         }
    486        
    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);
    492                 return;
    493         }
    494        
    495         rc = ops->link(parent, child, component);
    496         ops->node_put(parent);
    497         ops->node_put(child);
    498         async_answer_0(rid, rc);
    499497}
    500498
     
    515513    ipc_call_t *req)
    516514{
    517         unsigned first = IPC_GET_ARG1(*req);
    518         unsigned len = IPC_GET_ARG2(*req);
     515        unsigned int first = IPC_GET_ARG1(*req);
     516        unsigned int last = IPC_GET_ARG2(*req);
     517        unsigned int next = first;
    519518        service_id_t service_id = IPC_GET_ARG3(*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        
     519        int lflag = IPC_GET_ARG4(*req);
     520        fs_index_t index = IPC_GET_ARG5(*req);
    528521        char component[NAME_MAX + 1];
     522        int len;
    529523        int rc;
     524       
     525        if (last < next)
     526                last += PLB_SIZE;
    530527       
    531528        fs_node_t *par = NULL;
    532529        fs_node_t *cur = NULL;
    533530        fs_node_t *tmp = NULL;
    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;
     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);
     541               
     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;
     552               
     553                rc = ops->has_children(&has_children, cur);
     554                on_error(rc, goto out_with_answer);
     555                if (!has_children)
     556                        break;
     557               
     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++;
    552569                }
    553 
    554                 if (!ops->is_directory(cur)) {
    555                         async_answer_0(rid, ENOTDIR);
     570               
     571                assert(len);
     572                component[len] = '\0';
     573                /* Eat slash */
     574                next++;
     575               
     576                /* Match the component */
     577                rc = ops->match(&tmp, cur, component);
     578                on_error(rc, goto out_with_answer);
     579               
     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;
     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);
     615                                goto out;
     616                        }
     617                       
     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                               
     651                                goto out;
     652                        }
     653                       
     654                        async_answer_0(rid, ENOENT);
    556655                        goto out;
    557656                }
    558657               
    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                 }
    567                
    568                 if (clen == 0) {
    569                         /* The path is just "/". */
    570                         break;
    571                 }
    572                
    573                 assert(component[clen] == 0);
    574                
    575                 /* Match the component */
    576                 rc = ops->match(&tmp, cur, component);
    577                 if (rc != EOK) {
    578                         async_answer_0(rid, rc);
    579                         goto out;
    580                 }
    581                
    582                 /* Descend one level */
    583658                if (par) {
    584659                        rc = ops->node_put(par);
    585                         if (rc != EOK) {
    586                                 async_answer_0(rid, rc);
    587                                 goto out;
    588                         }
     660                        on_error(rc, goto out_with_answer);
    589661                }
    590662               
     663                /* Descend one level */
    591664                par = cur;
    592665                cur = tmp;
     
    594667        }
    595668       
    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);
     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                       
    620730                        goto out;
    621731                }
    622                 if (!par) {
    623                         async_answer_0(rid, EINVAL);
    624                         goto out;
    625                 }
    626                
     732               
     733                async_answer_0(rid, ENOENT);
     734                goto out;
     735        }
     736       
     737skip_miss:
     738       
     739        /* Handle hit */
     740        if (lflag & L_UNLINK) {
     741                unsigned int old_lnkcnt = ops->lnkcnt_get(cur);
    627742                rc = ops->unlink(par, cur, component);
     743               
    628744                if (rc == EOK) {
    629745                        aoff64_t size = ops->size_get(cur);
    630746                        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 {
     747                            ops->index_get(cur), LOWER32(size), UPPER32(size),
     748                            old_lnkcnt);
     749                } else
    635750                        async_answer_0(rid, rc);
    636                 }
     751               
    637752                goto out;
    638753        }
    639754       
    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);
    657                                 goto out;
    658                         }
    659                        
    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);
    665                                 goto out;
    666                         }
    667                 }
    668         }
    669        
    670         /* Return. */
    671 out1:
    672         if (!cur) {
    673                 async_answer_5(rid, fs_handle, service_id, ops->index_get(par),
    674                     last_next, -1, true);
     755        if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) ||
     756            (lflag & L_LINK)) {
     757                async_answer_0(rid, EEXIST);
    675758                goto out;
    676759        }
    677760       
    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));
     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       
     776out_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);
    682792       
    683793out:
     794       
    684795        if (par)
    685796                (void) ops->node_put(par);
     
    751862        memset(&st, 0, sizeof(struct statfs));
    752863
    753         str_cpy(st.fs_name, sizeof(st.fs_name), fs_name);
    754 
    755864        if (ops->size_block != NULL) {
    756865                rc = ops->size_block(service_id, &st.f_bsize);
     
    810919        async_answer_4(rid, rc, LOWER32(size), UPPER32(size),
    811920            ops->lnkcnt_get(fn),
    812             (ops->is_file(fn) ? L_FILE : 0) |
    813             (ops->is_directory(fn) ? L_DIRECTORY : 0));
     921            (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
    814922       
    815923        (void) ops->node_put(fn);
Note: See TracChangeset for help on using the changeset viewer.