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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d776329b was 356e6882, checked in by Maurizio Lombardi <m.lombardi85@…>, 10 years ago

libext4: remove unnecessary check

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