Pedanitic warning check fixes. Pointer arithmetic, anonymus unions etc
[lwext4.git] / lwext4 / ext4_dir.c
1 /*\r
2  * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
3  *\r
4  *\r
5  * HelenOS:\r
6  * Copyright (c) 2012 Martin Sucha\r
7  * Copyright (c) 2012 Frantisek Princ\r
8  * All rights reserved.\r
9  *\r
10  * Redistribution and use in source and binary forms, with or without\r
11  * modification, are permitted provided that the following conditions\r
12  * are met:\r
13  *\r
14  * - Redistributions of source code must retain the above copyright\r
15  *   notice, this list of conditions and the following disclaimer.\r
16  * - Redistributions in binary form must reproduce the above copyright\r
17  *   notice, this list of conditions and the following disclaimer in the\r
18  *   documentation and/or other materials provided with the distribution.\r
19  * - The name of the author may not be used to endorse or promote products\r
20  *   derived from this software without specific prior written permission.\r
21  *\r
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
32  */\r
33 \r
34 /** @addtogroup lwext4\r
35  * @{\r
36  */\r
37 /**\r
38  * @file  ext4_dir.h\r
39  * @brief Directory handle procedures.\r
40  */\r
41 \r
42 #include <ext4_config.h>\r
43 #include <ext4_dir.h>\r
44 #include <ext4_dir_idx.h>\r
45 #include <ext4_inode.h>\r
46 #include <ext4_fs.h>\r
47 \r
48 #include <string.h>\r
49 \r
50 uint32_t ext4_dir_entry_ll_get_inode(struct ext4_directory_entry_ll *de)\r
51 {\r
52     return to_le32(de->inode);\r
53 }\r
54 \r
55 void ext4_dir_entry_ll_set_inode(struct ext4_directory_entry_ll *de,\r
56     uint32_t inode)\r
57 {\r
58     de->inode = to_le32(inode);\r
59 }\r
60 \r
61 \r
62 uint16_t ext4_dir_entry_ll_get_entry_length(struct ext4_directory_entry_ll *de)\r
63 {\r
64     return to_le16(de->entry_length);\r
65 }\r
66 \r
67 void ext4_dir_entry_ll_set_entry_length(struct ext4_directory_entry_ll *de,\r
68     uint16_t len)\r
69 {\r
70     de->entry_length = to_le16(len);\r
71 }\r
72 \r
73 \r
74 uint16_t ext4_dir_entry_ll_get_name_length(struct ext4_sblock *sb,\r
75     struct ext4_directory_entry_ll *de)\r
76 {\r
77     uint16_t v = de->name_length;\r
78 \r
79     if ((ext4_get32(sb, rev_level) == 0) &&\r
80             (ext4_get32(sb, minor_rev_level) < 5))\r
81         v |= ((uint16_t)de->in.name_length_high) << 8;\r
82 \r
83     return v;\r
84 }\r
85 void ext4_dir_entry_ll_set_name_length(struct ext4_sblock *sb,\r
86     struct ext4_directory_entry_ll *de, uint16_t len)\r
87 {\r
88     de->name_length = (len << 8) >> 8;\r
89 \r
90     if ((ext4_get32(sb, rev_level) == 0) &&\r
91             (ext4_get32(sb, minor_rev_level) < 5))\r
92         de->in.name_length_high = len >> 8;\r
93 }\r
94 \r
95 \r
96 \r
97 uint8_t ext4_dir_entry_ll_get_inode_type(struct ext4_sblock *sb,\r
98     struct ext4_directory_entry_ll *de)\r
99 {\r
100     if ((ext4_get32(sb, rev_level) > 0) ||\r
101             (ext4_get32(sb, minor_rev_level) >= 5))\r
102         return de->in.inode_type;\r
103 \r
104     return EXT4_DIRECTORY_FILETYPE_UNKNOWN;\r
105 }\r
106 \r
107 \r
108 void ext4_dir_entry_ll_set_inode_type(struct ext4_sblock *sb,\r
109     struct ext4_directory_entry_ll *de, uint8_t type)\r
110 {\r
111     if ((ext4_get32(sb, rev_level) > 0) ||\r
112             (ext4_get32(sb, minor_rev_level) >= 5))\r
113         de->in.inode_type = type;\r
114 }\r
115 \r
116 /****************************************************************************/\r
117 \r
118 /**@brief Do some checks before returning iterator.\r
119  * @param it Iterator to be checked\r
120  * @param block_size Size of data block\r
121  * @return Error code\r
122  */\r
123 static int ext4_dir_iterator_set(struct ext4_directory_iterator *it,\r
124     uint32_t block_size)\r
125 {\r
126     it->current = NULL;\r
127 \r
128     uint32_t offset_in_block = it->current_offset % block_size;\r
129 \r
130     /* Ensure proper alignment */\r
131     if ((offset_in_block % 4) != 0)\r
132         return EIO;\r
133 \r
134     /* Ensure that the core of the entry does not overflow the block */\r
135     if (offset_in_block > block_size - 8)\r
136         return EIO;\r
137 \r
138     struct ext4_directory_entry_ll *entry =\r
139             (void *)(it->current_block.data + offset_in_block);\r
140 \r
141     /* Ensure that the whole entry does not overflow the block */\r
142     uint16_t length = ext4_dir_entry_ll_get_entry_length(entry);\r
143     if (offset_in_block + length > block_size)\r
144         return EIO;\r
145 \r
146     /* Ensure the name length is not too large */\r
147     if (ext4_dir_entry_ll_get_name_length(\r
148             &it->inode_ref->fs->sb, entry) > length-8)\r
149         return EIO;\r
150 \r
151     /* Everything OK - "publish" the entry */\r
152     it->current = entry;\r
153     return EOK;\r
154 }\r
155 \r
156 /**@brief Seek to next valid directory entry.\r
157  *        Here can be jumped to the next data block.\r
158  * @param it  Initialized iterator\r
159  * @param pos Position of the next entry\r
160  * @return Error code\r
161  */\r
162 static int ext4_dir_iterator_seek(struct ext4_directory_iterator *it,\r
163     uint64_t pos)\r
164 {\r
165     uint64_t size = ext4_inode_get_size(&it->inode_ref->fs->sb,\r
166             it->inode_ref->inode);\r
167 \r
168     /* The iterator is not valid until we seek to the desired position */\r
169     it->current = NULL;\r
170 \r
171     /* Are we at the end? */\r
172     if (pos >= size) {\r
173         if (it->current_block.lb_id) {\r
174 \r
175             int rc = ext4_block_set(it->inode_ref->fs->bdev,\r
176                     &it->current_block);\r
177             it->current_block.lb_id = 0;\r
178 \r
179             if (rc != EOK)\r
180                 return rc;\r
181         }\r
182 \r
183         it->current_offset = pos;\r
184         return EOK;\r
185     }\r
186 \r
187     /* Compute next block address */\r
188     uint32_t block_size =\r
189             ext4_sb_get_block_size(&it->inode_ref->fs->sb);\r
190     uint64_t current_block_idx = it->current_offset / block_size;\r
191     uint64_t next_block_idx = pos / block_size;\r
192 \r
193     /*\r
194      * If we don't have a block or are moving accross block boundary,\r
195      * we need to get another block\r
196      */\r
197     if ((it->current_block.lb_id == 0) ||\r
198             (current_block_idx != next_block_idx)) {\r
199         if (it->current_block.lb_id) {\r
200             int rc = ext4_block_set(it->inode_ref->fs->bdev, &it->current_block);\r
201             it->current_block.lb_id = 0;\r
202 \r
203             if (rc != EOK)\r
204                 return rc;\r
205         }\r
206 \r
207         uint32_t next_block_phys_idx;\r
208         int rc = ext4_fs_get_inode_data_block_index(it->inode_ref,\r
209                 next_block_idx, &next_block_phys_idx);\r
210         if (rc != EOK)\r
211             return rc;\r
212 \r
213 \r
214         rc = ext4_block_get(it->inode_ref->fs->bdev, &it->current_block,\r
215                 next_block_phys_idx);\r
216         if (rc != EOK) {\r
217             it->current_block.lb_id = 0;\r
218             return rc;\r
219         }\r
220     }\r
221 \r
222     it->current_offset = pos;\r
223 \r
224     return ext4_dir_iterator_set(it, block_size);\r
225 }\r
226 \r
227 \r
228 int ext4_dir_iterator_init(struct ext4_directory_iterator *it,\r
229     struct ext4_inode_ref *inode_ref, uint64_t pos)\r
230 {\r
231     it->inode_ref = inode_ref;\r
232     it->current = 0;\r
233     it->current_offset = 0;\r
234     it->current_block.lb_id = 0;\r
235 \r
236     return ext4_dir_iterator_seek(it, pos);\r
237 }\r
238 \r
239 int ext4_dir_iterator_next(struct ext4_directory_iterator *it)\r
240 {\r
241     int r = EOK;\r
242     uint16_t skip;\r
243 \r
244     while(r == EOK){\r
245         skip = ext4_dir_entry_ll_get_entry_length(it->current);\r
246         r = ext4_dir_iterator_seek(it, it->current_offset + skip);\r
247 \r
248         if(!it->current)\r
249             break;\r
250         /*Skip NULL referenced entry*/\r
251         if(it->current->inode != 0)\r
252             break;\r
253     }\r
254 \r
255     return r;\r
256 }\r
257 \r
258 int ext4_dir_iterator_fini(struct ext4_directory_iterator *it)\r
259 {\r
260     it->current = 0;\r
261 \r
262     if (it->current_block.lb_id)\r
263         return ext4_block_set(it->inode_ref->fs->bdev, &it->current_block);\r
264 \r
265     return EOK;\r
266 }\r
267 \r
268 void ext4_dir_write_entry(struct ext4_sblock *sb,\r
269     struct ext4_directory_entry_ll *entry, uint16_t entry_len,\r
270     struct ext4_inode_ref *child,  const char *name, size_t name_len)\r
271 {\r
272     /* Check maximum entry length */\r
273     uint32_t block_size = ext4_sb_get_block_size(sb);\r
274     ext4_assert(entry_len <= block_size);\r
275 \r
276     /* Set basic attributes */\r
277     ext4_dir_entry_ll_set_inode(entry, child->index);\r
278     ext4_dir_entry_ll_set_entry_length(entry, entry_len);\r
279     ext4_dir_entry_ll_set_name_length(sb, entry, name_len);\r
280 \r
281     /* Write name */\r
282     memcpy(entry->name, name, name_len);\r
283 \r
284     /* Set type of entry */\r
285     if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY))\r
286         ext4_dir_entry_ll_set_inode_type(sb, entry,\r
287                 EXT4_DIRECTORY_FILETYPE_DIR);\r
288     else\r
289         ext4_dir_entry_ll_set_inode_type(sb, entry,\r
290                 EXT4_DIRECTORY_FILETYPE_REG_FILE);\r
291 }\r
292 \r
293 int ext4_dir_add_entry(struct ext4_inode_ref *parent, const char *name,\r
294     uint32_t name_len, struct ext4_inode_ref *child)\r
295 {\r
296     struct ext4_fs *fs = parent->fs;\r
297 \r
298 #if CONFIG_DIR_INDEX_ENABLE\r
299     /* Index adding (if allowed) */\r
300     if ((ext4_sb_check_feature_compatible(&fs->sb,\r
301             EXT4_FEATURE_COMPAT_DIR_INDEX)) &&\r
302             (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {\r
303         int rc = ext4_dir_dx_add_entry(parent, child, name);\r
304 \r
305         /* Check if index is not corrupted */\r
306         if (rc != EXT4_ERR_BAD_DX_DIR) {\r
307             if (rc != EOK)\r
308                 return rc;\r
309 \r
310             return EOK;\r
311         }\r
312 \r
313         /* Needed to clear dir index flag if corrupted */\r
314         ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);\r
315         parent->dirty = true;\r
316     }\r
317 #endif\r
318 \r
319     /* Linear algorithm */\r
320     uint32_t iblock = 0;\r
321     uint32_t fblock = 0;\r
322     uint32_t block_size = ext4_sb_get_block_size(&fs->sb);\r
323     uint32_t inode_size = ext4_inode_get_size(&fs->sb, parent->inode);\r
324     uint32_t total_blocks = inode_size / block_size;\r
325 \r
326 \r
327     /* Find block, where is space for new entry and try to add */\r
328     bool success = false;\r
329     for (iblock = 0; iblock < total_blocks; ++iblock) {\r
330         int rc = ext4_fs_get_inode_data_block_index(parent,\r
331                 iblock, &fblock);\r
332         if (rc != EOK)\r
333             return rc;\r
334 \r
335 \r
336         struct ext4_block block;\r
337         rc = ext4_block_get(fs->bdev, &block, fblock);\r
338         if (rc != EOK)\r
339             return rc;\r
340 \r
341         /* If adding is successful, function can finish */\r
342         rc = ext4_dir_try_insert_entry(&fs->sb, &block,\r
343                 child, name, name_len);\r
344         if (rc == EOK)\r
345             success = true;\r
346 \r
347         rc = ext4_block_set(fs->bdev, &block);\r
348         if (rc != EOK)\r
349             return rc;\r
350 \r
351         if (success)\r
352             return EOK;\r
353     }\r
354 \r
355     /* No free block found - needed to allocate next data block */\r
356 \r
357     iblock = 0;\r
358     fblock = 0;\r
359     int rc = ext4_fs_append_inode_block(parent, &fblock, &iblock);\r
360     if (rc != EOK)\r
361         return rc;\r
362 \r
363     /* Load new block */\r
364     struct ext4_block new_block;\r
365 \r
366     rc = ext4_block_get(fs->bdev, &new_block, fblock);\r
367     if (rc != EOK)\r
368         return rc;\r
369 \r
370     /* Fill block with zeroes */\r
371     memset(new_block.data, 0, block_size);\r
372     struct ext4_directory_entry_ll *block_entry = (void *)new_block.data;\r
373     ext4_dir_write_entry(&fs->sb, block_entry, block_size,\r
374         child, name, name_len);\r
375 \r
376     /* Save new block */\r
377     new_block.dirty = true;\r
378     rc = ext4_block_set(fs->bdev, &new_block);\r
379 \r
380     return rc;\r
381 }\r
382 \r
383 int ext4_dir_find_entry(struct ext4_directory_search_result *result,\r
384     struct ext4_inode_ref *parent, const char *name, uint32_t name_len)\r
385 {\r
386     struct ext4_sblock *sb = &parent->fs->sb;\r
387 \r
388 \r
389 #if CONFIG_DIR_INDEX_ENABLE\r
390     /* Index search */\r
391     if ((ext4_sb_check_feature_compatible(sb,\r
392             EXT4_FEATURE_COMPAT_DIR_INDEX)) &&\r
393             (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {\r
394         int rc = ext4_dir_dx_find_entry(result, parent, name_len,\r
395                 name);\r
396 \r
397         /* Check if index is not corrupted */\r
398         if (rc != EXT4_ERR_BAD_DX_DIR) {\r
399             if (rc != EOK)\r
400                 return rc;\r
401 \r
402             return EOK;\r
403         }\r
404 \r
405         /* Needed to clear dir index flag if corrupted */\r
406         ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);\r
407         parent->dirty = true;\r
408     }\r
409 #endif\r
410 \r
411     /* Linear algorithm */\r
412 \r
413     uint32_t iblock;\r
414     uint32_t fblock;\r
415     uint32_t block_size = ext4_sb_get_block_size(sb);\r
416     uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);\r
417     uint32_t total_blocks = inode_size / block_size;\r
418 \r
419     /* Walk through all data blocks */\r
420     for (iblock = 0; iblock < total_blocks; ++iblock) {\r
421         /* Load block address */\r
422         int rc = ext4_fs_get_inode_data_block_index(parent, iblock,\r
423                 &fblock);\r
424         if (rc != EOK)\r
425             return rc;\r
426 \r
427         /* Load data block */\r
428         struct ext4_block block;\r
429         rc = ext4_block_get( parent->fs->bdev, &block, fblock);\r
430         if (rc != EOK)\r
431             return rc;\r
432 \r
433         /* Try to find entry in block */\r
434         struct ext4_directory_entry_ll *res_entry;\r
435         rc = ext4_dir_find_in_block(&block, sb, name_len, name,\r
436                 &res_entry);\r
437         if (rc == EOK) {\r
438             result->block = block;\r
439             result->dentry = res_entry;\r
440             return EOK;\r
441         }\r
442 \r
443         /* Entry not found - put block and continue to the next block */\r
444 \r
445         rc = ext4_block_set(parent->fs->bdev, &block);\r
446         if (rc != EOK)\r
447             return rc;\r
448     }\r
449 \r
450     /* Entry was not found */\r
451 \r
452     result->block.lb_id = 0;\r
453     result->dentry = NULL;\r
454 \r
455     return ENOENT;\r
456 }\r
457 \r
458 int ext4_dir_remove_entry(struct ext4_inode_ref *parent, const char *name,\r
459     uint32_t name_len)\r
460 {\r
461     /* Check if removing from directory */\r
462     if (!ext4_inode_is_type(&parent->fs->sb, parent->inode,\r
463             EXT4_INODE_MODE_DIRECTORY))\r
464         return ENOTDIR;\r
465 \r
466     /* Try to find entry */\r
467     struct ext4_directory_search_result result;\r
468     int rc = ext4_dir_find_entry(&result, parent, name, name_len);\r
469     if (rc != EOK)\r
470         return rc;\r
471 \r
472     /* Invalidate entry */\r
473     ext4_dir_entry_ll_set_inode(result.dentry, 0);\r
474 \r
475     /* Store entry position in block */\r
476     uint32_t pos = (uint8_t *) result.dentry - result.block.data;\r
477 \r
478     /*\r
479      * If entry is not the first in block, it must be merged\r
480      * with previous entry\r
481      */\r
482     if (pos != 0) {\r
483         uint32_t offset = 0;\r
484 \r
485         /* Start from the first entry in block */\r
486         struct ext4_directory_entry_ll *tmp_dentry = (void *)result.block.data;\r
487         uint16_t tmp_dentry_length =\r
488                 ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
489 \r
490         /* Find direct predecessor of removed entry */\r
491         while ((offset + tmp_dentry_length) < pos) {\r
492             offset +=\r
493                     ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
494             tmp_dentry = (void *)(result.block.data + offset);\r
495             tmp_dentry_length =\r
496                     ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
497         }\r
498 \r
499         ext4_assert(tmp_dentry_length + offset == pos);\r
500 \r
501         /* Add to removed entry length to predecessor's length */\r
502         uint16_t del_entry_length =\r
503                 ext4_dir_entry_ll_get_entry_length(result.dentry);\r
504         ext4_dir_entry_ll_set_entry_length(tmp_dentry,\r
505             tmp_dentry_length + del_entry_length);\r
506     }\r
507 \r
508     result.block.dirty = true;\r
509 \r
510     return ext4_dir_destroy_result(parent, &result);\r
511 }\r
512 \r
513 int ext4_dir_try_insert_entry(struct ext4_sblock *sb,\r
514     struct ext4_block *target_block, struct ext4_inode_ref *child,\r
515     const char *name, uint32_t name_len)\r
516 {\r
517     /* Compute required length entry and align it to 4 bytes */\r
518     uint32_t block_size = ext4_sb_get_block_size(sb);\r
519     uint16_t required_len = sizeof(struct ext4_fake_directory_entry) + name_len;\r
520 \r
521     if ((required_len % 4) != 0)\r
522         required_len += 4 - (required_len % 4);\r
523 \r
524     /* Initialize pointers, stop means to upper bound */\r
525     struct ext4_directory_entry_ll *dentry  = (void *)target_block->data;\r
526     struct ext4_directory_entry_ll *stop =\r
527             (void *)(target_block->data + block_size);\r
528 \r
529     /*\r
530      * Walk through the block and check for invalid entries\r
531      * or entries with free space for new entry\r
532      */\r
533     while (dentry < stop) {\r
534         uint32_t inode = ext4_dir_entry_ll_get_inode(dentry);\r
535         uint16_t rec_len = ext4_dir_entry_ll_get_entry_length(dentry);\r
536 \r
537         /* If invalid and large enough entry, use it */\r
538         if ((inode == 0) && (rec_len >= required_len)) {\r
539             ext4_dir_write_entry(sb, dentry, rec_len, child,\r
540                     name, name_len);\r
541             target_block->dirty = true;\r
542 \r
543             return EOK;\r
544         }\r
545 \r
546         /* Valid entry, try to split it */\r
547         if (inode != 0) {\r
548             uint16_t used_name_len =\r
549                     ext4_dir_entry_ll_get_name_length(sb, dentry);\r
550 \r
551             uint16_t used_space =\r
552                     sizeof(struct ext4_fake_directory_entry) + used_name_len;\r
553 \r
554             if ((used_name_len % 4) != 0)\r
555                 used_space += 4 - (used_name_len % 4);\r
556 \r
557             uint16_t free_space = rec_len - used_space;\r
558 \r
559             /* There is free space for new entry */\r
560             if (free_space >= required_len) {\r
561                 /* Cut tail of current entry */\r
562                 ext4_dir_entry_ll_set_entry_length(dentry, used_space);\r
563                 struct ext4_directory_entry_ll *new_entry =\r
564                         (void *) ((uint8_t *)dentry + used_space);\r
565                 ext4_dir_write_entry(sb, new_entry,\r
566                     free_space, child, name, name_len);\r
567 \r
568                 target_block->dirty = true;\r
569                 return EOK;\r
570             }\r
571         }\r
572 \r
573         /* Jump to the next entry */\r
574         dentry = (void *) ((uint8_t *)dentry + rec_len);\r
575     }\r
576 \r
577     /* No free space found for new entry */\r
578     return ENOSPC;\r
579 }\r
580 \r
581 \r
582 int ext4_dir_find_in_block(struct ext4_block *block, struct ext4_sblock *sb,\r
583     size_t name_len, const char *name,\r
584     struct ext4_directory_entry_ll **res_entry)\r
585 {\r
586     /* Start from the first entry in block */\r
587     struct ext4_directory_entry_ll *dentry =\r
588             (struct ext4_directory_entry_ll *) block->data;\r
589 \r
590     /* Set upper bound for cycling */\r
591     uint8_t *addr_limit = block->data + ext4_sb_get_block_size(sb);\r
592 \r
593     /* Walk through the block and check entries */\r
594     while ((uint8_t *) dentry < addr_limit) {\r
595         /* Termination condition */\r
596         if ((uint8_t *) dentry + name_len > addr_limit)\r
597             break;\r
598 \r
599         /* Valid entry - check it */\r
600         if (dentry->inode != 0) {\r
601             /* For more effectivity compare firstly only lengths */\r
602             if (ext4_dir_entry_ll_get_name_length(sb, dentry) ==\r
603                     name_len) {\r
604                 /* Compare names */\r
605                 if (memcmp((uint8_t *) name, dentry->name, name_len) == 0) {\r
606                     *res_entry = dentry;\r
607                     return EOK;\r
608                 }\r
609             }\r
610         }\r
611 \r
612         uint16_t dentry_len =\r
613                 ext4_dir_entry_ll_get_entry_length(dentry);\r
614 \r
615         /* Corrupted entry */\r
616         if (dentry_len == 0)\r
617             return EINVAL;\r
618 \r
619         /* Jump to next entry */\r
620         dentry = (struct ext4_directory_entry_ll *)\r
621                         ((uint8_t *) dentry + dentry_len);\r
622     }\r
623 \r
624     /* Entry not found */\r
625     return ENOENT;\r
626 }\r
627 \r
628 int ext4_dir_destroy_result(struct ext4_inode_ref *parent,\r
629     struct ext4_directory_search_result *result)\r
630 {\r
631     if (result->block.lb_id)\r
632         return ext4_block_set(parent->fs->bdev, &result->block);\r
633 \r
634     return EOK;\r
635 }\r
636 \r
637 /**\r
638  * @}\r
639  */\r