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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 19.9 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_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY))
372 ext4_directory_entry_ll_set_inode_type(sb, entry,
373 EXT4_DIRECTORY_FILETYPE_DIR);
374 else
375 ext4_directory_entry_ll_set_inode_type(sb, entry,
376 EXT4_DIRECTORY_FILETYPE_REG_FILE);
377}
378
379/** Add new entry to the directory.
380 *
381 * @param parent Directory i-node
382 * @param name Name of new entry
383 * @param child I-node to be referenced from new entry
384 *
385 * @return Error code
386 *
387 */
388errno_t ext4_directory_add_entry(ext4_inode_ref_t *parent, const char *name,
389 ext4_inode_ref_t *child)
390{
391 ext4_filesystem_t *fs = parent->fs;
392
393 /* Index adding (if allowed) */
394 if ((ext4_superblock_has_feature_compatible(fs->superblock,
395 EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
396 (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
397 errno_t rc = ext4_directory_dx_add_entry(parent, child, name);
398
399 /* Check if index is not corrupted */
400 if (rc != EXT4_ERR_BAD_DX_DIR)
401 return rc;
402
403 /* Needed to clear dir index flag if corrupted */
404 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
405 parent->dirty = true;
406 }
407
408 /* Linear algorithm */
409
410 uint32_t iblock = 0;
411 uint32_t fblock = 0;
412 uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
413 uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode);
414 uint32_t total_blocks = inode_size / block_size;
415
416 uint32_t name_len = str_size(name);
417
418 /* Find block, where is space for new entry and try to add */
419 bool success = false;
420 for (iblock = 0; iblock < total_blocks; ++iblock) {
421 errno_t rc = ext4_filesystem_get_inode_data_block_index(parent,
422 iblock, &fblock);
423 if (rc != EOK)
424 return rc;
425
426 block_t *block;
427 rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
428 if (rc != EOK)
429 return rc;
430
431 /* If adding is successful, function can finish */
432 rc = ext4_directory_try_insert_entry(fs->superblock, block,
433 child, name, name_len);
434 if (rc == EOK)
435 success = true;
436
437 rc = block_put(block);
438 if (rc != EOK)
439 return rc;
440
441 if (success)
442 return EOK;
443 }
444
445 /* No free block found - needed to allocate next data block */
446
447 iblock = 0;
448 fblock = 0;
449 errno_t rc = ext4_filesystem_append_inode_block(parent, &fblock, &iblock);
450 if (rc != EOK)
451 return rc;
452
453 /* Load new block */
454 block_t *new_block;
455 rc = block_get(&new_block, fs->device, fblock, BLOCK_FLAGS_NOREAD);
456 if (rc != EOK)
457 return rc;
458
459 /* Fill block with zeroes */
460 memset(new_block->data, 0, block_size);
461 ext4_directory_entry_ll_t *block_entry = new_block->data;
462 ext4_directory_write_entry(fs->superblock, block_entry, block_size,
463 child, name, name_len);
464
465 /* Save new block */
466 new_block->dirty = true;
467 rc = block_put(new_block);
468
469 return rc;
470}
471
472/** Find directory entry with passed name.
473 *
474 * @param result Result structure to be returned if entry found
475 * @param parent Directory i-node
476 * @param name Name of entry to be found
477 *
478 * @return Error code
479 *
480 */
481errno_t ext4_directory_find_entry(ext4_directory_search_result_t *result,
482 ext4_inode_ref_t *parent, const char *name)
483{
484 uint32_t name_len = str_size(name);
485
486 ext4_superblock_t *sb = parent->fs->superblock;
487
488 /* Index search */
489 if ((ext4_superblock_has_feature_compatible(sb,
490 EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
491 (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
492 errno_t rc = ext4_directory_dx_find_entry(result, parent, name_len,
493 name);
494
495 /* Check if index is not corrupted */
496 if (rc != EXT4_ERR_BAD_DX_DIR) {
497 if (rc != EOK)
498 return rc;
499
500 return EOK;
501 }
502
503 /* Needed to clear dir index flag if corrupted */
504 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
505 parent->dirty = true;
506 }
507
508 /* Linear algorithm */
509
510 uint32_t iblock;
511 uint32_t fblock;
512 uint32_t block_size = ext4_superblock_get_block_size(sb);
513 uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);
514 uint32_t total_blocks = inode_size / block_size;
515
516 /* Walk through all data blocks */
517 for (iblock = 0; iblock < total_blocks; ++iblock) {
518 /* Load block address */
519 errno_t rc = ext4_filesystem_get_inode_data_block_index(parent, iblock,
520 &fblock);
521 if (rc != EOK)
522 return rc;
523
524 /* Load data block */
525 block_t *block;
526 rc = block_get(&block, parent->fs->device, fblock, BLOCK_FLAGS_NONE);
527 if (rc != EOK)
528 return rc;
529
530 /* Try to find entry in block */
531 ext4_directory_entry_ll_t *res_entry;
532 rc = ext4_directory_find_in_block(block, sb, name_len, name,
533 &res_entry);
534 if (rc == EOK) {
535 result->block = block;
536 result->dentry = res_entry;
537 return EOK;
538 }
539
540 /* Entry not found - put block and continue to the next block */
541
542 rc = block_put(block);
543 if (rc != EOK)
544 return rc;
545 }
546
547 /* Entry was not found */
548
549 result->block = NULL;
550 result->dentry = NULL;
551
552 return ENOENT;
553}
554
555/** Remove directory entry.
556 *
557 * @param parent Directory i-node
558 * @param name Name of the entry to be removed
559 *
560 * @return Error code
561 *
562 */
563errno_t ext4_directory_remove_entry(ext4_inode_ref_t *parent, const char *name)
564{
565 /* Check if removing from directory */
566 if (!ext4_inode_is_type(parent->fs->superblock, parent->inode,
567 EXT4_INODE_MODE_DIRECTORY))
568 return ENOTDIR;
569
570 /* Try to find entry */
571 ext4_directory_search_result_t result;
572 errno_t rc = ext4_directory_find_entry(&result, parent, name);
573 if (rc != EOK)
574 return rc;
575
576 /* Invalidate entry */
577 ext4_directory_entry_ll_set_inode(result.dentry, 0);
578
579 /* Store entry position in block */
580 uint32_t pos = (void *) result.dentry - result.block->data;
581
582 /*
583 * If entry is not the first in block, it must be merged
584 * with previous entry
585 */
586 if (pos != 0) {
587 uint32_t offset = 0;
588
589 /* Start from the first entry in block */
590 ext4_directory_entry_ll_t *tmp_dentry = result.block->data;
591 uint16_t tmp_dentry_length =
592 ext4_directory_entry_ll_get_entry_length(tmp_dentry);
593
594 /* Find direct predecessor of removed entry */
595 while ((offset + tmp_dentry_length) < pos) {
596 offset +=
597 ext4_directory_entry_ll_get_entry_length(tmp_dentry);
598 tmp_dentry = result.block->data + offset;
599 tmp_dentry_length =
600 ext4_directory_entry_ll_get_entry_length(tmp_dentry);
601 }
602
603 assert(tmp_dentry_length + offset == pos);
604
605 /* Add to removed entry length to predecessor's length */
606 uint16_t del_entry_length =
607 ext4_directory_entry_ll_get_entry_length(result.dentry);
608 ext4_directory_entry_ll_set_entry_length(tmp_dentry,
609 tmp_dentry_length + del_entry_length);
610 }
611
612 result.block->dirty = true;
613
614 return ext4_directory_destroy_result(&result);
615}
616
617/** Try to insert entry to concrete data block.
618 *
619 * @param sb Superblock
620 * @param target_block Block to try to insert entry to
621 * @param child Child i-node to be inserted by new entry
622 * @param name Name of the new entry
623 * @param name_len Length of the new entry name
624 *
625 * @return Error code
626 *
627 */
628errno_t ext4_directory_try_insert_entry(ext4_superblock_t *sb,
629 block_t *target_block, ext4_inode_ref_t *child, const char *name,
630 uint32_t name_len)
631{
632 /* Compute required length entry and align it to 4 bytes */
633 uint32_t block_size = ext4_superblock_get_block_size(sb);
634 uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len;
635
636 if ((required_len % 4) != 0)
637 required_len += 4 - (required_len % 4);
638
639 /* Initialize pointers, stop means to upper bound */
640 ext4_directory_entry_ll_t *dentry = target_block->data;
641 ext4_directory_entry_ll_t *stop = target_block->data + block_size;
642
643 /*
644 * Walk through the block and check for invalid entries
645 * or entries with free space for new entry
646 */
647 while (dentry < stop) {
648 uint32_t inode = ext4_directory_entry_ll_get_inode(dentry);
649 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry);
650
651 /* If invalid and large enough entry, use it */
652 if ((inode == 0) && (rec_len >= required_len)) {
653 ext4_directory_write_entry(sb, dentry, rec_len, child,
654 name, name_len);
655 target_block->dirty = true;
656
657 return EOK;
658 }
659
660 /* Valid entry, try to split it */
661 if (inode != 0) {
662 uint16_t used_name_len =
663 ext4_directory_entry_ll_get_name_length(sb, dentry);
664
665 uint16_t used_space =
666 sizeof(ext4_fake_directory_entry_t) + used_name_len;
667
668 if ((used_name_len % 4) != 0)
669 used_space += 4 - (used_name_len % 4);
670
671 uint16_t free_space = rec_len - used_space;
672
673 /* There is free space for new entry */
674 if (free_space >= required_len) {
675 /* Cut tail of current entry */
676 ext4_directory_entry_ll_set_entry_length(dentry, used_space);
677 ext4_directory_entry_ll_t *new_entry =
678 (void *) dentry + used_space;
679 ext4_directory_write_entry(sb, new_entry,
680 free_space, child, name, name_len);
681
682 target_block->dirty = true;
683
684 return EOK;
685 }
686 }
687
688 /* Jump to the next entry */
689 dentry = (void *) dentry + rec_len;
690 }
691
692 /* No free space found for new entry */
693 return ENOSPC;
694}
695
696/** Try to find entry in block by name.
697 *
698 * @param block Block containing entries
699 * @param sb Superblock
700 * @param name_len Length of entry name
701 * @param name Name of entry to be found
702 * @param res_entry Output pointer to found entry, NULL if not found
703 *
704 * @return Error code
705 *
706 */
707errno_t ext4_directory_find_in_block(block_t *block, ext4_superblock_t *sb,
708 size_t name_len, const char *name, ext4_directory_entry_ll_t **res_entry)
709{
710 /* Start from the first entry in block */
711 ext4_directory_entry_ll_t *dentry =
712 (ext4_directory_entry_ll_t *) block->data;
713
714 /* Set upper bound for cycling */
715 uint8_t *addr_limit = block->data + ext4_superblock_get_block_size(sb);
716
717 /* Walk through the block and check entries */
718 while ((uint8_t *) dentry < addr_limit) {
719 /* Termination condition */
720 if ((uint8_t *) dentry + name_len > addr_limit)
721 break;
722
723 /* Valid entry - check it */
724 if (dentry->inode != 0) {
725 /* For more effectivity compare firstly only lengths */
726 if (ext4_directory_entry_ll_get_name_length(sb, dentry) ==
727 name_len) {
728 /* Compare names */
729 if (memcmp((uint8_t *) name, dentry->name, name_len) == 0) {
730 *res_entry = dentry;
731 return EOK;
732 }
733 }
734 }
735
736 uint16_t dentry_len =
737 ext4_directory_entry_ll_get_entry_length(dentry);
738
739 /* Corrupted entry */
740 if (dentry_len == 0)
741 return EINVAL;
742
743 /* Jump to next entry */
744 dentry = (ext4_directory_entry_ll_t *) ((uint8_t *) dentry + dentry_len);
745 }
746
747 /* Entry not found */
748 return ENOENT;
749}
750
751/** Simple function to release allocated data from result.
752 *
753 * @param result Search result to destroy
754 *
755 * @return Error code
756 *
757 */
758errno_t ext4_directory_destroy_result(ext4_directory_search_result_t *result)
759{
760 if (result->block)
761 return block_put(result->block);
762
763 return EOK;
764}
765
766/**
767 * @}
768 */
Note: See TracBrowser for help on using the repository browser.