Changeset 9b9d37bb in mainline for uspace/lib/ext4/libext4_directory.c


Ignore:
Timestamp:
2011-10-06T09:48:53Z (14 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1114173
Parents:
3712434
Message:

mounting + list of mounted directory (ported from ext2) - many TODO remaining

File:
1 edited

Legend:

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

    r3712434 r9b9d37bb  
    3636 */
    3737
     38#include <byteorder.h>
     39#include <errno.h>
    3840#include "libext4.h"
     41
     42static int ext4_directory_iterator_set(ext4_directory_iterator_t *,
     43    uint32_t);
     44
     45
     46uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *de)
     47{
     48        return uint32_t_le2host(de->inode);
     49}
     50
     51uint16_t ext4_directory_entry_ll_get_entry_length(
     52    ext4_directory_entry_ll_t *de)
     53{
     54        return uint16_t_le2host(de->entry_length);
     55}
     56
     57uint16_t ext4_directory_entry_ll_get_name_length(
     58    ext4_superblock_t *sb, ext4_directory_entry_ll_t *de)
     59{
     60        if (ext4_superblock_get_rev_level(sb) == 0 &&
     61            ext4_superblock_get_minor_rev_level(sb) < 5) {
     62                return ((uint16_t)de->name_length_high) << 8 |
     63                    ((uint16_t)de->name_length);
     64        }
     65        return de->name_length;
     66}
     67
     68int ext4_directory_iterator_init(ext4_directory_iterator_t *it,
     69    ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, aoff64_t pos)
     70{
     71        it->inode_ref = inode_ref;
     72        it->fs = fs;
     73        it->current = NULL;
     74        it->current_offset = 0;
     75        it->current_block = NULL;
     76
     77        return ext4_directory_iterator_seek(it, pos);
     78}
     79
     80
     81int ext4_directory_iterator_next(ext4_directory_iterator_t *it)
     82{
     83        uint16_t skip;
     84
     85        assert(it->current != NULL);
     86
     87        skip = ext4_directory_entry_ll_get_entry_length(it->current);
     88
     89        return ext4_directory_iterator_seek(it, it->current_offset + skip);
     90}
     91
     92
     93int ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos)
     94{
     95        int rc;
     96
     97        uint64_t size;
     98        aoff64_t current_block_idx;
     99        aoff64_t next_block_idx;
     100        uint32_t next_block_phys_idx;
     101        uint32_t block_size;
     102
     103        size = ext4_inode_get_size(it->fs->superblock, it->inode_ref->inode);
     104
     105        /* The iterator is not valid until we seek to the desired position */
     106        it->current = NULL;
     107
     108        /* Are we at the end? */
     109        if (pos >= size) {
     110                if (it->current_block) {
     111                        rc = block_put(it->current_block);
     112                        it->current_block = NULL;
     113                        if (rc != EOK) {
     114                                return rc;
     115                        }
     116                }
     117
     118                it->current_offset = pos;
     119                return EOK;
     120        }
     121
     122        block_size = ext4_superblock_get_block_size(it->fs->superblock);
     123        current_block_idx = it->current_offset / block_size;
     124        next_block_idx = pos / block_size;
     125
     126        /* If we don't have a block or are moving accross block boundary,
     127         * we need to get another block
     128         */
     129        if (it->current_block == NULL || current_block_idx != next_block_idx) {
     130                if (it->current_block) {
     131                        rc = block_put(it->current_block);
     132                        it->current_block = NULL;
     133                        if (rc != EOK) {
     134                                return rc;
     135                        }
     136                }
     137
     138                rc = ext4_filesystem_get_inode_data_block_index(it->fs,
     139                    it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
     140                if (rc != EOK) {
     141                        return rc;
     142                }
     143
     144                rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx,
     145                    BLOCK_FLAGS_NONE);
     146                if (rc != EOK) {
     147                        it->current_block = NULL;
     148                        return rc;
     149                }
     150        }
     151
     152        it->current_offset = pos;
     153        return ext4_directory_iterator_set(it, block_size);
     154}
     155
     156static int ext4_directory_iterator_set(ext4_directory_iterator_t *it,
     157    uint32_t block_size)
     158{
     159        uint32_t offset_in_block = it->current_offset % block_size;
     160
     161        it->current = NULL;
     162
     163        /* Ensure proper alignment */
     164        if ((offset_in_block % 4) != 0) {
     165                return EIO;
     166        }
     167
     168        /* Ensure that the core of the entry does not overflow the block */
     169        if (offset_in_block > block_size - 8) {
     170                return EIO;
     171        }
     172
     173        ext4_directory_entry_ll_t *entry = it->current_block->data + offset_in_block;
     174
     175        /* Ensure that the whole entry does not overflow the block */
     176        uint16_t length = ext4_directory_entry_ll_get_entry_length(entry);
     177        if (offset_in_block + length > block_size) {
     178                return EIO;
     179        }
     180
     181        /* Ensure the name length is not too large */
     182        if (ext4_directory_entry_ll_get_name_length(it->fs->superblock,
     183            entry) > length-8) {
     184                return EIO;
     185        }
     186
     187        it->current = entry;
     188        return EOK;
     189}
     190
     191
     192int ext4_directory_iterator_fini(ext4_directory_iterator_t *it)
     193{
     194        int rc;
     195
     196        it->fs = NULL;
     197        it->inode_ref = NULL;
     198        it->current = NULL;
     199
     200        if (it->current_block) {
     201                rc = block_put(it->current_block);
     202                if (rc != EOK) {
     203                        return rc;
     204                }
     205        }
     206
     207        return EOK;
     208}
    39209
    40210
Note: See TracChangeset for help on using the changeset viewer.