Changeset 38542dc in mainline for uspace/lib/ext4/libext4_directory.c


Ignore:
Timestamp:
2012-08-12T18:36:10Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
49505fe
Parents:
b08e7970
Message:

ext4 code review and coding style cleanup

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ext4/libext4_directory.c

    rb08e7970 r38542dc  
    2929/** @addtogroup libext4
    3030 * @{
    31  */
    32 
     31 */
    3332/**
    34  * @file        libext4_directory.c
    35  * @brief       Ext4 directory structure operations.
     33 * @file  libext4_directory.c
     34 * @brief Ext4 directory structure operations.
    3635 */
    3736
     
    3938#include <errno.h>
    4039#include <malloc.h>
    41 #include <string.h>
    4240#include "libext4.h"
    4341
    44 
    4542/** Get i-node number from directory entry.
    4643 *
    47  * @param de    directory entry
    48  * @return              i-node number
     44 * @param de Directory entry
     45 *
     46 * @return I-node number
     47 *
    4948 */
    5049uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *de)
     
    5554/** Set i-node number to directory entry.
    5655 *
    57  * @param de    directory entry
    58  * @param inode i-node number
     56 * @param de    Directory entry
     57 * @param inode I-node number
     58 *
    5959 */
    6060void ext4_directory_entry_ll_set_inode(ext4_directory_entry_ll_t *de,
    61                 uint32_t inode)
     61    uint32_t inode)
    6262{
    6363        de->inode = host2uint32_t_le(inode);
     
    6666/** Get directory entry length.
    6767 *
    68  * @param de    directory entry
    69  * @return              entry length
    70  */
    71 uint16_t ext4_directory_entry_ll_get_entry_length(
    72                 ext4_directory_entry_ll_t *de)
     68 * @param de Directory entry
     69 *
     70 * @return Entry length
     71 *
     72 */
     73uint16_t ext4_directory_entry_ll_get_entry_length(ext4_directory_entry_ll_t *de)
    7374{
    7475        return uint16_t_le2host(de->entry_length);
     
    7778/** Set directory entry length.
    7879 *
    79  * @param de            directory entry
    80  * @param length        entry length
    81  */
    82 
     80 * @param de     Directory entry
     81 * @param length Entry length
     82 *
     83 */
    8384void ext4_directory_entry_ll_set_entry_length(ext4_directory_entry_ll_t *de,
    84                 uint16_t length)
     85    uint16_t length)
    8586{
    8687        de->entry_length = host2uint16_t_le(length);
     
    8990/** Get directory entry name length.
    9091 *
    91  * @param sb    superblock
    92  * @param de    directory entry
    93  * @return              entry name length
    94  */
    95 uint16_t ext4_directory_entry_ll_get_name_length(
    96     ext4_superblock_t *sb, ext4_directory_entry_ll_t *de)
    97 {
    98         if (ext4_superblock_get_rev_level(sb) == 0 &&
    99             ext4_superblock_get_minor_rev_level(sb) < 5) {
    100 
     92 * @param sb Superblock
     93 * @param de Directory entry
     94 *
     95 * @return Entry name length
     96 *
     97 */
     98uint16_t ext4_directory_entry_ll_get_name_length(ext4_superblock_t *sb,
     99    ext4_directory_entry_ll_t *de)
     100{
     101        if ((ext4_superblock_get_rev_level(sb) == 0) &&
     102            (ext4_superblock_get_minor_rev_level(sb) < 5))
    101103                return ((uint16_t)de->name_length_high) << 8 |
    102                             ((uint16_t)de->name_length);
    103 
    104         }
     104                    ((uint16_t)de->name_length);
     105       
    105106        return de->name_length;
    106107
     
    109110/** Set directory entry name length.
    110111 *
    111  * @param sb            superblock
    112  * @param de            directory entry
    113  * @param length        entry name length
     112 * @param sb     Superblock
     113 * @param de     Directory entry
     114 * @param length Entry name length
     115 *
    114116 */
    115117void ext4_directory_entry_ll_set_name_length(ext4_superblock_t *sb,
    116                 ext4_directory_entry_ll_t *de, uint16_t length)
     118    ext4_directory_entry_ll_t *de, uint16_t length)
    117119{
    118120        de->name_length = (length << 8) >> 8;
    119 
    120         if (ext4_superblock_get_rev_level(sb) == 0 &&
    121                     ext4_superblock_get_minor_rev_level(sb) < 5) {
    122 
     121       
     122        if ((ext4_superblock_get_rev_level(sb) == 0) &&
     123            (ext4_superblock_get_minor_rev_level(sb) < 5))
    123124                de->name_length_high = length >> 8;
    124         }
     125       
     126        /* Else do nothing */
    125127}
    126128
    127129/** Get i-node type of directory entry.
    128130 *
    129  * @param sb    superblock
    130  * @param de    directory entry
    131  * @return              i-node type (file, dir, etc.)
    132  */
    133 uint8_t ext4_directory_entry_ll_get_inode_type(
    134                 ext4_superblock_t *sb, ext4_directory_entry_ll_t *de)
    135 {
    136         if (ext4_superblock_get_rev_level(sb) > 0 ||
    137                     ext4_superblock_get_minor_rev_level(sb) >= 5) {
    138 
    139                         return de->inode_type;
    140         }
    141 
     131 * @param sb Superblock
     132 * @param de Directory entry
     133 *
     134 * @return I-node type (file, dir, etc.)
     135 *
     136 */
     137uint8_t ext4_directory_entry_ll_get_inode_type(ext4_superblock_t *sb,
     138    ext4_directory_entry_ll_t *de)
     139{
     140        if ((ext4_superblock_get_rev_level(sb) > 0) ||
     141            (ext4_superblock_get_minor_rev_level(sb) >= 5))
     142                return de->inode_type;
     143       
    142144        return EXT4_DIRECTORY_FILETYPE_UNKNOWN;
    143 
    144145}
    145146
    146147/** Set i-node type of directory entry.
    147148 *
    148  * @param sb    superblock
    149  * @param de    directory entry
    150  * @param type  i-node type (file, dir, etc.)
    151  */
    152 void ext4_directory_entry_ll_set_inode_type(
    153                 ext4_superblock_t *sb, ext4_directory_entry_ll_t *de, uint8_t type)
    154 {
    155         if (ext4_superblock_get_rev_level(sb) > 0 ||
    156                         ext4_superblock_get_minor_rev_level(sb) >= 5) {
    157 
     149 * @param sb   Superblock
     150 * @param de   Directory entry
     151 * @param type I-node type (file, dir, etc.)
     152 *
     153 */
     154void ext4_directory_entry_ll_set_inode_type(ext4_superblock_t *sb,
     155    ext4_directory_entry_ll_t *de, uint8_t type)
     156{
     157        if ((ext4_superblock_get_rev_level(sb) > 0) ||
     158            (ext4_superblock_get_minor_rev_level(sb) >= 5))
    158159                de->inode_type = type;
    159         }
    160 
    161         /* else do nothing */
    162 
    163 }
    164 
    165 static int ext4_directory_iterator_seek(
    166                 ext4_directory_iterator_t *, aoff64_t);
    167 static int ext4_directory_iterator_set(
    168                 ext4_directory_iterator_t *, uint32_t);
    169 
     160       
     161        /* Else do nothing */
     162}
     163
     164static int ext4_directory_iterator_seek(ext4_directory_iterator_t *, aoff64_t);
     165static int ext4_directory_iterator_set(ext4_directory_iterator_t *, uint32_t);
    170166
    171167/** Initialize directory iterator.
     
    173169 * Set position to the first valid entry from the required position.
    174170 *
    175  * @param it                    pointer to iterator to be initialized
    176  * @param inode_ref             directory i-node
    177  * @param pos                   position to start reading entries from
    178  * @return                              error code
     171 * @param it        Pointer to iterator to be initialized
     172 * @param inode_ref Directory i-node
     173 * @param pos       Position to start reading entries from
     174 *
     175 * @return Error code
     176 *
    179177 */
    180178int ext4_directory_iterator_init(ext4_directory_iterator_t *it,
    181                 ext4_inode_ref_t *inode_ref, aoff64_t pos)
     179    ext4_inode_ref_t *inode_ref, aoff64_t pos)
    182180{
    183181        it->inode_ref = inode_ref;
     
    185183        it->current_offset = 0;
    186184        it->current_block = NULL;
    187 
     185       
    188186        return ext4_directory_iterator_seek(it, pos);
    189187}
     
    191189/** Jump to the next valid entry
    192190 *
    193  * @param it    initialized iterator
    194  * @return              error code
     191 * @param it Initialized iterator
     192 *
     193 * @return Error code
     194 *
    195195 */
    196196int ext4_directory_iterator_next(ext4_directory_iterator_t *it)
    197197{
    198         uint16_t skip;
    199 
    200198        assert(it->current != NULL);
    201 
    202         skip = ext4_directory_entry_ll_get_entry_length(it->current);
    203 
     199       
     200        uint16_t skip = ext4_directory_entry_ll_get_entry_length(it->current);
     201       
    204202        return ext4_directory_iterator_seek(it, it->current_offset + skip);
    205203}
     
    209207 * Here can be jumped to the next data block.
    210208 *
    211  * @param it    initialized iterator
    212  * @param pos   position of the next entry
    213  * @return              error code
     209 * @param it  Initialized iterator
     210 * @param pos Position of the next entry
     211 *
     212 * @return Error code
     213 *
    214214 */
    215215int ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos)
    216216{
    217         int rc;
    218 
    219         uint64_t size = ext4_inode_get_size(
    220                         it->inode_ref->fs->superblock, it->inode_ref->inode);
    221 
     217        uint64_t size = ext4_inode_get_size(it->inode_ref->fs->superblock,
     218            it->inode_ref->inode);
     219       
    222220        /* The iterator is not valid until we seek to the desired position */
    223221        it->current = NULL;
    224 
     222       
    225223        /* Are we at the end? */
    226224        if (pos >= size) {
    227225                if (it->current_block) {
    228                         rc = block_put(it->current_block);
     226                        int rc = block_put(it->current_block);
    229227                        it->current_block = NULL;
    230                         if (rc != EOK) {
     228                       
     229                        if (rc != EOK)
    231230                                return rc;
    232                         }
    233                 }
    234 
     231                }
     232               
    235233                it->current_offset = pos;
    236234                return EOK;
    237235        }
    238 
     236       
    239237        /* Compute next block address */
    240         uint32_t block_size = ext4_superblock_get_block_size(
    241                         it->inode_ref->fs->superblock);
     238        uint32_t block_size =
     239            ext4_superblock_get_block_size(it->inode_ref->fs->superblock);
    242240        aoff64_t current_block_idx = it->current_offset / block_size;
    243241        aoff64_t next_block_idx = pos / block_size;
    244 
    245         /* If we don't have a block or are moving accross block boundary,
     242       
     243        /*
     244         * If we don't have a block or are moving accross block boundary,
    246245         * we need to get another block
    247246         */
    248         if (it->current_block == NULL || current_block_idx != next_block_idx) {
     247        if ((it->current_block == NULL) ||
     248            (current_block_idx != next_block_idx)) {
    249249                if (it->current_block) {
    250                         rc = block_put(it->current_block);
     250                        int rc = block_put(it->current_block);
    251251                        it->current_block = NULL;
    252                         if (rc != EOK) {
     252                       
     253                        if (rc != EOK)
    253254                                return rc;
    254                         }
    255                 }
    256 
     255                }
     256               
    257257                uint32_t next_block_phys_idx;
    258                 rc = ext4_filesystem_get_inode_data_block_index(it->inode_ref,
    259                                 next_block_idx, &next_block_phys_idx);
    260                 if (rc != EOK) {
     258                int rc = ext4_filesystem_get_inode_data_block_index(it->inode_ref,
     259                    next_block_idx, &next_block_phys_idx);
     260                if (rc != EOK)
    261261                        return rc;
    262                 }
    263 
     262               
    264263                rc = block_get(&it->current_block, it->inode_ref->fs->device,
    265                                 next_block_phys_idx, BLOCK_FLAGS_NONE);
     264                    next_block_phys_idx, BLOCK_FLAGS_NONE);
    266265                if (rc != EOK) {
    267266                        it->current_block = NULL;
     
    269268                }
    270269        }
    271 
     270       
    272271        it->current_offset = pos;
    273 
     272       
    274273        return ext4_directory_iterator_set(it, block_size);
    275274}
     
    277276/** Do some checks before returning iterator.
    278277 *
    279  * @param it                    iterator to be checked
    280  * @param block_size    size of data block
    281  * @return                              error code
     278 * @param it         Iterator to be checked
     279 * @param block_size Size of data block
     280 *
     281 * @return Error code
     282 *
    282283 */
    283284static int ext4_directory_iterator_set(ext4_directory_iterator_t *it,
    284285    uint32_t block_size)
    285286{
    286 
    287287        it->current = NULL;
    288 
     288       
    289289        uint32_t offset_in_block = it->current_offset % block_size;
    290 
     290       
    291291        /* Ensure proper alignment */
    292         if ((offset_in_block % 4) != 0) {
     292        if ((offset_in_block % 4) != 0)
    293293                return EIO;
    294         }
    295 
     294       
    296295        /* Ensure that the core of the entry does not overflow the block */
    297         if (offset_in_block > block_size - 8) {
     296        if (offset_in_block > block_size - 8)
    298297                return EIO;
    299         }
    300 
    301         ext4_directory_entry_ll_t *entry = it->current_block->data + offset_in_block;
    302 
     298       
     299        ext4_directory_entry_ll_t *entry =
     300            it->current_block->data + offset_in_block;
     301       
    303302        /* Ensure that the whole entry does not overflow the block */
    304303        uint16_t length = ext4_directory_entry_ll_get_entry_length(entry);
    305         if (offset_in_block + length > block_size) {
     304        if (offset_in_block + length > block_size)
    306305                return EIO;
    307         }
    308 
     306       
    309307        /* Ensure the name length is not too large */
    310         if (ext4_directory_entry_ll_get_name_length(it->inode_ref->fs->superblock,
    311             entry) > length-8) {
     308        if (ext4_directory_entry_ll_get_name_length(
     309            it->inode_ref->fs->superblock, entry) > length-8)
    312310                return EIO;
    313         }
    314 
     311       
    315312        /* Everything OK - "publish" the entry */
    316313        it->current = entry;
     
    318315}
    319316
    320 
    321317/** Uninitialize directory iterator.
    322318 *
    323319 * Release all allocated structures.
    324320 *
    325  * @param it    iterator to be finished
    326  * @return              error code
     321 * @param it Iterator to be finished
     322 *
     323 * @return Error code
     324 *
    327325 */
    328326int ext4_directory_iterator_fini(ext4_directory_iterator_t *it)
    329327{
    330         int rc;
    331 
    332328        it->inode_ref = NULL;
    333329        it->current = NULL;
    334 
    335         if (it->current_block) {
    336                 rc = block_put(it->current_block);
    337                 if (rc != EOK) {
    338                         return rc;
    339                 }
    340         }
    341 
     330       
     331        if (it->current_block)
     332                return block_put(it->current_block);
     333       
    342334        return EOK;
    343335}
    344336
    345 /**     Write directory entry to concrete data block.
    346  *
    347  * @param sb            superblock
    348  * @param entry         pointer to entry to be written
    349  * @param entry_len     lenght of new entry
    350  * @param child         child i-node to be written to new entry
    351  * @param name          name of the new entry
    352  * @param name_len      length of entry name
     337/** Write directory entry to concrete data block.
     338 *
     339 * @param sb        Superblock
     340 * @param entry     Pointer to entry to be written
     341 * @param entry_len Length of new entry
     342 * @param child     Child i-node to be written to new entry
     343 * @param name      Name of the new entry
     344 * @param name_len  Length of entry name
     345 *
    353346 */
    354347void ext4_directory_write_entry(ext4_superblock_t *sb,
    355                 ext4_directory_entry_ll_t *entry, uint16_t entry_len,
    356                 ext4_inode_ref_t *child, const char *name, size_t name_len)
    357 {
    358 
     348    ext4_directory_entry_ll_t *entry, uint16_t entry_len,
     349    ext4_inode_ref_t *child, const char *name, size_t name_len)
     350{
    359351        /* Check maximum entry length */
    360352        uint32_t block_size = ext4_superblock_get_block_size(sb);
    361353        assert(entry_len <= block_size);
    362 
     354       
    363355        /* Set basic attributes */
    364356        ext4_directory_entry_ll_set_inode(entry, child->index);
    365357        ext4_directory_entry_ll_set_entry_length(entry, entry_len);
    366358        ext4_directory_entry_ll_set_name_length(sb, entry, name_len);
    367 
     359       
    368360        /* Write name */
    369361        memcpy(entry->name, name, name_len);
    370 
     362       
    371363        /* Set type of entry */
    372         if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY)) {
    373                 ext4_directory_entry_ll_set_inode_type(
    374                                 sb, entry, EXT4_DIRECTORY_FILETYPE_DIR);
    375         } else {
    376                 ext4_directory_entry_ll_set_inode_type(
    377                                 sb, entry, EXT4_DIRECTORY_FILETYPE_REG_FILE);
    378         }
    379 
     364        if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY))
     365                ext4_directory_entry_ll_set_inode_type(sb, entry,
     366                    EXT4_DIRECTORY_FILETYPE_DIR);
     367        else
     368                ext4_directory_entry_ll_set_inode_type(sb, entry,
     369                    EXT4_DIRECTORY_FILETYPE_REG_FILE);
    380370}
    381371
    382372/** Add new entry to the directory.
    383373 *
    384  * @param parent        directory i-node
    385  * @param name          name of new entry
    386  * @param child         i-node to be referenced from new entry
    387  * @return                      error code
    388  */
    389 int ext4_directory_add_entry(ext4_inode_ref_t * parent,
    390                 const char *name, ext4_inode_ref_t *child)
    391 {
    392         int rc;
    393 
     374 * @param parent Directory i-node
     375 * @param name   Name of new entry
     376 * @param child  I-node to be referenced from new entry
     377 *
     378 * @return Error code
     379 *
     380 */
     381int ext4_directory_add_entry(ext4_inode_ref_t *parent, const char *name,
     382    ext4_inode_ref_t *child)
     383{
    394384        ext4_filesystem_t *fs = parent->fs;
    395 
     385       
    396386        /* Index adding (if allowed) */
    397         if (ext4_superblock_has_feature_compatible(fs->superblock, EXT4_FEATURE_COMPAT_DIR_INDEX) &&
    398                         ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) {
    399 
    400                 rc = ext4_directory_dx_add_entry(parent, child, name);
    401 
     387        if ((ext4_superblock_has_feature_compatible(fs->superblock,
     388            EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
     389            (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
     390                int rc = ext4_directory_dx_add_entry(parent, child, name);
     391               
    402392                /* Check if index is not corrupted */
    403393                if (rc != EXT4_ERR_BAD_DX_DIR) {
    404 
    405                         if (rc != EOK) {
     394                        if (rc != EOK)
    406395                                return rc;
    407                         }
    408 
     396                       
    409397                        return EOK;
    410398                }
    411 
     399               
    412400                /* Needed to clear dir index flag if corrupted */
    413401                ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
    414402                parent->dirty = true;
    415403        }
    416 
     404       
    417405        /* Linear algorithm */
    418 
    419         uint32_t iblock = 0, fblock = 0;
     406       
     407        uint32_t iblock = 0;
     408        uint32_t fblock = 0;
    420409        uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
    421410        uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode);
    422411        uint32_t total_blocks = inode_size / block_size;
    423 
    424         uint32_t name_len = strlen(name);
    425 
     412       
     413        uint32_t name_len = str_size(name);
     414       
    426415        /* Find block, where is space for new entry and try to add */
    427416        bool success = false;
    428417        for (iblock = 0; iblock < total_blocks; ++iblock) {
    429 
    430                 rc = ext4_filesystem_get_inode_data_block_index(parent, iblock, &fblock);
    431                 if (rc != EOK) {
     418                int rc = ext4_filesystem_get_inode_data_block_index(parent,
     419                    iblock, &fblock);
     420                if (rc != EOK)
    432421                        return rc;
    433                 }
    434 
     422               
    435423                block_t *block;
    436424                rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
    437                 if (rc != EOK) {
     425                if (rc != EOK)
    438426                        return rc;
    439                 }
    440 
     427               
    441428                /* If adding is successful, function can finish */
    442                 rc = ext4_directory_try_insert_entry(fs->superblock, block, child, name, name_len);
    443                 if (rc == EOK) {
     429                rc = ext4_directory_try_insert_entry(fs->superblock, block,
     430                    child, name, name_len);
     431                if (rc == EOK)
    444432                        success = true;
    445                 }
    446 
     433               
    447434                rc = block_put(block);
    448                 if (rc != EOK) {
     435                if (rc != EOK)
    449436                        return rc;
    450                 }
    451 
    452                 if (success) {
     437               
     438                if (success)
    453439                        return EOK;
    454                 }
    455         }
    456 
     440        }
     441       
    457442        /* No free block found - needed to allocate next data block */
    458 
     443       
    459444        iblock = 0;
    460445        fblock = 0;
    461         rc = ext4_filesystem_append_inode_block(parent, &fblock, &iblock);
    462         if (rc != EOK) {
     446        int rc = ext4_filesystem_append_inode_block(parent, &fblock, &iblock);
     447        if (rc != EOK)
    463448                return rc;
    464         }
    465 
     449       
    466450        /* Load new block */
    467451        block_t *new_block;
    468452        rc = block_get(&new_block, fs->device, fblock, BLOCK_FLAGS_NOREAD);
    469         if (rc != EOK) {
     453        if (rc != EOK)
    470454                return rc;
    471         }
    472 
     455       
    473456        /* Fill block with zeroes */
    474457        memset(new_block->data, 0, block_size);
    475458        ext4_directory_entry_ll_t *block_entry = new_block->data;
    476         ext4_directory_write_entry(fs->superblock, block_entry, block_size, child, name, name_len);
    477 
     459        ext4_directory_write_entry(fs->superblock, block_entry, block_size,
     460            child, name, name_len);
     461       
    478462        /* Save new block */
    479463        new_block->dirty = true;
    480464        rc = block_put(new_block);
    481         if (rc != EOK) {
    482                 return rc;
    483         }
    484 
    485         return EOK;
     465       
     466        return rc;
    486467}
    487468
    488469/** Find directory entry with passed name.
    489470 *
    490  * @param result        result structure to be returned if entry found
    491  * @param parent        directory i-node
    492  * @param name          name of entry to be found
    493  * @return                      error code
     471 * @param result Result structure to be returned if entry found
     472 * @param parent Directory i-node
     473 * @param name   Name of entry to be found
     474 *
     475 * @return Error code
     476 *
    494477 */
    495478int ext4_directory_find_entry(ext4_directory_search_result_t *result,
    496                 ext4_inode_ref_t *parent, const char *name)
    497 {
    498         int rc;
    499         uint32_t name_len = strlen(name);
    500 
     479    ext4_inode_ref_t *parent, const char *name)
     480{
     481        uint32_t name_len = str_size(name);
     482       
    501483        ext4_superblock_t *sb = parent->fs->superblock;
    502 
     484       
    503485        /* Index search */
    504         if (ext4_superblock_has_feature_compatible(sb, EXT4_FEATURE_COMPAT_DIR_INDEX) &&
    505                         ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) {
    506 
    507                 rc = ext4_directory_dx_find_entry(result, parent, name_len, name);
    508 
     486        if ((ext4_superblock_has_feature_compatible(sb,
     487            EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
     488            (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
     489                int rc = ext4_directory_dx_find_entry(result, parent, name_len,
     490                    name);
     491               
    509492                /* Check if index is not corrupted */
    510493                if (rc != EXT4_ERR_BAD_DX_DIR) {
    511 
    512                         if (rc != EOK) {
     494                        if (rc != EOK)
    513495                                return rc;
    514                         }
     496                       
    515497                        return EOK;
    516498                }
    517 
     499               
    518500                /* Needed to clear dir index flag if corrupted */
    519501                ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
    520502                parent->dirty = true;
    521 
    522         }
    523 
     503        }
     504       
    524505        /* Linear algorithm */
    525 
    526         uint32_t iblock, fblock;
     506       
     507        uint32_t iblock;
     508        uint32_t fblock;
    527509        uint32_t block_size = ext4_superblock_get_block_size(sb);
    528510        uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);
    529511        uint32_t total_blocks = inode_size / block_size;
    530 
     512       
    531513        /* Walk through all data blocks */
    532514        for (iblock = 0; iblock < total_blocks; ++iblock) {
    533 
    534515                /* Load block address */
    535                 rc = ext4_filesystem_get_inode_data_block_index(parent, iblock, &fblock);
    536                 if (rc != EOK) {
     516                int rc = ext4_filesystem_get_inode_data_block_index(parent, iblock,
     517                    &fblock);
     518                if (rc != EOK)
    537519                        return rc;
    538                 }
    539 
     520               
    540521                /* Load data block */
    541522                block_t *block;
    542523                rc = block_get(&block, parent->fs->device, fblock, BLOCK_FLAGS_NONE);
    543                 if (rc != EOK) {
     524                if (rc != EOK)
    544525                        return rc;
    545                 }
    546 
     526               
    547527                /* Try to find entry in block */
    548528                ext4_directory_entry_ll_t *res_entry;
    549                 rc = ext4_directory_find_in_block(block, sb, name_len, name, &res_entry);
     529                rc = ext4_directory_find_in_block(block, sb, name_len, name,
     530                    &res_entry);
    550531                if (rc == EOK) {
    551532                        result->block = block;
     
    553534                        return EOK;
    554535                }
    555 
     536               
    556537                /* Entry not found - put block and continue to the next block */
    557 
     538               
    558539                rc = block_put(block);
    559                 if (rc != EOK) {
     540                if (rc != EOK)
    560541                        return rc;
    561                 }
    562         }
    563 
     542        }
     543       
    564544        /* Entry was not found */
    565 
     545       
    566546        result->block = NULL;
    567547        result->dentry =  NULL;
    568 
     548       
    569549        return ENOENT;
    570550}
    571551
    572 
    573552/** Remove directory entry.
    574553 *
    575  * @param parent        directory i-node
    576  * @param name          name of the entry to be removed
    577  * @return                      error code
     554 * @param parent Directory i-node
     555 * @param name   Name of the entry to be removed
     556 *
     557 * @return Error code
     558 *
    578559 */
    579560int ext4_directory_remove_entry(ext4_inode_ref_t *parent, const char *name)
    580561{
    581         int rc;
    582 
    583562        /* Check if removing from directory */
    584563        if (!ext4_inode_is_type(parent->fs->superblock, parent->inode,
    585             EXT4_INODE_MODE_DIRECTORY)) {
     564            EXT4_INODE_MODE_DIRECTORY))
    586565                return ENOTDIR;
    587         }
    588 
     566       
    589567        /* Try to find entry */
    590568        ext4_directory_search_result_t result;
    591         rc = ext4_directory_find_entry(&result, parent, name);
    592         if (rc != EOK) {
     569        int rc = ext4_directory_find_entry(&result, parent, name);
     570        if (rc != EOK)
    593571                return rc;
    594         }
    595 
     572       
    596573        /* Invalidate entry */
    597574        ext4_directory_entry_ll_set_inode(result.dentry, 0);
    598 
     575       
    599576        /* Store entry position in block */
    600         uint32_t pos = (void *)result.dentry - result.block->data;
    601 
    602         /* If entry is not the first in block, it must be merged
     577        uint32_t pos = (void *) result.dentry - result.block->data;
     578       
     579        /*
     580         * If entry is not the first in block, it must be merged
    603581         * with previous entry
    604582         */
    605583        if (pos != 0) {
    606 
    607584                uint32_t offset = 0;
    608 
     585               
    609586                /* Start from the first entry in block */
    610587                ext4_directory_entry_ll_t *tmp_dentry = result.block->data;
    611588                uint16_t tmp_dentry_length =
    612                                 ext4_directory_entry_ll_get_entry_length(tmp_dentry);
    613 
     589                    ext4_directory_entry_ll_get_entry_length(tmp_dentry);
     590               
    614591                /* Find direct predecessor of removed entry */
    615592                while ((offset + tmp_dentry_length) < pos) {
    616                         offset += ext4_directory_entry_ll_get_entry_length(tmp_dentry);
     593                        offset +=
     594                            ext4_directory_entry_ll_get_entry_length(tmp_dentry);
    617595                        tmp_dentry = result.block->data + offset;
    618596                        tmp_dentry_length =
    619                                         ext4_directory_entry_ll_get_entry_length(tmp_dentry);
    620                 }
    621 
     597                            ext4_directory_entry_ll_get_entry_length(tmp_dentry);
     598                }
     599               
    622600                assert(tmp_dentry_length + offset == pos);
    623 
     601               
    624602                /* Add to removed entry length to predecessor's length */
    625603                uint16_t del_entry_length =
    626                                 ext4_directory_entry_ll_get_entry_length(result.dentry);
     604                    ext4_directory_entry_ll_get_entry_length(result.dentry);
    627605                ext4_directory_entry_ll_set_entry_length(tmp_dentry,
    628                                 tmp_dentry_length + del_entry_length);
    629 
    630         }
    631 
     606                    tmp_dentry_length + del_entry_length);
     607        }
     608       
    632609        result.block->dirty = true;
    633 
     610       
    634611        return ext4_directory_destroy_result(&result);
    635612}
     
    637614/** Try to insert entry to concrete data block.
    638615 *
    639  * @param sb                    superblock
    640  * @param target_block  block to try to insert entry to
    641  * @param child                 child i-node to be inserted by new entry
    642  * @param name                  name of the new entry
    643  * @param name_len              length of the new entry name
    644  * @return                              error code
     616 * @param sb           Superblock
     617 * @param target_block Block to try to insert entry to
     618 * @param child        Child i-node to be inserted by new entry
     619 * @param name         Name of the new entry
     620 * @param name_len     Length of the new entry name
     621 *
     622 * @return Error code
     623 *
    645624 */
    646625int ext4_directory_try_insert_entry(ext4_superblock_t *sb,
    647                 block_t *target_block, ext4_inode_ref_t *child,
    648                 const char *name, uint32_t name_len)
     626    block_t *target_block, ext4_inode_ref_t *child, const char *name,
     627    uint32_t name_len)
    649628{
    650629        /* Compute required length entry and align it to 4 bytes */
    651         uint32_t block_size = ext4_superblock_get_block_size(sb);
    652         uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len;
    653         if ((required_len % 4) != 0) {
    654                 required_len += 4 - (required_len % 4);
    655         }
    656 
    657         /* Initialize pointers, stop means to upper bound */
    658         ext4_directory_entry_ll_t *dentry = target_block->data;
    659         ext4_directory_entry_ll_t *stop = target_block->data + block_size;
    660 
    661         /* Walk through the block and check for invalid entries
    662          * or entries with free space for new entry
    663          */
    664         while (dentry < stop) {
    665 
    666                 uint32_t inode = ext4_directory_entry_ll_get_inode(dentry);
    667                 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry);
    668 
    669                 /* If invalid and large enough entry, use it */
    670                 if ((inode == 0) && (rec_len >= required_len)) {
    671                         ext4_directory_write_entry(sb, dentry, rec_len, child, name, name_len);
    672                         target_block->dirty = true;
    673                         return EOK;
    674                 }
    675 
    676                 /* Valid entry, try to split it */
    677                 if (inode != 0) {
    678                         uint16_t used_name_len =
    679                                         ext4_directory_entry_ll_get_name_length(sb, dentry);
    680 
    681                         uint16_t used_space =
    682                                         sizeof(ext4_fake_directory_entry_t) + used_name_len;
    683                         if ((used_name_len % 4) != 0) {
    684                                 used_space += 4 - (used_name_len % 4);
    685                         }
    686                         uint16_t free_space = rec_len - used_space;
    687 
    688                         /* There is free space for new entry */
    689                         if (free_space >= required_len) {
    690 
    691                                 /* Cut tail of current entry */
    692                                 ext4_directory_entry_ll_set_entry_length(dentry, used_space);
    693                                 ext4_directory_entry_ll_t *new_entry =
    694                                                 (void *)dentry + used_space;
    695                                 ext4_directory_write_entry(sb, new_entry,
    696                                                 free_space, child, name, name_len);
    697 
    698                                 target_block->dirty = true;
     630        uint32_t block_size = ext4_superblock_get_block_size(sb);
     631        uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len;
     632       
     633        if ((required_len % 4) != 0)
     634                required_len += 4 - (required_len % 4);
     635       
     636        /* Initialize pointers, stop means to upper bound */
     637        ext4_directory_entry_ll_t *dentry = target_block->data;
     638        ext4_directory_entry_ll_t *stop = target_block->data + block_size;
     639       
     640        /*
     641         * Walk through the block and check for invalid entries
     642         * or entries with free space for new entry
     643         */
     644        while (dentry < stop) {
     645                uint32_t inode = ext4_directory_entry_ll_get_inode(dentry);
     646                uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry);
     647               
     648                /* If invalid and large enough entry, use it */
     649                if ((inode == 0) && (rec_len >= required_len)) {
     650                        ext4_directory_write_entry(sb, dentry, rec_len, child,
     651                            name, name_len);
     652                        target_block->dirty = true;
     653                       
     654                        return EOK;
     655                }
     656               
     657                /* Valid entry, try to split it */
     658                if (inode != 0) {
     659                        uint16_t used_name_len =
     660                            ext4_directory_entry_ll_get_name_length(sb, dentry);
     661                       
     662                        uint16_t used_space =
     663                            sizeof(ext4_fake_directory_entry_t) + used_name_len;
     664                       
     665                        if ((used_name_len % 4) != 0)
     666                                used_space += 4 - (used_name_len % 4);
     667                       
     668                        uint16_t free_space = rec_len - used_space;
     669                       
     670                        /* There is free space for new entry */
     671                        if (free_space >= required_len) {
     672                                /* Cut tail of current entry */
     673                                ext4_directory_entry_ll_set_entry_length(dentry, used_space);
     674                                ext4_directory_entry_ll_t *new_entry =
     675                                    (void *) dentry + used_space;
     676                                ext4_directory_write_entry(sb, new_entry,
     677                                    free_space, child, name, name_len);
     678                               
     679                                target_block->dirty = true;
     680                               
    699681                                return EOK;
    700                         }
    701                 }
    702 
    703                 /* Jump to the next entry */
    704                 dentry = (void *)dentry + rec_len;
    705         }
    706 
    707         /* No free space found for new entry */
    708 
    709         return ENOSPC;
     682                        }
     683                }
     684               
     685                /* Jump to the next entry */
     686                dentry = (void *) dentry + rec_len;
     687        }
     688       
     689        /* No free space found for new entry */
     690        return ENOSPC;
    710691}
    711692
    712693/** Try to find entry in block by name.
    713694 *
    714  * @param block         block containing entries
    715  * @param sb            superblock
    716  * @param name_len      length of entry name
    717  * @param name          name of entry to be found
    718  * @param res_entry     output pointer to found entry, NULL if not found
    719  * @return                      error code
    720  */
    721 int ext4_directory_find_in_block(block_t *block,
    722                 ext4_superblock_t *sb, size_t name_len, const char *name,
    723                 ext4_directory_entry_ll_t **res_entry)
     695 * @param block     Block containing entries
     696 * @param sb        Superblock
     697 * @param name_len  Length of entry name
     698 * @param name      Name of entry to be found
     699 * @param res_entry Output pointer to found entry, NULL if not found
     700 *
     701 * @return Error code
     702 *
     703 */
     704int ext4_directory_find_in_block(block_t *block, ext4_superblock_t *sb,
     705    size_t name_len, const char *name, ext4_directory_entry_ll_t **res_entry)
    724706{
    725707        /* Start from the first entry in block */
    726         ext4_directory_entry_ll_t *dentry = (ext4_directory_entry_ll_t *)block->data;
    727         /*Set upper bound for cycling */
     708        ext4_directory_entry_ll_t *dentry =
     709            (ext4_directory_entry_ll_t *) block->data;
     710       
     711        /* Set upper bound for cycling */
    728712        uint8_t *addr_limit = block->data + ext4_superblock_get_block_size(sb);
    729 
     713       
    730714        /* Walk through the block and check entries */
    731         while ((uint8_t *)dentry < addr_limit) {
    732 
     715        while ((uint8_t *) dentry < addr_limit) {
    733716                /* Termination condition */
    734                 if ((uint8_t*) dentry + name_len > addr_limit) {
     717                if ((uint8_t *) dentry + name_len > addr_limit)
    735718                        break;
    736                 }
    737 
     719               
    738720                /* Valid entry - check it */
    739721                if (dentry->inode != 0) {
    740 
    741722                        /* For more effectivity compare firstly only lengths */
    742                         if (name_len == ext4_directory_entry_ll_get_name_length(sb, dentry)) {
     723                        if (ext4_directory_entry_ll_get_name_length(sb, dentry) ==
     724                            name_len) {
    743725                                /* Compare names */
    744                                 if (bcmp((uint8_t *)name, dentry->name, name_len) == 0) {
     726                                if (bcmp((uint8_t *) name, dentry->name, name_len) == 0) {
    745727                                        *res_entry = dentry;
    746728                                        return EOK;
     
    748730                        }
    749731                }
    750 
    751                 uint16_t dentry_len = ext4_directory_entry_ll_get_entry_length(dentry);
    752 
     732               
     733                uint16_t dentry_len =
     734                    ext4_directory_entry_ll_get_entry_length(dentry);
     735               
    753736                /* Corrupted entry */
    754                 if (dentry_len == 0) {
     737                if (dentry_len == 0)
    755738                        return EINVAL;
    756                 }
    757 
     739               
    758740                /* Jump to next entry */
    759                 dentry = (ext4_directory_entry_ll_t *)((uint8_t *)dentry + dentry_len);
    760         }
    761 
     741                dentry = (ext4_directory_entry_ll_t *) ((uint8_t *) dentry + dentry_len);
     742        }
     743       
    762744        /* Entry not found */
    763745        return ENOENT;
     
    766748/** Simple function to release allocated data from result.
    767749 *
    768  * @param result        search result to destroy
    769  * @return                      error code
     750 * @param result Search result to destroy
     751 *
     752 * @return Error code
     753 *
    770754 */
    771755int ext4_directory_destroy_result(ext4_directory_search_result_t *result)
    772756{
    773         if (result->block) {
     757        if (result->block)
    774758                return block_put(result->block);
    775         }
    776 
     759       
    777760        return EOK;
    778761}
Note: See TracChangeset for help on using the changeset viewer.