source: mainline/uspace/lib/ext4/libext4_directory.c@ 2ea6392

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

cleaning debug some debug messages and added feature checkers

  • Property mode set to 100644
File size: 5.3 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 TODO
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
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
154 return ext4_directory_iterator_set(it, block_size);
155}
156
157static int ext4_directory_iterator_set(ext4_directory_iterator_t *it,
158 uint32_t block_size)
159{
160 uint32_t offset_in_block = it->current_offset % block_size;
161
162 it->current = NULL;
163
164 /* Ensure proper alignment */
165 if ((offset_in_block % 4) != 0) {
166 return EIO;
167 }
168
169 /* Ensure that the core of the entry does not overflow the block */
170 if (offset_in_block > block_size - 8) {
171 return EIO;
172 }
173
174 ext4_directory_entry_ll_t *entry = it->current_block->data + offset_in_block;
175
176 /* Ensure that the whole entry does not overflow the block */
177 uint16_t length = ext4_directory_entry_ll_get_entry_length(entry);
178 if (offset_in_block + length > block_size) {
179 return EIO;
180 }
181
182 /* Ensure the name length is not too large */
183 if (ext4_directory_entry_ll_get_name_length(it->fs->superblock,
184 entry) > length-8) {
185 return EIO;
186 }
187
188 it->current = entry;
189 return EOK;
190}
191
192
193int ext4_directory_iterator_fini(ext4_directory_iterator_t *it)
194{
195 int rc;
196
197 it->fs = NULL;
198 it->inode_ref = NULL;
199 it->current = NULL;
200
201 if (it->current_block) {
202 rc = block_put(it->current_block);
203 if (rc != EOK) {
204 return rc;
205 }
206 }
207
208 return EOK;
209}
210
211
212/**
213 * @}
214 */
Note: See TracBrowser for help on using the repository browser.