2
* Copyright (c) 2011 Martin Sucha
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* - Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* - The name of the author may not be used to endorse or promote products
15
* derived from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
/** @addtogroup libext2
37
#include "libext2_directory.h"
38
#include <byteorder.h>
43
* Get inode number for the directory entry
45
* @param de pointer to linked list directory entry
47
uint32_t ext2_directory_entry_ll_get_inode(ext2_directory_entry_ll_t *de)
49
return uint32_t_le2host(de->inode);
53
* Get length of the directory entry
55
* @param de pointer to linked list directory entry
57
uint16_t ext2_directory_entry_ll_get_entry_length(
58
ext2_directory_entry_ll_t *de)
60
return uint16_t_le2host(de->entry_length);
64
* Get length of the name stored in the directory entry
66
* @param de pointer to linked list directory entry
68
uint16_t ext2_directory_entry_ll_get_name_length(
69
ext2_superblock_t *sb, ext2_directory_entry_ll_t *de)
71
if (ext2_superblock_get_rev_major(sb) == 0 &&
72
ext2_superblock_get_rev_minor(sb) < 5) {
73
return ((uint16_t)de->name_length_high) << 8 |
74
((uint16_t)de->name_length);
76
return de->name_length;
80
* Initialize a directory iterator
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
87
int ext2_directory_iterator_init(ext2_directory_iterator_t *it,
88
ext2_filesystem_t *fs, ext2_inode_ref_t *inode_ref)
92
it->inode_ref = inode_ref;
95
/* Get the first data block, so we can get the first entry */
96
rc = ext2_filesystem_get_inode_data_block_index(fs, inode_ref->inode, 0,
102
rc = block_get(&it->current_block, fs->device, block_id, 0);
107
it->current = it->current_block->data;
108
it->current_offset = 0;
114
* Advance the directory iterator to the next entry
116
* @param it pointer to iterator to initialize
117
* @return EOK on success or negative error code on failure
119
int ext2_directory_iterator_next(ext2_directory_iterator_t *it)
124
aoff64_t current_block_idx;
125
aoff64_t next_block_idx;
126
uint32_t next_block_phys_idx;
128
uint32_t offset_in_block;
130
assert(it->current != NULL);
132
skip = ext2_directory_entry_ll_get_entry_length(it->current);
133
size = ext2_inode_get_size(it->fs->superblock, it->inode_ref->inode);
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;
144
it->current_offset += skip;
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;
152
/* If we are moving accross block boundary,
153
* we need to get another block
155
if (current_block_idx != next_block_idx) {
156
rc = block_put(it->current_block);
157
it->current_block = NULL;
163
rc = ext2_filesystem_get_inode_data_block_index(it->fs,
164
it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
169
rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx,
172
it->current_block = NULL;
177
offset_in_block = (it->current_offset + skip) % block_size;
179
/* Ensure proper alignment */
180
if ((offset_in_block % 4) != 0) {
185
/* Ensure that the core of the entry does not overflow the block */
186
if (offset_in_block > block_size - 8) {
191
it->current = it->current_block->data + offset_in_block;
192
it->current_offset += skip;
194
/* Ensure that the whole entry does not overflow the block */
195
skip = ext2_directory_entry_ll_get_entry_length(it->current);
196
if (offset_in_block + skip > block_size) {
201
/* Ensure the name length is not too large */
202
if (ext2_directory_entry_ll_get_name_length(it->fs->superblock,
203
it->current) > skip-8) {
212
* Release all resources asociated with the directory iterator
214
* @param it pointer to iterator to initialize
215
* @return EOK on success or negative error code on failure
217
int ext2_directory_iterator_fini(ext2_directory_iterator_t *it)
222
it->inode_ref = NULL;
225
if (it->current_block) {
226
rc = block_put(it->current_block);