Changes in / [2e37308:d27ed12] in mainline


Ignore:
Location:
uspace
Files:
5 edited

Legend:

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

    r2e37308 rd27ed12  
    4646#include <sys/stat.h>
    4747
    48 #define on_error(rc, action) \
    49         do { \
    50                 if ((rc) != EOK) \
    51                         action; \
    52         } while (0)
    53 
    54 #define combine_rc(rc1, rc2) \
    55         ((rc1) == EOK ? (rc2) : (rc1))
    56 
    57 #define answer_and_return(rid, rc) \
    58         do { \
    59                 ipc_answer_0((rid), (rc)); \
    60                 return; \
    61         } while (0)
    62 
    6348/** Register file system server.
    6449 *
     
    177162        }
    178163
    179         fs_node_t *fn;
    180         res = ops->node_get(&fn, mp_dev_handle, mp_fs_index);
    181         if (res != EOK || !fn) {
     164        fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index);
     165        if (!fn) {
    182166                ipc_hangup(mountee_phone);
    183                 ipc_answer_0(callid, combine_rc(res, ENOENT));
    184                 ipc_answer_0(rid, combine_rc(res, ENOENT));
     167                ipc_answer_0(callid, ENOENT);
     168                ipc_answer_0(rid, ENOENT);
    185169                return;
    186170        }
     
    188172        if (fn->mp_data.mp_active) {
    189173                ipc_hangup(mountee_phone);
    190                 (void) ops->node_put(fn);
     174                ops->node_put(fn);
    191175                ipc_answer_0(callid, EBUSY);
    192176                ipc_answer_0(rid, EBUSY);
     
    195179
    196180        rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
    197         if (rc != EOK) {
     181        if (rc != 0) {
    198182                ipc_hangup(mountee_phone);
    199                 (void) ops->node_put(fn);
     183                ops->node_put(fn);
    200184                ipc_answer_0(callid, rc);
    201185                ipc_answer_0(rid, rc);
     
    246230        char component[NAME_MAX + 1];
    247231        int len;
    248         int rc;
    249232
    250233        if (last < next)
     
    252235
    253236        fs_node_t *par = NULL;
    254         fs_node_t *cur = NULL;
     237        fs_node_t *cur = ops->root_get(dev_handle);
    255238        fs_node_t *tmp = NULL;
    256 
    257         rc = ops->root_get(&cur, dev_handle);
    258         on_error(rc, goto out_with_answer);
    259239
    260240        if (cur->mp_data.mp_active) {
     
    262242                    next, last, cur->mp_data.dev_handle, lflag, index,
    263243                    IPC_FF_ROUTE_FROM_ME);
    264                 (void) ops->node_put(cur);
     244                ops->node_put(cur);
    265245                return;
    266246        }
     
    269249                next++;         /* eat slash */
    270250       
    271         while (next <= last) {
    272                 bool has_children;
    273 
    274                 rc = ops->has_children(&has_children, cur);
    275                 on_error(rc, goto out_with_answer);
    276                 if (!has_children)
    277                         break;
    278 
     251        while (next <= last && ops->has_children(cur)) {
    279252                /* collect the component */
    280253                len = 0;
     
    294267
    295268                /* match the component */
    296                 rc = ops->match(&tmp, cur, component);
    297                 on_error(rc, goto out_with_answer);
    298 
     269                tmp = ops->match(cur, component);
    299270                if (tmp && tmp->mp_data.mp_active) {
    300271                        if (next > last)
     
    306277                            VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle,
    307278                            lflag, index, IPC_FF_ROUTE_FROM_ME);
    308                         (void) ops->node_put(cur);
    309                         (void) ops->node_put(tmp);
     279                        ops->node_put(cur);
     280                        ops->node_put(tmp);
    310281                        if (par)
    311                                 (void) ops->node_put(par);
     282                                ops->node_put(par);
    312283                        return;
    313284                }
     
    329300                                fs_node_t *fn;
    330301                                if (lflag & L_CREATE)
    331                                         rc = ops->create(&fn, dev_handle,
    332                                             lflag);
     302                                        fn = ops->create(dev_handle, lflag);
    333303                                else
    334                                         rc = ops->node_get(&fn, dev_handle,
     304                                        fn = ops->node_get(dev_handle,
    335305                                            index);
    336                                 on_error(rc, goto out_with_answer);
    337306                                if (fn) {
     307                                        int rc;
     308
    338309                                        rc = ops->link(cur, fn, component);
    339310                                        if (rc != EOK) {
    340                                                 if (lflag & L_CREATE)
    341                                                         (void) ops->destroy(fn);
     311                                                if (lflag & L_CREATE) {
     312                                                        (void)ops->destroy(fn);
     313                                                }
    342314                                                ipc_answer_0(rid, rc);
    343315                                        } else {
     
    347319                                                    ops->size_get(fn),
    348320                                                    ops->lnkcnt_get(fn));
    349                                                 (void) ops->node_put(fn);
     321                                                ops->node_put(fn);
    350322                                        }
    351323                                } else {
     
    358330                }
    359331
    360                 if (par) {
    361                         rc = ops->node_put(par);
    362                         on_error(rc, goto out_with_answer);
    363                 }
     332                if (par)
     333                        ops->node_put(par);
    364334
    365335                /* descend one level */
     
    370340
    371341        /* handle miss: excessive components */
    372         if (next <= last) {
    373                 bool has_children;
    374 
    375                 rc = ops->has_children(&has_children, cur);
    376                 on_error(rc, goto out_with_answer);
    377                 if (has_children)
    378                         goto skip_miss;
    379 
     342        if (next <= last && !ops->has_children(cur)) {
    380343                if (lflag & (L_CREATE | L_LINK)) {
    381344                        if (!ops->is_directory(cur)) {
     
    405368                        fs_node_t *fn;
    406369                        if (lflag & L_CREATE)
    407                                 rc = ops->create(&fn, dev_handle, lflag);
     370                                fn = ops->create(dev_handle, lflag);
    408371                        else
    409                                 rc = ops->node_get(&fn, dev_handle, index);
    410                         on_error(rc, goto out_with_answer);
     372                                fn = ops->node_get(dev_handle, index);
    411373                        if (fn) {
     374                                int rc;
     375
    412376                                rc = ops->link(cur, fn, component);
    413377                                if (rc != EOK) {
    414378                                        if (lflag & L_CREATE)
    415                                                 (void) ops->destroy(fn);
     379                                                (void)ops->destroy(fn);
    416380                                        ipc_answer_0(rid, rc);
    417381                                } else {
     
    421385                                            ops->size_get(fn),
    422386                                            ops->lnkcnt_get(fn));
    423                                         (void) ops->node_put(fn);
     387                                        ops->node_put(fn);
    424388                                }
    425389                        } else {
     
    431395                goto out;
    432396        }
    433 skip_miss:
    434397
    435398        /* handle hit */
    436399        if (lflag & L_UNLINK) {
    437400                unsigned old_lnkcnt = ops->lnkcnt_get(cur);
    438                 rc = ops->unlink(par, cur, component);
    439                 ipc_answer_5(rid, (ipcarg_t)rc, fs_handle, dev_handle,
     401                int res = ops->unlink(par, cur, component);
     402                ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
    440403                    ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
    441404                goto out;
     
    455418        }
    456419
    457 out_with_answer:
    458         if (rc == EOK) {
    459                 ipc_answer_5(rid, EOK, fs_handle, dev_handle,
    460                     ops->index_get(cur), ops->size_get(cur),
    461                     ops->lnkcnt_get(cur));
    462         } else {
    463                 ipc_answer_0(rid, rc);
    464         }
     420        ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
     421            ops->size_get(cur), ops->lnkcnt_get(cur));
    465422
    466423out:
    467424        if (par)
    468                 (void) ops->node_put(par);
     425                ops->node_put(par);
    469426        if (cur)
    470                 (void) ops->node_put(cur);
     427                ops->node_put(cur);
    471428        if (tmp)
    472                 (void) ops->node_put(tmp);
     429                ops->node_put(tmp);
    473430}
    474431
     
    478435        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
    479436        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    480         fs_node_t *fn;
    481         int rc;
    482 
    483         rc = ops->node_get(&fn, dev_handle, index);
    484         on_error(rc, answer_and_return(rid, rc));
     437        fs_node_t *fn = ops->node_get(dev_handle, index);
    485438
    486439        ipc_callid_t callid;
     
    520473        dev_handle_t dev_handle = IPC_GET_ARG1(*request);
    521474        fs_index_t index = IPC_GET_ARG2(*request);
    522         fs_node_t *fn;
    523         int rc;
    524        
    525         rc = ops->node_get(&fn, dev_handle, index);
    526         on_error(rc, answer_and_return(rid, rc));
    527        
    528         if (fn == NULL) {
     475       
     476        fs_node_t *node = ops->node_get(dev_handle, index);
     477       
     478        if (node == NULL) {
    529479                ipc_answer_0(rid, ENOENT);
    530480                return;
    531481        }
    532482       
    533         ipc_answer_5(rid, EOK, fs_handle, dev_handle, index, ops->size_get(fn),
    534             ops->lnkcnt_get(fn));
    535        
    536         (void) ops->node_put(fn);
     483        ipc_answer_5(rid, EOK, fs_handle, dev_handle, index,
     484            ops->size_get(node), ops->lnkcnt_get(node));
     485       
     486        ops->node_put(node);
    537487}
    538488
  • uspace/lib/libfs/libfs.h

    r2e37308 rd27ed12  
    5656
    5757typedef struct {
    58         /*
    59          * The first set of methods are functions that return an integer error
    60          * code. If some additional return value is to be returned, the first
    61          * argument holds the output argument.
    62          */
    63         int (* root_get)(fs_node_t **, dev_handle_t);
    64         int (* match)(fs_node_t **, fs_node_t *, const char *);
    65         int (* node_get)(fs_node_t **, dev_handle_t, fs_index_t);
    66         int (* node_put)(fs_node_t *);
    67         int (* create)(fs_node_t **, dev_handle_t, int);
     58        fs_node_t * (* match)(fs_node_t *, const char *);
     59        fs_node_t * (* node_get)(dev_handle_t, fs_index_t);
     60        void (* node_put)(fs_node_t *);
     61        fs_node_t * (* create)(dev_handle_t, int);
    6862        int (* destroy)(fs_node_t *);
    6963        int (* link)(fs_node_t *, fs_node_t *, const char *);
    7064        int (* unlink)(fs_node_t *, fs_node_t *, const char *);
    71         int (* has_children)(bool *, fs_node_t *);
    72         /*
    73          * The second set of methods are usually mere getters that do not return
    74          * an integer error code.
    75          */
    7665        fs_index_t (* index_get)(fs_node_t *);
    7766        size_t (* size_get)(fs_node_t *);
    7867        unsigned (* lnkcnt_get)(fs_node_t *);
     68        bool (* has_children)(fs_node_t *);
     69        fs_node_t *(* root_get)(dev_handle_t);
    7970        char (* plb_get_char)(unsigned pos);
    8071        bool (* is_directory)(fs_node_t *);
  • uspace/srv/fs/fat/fat_ops.c

    r2e37308 rd27ed12  
    250250 * Forward declarations of FAT libfs operations.
    251251 */
    252 static int fat_root_get(fs_node_t **, dev_handle_t);
    253 static int fat_match(fs_node_t **, fs_node_t *, const char *);
    254 static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t);
    255 static int fat_node_put(fs_node_t *);
    256 static int fat_create_node(fs_node_t **, dev_handle_t, int);
     252static fs_node_t *fat_node_get(dev_handle_t, fs_index_t);
     253static void fat_node_put(fs_node_t *);
     254static fs_node_t *fat_create_node(dev_handle_t, int);
    257255static int fat_destroy_node(fs_node_t *);
    258256static int fat_link(fs_node_t *, fs_node_t *, const char *);
    259257static int fat_unlink(fs_node_t *, fs_node_t *, const char *);
    260 static int fat_has_children(bool *, fs_node_t *);
     258static fs_node_t *fat_match(fs_node_t *, const char *);
    261259static fs_index_t fat_index_get(fs_node_t *);
    262260static size_t fat_size_get(fs_node_t *);
    263261static unsigned fat_lnkcnt_get(fs_node_t *);
     262static bool fat_has_children(fs_node_t *);
     263static fs_node_t *fat_root_get(dev_handle_t);
    264264static char fat_plb_get_char(unsigned);
    265265static bool fat_is_directory(fs_node_t *);
     
    270270 */
    271271
    272 int fat_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
    273 {
    274         return fat_node_get(rfn, dev_handle, 0);
    275 }
    276 
    277 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     272/** Instantiate a FAT in-core node. */
     273fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
     274{
     275        fat_node_t *nodep;
     276        fat_idx_t *idxp;
     277
     278        idxp = fat_idx_get_by_index(dev_handle, index);
     279        if (!idxp)
     280                return NULL;
     281        /* idxp->lock held */
     282        nodep = fat_node_get_core(idxp);
     283        fibril_mutex_unlock(&idxp->lock);
     284        return FS_NODE(nodep);
     285}
     286
     287void fat_node_put(fs_node_t *fn)
     288{
     289        fat_node_t *nodep = FAT_NODE(fn);
     290        bool destroy = false;
     291
     292        fibril_mutex_lock(&nodep->lock);
     293        if (!--nodep->refcnt) {
     294                if (nodep->idx) {
     295                        fibril_mutex_lock(&ffn_mutex);
     296                        list_append(&nodep->ffn_link, &ffn_head);
     297                        fibril_mutex_unlock(&ffn_mutex);
     298                } else {
     299                        /*
     300                         * The node does not have any index structure associated
     301                         * with itself. This can only mean that we are releasing
     302                         * the node after a failed attempt to allocate the index
     303                         * structure for it.
     304                         */
     305                        destroy = true;
     306                }
     307        }
     308        fibril_mutex_unlock(&nodep->lock);
     309        if (destroy) {
     310                free(nodep->bp);
     311                free(nodep);
     312        }
     313}
     314
     315fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags)
     316{
     317        fat_idx_t *idxp;
     318        fat_node_t *nodep;
     319        fat_bs_t *bs;
     320        fat_cluster_t mcl, lcl;
     321        uint16_t bps;
     322        int rc;
     323
     324        bs = block_bb_get(dev_handle);
     325        bps = uint16_t_le2host(bs->bps);
     326        if (flags & L_DIRECTORY) {
     327                /* allocate a cluster */
     328                rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
     329                if (rc != EOK)
     330                        return NULL;
     331        }
     332
     333        nodep = fat_node_get_new();
     334        if (!nodep) {
     335                (void) fat_free_clusters(bs, dev_handle, mcl);
     336                return NULL;
     337        }
     338        idxp = fat_idx_get_new(dev_handle);
     339        if (!idxp) {
     340                (void) fat_free_clusters(bs, dev_handle, mcl); 
     341                fat_node_put(FS_NODE(nodep));
     342                return NULL;
     343        }
     344        /* idxp->lock held */
     345        if (flags & L_DIRECTORY) {
     346                /* Populate the new cluster with unused dentries. */
     347                rc = fat_zero_cluster(bs, dev_handle, mcl);
     348                assert(rc == EOK);
     349                nodep->type = FAT_DIRECTORY;
     350                nodep->firstc = mcl;
     351                nodep->size = bps * bs->spc;
     352        } else {
     353                nodep->type = FAT_FILE;
     354                nodep->firstc = FAT_CLST_RES0;
     355                nodep->size = 0;
     356        }
     357        nodep->lnkcnt = 0;      /* not linked anywhere */
     358        nodep->refcnt = 1;
     359        nodep->dirty = true;
     360
     361        nodep->idx = idxp;
     362        idxp->nodep = nodep;
     363
     364        fibril_mutex_unlock(&idxp->lock);
     365        return FS_NODE(nodep);
     366}
     367
     368int fat_destroy_node(fs_node_t *fn)
     369{
     370        fat_node_t *nodep = FAT_NODE(fn);
     371        fat_bs_t *bs;
     372        int rc = EOK;
     373
     374        /*
     375         * The node is not reachable from the file system. This means that the
     376         * link count should be zero and that the index structure cannot be
     377         * found in the position hash. Obviously, we don't need to lock the node
     378         * nor its index structure.
     379         */
     380        assert(nodep->lnkcnt == 0);
     381
     382        /*
     383         * The node may not have any children.
     384         */
     385        assert(fat_has_children(fn) == false);
     386
     387        bs = block_bb_get(nodep->idx->dev_handle);
     388        if (nodep->firstc != FAT_CLST_RES0) {
     389                assert(nodep->size);
     390                /* Free all clusters allocated to the node. */
     391                rc = fat_free_clusters(bs, nodep->idx->dev_handle,
     392                    nodep->firstc);
     393        }
     394
     395        fat_idx_destroy(nodep->idx);
     396        free(nodep->bp);
     397        free(nodep);
     398        return rc;
     399}
     400
     401int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
     402{
     403        fat_node_t *parentp = FAT_NODE(pfn);
     404        fat_node_t *childp = FAT_NODE(cfn);
     405        fat_dentry_t *d;
     406        fat_bs_t *bs;
     407        block_t *b;
     408        unsigned i, j;
     409        uint16_t bps;
     410        unsigned dps;
     411        unsigned blocks;
     412        fat_cluster_t mcl, lcl;
     413        int rc;
     414
     415        fibril_mutex_lock(&childp->lock);
     416        if (childp->lnkcnt == 1) {
     417                /*
     418                 * On FAT, we don't support multiple hard links.
     419                 */
     420                fibril_mutex_unlock(&childp->lock);
     421                return EMLINK;
     422        }
     423        assert(childp->lnkcnt == 0);
     424        fibril_mutex_unlock(&childp->lock);
     425
     426        if (!fat_dentry_name_verify(name)) {
     427                /*
     428                 * Attempt to create unsupported name.
     429                 */
     430                return ENOTSUP;
     431        }
     432
     433        /*
     434         * Get us an unused parent node's dentry or grow the parent and allocate
     435         * a new one.
     436         */
     437       
     438        fibril_mutex_lock(&parentp->idx->lock);
     439        bs = block_bb_get(parentp->idx->dev_handle);
     440        bps = uint16_t_le2host(bs->bps);
     441        dps = bps / sizeof(fat_dentry_t);
     442
     443        blocks = parentp->size / bps;
     444
     445        for (i = 0; i < blocks; i++) {
     446                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     447                if (rc != EOK) {
     448                        fibril_mutex_unlock(&parentp->idx->lock);
     449                        return rc;
     450                }
     451                for (j = 0; j < dps; j++) {
     452                        d = ((fat_dentry_t *)b->data) + j;
     453                        switch (fat_classify_dentry(d)) {
     454                        case FAT_DENTRY_SKIP:
     455                        case FAT_DENTRY_VALID:
     456                                /* skipping used and meta entries */
     457                                continue;
     458                        case FAT_DENTRY_FREE:
     459                        case FAT_DENTRY_LAST:
     460                                /* found an empty slot */
     461                                goto hit;
     462                        }
     463                }
     464                rc = block_put(b);
     465                if (rc != EOK) {
     466                        fibril_mutex_unlock(&parentp->idx->lock);
     467                        return rc;
     468                }
     469        }
     470        j = 0;
     471       
     472        /*
     473         * We need to grow the parent in order to create a new unused dentry.
     474         */
     475        if (parentp->firstc == FAT_CLST_ROOT) {
     476                /* Can't grow the root directory. */
     477                fibril_mutex_unlock(&parentp->idx->lock);
     478                return ENOSPC;
     479        }
     480        rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
     481        if (rc != EOK) {
     482                fibril_mutex_unlock(&parentp->idx->lock);
     483                return rc;
     484        }
     485        rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl);
     486        if (rc != EOK) {
     487                fibril_mutex_unlock(&parentp->idx->lock);
     488                return rc;
     489        }
     490        rc = fat_append_clusters(bs, parentp, mcl);
     491        if (rc != EOK) {
     492                fibril_mutex_unlock(&parentp->idx->lock);
     493                return rc;
     494        }
     495        parentp->size += bps * bs->spc;
     496        parentp->dirty = true;          /* need to sync node */
     497        rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     498        if (rc != EOK) {
     499                fibril_mutex_unlock(&parentp->idx->lock);
     500                return rc;
     501        }
     502        d = (fat_dentry_t *)b->data;
     503
     504hit:
     505        /*
     506         * At this point we only establish the link between the parent and the
     507         * child.  The dentry, except of the name and the extension, will remain
     508         * uninitialized until the corresponding node is synced. Thus the valid
     509         * dentry data is kept in the child node structure.
     510         */
     511        memset(d, 0, sizeof(fat_dentry_t));
     512        fat_dentry_name_set(d, name);
     513        b->dirty = true;                /* need to sync block */
     514        rc = block_put(b);
     515        fibril_mutex_unlock(&parentp->idx->lock);
     516        if (rc != EOK)
     517                return rc;
     518
     519        fibril_mutex_lock(&childp->idx->lock);
     520       
     521        /*
     522         * If possible, create the Sub-directory Identifier Entry and the
     523         * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
     524         * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
     525         * not use them anyway, so this is rather a sign of our good will.
     526         */
     527        rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
     528        if (rc != EOK) {
     529                /*
     530                 * Rather than returning an error, simply skip the creation of
     531                 * these two entries.
     532                 */
     533                goto skip_dots;
     534        }
     535        d = (fat_dentry_t *)b->data;
     536        if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
     537            str_cmp(d->name, FAT_NAME_DOT) == 0) {
     538                memset(d, 0, sizeof(fat_dentry_t));
     539                str_cpy(d->name, 8, FAT_NAME_DOT);
     540                str_cpy(d->ext, 3, FAT_EXT_PAD);
     541                d->attr = FAT_ATTR_SUBDIR;
     542                d->firstc = host2uint16_t_le(childp->firstc);
     543                /* TODO: initialize also the date/time members. */
     544        }
     545        d++;
     546        if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
     547            str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
     548                memset(d, 0, sizeof(fat_dentry_t));
     549                str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
     550                str_cpy(d->ext, 3, FAT_EXT_PAD);
     551                d->attr = FAT_ATTR_SUBDIR;
     552                d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
     553                    host2uint16_t_le(FAT_CLST_RES0) :
     554                    host2uint16_t_le(parentp->firstc);
     555                /* TODO: initialize also the date/time members. */
     556        }
     557        b->dirty = true;                /* need to sync block */
     558        /*
     559         * Ignore the return value as we would have fallen through on error
     560         * anyway.
     561         */
     562        (void) block_put(b);
     563skip_dots:
     564
     565        childp->idx->pfc = parentp->firstc;
     566        childp->idx->pdi = i * dps + j;
     567        fibril_mutex_unlock(&childp->idx->lock);
     568
     569        fibril_mutex_lock(&childp->lock);
     570        childp->lnkcnt = 1;
     571        childp->dirty = true;           /* need to sync node */
     572        fibril_mutex_unlock(&childp->lock);
     573
     574        /*
     575         * Hash in the index structure into the position hash.
     576         */
     577        fat_idx_hashin(childp->idx);
     578
     579        return EOK;
     580}
     581
     582int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
     583{
     584        fat_node_t *parentp = FAT_NODE(pfn);
     585        fat_node_t *childp = FAT_NODE(cfn);
     586        fat_bs_t *bs;
     587        fat_dentry_t *d;
     588        uint16_t bps;
     589        block_t *b;
     590        int rc;
     591
     592        if (!parentp)
     593                return EBUSY;
     594       
     595        if (fat_has_children(cfn))
     596                return ENOTEMPTY;
     597
     598        fibril_mutex_lock(&parentp->lock);
     599        fibril_mutex_lock(&childp->lock);
     600        assert(childp->lnkcnt == 1);
     601        fibril_mutex_lock(&childp->idx->lock);
     602        bs = block_bb_get(childp->idx->dev_handle);
     603        bps = uint16_t_le2host(bs->bps);
     604
     605        rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc,
     606            (childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
     607            BLOCK_FLAGS_NONE);
     608        if (rc != EOK)
     609                goto error;
     610        d = (fat_dentry_t *)b->data +
     611            (childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
     612        /* mark the dentry as not-currently-used */
     613        d->name[0] = FAT_DENTRY_ERASED;
     614        b->dirty = true;                /* need to sync block */
     615        rc = block_put(b);
     616        if (rc != EOK)
     617                goto error;
     618
     619        /* remove the index structure from the position hash */
     620        fat_idx_hashout(childp->idx);
     621        /* clear position information */
     622        childp->idx->pfc = FAT_CLST_RES0;
     623        childp->idx->pdi = 0;
     624        fibril_mutex_unlock(&childp->idx->lock);
     625        childp->lnkcnt = 0;
     626        childp->dirty = true;
     627        fibril_mutex_unlock(&childp->lock);
     628        fibril_mutex_unlock(&parentp->lock);
     629
     630        return EOK;
     631
     632error:
     633        fibril_mutex_unlock(&parentp->idx->lock);
     634        fibril_mutex_unlock(&childp->lock);
     635        fibril_mutex_unlock(&childp->idx->lock);
     636        return rc;
     637}
     638
     639fs_node_t *fat_match(fs_node_t *pfn, const char *component)
    278640{
    279641        fat_bs_t *bs;
     
    295657        for (i = 0; i < blocks; i++) {
    296658                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    297                 if (rc != EOK) {
    298                         fibril_mutex_unlock(&parentp->idx->lock);
    299                         return rc;
    300                 }
     659                assert(rc == EOK);
    301660                for (j = 0; j < dps; j++) {
    302661                        d = ((fat_dentry_t *)b->data) + j;
     
    307666                        case FAT_DENTRY_LAST:
    308667                                rc = block_put(b);
    309                                 /* expect EOK as b was not dirty */
    310                                 assert(rc == EOK);     
     668                                assert(rc == EOK);
    311669                                fibril_mutex_unlock(&parentp->idx->lock);
    312                                 *rfn = NULL;
    313                                 return EOK;
     670                                return NULL;
    314671                        default:
    315672                        case FAT_DENTRY_VALID:
     
    336693                                         */
    337694                                        rc = block_put(b);
    338                                         /* expect EOK as b was not dirty */
    339                                         assert(rc == EOK);     
    340                                         return ENOMEM;
     695                                        assert(rc == EOK);
     696                                        return NULL;
    341697                                }
    342698                                nodep = fat_node_get_core(idx);
    343699                                fibril_mutex_unlock(&idx->lock);
    344700                                rc = block_put(b);
    345                                 /* expect EOK as b was not dirty */
    346701                                assert(rc == EOK);
    347                                 *rfn = FS_NODE(nodep);
    348                                 return EOK;
     702                                return FS_NODE(nodep);
    349703                        }
    350704                }
    351705                rc = block_put(b);
    352                 assert(rc == EOK);      /* expect EOK as b was not dirty */
     706                assert(rc == EOK);
    353707        }
    354708
    355709        fibril_mutex_unlock(&parentp->idx->lock);
    356         *rfn = NULL;
    357         return EOK;
    358 }
    359 
    360 /** Instantiate a FAT in-core node. */
    361 int fat_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
    362 {
    363         fat_node_t *nodep;
    364         fat_idx_t *idxp;
    365 
    366         idxp = fat_idx_get_by_index(dev_handle, index);
    367         if (!idxp) {
    368                 *rfn = NULL;
    369                 return EOK;
    370         }
    371         /* idxp->lock held */
    372         nodep = fat_node_get_core(idxp);
    373         fibril_mutex_unlock(&idxp->lock);
    374         *rfn = FS_NODE(nodep);
    375         return EOK;
    376 }
    377 
    378 int fat_node_put(fs_node_t *fn)
    379 {
    380         fat_node_t *nodep = FAT_NODE(fn);
    381         bool destroy = false;
    382 
    383         fibril_mutex_lock(&nodep->lock);
    384         if (!--nodep->refcnt) {
    385                 if (nodep->idx) {
    386                         fibril_mutex_lock(&ffn_mutex);
    387                         list_append(&nodep->ffn_link, &ffn_head);
    388                         fibril_mutex_unlock(&ffn_mutex);
    389                 } else {
    390                         /*
    391                          * The node does not have any index structure associated
    392                          * with itself. This can only mean that we are releasing
    393                          * the node after a failed attempt to allocate the index
    394                          * structure for it.
    395                          */
    396                         destroy = true;
    397                 }
    398         }
    399         fibril_mutex_unlock(&nodep->lock);
    400         if (destroy) {
    401                 free(nodep->bp);
    402                 free(nodep);
    403         }
    404         return EOK;
    405 }
    406 
    407 int fat_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int flags)
    408 {
    409         fat_idx_t *idxp;
    410         fat_node_t *nodep;
    411         fat_bs_t *bs;
    412         fat_cluster_t mcl, lcl;
    413         uint16_t bps;
    414         int rc;
    415 
    416         bs = block_bb_get(dev_handle);
    417         bps = uint16_t_le2host(bs->bps);
    418         if (flags & L_DIRECTORY) {
    419                 /* allocate a cluster */
    420                 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
    421                 if (rc != EOK)
    422                         return rc;
    423                 /* populate the new cluster with unused dentries */
    424                 rc = fat_zero_cluster(bs, dev_handle, mcl);
    425                 if (rc != EOK) {
    426                         (void) fat_free_clusters(bs, dev_handle, mcl);
    427                         return rc;
    428                 }
    429         }
    430 
    431         nodep = fat_node_get_new();
    432         if (!nodep) {
    433                 (void) fat_free_clusters(bs, dev_handle, mcl);
    434                 return ENOMEM;  /* FIXME: determine the true error code */
    435         }
    436         idxp = fat_idx_get_new(dev_handle);
    437         if (!idxp) {
    438                 (void) fat_free_clusters(bs, dev_handle, mcl); 
    439                 (void) fat_node_put(FS_NODE(nodep));
    440                 return ENOMEM;  /* FIXME: determine the true error code */
    441         }
    442         /* idxp->lock held */
    443         if (flags & L_DIRECTORY) {
    444                 nodep->type = FAT_DIRECTORY;
    445                 nodep->firstc = mcl;
    446                 nodep->size = bps * bs->spc;
    447         } else {
    448                 nodep->type = FAT_FILE;
    449                 nodep->firstc = FAT_CLST_RES0;
    450                 nodep->size = 0;
    451         }
    452         nodep->lnkcnt = 0;      /* not linked anywhere */
    453         nodep->refcnt = 1;
    454         nodep->dirty = true;
    455 
    456         nodep->idx = idxp;
    457         idxp->nodep = nodep;
    458 
    459         fibril_mutex_unlock(&idxp->lock);
    460         *rfn = FS_NODE(nodep);
    461         return EOK;
    462 }
    463 
    464 int fat_destroy_node(fs_node_t *fn)
    465 {
    466         fat_node_t *nodep = FAT_NODE(fn);
    467         fat_bs_t *bs;
    468         bool has_children;
    469         int rc;
    470 
    471         /*
    472          * The node is not reachable from the file system. This means that the
    473          * link count should be zero and that the index structure cannot be
    474          * found in the position hash. Obviously, we don't need to lock the node
    475          * nor its index structure.
    476          */
    477         assert(nodep->lnkcnt == 0);
    478 
    479         /*
    480          * The node may not have any children.
    481          */
    482         rc = fat_has_children(&has_children, fn);
    483         if (rc != EOK)
    484                 return rc;
    485         assert(!has_children);
    486 
    487         bs = block_bb_get(nodep->idx->dev_handle);
    488         if (nodep->firstc != FAT_CLST_RES0) {
    489                 assert(nodep->size);
    490                 /* Free all clusters allocated to the node. */
    491                 rc = fat_free_clusters(bs, nodep->idx->dev_handle,
    492                     nodep->firstc);
    493         }
    494 
    495         fat_idx_destroy(nodep->idx);
    496         free(nodep->bp);
    497         free(nodep);
    498         return rc;
    499 }
    500 
    501 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
    502 {
    503         fat_node_t *parentp = FAT_NODE(pfn);
    504         fat_node_t *childp = FAT_NODE(cfn);
    505         fat_dentry_t *d;
    506         fat_bs_t *bs;
    507         block_t *b;
    508         unsigned i, j;
    509         uint16_t bps;
    510         unsigned dps;
    511         unsigned blocks;
    512         fat_cluster_t mcl, lcl;
    513         int rc;
    514 
    515         fibril_mutex_lock(&childp->lock);
    516         if (childp->lnkcnt == 1) {
    517                 /*
    518                  * On FAT, we don't support multiple hard links.
    519                  */
    520                 fibril_mutex_unlock(&childp->lock);
    521                 return EMLINK;
    522         }
    523         assert(childp->lnkcnt == 0);
    524         fibril_mutex_unlock(&childp->lock);
    525 
    526         if (!fat_dentry_name_verify(name)) {
    527                 /*
    528                  * Attempt to create unsupported name.
    529                  */
    530                 return ENOTSUP;
    531         }
    532 
    533         /*
    534          * Get us an unused parent node's dentry or grow the parent and allocate
    535          * a new one.
    536          */
    537        
    538         fibril_mutex_lock(&parentp->idx->lock);
    539         bs = block_bb_get(parentp->idx->dev_handle);
    540         bps = uint16_t_le2host(bs->bps);
    541         dps = bps / sizeof(fat_dentry_t);
    542 
    543         blocks = parentp->size / bps;
    544 
    545         for (i = 0; i < blocks; i++) {
    546                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    547                 if (rc != EOK) {
    548                         fibril_mutex_unlock(&parentp->idx->lock);
    549                         return rc;
    550                 }
    551                 for (j = 0; j < dps; j++) {
    552                         d = ((fat_dentry_t *)b->data) + j;
    553                         switch (fat_classify_dentry(d)) {
    554                         case FAT_DENTRY_SKIP:
    555                         case FAT_DENTRY_VALID:
    556                                 /* skipping used and meta entries */
    557                                 continue;
    558                         case FAT_DENTRY_FREE:
    559                         case FAT_DENTRY_LAST:
    560                                 /* found an empty slot */
    561                                 goto hit;
    562                         }
    563                 }
    564                 rc = block_put(b);
    565                 if (rc != EOK) {
    566                         fibril_mutex_unlock(&parentp->idx->lock);
    567                         return rc;
    568                 }
    569         }
    570         j = 0;
    571        
    572         /*
    573          * We need to grow the parent in order to create a new unused dentry.
    574          */
    575         if (parentp->firstc == FAT_CLST_ROOT) {
    576                 /* Can't grow the root directory. */
    577                 fibril_mutex_unlock(&parentp->idx->lock);
    578                 return ENOSPC;
    579         }
    580         rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
    581         if (rc != EOK) {
    582                 fibril_mutex_unlock(&parentp->idx->lock);
    583                 return rc;
    584         }
    585         rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl);
    586         if (rc != EOK) {
    587                 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl);
    588                 fibril_mutex_unlock(&parentp->idx->lock);
    589                 return rc;
    590         }
    591         rc = fat_append_clusters(bs, parentp, mcl);
    592         if (rc != EOK) {
    593                 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl);
    594                 fibril_mutex_unlock(&parentp->idx->lock);
    595                 return rc;
    596         }
    597         parentp->size += bps * bs->spc;
    598         parentp->dirty = true;          /* need to sync node */
    599         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    600         if (rc != EOK) {
    601                 fibril_mutex_unlock(&parentp->idx->lock);
    602                 return rc;
    603         }
    604         d = (fat_dentry_t *)b->data;
    605 
    606 hit:
    607         /*
    608          * At this point we only establish the link between the parent and the
    609          * child.  The dentry, except of the name and the extension, will remain
    610          * uninitialized until the corresponding node is synced. Thus the valid
    611          * dentry data is kept in the child node structure.
    612          */
    613         memset(d, 0, sizeof(fat_dentry_t));
    614         fat_dentry_name_set(d, name);
    615         b->dirty = true;                /* need to sync block */
    616         rc = block_put(b);
    617         fibril_mutex_unlock(&parentp->idx->lock);
    618         if (rc != EOK)
    619                 return rc;
    620 
    621         fibril_mutex_lock(&childp->idx->lock);
    622        
    623         /*
    624          * If possible, create the Sub-directory Identifier Entry and the
    625          * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
    626          * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
    627          * not use them anyway, so this is rather a sign of our good will.
    628          */
    629         rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
    630         if (rc != EOK) {
    631                 /*
    632                  * Rather than returning an error, simply skip the creation of
    633                  * these two entries.
    634                  */
    635                 goto skip_dots;
    636         }
    637         d = (fat_dentry_t *)b->data;
    638         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    639             str_cmp(d->name, FAT_NAME_DOT) == 0) {
    640                 memset(d, 0, sizeof(fat_dentry_t));
    641                 str_cpy(d->name, 8, FAT_NAME_DOT);
    642                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    643                 d->attr = FAT_ATTR_SUBDIR;
    644                 d->firstc = host2uint16_t_le(childp->firstc);
    645                 /* TODO: initialize also the date/time members. */
    646         }
    647         d++;
    648         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    649             str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
    650                 memset(d, 0, sizeof(fat_dentry_t));
    651                 str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
    652                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    653                 d->attr = FAT_ATTR_SUBDIR;
    654                 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    655                     host2uint16_t_le(FAT_CLST_RES0) :
    656                     host2uint16_t_le(parentp->firstc);
    657                 /* TODO: initialize also the date/time members. */
    658         }
    659         b->dirty = true;                /* need to sync block */
    660         /*
    661          * Ignore the return value as we would have fallen through on error
    662          * anyway.
    663          */
    664         (void) block_put(b);
    665 skip_dots:
    666 
    667         childp->idx->pfc = parentp->firstc;
    668         childp->idx->pdi = i * dps + j;
    669         fibril_mutex_unlock(&childp->idx->lock);
    670 
    671         fibril_mutex_lock(&childp->lock);
    672         childp->lnkcnt = 1;
    673         childp->dirty = true;           /* need to sync node */
    674         fibril_mutex_unlock(&childp->lock);
    675 
    676         /*
    677          * Hash in the index structure into the position hash.
    678          */
    679         fat_idx_hashin(childp->idx);
    680 
    681         return EOK;
    682 }
    683 
    684 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
    685 {
    686         fat_node_t *parentp = FAT_NODE(pfn);
    687         fat_node_t *childp = FAT_NODE(cfn);
    688         fat_bs_t *bs;
    689         fat_dentry_t *d;
    690         uint16_t bps;
    691         block_t *b;
    692         bool has_children;
    693         int rc;
    694 
    695         if (!parentp)
    696                 return EBUSY;
    697        
    698         rc = fat_has_children(&has_children, cfn);
    699         if (rc != EOK)
    700                 return rc;
    701         if (has_children)
    702                 return ENOTEMPTY;
    703 
    704         fibril_mutex_lock(&parentp->lock);
    705         fibril_mutex_lock(&childp->lock);
    706         assert(childp->lnkcnt == 1);
    707         fibril_mutex_lock(&childp->idx->lock);
    708         bs = block_bb_get(childp->idx->dev_handle);
    709         bps = uint16_t_le2host(bs->bps);
    710 
    711         rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc,
    712             (childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
    713             BLOCK_FLAGS_NONE);
    714         if (rc != EOK)
    715                 goto error;
    716         d = (fat_dentry_t *)b->data +
    717             (childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
    718         /* mark the dentry as not-currently-used */
    719         d->name[0] = FAT_DENTRY_ERASED;
    720         b->dirty = true;                /* need to sync block */
    721         rc = block_put(b);
    722         if (rc != EOK)
    723                 goto error;
    724 
    725         /* remove the index structure from the position hash */
    726         fat_idx_hashout(childp->idx);
    727         /* clear position information */
    728         childp->idx->pfc = FAT_CLST_RES0;
    729         childp->idx->pdi = 0;
    730         fibril_mutex_unlock(&childp->idx->lock);
    731         childp->lnkcnt = 0;
    732         childp->dirty = true;
    733         fibril_mutex_unlock(&childp->lock);
    734         fibril_mutex_unlock(&parentp->lock);
    735 
    736         return EOK;
    737 
    738 error:
    739         fibril_mutex_unlock(&parentp->idx->lock);
    740         fibril_mutex_unlock(&childp->lock);
    741         fibril_mutex_unlock(&childp->idx->lock);
    742         return rc;
    743 }
    744 
    745 int fat_has_children(bool *has_children, fs_node_t *fn)
     710        return NULL;
     711}
     712
     713fs_index_t fat_index_get(fs_node_t *fn)
     714{
     715        return FAT_NODE(fn)->idx->index;
     716}
     717
     718size_t fat_size_get(fs_node_t *fn)
     719{
     720        return FAT_NODE(fn)->size;
     721}
     722
     723unsigned fat_lnkcnt_get(fs_node_t *fn)
     724{
     725        return FAT_NODE(fn)->lnkcnt;
     726}
     727
     728bool fat_has_children(fs_node_t *fn)
    746729{
    747730        fat_bs_t *bs;
     
    754737        int rc;
    755738
    756         if (nodep->type != FAT_DIRECTORY) {
    757                 *has_children = false;
    758                 return EOK;
    759         }
     739        if (nodep->type != FAT_DIRECTORY)
     740                return false;
    760741       
    761742        fibril_mutex_lock(&nodep->idx->lock);
     
    770751       
    771752                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    772                 if (rc != EOK) {
    773                         fibril_mutex_unlock(&nodep->idx->lock);
    774                         return rc;
    775                 }
     753                assert(rc == EOK);
    776754                for (j = 0; j < dps; j++) {
    777755                        d = ((fat_dentry_t *)b->data) + j;
     
    782760                        case FAT_DENTRY_LAST:
    783761                                rc = block_put(b);
    784                                 /* expect EOK as b was not dirty */
    785762                                assert(rc == EOK);
    786763                                fibril_mutex_unlock(&nodep->idx->lock);
    787                                 *has_children = false;
    788                                 return EOK;
     764                                return false;
    789765                        default:
    790766                        case FAT_DENTRY_VALID:
    791767                                rc = block_put(b);
    792                                 /* expect EOK as b was not dirty */
    793768                                assert(rc == EOK);
    794769                                fibril_mutex_unlock(&nodep->idx->lock);
    795                                 *has_children = true;
    796                                 return EOK;
     770                                return true;
    797771                        }
     772                        rc = block_put(b);
     773                        assert(rc == EOK);
     774                        fibril_mutex_unlock(&nodep->idx->lock);
     775                        return true;
    798776                }
    799777                rc = block_put(b);
    800                 assert(rc == EOK);      /* expect EOK as b was not dirty */
     778                assert(rc == EOK);
    801779        }
    802780
    803781        fibril_mutex_unlock(&nodep->idx->lock);
    804         *has_children = false;
    805         return EOK;
    806 }
    807 
    808 
    809 fs_index_t fat_index_get(fs_node_t *fn)
    810 {
    811         return FAT_NODE(fn)->idx->index;
    812 }
    813 
    814 size_t fat_size_get(fs_node_t *fn)
    815 {
    816         return FAT_NODE(fn)->size;
    817 }
    818 
    819 unsigned fat_lnkcnt_get(fs_node_t *fn)
    820 {
    821         return FAT_NODE(fn)->lnkcnt;
     782        return false;
     783}
     784
     785fs_node_t *fat_root_get(dev_handle_t dev_handle)
     786{
     787        return fat_node_get(dev_handle, 0);
    822788}
    823789
     
    839805/** libfs operations */
    840806libfs_ops_t fat_libfs_ops = {
    841         .root_get = fat_root_get,
    842807        .match = fat_match,
    843808        .node_get = fat_node_get,
     
    847812        .link = fat_link,
    848813        .unlink = fat_unlink,
    849         .has_children = fat_has_children,
    850814        .index_get = fat_index_get,
    851815        .size_get = fat_size_get,
    852816        .lnkcnt_get = fat_lnkcnt_get,
     817        .has_children = fat_has_children,
     818        .root_get = fat_root_get,
    853819        .plb_get_char = fat_plb_get_char,
    854820        .is_directory = fat_is_directory,
     
    1001967        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1002968        off_t pos = (off_t)IPC_GET_ARG3(*request);
    1003         fs_node_t *fn;
     969        fs_node_t *fn = fat_node_get(dev_handle, index);
    1004970        fat_node_t *nodep;
    1005971        fat_bs_t *bs;
     
    1009975        int rc;
    1010976
    1011         rc = fat_node_get(&fn, dev_handle, index);
    1012         if (rc != EOK) {
    1013                 ipc_answer_0(rid, rc);
    1014                 return;
    1015         }
    1016977        if (!fn) {
    1017978                ipc_answer_0(rid, ENOENT);
     
    10911052                                case FAT_DENTRY_VALID:
    10921053                                        fat_dentry_name_get(d, name);
    1093                                         rc = block_put(b);
     1054                                        rc == block_put(b);
    10941055                                        assert(rc == EOK);
    10951056                                        goto hit;
     
    11191080        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    11201081        off_t pos = (off_t)IPC_GET_ARG3(*request);
    1121         fs_node_t *fn;
     1082        fs_node_t *fn = fat_node_get(dev_handle, index);
    11221083        fat_node_t *nodep;
    11231084        fat_bs_t *bs;
     
    11311092        int rc;
    11321093       
    1133         rc = fat_node_get(&fn, dev_handle, index);
    1134         if (rc != EOK) {
    1135                 ipc_answer_0(rid, rc);
    1136                 return;
    1137         }
    11381094        if (!fn) {
    11391095                ipc_answer_0(rid, ENOENT);
     
    12401196        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    12411197        size_t size = (off_t)IPC_GET_ARG3(*request);
    1242         fs_node_t *fn;
     1198        fs_node_t *fn = fat_node_get(dev_handle, index);
    12431199        fat_node_t *nodep;
    12441200        fat_bs_t *bs;
     
    12481204        int rc;
    12491205
    1250         rc = fat_node_get(&fn, dev_handle, index);
    1251         if (rc != EOK) {
    1252                 ipc_answer_0(rid, rc);
    1253                 return;
    1254         }
    12551206        if (!fn) {
    12561207                ipc_answer_0(rid, ENOENT);
     
    13161267        dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    13171268        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1318         fs_node_t *fn;
    13191269        int rc;
    13201270
    1321         rc = fat_node_get(&fn, dev_handle, index);
    1322         if (rc != EOK) {
    1323                 ipc_answer_0(rid, rc);
    1324                 return;
    1325         }
     1271        fs_node_t *fn = fat_node_get(dev_handle, index);
    13261272        if (!fn) {
    13271273                ipc_answer_0(rid, ENOENT);
  • uspace/srv/fs/tmpfs/tmpfs_dump.c

    r2e37308 rd27ed12  
    8282                                return false;
    8383                       
    84                         rc = ops->create(&fn, dev, L_FILE);
    85                         if (rc != EOK || fn == NULL) {
     84                        fn = ops->create(dev, L_FILE);
     85                        if (fn == NULL) {
    8686                                free(fname);
    8787                                return false;
     
    9090                        if (block_seqread(dev, bufpos, buflen, pos, fname,
    9191                            entry.len) != EOK) {
    92                                 (void) ops->destroy(fn);
     92                                ops->destroy(fn);
    9393                                free(fname);
    9494                                return false;
     
    9898                        rc = ops->link(pfn, fn, fname);
    9999                        if (rc != EOK) {
    100                                 (void) ops->destroy(fn);
     100                                ops->destroy(fn);
    101101                                free(fname);
    102102                                return false;
     
    126126                                return false;
    127127                       
    128                         rc = ops->create(&fn, dev, L_DIRECTORY);
    129                         if (rc != EOK || fn == NULL) {
     128                        fn = ops->create(dev, L_DIRECTORY);
     129                        if (fn == NULL) {
    130130                                free(fname);
    131131                                return false;
     
    134134                        if (block_seqread(dev, bufpos, buflen, pos, fname,
    135135                            entry.len) != EOK) {
    136                                 (void) ops->destroy(fn);
     136                                ops->destroy(fn);
    137137                                free(fname);
    138138                                return false;
     
    142142                        rc = ops->link(pfn, fn, fname);
    143143                        if (rc != EOK) {
    144                                 (void) ops->destroy(fn);
     144                                ops->destroy(fn);
    145145                                free(fname);
    146146                                return false;
     
    164164{
    165165        libfs_ops_t *ops = &tmpfs_libfs_ops;
    166         fs_node_t *fn;
    167166        int rc;
    168167
     
    183182                goto error;
    184183       
    185         rc = ops->root_get(&fn, dev);
    186         if (rc != EOK)
    187                 goto error;
    188 
    189         if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, fn))
     184        if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos,
     185            ops->root_get(dev)))
    190186                goto error;
    191187               
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    r2e37308 rd27ed12  
    6767
    6868/* Forward declarations of static functions. */
    69 static int tmpfs_match(fs_node_t **, fs_node_t *, const char *);
    70 static int tmpfs_node_get(fs_node_t **, dev_handle_t, fs_index_t);
    71 static int tmpfs_node_put(fs_node_t *);
    72 static int tmpfs_create_node(fs_node_t **, dev_handle_t, int);
    73 static int tmpfs_destroy_node(fs_node_t *);
     69static fs_node_t *tmpfs_match(fs_node_t *, const char *);
     70static fs_node_t *tmpfs_node_get(dev_handle_t, fs_index_t);
     71static void tmpfs_node_put(fs_node_t *);
     72static fs_node_t *tmpfs_create_node(dev_handle_t, int);
    7473static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *);
    7574static int tmpfs_unlink_node(fs_node_t *, fs_node_t *, const char *);
     75static int tmpfs_destroy_node(fs_node_t *);
    7676
    7777/* Implementation of helper functions. */
    78 static int tmpfs_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
    79 {
    80         return tmpfs_node_get(rfn, dev_handle, TMPFS_SOME_ROOT);
    81 }
    82 
    83 static int tmpfs_has_children(bool *has_children, fs_node_t *fn)
    84 {
    85         *has_children = !list_empty(&TMPFS_NODE(fn)->cs_head);
    86         return EOK;
    87 }
    88 
    8978static fs_index_t tmpfs_index_get(fs_node_t *fn)
    9079{
     
    10089{
    10190        return TMPFS_NODE(fn)->lnkcnt;
     91}
     92
     93static bool tmpfs_has_children(fs_node_t *fn)
     94{
     95        return !list_empty(&TMPFS_NODE(fn)->cs_head);
     96}
     97
     98static fs_node_t *tmpfs_root_get(dev_handle_t dev_handle)
     99{
     100        return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT);
    102101}
    103102
     
    119118/** libfs operations */
    120119libfs_ops_t tmpfs_libfs_ops = {
    121         .root_get = tmpfs_root_get,
    122120        .match = tmpfs_match,
    123121        .node_get = tmpfs_node_get,
     
    127125        .link = tmpfs_link_node,
    128126        .unlink = tmpfs_unlink_node,
    129         .has_children = tmpfs_has_children,
    130127        .index_get = tmpfs_index_get,
    131128        .size_get = tmpfs_size_get,
    132129        .lnkcnt_get = tmpfs_lnkcnt_get,
     130        .has_children = tmpfs_has_children,
     131        .root_get = tmpfs_root_get,
    133132        .plb_get_char = tmpfs_plb_get_char,
    134133        .is_directory = tmpfs_is_directory,
     
    198197{
    199198        fs_node_t *rfn;
    200         int rc;
    201199       
    202         rc = tmpfs_create_node(&rfn, dev_handle, L_DIRECTORY);
    203         if (rc != EOK || !rfn)
     200        rfn = tmpfs_create_node(dev_handle, L_DIRECTORY);
     201        if (!rfn)
    204202                return false;
    205203        TMPFS_NODE(rfn)->lnkcnt = 0;    /* FS root is not linked */
     
    207205}
    208206
    209 int tmpfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     207fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component)
    210208{
    211209        tmpfs_node_t *parentp = TMPFS_NODE(pfn);
     
    214212        for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
    215213            lnk = lnk->next) {
    216                 tmpfs_dentry_t *dentryp;
    217                 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
    218                 if (!str_cmp(dentryp->name, component)) {
    219                         *rfn = FS_NODE(dentryp->node);
    220                         return EOK;
    221                 }
    222         }
    223 
    224         *rfn = NULL;
    225         return EOK;
    226 }
    227 
    228 int tmpfs_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
     214                tmpfs_dentry_t *dentryp = list_get_instance(lnk, tmpfs_dentry_t,
     215                    link);
     216                if (!str_cmp(dentryp->name, component))
     217                        return FS_NODE(dentryp->node);
     218        }
     219
     220        return NULL;
     221}
     222
     223fs_node_t *tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index)
    229224{
    230225        unsigned long key[] = {
     
    233228        };
    234229        link_t *lnk = hash_table_find(&nodes, key);
    235         if (lnk) {
    236                 tmpfs_node_t *nodep;
    237                 nodep = hash_table_get_instance(lnk, tmpfs_node_t, nh_link);
    238                 *rfn = FS_NODE(nodep);
    239         } else {
    240                 *rfn = NULL;
    241         }
    242         return EOK;     
    243 }
    244 
    245 int tmpfs_node_put(fs_node_t *fn)
     230        if (!lnk)
     231                return NULL;
     232        return FS_NODE(hash_table_get_instance(lnk, tmpfs_node_t, nh_link));
     233}
     234
     235void tmpfs_node_put(fs_node_t *fn)
    246236{
    247237        /* nothing to do */
    248         return EOK;
    249 }
    250 
    251 int tmpfs_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int lflag)
    252 {
    253         fs_node_t *rootfn;
    254         int rc;
    255 
     238}
     239
     240fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag)
     241{
    256242        assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
    257243
    258244        tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t));
    259245        if (!nodep)
    260                 return ENOMEM;
     246                return NULL;
    261247        tmpfs_node_initialize(nodep);
    262248        nodep->bp = malloc(sizeof(fs_node_t));
    263249        if (!nodep->bp) {
    264250                free(nodep);
    265                 return ENOMEM;
     251                return NULL;
    266252        }
    267253        fs_node_initialize(nodep->bp);
    268254        nodep->bp->data = nodep;        /* link the FS and TMPFS nodes */
    269 
    270         rc = tmpfs_root_get(&rootfn, dev_handle);
    271         assert(rc == EOK);
    272         if (!rootfn)
     255        if (!tmpfs_root_get(dev_handle))
    273256                nodep->index = TMPFS_SOME_ROOT;
    274257        else
     
    286269        };
    287270        hash_table_insert(&nodes, key, &nodep->nh_link);
    288         *rfn = FS_NODE(nodep);
    289         return EOK;
    290 }
    291 
    292 int tmpfs_destroy_node(fs_node_t *fn)
    293 {
    294         tmpfs_node_t *nodep = TMPFS_NODE(fn);
    295        
    296         assert(!nodep->lnkcnt);
    297         assert(list_empty(&nodep->cs_head));
    298 
    299         unsigned long key[] = {
    300                 [NODES_KEY_INDEX] = nodep->index,
    301                 [NODES_KEY_DEV] = nodep->dev_handle
    302         };
    303         hash_table_remove(&nodes, key, 2);
    304 
    305         if (nodep->type == TMPFS_FILE)
    306                 free(nodep->data);
    307         free(nodep->bp);
    308         free(nodep);
    309         return EOK;
     271        return FS_NODE(nodep);
    310272}
    311273
     
    381343}
    382344
     345int tmpfs_destroy_node(fs_node_t *fn)
     346{
     347        tmpfs_node_t *nodep = TMPFS_NODE(fn);
     348       
     349        assert(!nodep->lnkcnt);
     350        assert(list_empty(&nodep->cs_head));
     351
     352        unsigned long key[] = {
     353                [NODES_KEY_INDEX] = nodep->index,
     354                [NODES_KEY_DEV] = nodep->dev_handle
     355        };
     356        hash_table_remove(&nodes, key, 2);
     357
     358        if (nodep->type == TMPFS_FILE)
     359                free(nodep->data);
     360        free(nodep->bp);
     361        free(nodep);
     362        return EOK;
     363}
     364
    383365void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
    384366{
    385367        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
    386         int rc;
    387368
    388369        /* accept the mount options */
     
    414395        }
    415396
    416         fs_node_t *rootfn;
    417         rc = tmpfs_root_get(&rootfn, dev_handle);
    418         assert(rc == EOK);
    419         tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
     397        tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle));
    420398        if (str_cmp(opts, "restore") == 0) {
    421399                if (tmpfs_restore(dev_handle))
Note: See TracChangeset for help on using the changeset viewer.