Changeset a8e1aae in mainline for uspace/lib/ext2/libext2_directory.c


Ignore:
Timestamp:
2011-02-24T21:03:42Z (14 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9ffbdf1
Parents:
102d400
Message:

Add support for reading directories to libext2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ext2/libext2_directory.c

    r102d400 ra8e1aae  
    3737#include "libext2_directory.h"
    3838#include <byteorder.h>
     39#include <errno.h>
     40#include <assert.h>
    3941
    4042/**
     
    7577}
    7678
     79/**
     80 * Initialize a directory iterator
     81 *
     82 * @param it pointer to iterator to initialize
     83 * @param fs pointer to filesystem structure
     84 * @param inode pointer to inode reference structure
     85 * @return EOK on success or negative error code on failure
     86 */
     87int ext2_directory_iterator_init(ext2_directory_iterator_t *it,
     88    ext2_filesystem_t *fs, ext2_inode_ref_t *inode_ref)
     89{
     90        int rc;
     91        uint32_t block_id;
     92        it->inode_ref = inode_ref;
     93        it->fs = fs;
     94       
     95        // Get the first data block, so we can get first entry
     96        rc = ext2_filesystem_get_inode_data_block_index(fs, inode_ref->inode, 0,
     97            &block_id);
     98        if (rc != EOK) {
     99                return rc;
     100        }
     101       
     102        rc = block_get(&it->current_block, fs->device, block_id, 0);
     103        if (rc != EOK) {
     104                return rc;
     105        }
     106       
     107        it->current = it->current_block->data;
     108        it->current_offset = 0;
     109       
     110        return EOK;
     111}
     112
     113/**
     114 * Advance the directory iterator to the next entry
     115 *
     116 * @param it pointer to iterator to initialize
     117 * @return EOK on success or negative error code on failure
     118 */
     119int ext2_directory_iterator_next(ext2_directory_iterator_t *it)
     120{
     121        int rc;
     122        uint16_t skip;
     123        uint64_t size;
     124        aoff64_t current_block_idx;
     125        aoff64_t next_block_idx;
     126        uint32_t next_block_phys_idx;
     127        uint32_t block_size;
     128        uint32_t offset_in_block;
     129       
     130        assert(it->current != NULL);
     131       
     132        skip = ext2_directory_entry_ll_get_entry_length(it->current);
     133        size = ext2_inode_get_size(it->fs->superblock, it->inode_ref->inode);
     134       
     135        // Are we at the end?
     136        if (it->current_offset + skip >= size) {
     137                rc = block_put(it->current_block);
     138                it->current_block = NULL;
     139                it->current = NULL;
     140                if (rc != EOK) {
     141                        return rc;
     142                }
     143               
     144                it->current_offset += skip;
     145                return EOK;
     146        }
     147       
     148        block_size = ext2_superblock_get_block_size(it->fs->superblock);
     149        current_block_idx = it->current_offset / block_size;
     150        next_block_idx = (it->current_offset + skip) / block_size;
     151       
     152        // If we are moving accross block boundary,
     153        // we need to get another block
     154        if (current_block_idx != next_block_idx) {
     155                rc = block_put(it->current_block);
     156                it->current_block = NULL;
     157                it->current = NULL;
     158                if (rc != EOK) {
     159                        return rc;
     160                }
     161               
     162                rc = ext2_filesystem_get_inode_data_block_index(it->fs,
     163                    it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
     164                if (rc != EOK) {
     165                        return rc;
     166                }
     167               
     168                rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx,
     169                    BLOCK_FLAGS_NONE);
     170                if (rc != EOK) {
     171                        it->current_block = NULL;
     172                        return rc;
     173                }
     174        }
     175       
     176        offset_in_block = (it->current_offset + skip) % block_size;
     177       
     178        // Ensure proper alignment
     179        if ((offset_in_block % 4) != 0) {
     180                it->current = NULL;
     181                return EIO;
     182        }
     183       
     184        // Ensure that the core of the entry does not overflow the block
     185        if (offset_in_block > block_size - 8) {
     186                it->current = NULL;
     187                return EIO;
     188        }
     189               
     190        it->current = it->current_block->data + offset_in_block;
     191        it->current_offset += skip;
     192       
     193        // Ensure that the whole entry does not overflow the block
     194        skip = ext2_directory_entry_ll_get_entry_length(it->current);
     195        if (offset_in_block + skip > block_size) {
     196                it->current = NULL;
     197                return EIO;
     198        }
     199       
     200        // Ensure the name length is not too large
     201        if (ext2_directory_entry_ll_get_name_length(it->fs->superblock,
     202            it->current) > skip-8) {
     203                it->current = NULL;
     204                return EIO;
     205        }
     206       
     207        return EOK;
     208}
     209
     210/**
     211 * Release all resources asociated with the directory iterator
     212 *
     213 * @param it pointer to iterator to initialize
     214 * @return EOK on success or negative error code on failure
     215 */
     216int ext2_directory_iterator_fini(ext2_directory_iterator_t *it)
     217{
     218        int rc;
     219       
     220        it->fs = NULL;
     221        it->inode_ref = NULL;
     222        it->current = NULL;
     223       
     224        if (it->current_block) {
     225                rc = block_put(it->current_block);
     226                if (rc != EOK) {
     227                        return rc;
     228                }
     229        }
     230       
     231        return EOK;
     232}
     233
    77234/** @}
    78235 */
Note: See TracChangeset for help on using the changeset viewer.