source: mainline/uspace/lib/ext4/libext4_directory.c@ 052e82d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 052e82d was c25e39b, checked in by Frantisek Princ <frantisek.princ@…>, 14 years ago

bugfix, TODO resolving

  • Property mode set to 100644
File size: 6.3 KB
RevLine 
[eb91db7]1/*
2 * Copyright (c) 2011 Frantisek Princ
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/** @addtogroup libext4
30 * @{
31 */
32
33/**
34 * @file libext4_directory.c
[c25e39b]35 * @brief Ext4 directory structure operations.
[eb91db7]36 */
37
[9b9d37bb]38#include <byteorder.h>
39#include <errno.h>
[3711e7e]40#include "libext4.h"
[eb91db7]41
[9b9d37bb]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
[7bc4508]68uint8_t ext4_directory_dx_root_info_get_hash_version(ext4_directory_dx_root_info_t *root_info)
69{
70 return root_info->hash_version;
71}
72
73uint8_t ext4_directory_dx_root_info_get_info_length(ext4_directory_dx_root_info_t *root_info)
74{
75 return root_info->info_length;
76}
77
78uint8_t ext4_directory_dx_root_info_get_indirect_levels(ext4_directory_dx_root_info_t *root_info)
79{
80 return root_info->indirect_levels;
81}
82
83uint16_t ext4_directory_dx_countlimit_get_limit(ext4_directory_dx_countlimit_t *countlimit)
84{
85 return uint16_t_le2host(countlimit->limit);
86}
87uint16_t ext4_directory_dx_countlimit_get_count(ext4_directory_dx_countlimit_t *countlimit)
88{
89 return uint16_t_le2host(countlimit->count);
90}
91
92uint32_t ext4_directory_dx_entry_get_hash(ext4_directory_dx_entry_t *entry)
93{
94 return uint32_t_le2host(entry->hash);
95}
96
97uint32_t ext4_directory_dx_entry_get_block(ext4_directory_dx_entry_t *entry)
98{
99 return uint32_t_le2host(entry->block);
100}
101
102
103
[9b9d37bb]104int ext4_directory_iterator_init(ext4_directory_iterator_t *it,
105 ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, aoff64_t pos)
106{
107 it->inode_ref = inode_ref;
108 it->fs = fs;
109 it->current = NULL;
110 it->current_offset = 0;
111 it->current_block = NULL;
112
113 return ext4_directory_iterator_seek(it, pos);
114}
115
116
117int ext4_directory_iterator_next(ext4_directory_iterator_t *it)
118{
119 uint16_t skip;
120
121 assert(it->current != NULL);
122
123 skip = ext4_directory_entry_ll_get_entry_length(it->current);
124
125 return ext4_directory_iterator_seek(it, it->current_offset + skip);
126}
127
128
129int ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos)
130{
131 int rc;
132
133 uint64_t size;
134 aoff64_t current_block_idx;
135 aoff64_t next_block_idx;
136 uint32_t next_block_phys_idx;
137 uint32_t block_size;
138
139 size = ext4_inode_get_size(it->fs->superblock, it->inode_ref->inode);
140
141 /* The iterator is not valid until we seek to the desired position */
142 it->current = NULL;
143
144 /* Are we at the end? */
145 if (pos >= size) {
146 if (it->current_block) {
147 rc = block_put(it->current_block);
148 it->current_block = NULL;
149 if (rc != EOK) {
150 return rc;
151 }
152 }
153
154 it->current_offset = pos;
155 return EOK;
156 }
157
158 block_size = ext4_superblock_get_block_size(it->fs->superblock);
159 current_block_idx = it->current_offset / block_size;
160 next_block_idx = pos / block_size;
161
162 /* If we don't have a block or are moving accross block boundary,
163 * we need to get another block
164 */
165 if (it->current_block == NULL || current_block_idx != next_block_idx) {
166 if (it->current_block) {
167 rc = block_put(it->current_block);
168 it->current_block = NULL;
169 if (rc != EOK) {
170 return rc;
171 }
172 }
173
174 rc = ext4_filesystem_get_inode_data_block_index(it->fs,
175 it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
176 if (rc != EOK) {
177 return rc;
178 }
179
180 rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx,
181 BLOCK_FLAGS_NONE);
182 if (rc != EOK) {
183 it->current_block = NULL;
184 return rc;
185 }
186 }
187
188 it->current_offset = pos;
[e68c834]189
[9b9d37bb]190 return ext4_directory_iterator_set(it, block_size);
191}
192
193static int ext4_directory_iterator_set(ext4_directory_iterator_t *it,
194 uint32_t block_size)
195{
196 uint32_t offset_in_block = it->current_offset % block_size;
197
198 it->current = NULL;
199
200 /* Ensure proper alignment */
201 if ((offset_in_block % 4) != 0) {
202 return EIO;
203 }
204
205 /* Ensure that the core of the entry does not overflow the block */
206 if (offset_in_block > block_size - 8) {
207 return EIO;
208 }
209
210 ext4_directory_entry_ll_t *entry = it->current_block->data + offset_in_block;
211
212 /* Ensure that the whole entry does not overflow the block */
213 uint16_t length = ext4_directory_entry_ll_get_entry_length(entry);
214 if (offset_in_block + length > block_size) {
215 return EIO;
216 }
217
218 /* Ensure the name length is not too large */
219 if (ext4_directory_entry_ll_get_name_length(it->fs->superblock,
220 entry) > length-8) {
221 return EIO;
222 }
223
224 it->current = entry;
225 return EOK;
226}
227
228
229int ext4_directory_iterator_fini(ext4_directory_iterator_t *it)
230{
231 int rc;
232
233 it->fs = NULL;
234 it->inode_ref = NULL;
235 it->current = NULL;
236
237 if (it->current_block) {
238 rc = block_put(it->current_block);
239 if (rc != EOK) {
240 return rc;
241 }
242 }
243
244 return EOK;
245}
246
[246a5af]247
[7bc4508]248
[eb91db7]249
250/**
251 * @}
252 */
Note: See TracBrowser for help on using the repository browser.