source: mainline/uspace/lib/ext4/src/directory.c@ 1e4a937

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1e4a937 was 2175178, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Allow creating ext2 dynamic revision. Allow choosing ext filesystem version by mkext4 argument. Fix support for filesystems without filetype feature.

  • Property mode set to 100644
File size: 20.1 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Sucha
3 * Copyright (c) 2012 Frantisek Princ
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libext4
31 * @{
32 */
33/**
34 * @file directory.c
35 * @brief Ext4 directory structure operations.
36 */
37
38#include <byteorder.h>
39#include <errno.h>
40#include <mem.h>
41#include <stdlib.h>
42#include <str.h>
43#include "ext4/directory.h"
44#include "ext4/directory_index.h"
45#include "ext4/filesystem.h"
46#include "ext4/inode.h"
47#include "ext4/superblock.h"
48
49/** Get i-node number from directory entry.
50 *
51 * @param de Directory entry
52 *
53 * @return I-node number
54 *
55 */
56uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *de)
57{
58 return uint32_t_le2host(de->inode);
59}
60
61/** Set i-node number to directory entry.
62 *
63 * @param de Directory entry
64 * @param inode I-node number
65 *
66 */
67void ext4_directory_entry_ll_set_inode(ext4_directory_entry_ll_t *de,
68 uint32_t inode)
69{
70 de->inode = host2uint32_t_le(inode);
71}
72
73/** Get directory entry length.
74 *
75 * @param de Directory entry
76 *
77 * @return Entry length
78 *
79 */
80uint16_t ext4_directory_entry_ll_get_entry_length(ext4_directory_entry_ll_t *de)
81{
82 return uint16_t_le2host(de->entry_length);
83}
84
85/** Set directory entry length.
86 *
87 * @param de Directory entry
88 * @param length Entry length
89 *
90 */
91void ext4_directory_entry_ll_set_entry_length(ext4_directory_entry_ll_t *de,
92 uint16_t length)
93{
94 de->entry_length = host2uint16_t_le(length);
95}
96
97/** Get directory entry name length.
98 *
99 * @param sb Superblock
100 * @param de Directory entry
101 *
102 * @return Entry name length
103 *
104 */
105uint16_t ext4_directory_entry_ll_get_name_length(ext4_superblock_t *sb,
106 ext4_directory_entry_ll_t *de)
107{
108 if ((ext4_superblock_get_rev_level(sb) == 0) &&
109 (ext4_superblock_get_minor_rev_level(sb) < 5))
110 return ((uint16_t)de->name_length_high) << 8 |
111 ((uint16_t)de->name_length);
112
113 return de->name_length;
114
115}
116
117/** Set directory entry name length.
118 *
119 * @param sb Superblock
120 * @param de Directory entry
121 * @param length Entry name length
122 *
123 */
124void ext4_directory_entry_ll_set_name_length(ext4_superblock_t *sb,
125 ext4_directory_entry_ll_t *de, uint16_t length)
126{
127 de->name_length = (length << 8) >> 8;
128
129 if ((ext4_superblock_get_rev_level(sb) == 0) &&
130 (ext4_superblock_get_minor_rev_level(sb) < 5))
131 de->name_length_high = length >> 8;
132
133 /* Else do nothing */
134}
135
136/** Get i-node type of directory entry.
137 *
138 * @param sb Superblock
139 * @param de Directory entry
140 *
141 * @return I-node type (file, dir, etc.)
142 *
143 */
144uint8_t ext4_directory_entry_ll_get_inode_type(ext4_superblock_t *sb,
145 ext4_directory_entry_ll_t *de)
146{
147 if ((ext4_superblock_get_rev_level(sb) > 0) ||
148 (ext4_superblock_get_minor_rev_level(sb) >= 5))
149 return de->inode_type;
150
151 return EXT4_DIRECTORY_FILETYPE_UNKNOWN;
152}
153
154/** Set i-node type of directory entry.
155 *
156 * @param sb Superblock
157 * @param de Directory entry
158 * @param type I-node type (file, dir, etc.)
159 *
160 */
161void ext4_directory_entry_ll_set_inode_type(ext4_superblock_t *sb,
162 ext4_directory_entry_ll_t *de, uint8_t type)
163{
164 if ((ext4_superblock_get_rev_level(sb) > 0) ||
165 (ext4_superblock_get_minor_rev_level(sb) >= 5))
166 de->inode_type = type;
167
168 /* Else do nothing */
169}
170
171static errno_t ext4_directory_iterator_seek(ext4_directory_iterator_t *, aoff64_t);
172static errno_t ext4_directory_iterator_set(ext4_directory_iterator_t *, uint32_t);
173
174/** Initialize directory iterator.
175 *
176 * Set position to the first valid entry from the required position.
177 *
178 * @param it Pointer to iterator to be initialized
179 * @param inode_ref Directory i-node
180 * @param pos Position to start reading entries from
181 *
182 * @return Error code
183 *
184 */
185errno_t ext4_directory_iterator_init(ext4_directory_iterator_t *it,
186 ext4_inode_ref_t *inode_ref, aoff64_t pos)
187{
188 it->inode_ref = inode_ref;
189 it->current = NULL;
190 it->current_offset = 0;
191 it->current_block = NULL;
192
193 return ext4_directory_iterator_seek(it, pos);
194}
195
196/** Jump to the next valid entry
197 *
198 * @param it Initialized iterator
199 *
200 * @return Error code
201 *
202 */
203errno_t ext4_directory_iterator_next(ext4_directory_iterator_t *it)
204{
205 assert(it->current != NULL);
206
207 uint16_t skip = ext4_directory_entry_ll_get_entry_length(it->current);
208
209 return ext4_directory_iterator_seek(it, it->current_offset + skip);
210}
211
212/** Seek to next valid directory entry.
213 *
214 * Here can be jumped to the next data block.
215 *
216 * @param it Initialized iterator
217 * @param pos Position of the next entry
218 *
219 * @return Error code
220 *
221 */
222errno_t ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos)
223{
224 uint64_t size = ext4_inode_get_size(it->inode_ref->fs->superblock,
225 it->inode_ref->inode);
226
227 /* The iterator is not valid until we seek to the desired position */
228 it->current = NULL;
229
230 /* Are we at the end? */
231 if (pos >= size) {
232 if (it->current_block) {
233 errno_t rc = block_put(it->current_block);
234 it->current_block = NULL;
235
236 if (rc != EOK)
237 return rc;
238 }
239
240 it->current_offset = pos;
241 return EOK;
242 }
243
244 /* Compute next block address */
245 uint32_t block_size =
246 ext4_superblock_get_block_size(it->inode_ref->fs->superblock);
247 aoff64_t current_block_idx = it->current_offset / block_size;
248 aoff64_t next_block_idx = pos / block_size;
249
250 /*
251 * If we don't have a block or are moving accross block boundary,
252 * we need to get another block
253 */
254 if ((it->current_block == NULL) ||
255 (current_block_idx != next_block_idx)) {
256 if (it->current_block) {
257 errno_t rc = block_put(it->current_block);
258 it->current_block = NULL;
259
260 if (rc != EOK)
261 return rc;
262 }
263
264 uint32_t next_block_phys_idx;
265 errno_t rc = ext4_filesystem_get_inode_data_block_index(it->inode_ref,
266 next_block_idx, &next_block_phys_idx);
267 if (rc != EOK)
268 return rc;
269
270 rc = block_get(&it->current_block, it->inode_ref->fs->device,
271 next_block_phys_idx, BLOCK_FLAGS_NONE);
272 if (rc != EOK) {
273 it->current_block = NULL;
274 return rc;
275 }
276 }
277
278 it->current_offset = pos;
279
280 return ext4_directory_iterator_set(it, block_size);
281}
282
283/** Do some checks before returning iterator.
284 *
285 * @param it Iterator to be checked
286 * @param block_size Size of data block
287 *
288 * @return Error code
289 *
290 */
291static errno_t ext4_directory_iterator_set(ext4_directory_iterator_t *it,
292 uint32_t block_size)
293{
294 it->current = NULL;
295
296 uint32_t offset_in_block = it->current_offset % block_size;
297
298 /* Ensure proper alignment */
299 if ((offset_in_block % 4) != 0)
300 return EIO;
301
302 /* Ensure that the core of the entry does not overflow the block */
303 if (offset_in_block > block_size - 8)
304 return EIO;
305
306 ext4_directory_entry_ll_t *entry =
307 it->current_block->data + offset_in_block;
308
309 /* Ensure that the whole entry does not overflow the block */
310 uint16_t length = ext4_directory_entry_ll_get_entry_length(entry);
311 if (offset_in_block + length > block_size)
312 return EIO;
313
314 /* Ensure the name length is not too large */
315 if (ext4_directory_entry_ll_get_name_length(
316 it->inode_ref->fs->superblock, entry) > length - 8)
317 return EIO;
318
319 /* Everything OK - "publish" the entry */
320 it->current = entry;
321 return EOK;
322}
323
324/** Uninitialize directory iterator.
325 *
326 * Release all allocated structures.
327 *
328 * @param it Iterator to be finished
329 *
330 * @return Error code
331 *
332 */
333errno_t ext4_directory_iterator_fini(ext4_directory_iterator_t *it)
334{
335 it->inode_ref = NULL;
336 it->current = NULL;
337
338 if (it->current_block)
339 return block_put(it->current_block);
340
341 return EOK;
342}
343
344/** Write directory entry to concrete data block.
345 *
346 * @param sb Superblock
347 * @param entry Pointer to entry to be written
348 * @param entry_len Length of new entry
349 * @param child Child i-node to be written to new entry
350 * @param name Name of the new entry
351 * @param name_len Length of entry name
352 *
353 */
354void ext4_directory_write_entry(ext4_superblock_t *sb,
355 ext4_directory_entry_ll_t *entry, uint16_t entry_len,
356 ext4_inode_ref_t *child, const char *name, size_t name_len)
357{
358 /* Check maximum entry length */
359 uint32_t block_size = ext4_superblock_get_block_size(sb);
360 assert(entry_len <= block_size);
361
362 /* Set basic attributes */
363 ext4_directory_entry_ll_set_inode(entry, child->index);
364 ext4_directory_entry_ll_set_entry_length(entry, entry_len);
365 ext4_directory_entry_ll_set_name_length(sb, entry, name_len);
366
367 /* Write name */
368 memcpy(entry->name, name, name_len);
369
370 /* Set type of entry */
371 if (!ext4_superblock_has_feature_incompatible(sb, EXT4_FEATURE_INCOMPAT_FILETYPE))
372 ext4_directory_entry_ll_set_inode_type(sb, entry,
373 EXT4_DIRECTORY_FILETYPE_UNKNOWN);
374 else if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY))
375 ext4_directory_entry_ll_set_inode_type(sb, entry,
376 EXT4_DIRECTORY_FILETYPE_DIR);
377 else
378 ext4_directory_entry_ll_set_inode_type(sb, entry,
379 EXT4_DIRECTORY_FILETYPE_REG_FILE);
380}
381
382/** Add new entry to the directory.
383 *
384 * @param parent Directory i-node
385 * @param name Name of new entry
386 * @param child I-node to be referenced from new entry
387 *
388 * @return Error code
389 *
390 */
391errno_t ext4_directory_add_entry(ext4_inode_ref_t *parent, const char *name,
392 ext4_inode_ref_t *child)
393{
394 ext4_filesystem_t *fs = parent->fs;
395
396 /* Index adding (if allowed) */
397 if ((ext4_superblock_has_feature_compatible(fs->superblock,
398 EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
399 (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
400 errno_t rc = ext4_directory_dx_add_entry(parent, child, name);
401
402 /* Check if index is not corrupted */
403 if (rc != EXT4_ERR_BAD_DX_DIR)
404 return rc;
405
406 /* Needed to clear dir index flag if corrupted */
407 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
408 parent->dirty = true;
409 }
410
411 /* Linear algorithm */
412
413 uint32_t iblock = 0;
414 uint32_t fblock = 0;
415 uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
416 uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode);
417 uint32_t total_blocks = inode_size / block_size;
418
419 uint32_t name_len = str_size(name);
420
421 /* Find block, where is space for new entry and try to add */
422 bool success = false;
423 for (iblock = 0; iblock < total_blocks; ++iblock) {
424 errno_t rc = ext4_filesystem_get_inode_data_block_index(parent,
425 iblock, &fblock);
426 if (rc != EOK)
427 return rc;
428
429 block_t *block;
430 rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
431 if (rc != EOK)
432 return rc;
433
434 /* If adding is successful, function can finish */
435 rc = ext4_directory_try_insert_entry(fs->superblock, block,
436 child, name, name_len);
437 if (rc == EOK)
438 success = true;
439
440 rc = block_put(block);
441 if (rc != EOK)
442 return rc;
443
444 if (success)
445 return EOK;
446 }
447
448 /* No free block found - needed to allocate next data block */
449
450 iblock = 0;
451 fblock = 0;
452 errno_t rc = ext4_filesystem_append_inode_block(parent, &fblock, &iblock);
453 if (rc != EOK)
454 return rc;
455
456 /* Load new block */
457 block_t *new_block;
458 rc = block_get(&new_block, fs->device, fblock, BLOCK_FLAGS_NOREAD);
459 if (rc != EOK)
460 return rc;
461
462 /* Fill block with zeroes */
463 memset(new_block->data, 0, block_size);
464 ext4_directory_entry_ll_t *block_entry = new_block->data;
465 ext4_directory_write_entry(fs->superblock, block_entry, block_size,
466 child, name, name_len);
467
468 /* Save new block */
469 new_block->dirty = true;
470 rc = block_put(new_block);
471
472 return rc;
473}
474
475/** Find directory entry with passed name.
476 *
477 * @param result Result structure to be returned if entry found
478 * @param parent Directory i-node
479 * @param name Name of entry to be found
480 *
481 * @return Error code
482 *
483 */
484errno_t ext4_directory_find_entry(ext4_directory_search_result_t *result,
485 ext4_inode_ref_t *parent, const char *name)
486{
487 uint32_t name_len = str_size(name);
488
489 ext4_superblock_t *sb = parent->fs->superblock;
490
491 /* Index search */
492 if ((ext4_superblock_has_feature_compatible(sb,
493 EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
494 (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
495 errno_t rc = ext4_directory_dx_find_entry(result, parent, name_len,
496 name);
497
498 /* Check if index is not corrupted */
499 if (rc != EXT4_ERR_BAD_DX_DIR) {
500 if (rc != EOK)
501 return rc;
502
503 return EOK;
504 }
505
506 /* Needed to clear dir index flag if corrupted */
507 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
508 parent->dirty = true;
509 }
510
511 /* Linear algorithm */
512
513 uint32_t iblock;
514 uint32_t fblock;
515 uint32_t block_size = ext4_superblock_get_block_size(sb);
516 uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);
517 uint32_t total_blocks = inode_size / block_size;
518
519 /* Walk through all data blocks */
520 for (iblock = 0; iblock < total_blocks; ++iblock) {
521 /* Load block address */
522 errno_t rc = ext4_filesystem_get_inode_data_block_index(parent, iblock,
523 &fblock);
524 if (rc != EOK)
525 return rc;
526
527 /* Load data block */
528 block_t *block;
529 rc = block_get(&block, parent->fs->device, fblock, BLOCK_FLAGS_NONE);
530 if (rc != EOK)
531 return rc;
532
533 /* Try to find entry in block */
534 ext4_directory_entry_ll_t *res_entry;
535 rc = ext4_directory_find_in_block(block, sb, name_len, name,
536 &res_entry);
537 if (rc == EOK) {
538 result->block = block;
539 result->dentry = res_entry;
540 return EOK;
541 }
542
543 /* Entry not found - put block and continue to the next block */
544
545 rc = block_put(block);
546 if (rc != EOK)
547 return rc;
548 }
549
550 /* Entry was not found */
551
552 result->block = NULL;
553 result->dentry = NULL;
554
555 return ENOENT;
556}
557
558/** Remove directory entry.
559 *
560 * @param parent Directory i-node
561 * @param name Name of the entry to be removed
562 *
563 * @return Error code
564 *
565 */
566errno_t ext4_directory_remove_entry(ext4_inode_ref_t *parent, const char *name)
567{
568 /* Check if removing from directory */
569 if (!ext4_inode_is_type(parent->fs->superblock, parent->inode,
570 EXT4_INODE_MODE_DIRECTORY))
571 return ENOTDIR;
572
573 /* Try to find entry */
574 ext4_directory_search_result_t result;
575 errno_t rc = ext4_directory_find_entry(&result, parent, name);
576 if (rc != EOK)
577 return rc;
578
579 /* Invalidate entry */
580 ext4_directory_entry_ll_set_inode(result.dentry, 0);
581
582 /* Store entry position in block */
583 uint32_t pos = (void *) result.dentry - result.block->data;
584
585 /*
586 * If entry is not the first in block, it must be merged
587 * with previous entry
588 */
589 if (pos != 0) {
590 uint32_t offset = 0;
591
592 /* Start from the first entry in block */
593 ext4_directory_entry_ll_t *tmp_dentry = result.block->data;
594 uint16_t tmp_dentry_length =
595 ext4_directory_entry_ll_get_entry_length(tmp_dentry);
596
597 /* Find direct predecessor of removed entry */
598 while ((offset + tmp_dentry_length) < pos) {
599 offset +=
600 ext4_directory_entry_ll_get_entry_length(tmp_dentry);
601 tmp_dentry = result.block->data + offset;
602 tmp_dentry_length =
603 ext4_directory_entry_ll_get_entry_length(tmp_dentry);
604 }
605
606 assert(tmp_dentry_length + offset == pos);
607
608 /* Add to removed entry length to predecessor's length */
609 uint16_t del_entry_length =
610 ext4_directory_entry_ll_get_entry_length(result.dentry);
611 ext4_directory_entry_ll_set_entry_length(tmp_dentry,
612 tmp_dentry_length + del_entry_length);
613 }
614
615 result.block->dirty = true;
616
617 return ext4_directory_destroy_result(&result);
618}
619
620/** Try to insert entry to concrete data block.
621 *
622 * @param sb Superblock
623 * @param target_block Block to try to insert entry to
624 * @param child Child i-node to be inserted by new entry
625 * @param name Name of the new entry
626 * @param name_len Length of the new entry name
627 *
628 * @return Error code
629 *
630 */
631errno_t ext4_directory_try_insert_entry(ext4_superblock_t *sb,
632 block_t *target_block, ext4_inode_ref_t *child, const char *name,
633 uint32_t name_len)
634{
635 /* Compute required length entry and align it to 4 bytes */
636 uint32_t block_size = ext4_superblock_get_block_size(sb);
637 uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len;
638
639 if ((required_len % 4) != 0)
640 required_len += 4 - (required_len % 4);
641
642 /* Initialize pointers, stop means to upper bound */
643 ext4_directory_entry_ll_t *dentry = target_block->data;
644 ext4_directory_entry_ll_t *stop = target_block->data + block_size;
645
646 /*
647 * Walk through the block and check for invalid entries
648 * or entries with free space for new entry
649 */
650 while (dentry < stop) {
651 uint32_t inode = ext4_directory_entry_ll_get_inode(dentry);
652 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry);
653
654 /* If invalid and large enough entry, use it */
655 if ((inode == 0) && (rec_len >= required_len)) {
656 ext4_directory_write_entry(sb, dentry, rec_len, child,
657 name, name_len);
658 target_block->dirty = true;
659
660 return EOK;
661 }
662
663 /* Valid entry, try to split it */
664 if (inode != 0) {
665 uint16_t used_name_len =
666 ext4_directory_entry_ll_get_name_length(sb, dentry);
667
668 uint16_t used_space =
669 sizeof(ext4_fake_directory_entry_t) + used_name_len;
670
671 if ((used_name_len % 4) != 0)
672 used_space += 4 - (used_name_len % 4);
673
674 uint16_t free_space = rec_len - used_space;
675
676 /* There is free space for new entry */
677 if (free_space >= required_len) {
678 /* Cut tail of current entry */
679 ext4_directory_entry_ll_set_entry_length(dentry, used_space);
680 ext4_directory_entry_ll_t *new_entry =
681 (void *) dentry + used_space;
682 ext4_directory_write_entry(sb, new_entry,
683 free_space, child, name, name_len);
684
685 target_block->dirty = true;
686
687 return EOK;
688 }
689 }
690
691 /* Jump to the next entry */
692 dentry = (void *) dentry + rec_len;
693 }
694
695 /* No free space found for new entry */
696 return ENOSPC;
697}
698
699/** Try to find entry in block by name.
700 *
701 * @param block Block containing entries
702 * @param sb Superblock
703 * @param name_len Length of entry name
704 * @param name Name of entry to be found
705 * @param res_entry Output pointer to found entry, NULL if not found
706 *
707 * @return Error code
708 *
709 */
710errno_t ext4_directory_find_in_block(block_t *block, ext4_superblock_t *sb,
711 size_t name_len, const char *name, ext4_directory_entry_ll_t **res_entry)
712{
713 /* Start from the first entry in block */
714 ext4_directory_entry_ll_t *dentry =
715 (ext4_directory_entry_ll_t *) block->data;
716
717 /* Set upper bound for cycling */
718 uint8_t *addr_limit = block->data + ext4_superblock_get_block_size(sb);
719
720 /* Walk through the block and check entries */
721 while ((uint8_t *) dentry < addr_limit) {
722 /* Termination condition */
723 if ((uint8_t *) dentry + name_len > addr_limit)
724 break;
725
726 /* Valid entry - check it */
727 if (dentry->inode != 0) {
728 /* For more effectivity compare firstly only lengths */
729 if (ext4_directory_entry_ll_get_name_length(sb, dentry) ==
730 name_len) {
731 /* Compare names */
732 if (memcmp((uint8_t *) name, dentry->name, name_len) == 0) {
733 *res_entry = dentry;
734 return EOK;
735 }
736 }
737 }
738
739 uint16_t dentry_len =
740 ext4_directory_entry_ll_get_entry_length(dentry);
741
742 /* Corrupted entry */
743 if (dentry_len == 0)
744 return EINVAL;
745
746 /* Jump to next entry */
747 dentry = (ext4_directory_entry_ll_t *) ((uint8_t *) dentry + dentry_len);
748 }
749
750 /* Entry not found */
751 return ENOENT;
752}
753
754/** Simple function to release allocated data from result.
755 *
756 * @param result Search result to destroy
757 *
758 * @return Error code
759 *
760 */
761errno_t ext4_directory_destroy_result(ext4_directory_search_result_t *result)
762{
763 if (result->block)
764 return block_put(result->block);
765
766 return EOK;
767}
768
769/**
770 * @}
771 */
Note: See TracBrowser for help on using the repository browser.