Changeset 9b9d37bb in mainline for uspace/lib/ext4/libext4_directory.c
- Timestamp:
- 2011-10-06T09:48:53Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1114173
- Parents:
- 3712434
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_directory.c
r3712434 r9b9d37bb 36 36 */ 37 37 38 #include <byteorder.h> 39 #include <errno.h> 38 40 #include "libext4.h" 41 42 static int ext4_directory_iterator_set(ext4_directory_iterator_t *, 43 uint32_t); 44 45 46 uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *de) 47 { 48 return uint32_t_le2host(de->inode); 49 } 50 51 uint16_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 57 uint16_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 68 int 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 81 int 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 93 int 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 return ext4_directory_iterator_set(it, block_size); 154 } 155 156 static int ext4_directory_iterator_set(ext4_directory_iterator_t *it, 157 uint32_t block_size) 158 { 159 uint32_t offset_in_block = it->current_offset % block_size; 160 161 it->current = NULL; 162 163 /* Ensure proper alignment */ 164 if ((offset_in_block % 4) != 0) { 165 return EIO; 166 } 167 168 /* Ensure that the core of the entry does not overflow the block */ 169 if (offset_in_block > block_size - 8) { 170 return EIO; 171 } 172 173 ext4_directory_entry_ll_t *entry = it->current_block->data + offset_in_block; 174 175 /* Ensure that the whole entry does not overflow the block */ 176 uint16_t length = ext4_directory_entry_ll_get_entry_length(entry); 177 if (offset_in_block + length > block_size) { 178 return EIO; 179 } 180 181 /* Ensure the name length is not too large */ 182 if (ext4_directory_entry_ll_get_name_length(it->fs->superblock, 183 entry) > length-8) { 184 return EIO; 185 } 186 187 it->current = entry; 188 return EOK; 189 } 190 191 192 int ext4_directory_iterator_fini(ext4_directory_iterator_t *it) 193 { 194 int rc; 195 196 it->fs = NULL; 197 it->inode_ref = NULL; 198 it->current = NULL; 199 200 if (it->current_block) { 201 rc = block_put(it->current_block); 202 if (rc != EOK) { 203 return rc; 204 } 205 } 206 207 return EOK; 208 } 39 209 40 210
Note:
See TracChangeset
for help on using the changeset viewer.