source: mainline/uspace/lib/ext4/libext4_directory.c@ 343ccfd

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

next bunch of getters and setters added

  • Property mode set to 100644
File size: 6.0 KB
Line 
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
35 * @brief Ext4 directory structure operations.
36 */
37
38#include <byteorder.h>
39#include <errno.h>
40#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
51void ext4_directory_entry_ll_set_inode(ext4_directory_entry_ll_t *de,
52 uint32_t inode)
53{
54 de->inode = host2uint32_t_le(inode);
55}
56
57uint16_t ext4_directory_entry_ll_get_entry_length(
58 ext4_directory_entry_ll_t *de)
59{
60 return uint16_t_le2host(de->entry_length);
61}
62
63void ext4_directory_entry_ll_set_entry_length(ext4_directory_entry_ll_t *de,
64 uint16_t length)
65{
66 de->entry_length = host2uint16_t_le(length);
67}
68
69uint16_t ext4_directory_entry_ll_get_name_length(
70 ext4_superblock_t *sb, ext4_directory_entry_ll_t *de)
71{
72 if (ext4_superblock_get_rev_level(sb) == 0 &&
73 ext4_superblock_get_minor_rev_level(sb) < 5) {
74
75 return de->name_length;
76 }
77
78 return ((uint16_t)de->name_length_high) << 8 |
79 ((uint16_t)de->name_length);
80
81
82}
83
84void ext4_directory_entry_ll_set_name_length(ext4_superblock_t *sb,
85 ext4_directory_entry_ll_t *de, uint16_t length)
86{
87
88 de->name_length = (length << 8) >> 8;
89
90 if (ext4_superblock_get_rev_level(sb) > 0 ||
91 ext4_superblock_get_minor_rev_level(sb) >= 5) {
92
93 de->name_length_high = length >> 8;
94 }
95
96}
97
98
99int ext4_directory_iterator_init(ext4_directory_iterator_t *it,
100 ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, aoff64_t pos)
101{
102 it->inode_ref = inode_ref;
103 it->fs = fs;
104 it->current = NULL;
105 it->current_offset = 0;
106 it->current_block = NULL;
107
108 return ext4_directory_iterator_seek(it, pos);
109}
110
111
112int ext4_directory_iterator_next(ext4_directory_iterator_t *it)
113{
114 uint16_t skip;
115
116 assert(it->current != NULL);
117
118 skip = ext4_directory_entry_ll_get_entry_length(it->current);
119
120 return ext4_directory_iterator_seek(it, it->current_offset + skip);
121}
122
123
124int ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos)
125{
126 int rc;
127
128 uint64_t size;
129 aoff64_t current_block_idx;
130 aoff64_t next_block_idx;
131 uint32_t next_block_phys_idx;
132 uint32_t block_size;
133
134 size = ext4_inode_get_size(it->fs->superblock, it->inode_ref->inode);
135
136 /* The iterator is not valid until we seek to the desired position */
137 it->current = NULL;
138
139 /* Are we at the end? */
140 if (pos >= size) {
141 if (it->current_block) {
142 rc = block_put(it->current_block);
143 it->current_block = NULL;
144 if (rc != EOK) {
145 return rc;
146 }
147 }
148
149 it->current_offset = pos;
150 return EOK;
151 }
152
153 block_size = ext4_superblock_get_block_size(it->fs->superblock);
154 current_block_idx = it->current_offset / block_size;
155 next_block_idx = pos / block_size;
156
157 /* If we don't have a block or are moving accross block boundary,
158 * we need to get another block
159 */
160 if (it->current_block == NULL || current_block_idx != next_block_idx) {
161 if (it->current_block) {
162 rc = block_put(it->current_block);
163 it->current_block = NULL;
164 if (rc != EOK) {
165 return rc;
166 }
167 }
168
169 rc = ext4_filesystem_get_inode_data_block_index(it->fs,
170 it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
171 if (rc != EOK) {
172 return rc;
173 }
174
175 rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx,
176 BLOCK_FLAGS_NONE);
177 if (rc != EOK) {
178 it->current_block = NULL;
179 return rc;
180 }
181 }
182
183 it->current_offset = pos;
184
185 return ext4_directory_iterator_set(it, block_size);
186}
187
188static int ext4_directory_iterator_set(ext4_directory_iterator_t *it,
189 uint32_t block_size)
190{
191 uint32_t offset_in_block = it->current_offset % block_size;
192
193 it->current = NULL;
194
195 /* Ensure proper alignment */
196 if ((offset_in_block % 4) != 0) {
197 return EIO;
198 }
199
200 /* Ensure that the core of the entry does not overflow the block */
201 if (offset_in_block > block_size - 8) {
202 return EIO;
203 }
204
205 ext4_directory_entry_ll_t *entry = it->current_block->data + offset_in_block;
206
207 /* Ensure that the whole entry does not overflow the block */
208 uint16_t length = ext4_directory_entry_ll_get_entry_length(entry);
209 if (offset_in_block + length > block_size) {
210 return EIO;
211 }
212
213 /* Ensure the name length is not too large */
214 if (ext4_directory_entry_ll_get_name_length(it->fs->superblock,
215 entry) > length-8) {
216 return EIO;
217 }
218
219 it->current = entry;
220 return EOK;
221}
222
223
224int ext4_directory_iterator_fini(ext4_directory_iterator_t *it)
225{
226 int rc;
227
228 it->fs = NULL;
229 it->inode_ref = NULL;
230 it->current = NULL;
231
232 if (it->current_block) {
233 rc = block_put(it->current_block);
234 if (rc != EOK) {
235 return rc;
236 }
237 }
238
239 return EOK;
240}
241
242
243
244
245/**
246 * @}
247 */
Note: See TracBrowser for help on using the repository browser.