source: mainline/uspace/lib/ext4/libext4_directory.c@ e68c834

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

More functions ported from ext2

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