source: mainline/uspace/lib/ext4/libext4_superblock.c@ 22fb7ab

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

libext4: fix memory leak, release the superblock structure if the mount operation fails

  • Property mode set to 100644
File size: 28.6 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/**
35 * @file libext4_superblock.c
36 * @brief Ext4 superblock operations.
37 */
38
39#include <byteorder.h>
40#include <errno.h>
41#include <block.h>
42#include <malloc.h>
43#include "libext4.h"
44
45/** Get number of i-nodes in the whole filesystem.
46 *
47 * @param sb Superblock
48 *
49 * @return Number of i-nodes
50 *
51 */
52uint32_t ext4_superblock_get_inodes_count(ext4_superblock_t *sb)
53{
54 return uint32_t_le2host(sb->inodes_count);
55}
56
57/** Set number of i-nodes in the whole filesystem.
58 *
59 * @param sb Superblock
60 * @param count Number of i-nodes
61 *
62 */
63void ext4_superblock_set_inodes_count(ext4_superblock_t *sb, uint32_t count)
64{
65 sb->inodes_count = host2uint32_t_le(count);
66}
67
68/** Get number of data blocks in the whole filesystem.
69 *
70 * @param sb Superblock
71 *
72 * @return Number of data blocks
73 *
74 */
75uint64_t ext4_superblock_get_blocks_count(ext4_superblock_t *sb)
76{
77 return ((uint64_t) uint32_t_le2host(sb->blocks_count_hi) << 32) |
78 uint32_t_le2host(sb->blocks_count_lo);
79}
80
81/** Set number of data blocks in the whole filesystem.
82 *
83 * @param sb Superblock
84 * @param count Number of data blocks
85 *
86 */
87void ext4_superblock_set_blocks_count(ext4_superblock_t *sb, uint64_t count)
88{
89 sb->blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
90 sb->blocks_count_hi = host2uint32_t_le(count >> 32);
91}
92
93/** Get number of reserved data blocks in the whole filesystem.
94 *
95 * @param sb Superblock
96 *
97 * @return Number of reserved data blocks
98 *
99 */
100uint64_t ext4_superblock_get_reserved_blocks_count(ext4_superblock_t *sb)
101{
102 return ((uint64_t)
103 uint32_t_le2host(sb->reserved_blocks_count_hi) << 32) |
104 uint32_t_le2host(sb->reserved_blocks_count_lo);
105}
106
107/** Set number of reserved data blocks in the whole filesystem.
108 *
109 * @param sb Superblock
110 * @param count Number of reserved data blocks
111 *
112 */
113void ext4_superblock_set_reserved_blocks_count(ext4_superblock_t *sb,
114 uint64_t count)
115{
116 sb->reserved_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
117 sb->reserved_blocks_count_hi = host2uint32_t_le(count >> 32);
118}
119
120/** Get number of free data blocks in the whole filesystem.
121 *
122 * @param sb Superblock
123 *
124 * @return Number of free data blocks
125 *
126 */
127uint64_t ext4_superblock_get_free_blocks_count(ext4_superblock_t *sb)
128{
129 return ((uint64_t)
130 uint32_t_le2host(sb->free_blocks_count_hi) << 32) |
131 uint32_t_le2host(sb->free_blocks_count_lo);
132}
133
134/** Set number of free data blocks in the whole filesystem.
135 *
136 * @param sb Superblock
137 * @param count Number of free data blocks
138 *
139 */
140void ext4_superblock_set_free_blocks_count(ext4_superblock_t *sb,
141 uint64_t count)
142{
143 sb->free_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
144 sb->free_blocks_count_hi = host2uint32_t_le(count >> 32);
145}
146
147/** Get number of free i-nodes in the whole filesystem.
148 *
149 * @param sb Superblock
150 *
151 * @return Number of free i-nodes
152 *
153 */
154uint32_t ext4_superblock_get_free_inodes_count(ext4_superblock_t *sb)
155{
156 return uint32_t_le2host(sb->free_inodes_count);
157}
158
159/** Set number of free i-nodes in the whole filesystem.
160 *
161 * @param sb Superblock
162 * @param count Number of free i-nodes
163 *
164 */
165void ext4_superblock_set_free_inodes_count(ext4_superblock_t *sb,
166 uint32_t count)
167{
168 sb->free_inodes_count = host2uint32_t_le(count);
169}
170
171/** Get index of first data block (block where the superblock is located)
172 *
173 * @param sb Superblock
174 *
175 * @return Index of the first data block
176 *
177 */
178uint32_t ext4_superblock_get_first_data_block(ext4_superblock_t *sb)
179{
180 return uint32_t_le2host(sb->first_data_block);
181}
182
183/** Set index of first data block (block where the superblock is located)
184 *
185 * @param sb Superblock
186 * @param first Index of the first data block
187 *
188 */
189void ext4_superblock_set_first_data_block(ext4_superblock_t *sb,
190 uint32_t first)
191{
192 sb->first_data_block = host2uint32_t_le(first);
193}
194
195/** Get logarithmic block size (1024 << size == block_size)
196 *
197 * @param sb Superblock
198 *
199 * @return Logarithmic block size
200 *
201 */
202uint32_t ext4_superblock_get_log_block_size(ext4_superblock_t *sb)
203{
204 return uint32_t_le2host(sb->log_block_size);
205}
206
207/** Set logarithmic block size (1024 << size == block_size)
208 *
209 * @param sb Superblock
210 *
211 * @return Logarithmic block size
212 *
213 */
214void ext4_superblock_set_log_block_size(ext4_superblock_t *sb,
215 uint32_t log_size)
216{
217 sb->log_block_size = host2uint32_t_le(log_size);
218}
219
220/** Get size of data block (in bytes).
221 *
222 * @param sb Superblock
223 *
224 * @return Size of data block
225 *
226 */
227uint32_t ext4_superblock_get_block_size(ext4_superblock_t *sb)
228{
229 return 1024 << ext4_superblock_get_log_block_size(sb);
230}
231
232/** Set size of data block (in bytes).
233 *
234 * @param sb Superblock
235 * @param size Size of data block (must be power of 2, at least 1024)
236 *
237 */
238void ext4_superblock_set_block_size(ext4_superblock_t *sb, uint32_t size)
239{
240 uint32_t log = 0;
241 uint32_t tmp = size / EXT4_MIN_BLOCK_SIZE;
242
243 tmp >>= 1;
244 while (tmp) {
245 log++;
246 tmp >>= 1;
247 }
248
249 ext4_superblock_set_log_block_size(sb, log);
250}
251
252/** Get logarithmic fragment size (1024 << size)
253 *
254 * @param sb Superblock
255 *
256 * @return Logarithmic fragment size
257 *
258 */
259uint32_t ext4_superblock_get_log_frag_size(ext4_superblock_t *sb)
260{
261 return uint32_t_le2host(sb->log_frag_size);
262}
263
264/** Set logarithmic fragment size (1024 << size)
265 *
266 * @param sb Superblock
267 * @param frag_size Logarithmic fragment size
268 *
269 */
270void ext4_superblock_set_log_frag_size(ext4_superblock_t *sb,
271 uint32_t frag_size)
272{
273 sb->log_frag_size = host2uint32_t_le(frag_size);
274}
275
276/** Get size of fragment (in bytes).
277 *
278 * @param sb Superblock
279 *
280 * @return Size of fragment
281 *
282 */
283uint32_t ext4_superblock_get_frag_size(ext4_superblock_t *sb)
284{
285 return 1024 << ext4_superblock_get_log_frag_size(sb);
286}
287
288/** Set size of fragment (in bytes).
289 *
290 * @param sb Superblock
291 * @param size Size of fragment (must be power of 2, at least 1024)
292 *
293 */
294void ext4_superblock_set_frag_size(ext4_superblock_t *sb, uint32_t size)
295{
296 uint32_t log = 0;
297 uint32_t tmp = size / EXT4_MIN_BLOCK_SIZE;
298
299 tmp >>= 1;
300 while (tmp) {
301 log++;
302 tmp >>= 1;
303 }
304
305 ext4_superblock_set_log_frag_size(sb, log);
306}
307
308/** Get number of data blocks per block group (except last BG)
309 *
310 * @param sb Superblock
311 *
312 * @return Data blocks per block group
313 *
314 */
315uint32_t ext4_superblock_get_blocks_per_group(ext4_superblock_t *sb)
316{
317 return uint32_t_le2host(sb->blocks_per_group);
318}
319
320/** Set number of data blocks per block group (except last BG)
321 *
322 * @param sb Superblock
323 * @param blocks Data blocks per block group
324 *
325 */
326void ext4_superblock_set_blocks_per_group(ext4_superblock_t *sb,
327 uint32_t blocks)
328{
329 sb->blocks_per_group = host2uint32_t_le(blocks);
330}
331
332/** Get number of fragments per block group (except last BG)
333 *
334 * @param sb Superblock
335 *
336 * @return Fragments per block group
337 *
338 */
339uint32_t ext4_superblock_get_frags_per_group(ext4_superblock_t *sb)
340{
341 return uint32_t_le2host(sb->frags_per_group);
342}
343
344/** Set number of fragment per block group (except last BG)
345 *
346 * @param sb Superblock
347 * @param frags Fragments per block group
348 */
349void ext4_superblock_set_frags_per_group(ext4_superblock_t *sb, uint32_t frags)
350{
351 sb->frags_per_group = host2uint32_t_le(frags);
352}
353
354/** Get number of i-nodes per block group (except last BG)
355 *
356 * @param sb Superblock
357 *
358 * @return I-nodes per block group
359 *
360 */
361uint32_t ext4_superblock_get_inodes_per_group(ext4_superblock_t *sb)
362{
363 return uint32_t_le2host(sb->inodes_per_group);
364}
365
366/** Set number of i-nodes per block group (except last BG)
367 *
368 * @param sb Superblock
369 * @param inodes I-nodes per block group
370 *
371 */
372void ext4_superblock_set_inodes_per_group(ext4_superblock_t *sb,
373 uint32_t inodes)
374{
375 sb->inodes_per_group = host2uint32_t_le(inodes);
376}
377
378/** Get time when filesystem was mounted (POSIX time).
379 *
380 * @param sb Superblock
381 *
382 * @return Mount time
383 *
384 */
385uint32_t ext4_superblock_get_mount_time(ext4_superblock_t *sb)
386{
387 return uint32_t_le2host(sb->mount_time);
388}
389
390/** Set time when filesystem was mounted (POSIX time).
391 *
392 * @param sb Superblock
393 * @param time Mount time
394 *
395 */
396void ext4_superblock_set_mount_time(ext4_superblock_t *sb, uint32_t time)
397{
398 sb->mount_time = host2uint32_t_le(time);
399}
400
401/** Get time when filesystem was last accesed by write operation (POSIX time).
402 *
403 * @param sb Superblock
404 *
405 * @return Write time
406 *
407 */
408uint32_t ext4_superblock_get_write_time(ext4_superblock_t *sb)
409{
410 return uint32_t_le2host(sb->write_time);
411}
412
413/** Set time when filesystem was last accesed by write operation (POSIX time).
414 *
415 * @param sb Superblock
416 * @param time Write time
417 *
418 */
419void ext4_superblock_set_write_time(ext4_superblock_t *sb, uint32_t time)
420{
421 sb->write_time = host2uint32_t_le(time);
422}
423
424/** Get number of mount from last filesystem check.
425 *
426 * @param sb Superblock
427 *
428 * @return Number of mounts
429 *
430 */
431uint16_t ext4_superblock_get_mount_count(ext4_superblock_t *sb)
432{
433 return uint16_t_le2host(sb->mount_count);
434}
435
436/** Set number of mount from last filesystem check.
437 *
438 * @param sb Superblock
439 * @param count Number of mounts
440 *
441 */
442void ext4_superblock_set_mount_count(ext4_superblock_t *sb, uint16_t count)
443{
444 sb->mount_count = host2uint16_t_le(count);
445}
446
447/** Get maximum number of mount from last filesystem check.
448 *
449 * @param sb Superblock
450 *
451 * @return Maximum number of mounts
452 *
453 */
454uint16_t ext4_superblock_get_max_mount_count(ext4_superblock_t *sb)
455{
456 return uint16_t_le2host(sb->max_mount_count);
457}
458
459/** Set maximum number of mount from last filesystem check.
460 *
461 * @param sb Superblock
462 * @param count Maximum number of mounts
463 *
464 */
465void ext4_superblock_set_max_mount_count(ext4_superblock_t *sb, uint16_t count)
466{
467 sb->max_mount_count = host2uint16_t_le(count);
468}
469
470/** Get superblock magic value.
471 *
472 * @param sb Superblock
473 *
474 * @return Magic value
475 *
476 */
477uint16_t ext4_superblock_get_magic(ext4_superblock_t *sb)
478{
479 return uint16_t_le2host(sb->magic);
480}
481
482/** Set superblock magic value.
483 *
484 * @param sb Superblock
485 * @param magic Magic value
486 *
487 */
488void ext4_superblock_set_magic(ext4_superblock_t *sb, uint16_t magic)
489{
490 sb->magic = host2uint16_t_le(magic);
491}
492
493/** Get filesystem state.
494 *
495 * @param sb Superblock
496 *
497 * @return Filesystem state
498 *
499 */
500uint16_t ext4_superblock_get_state(ext4_superblock_t *sb)
501{
502 return uint16_t_le2host(sb->state);
503}
504
505/** Set filesystem state.
506 *
507 * @param sb Superblock
508 * @param state Filesystem state
509 *
510 */
511void ext4_superblock_set_state(ext4_superblock_t *sb, uint16_t state)
512{
513 sb->state = host2uint16_t_le(state);
514}
515
516/** Get behavior code when errors detected.
517 *
518 * @param sb Superblock
519 *
520 * @return Behavior code
521 *
522 */
523uint16_t ext4_superblock_get_errors(ext4_superblock_t *sb)
524{
525 return uint16_t_le2host(sb->errors);
526}
527
528/** Set behavior code when errors detected.
529 *
530 * @param sb Superblock
531 * @param errors Behavior code
532 *
533 */
534void ext4_superblock_set_errors(ext4_superblock_t *sb, uint16_t errors)
535{
536 sb->errors = host2uint16_t_le(errors);
537}
538
539/** Get minor revision level of the filesystem.
540 *
541 * @param sb Superblock
542 *
543 * @return Minor revision level
544 *
545 */
546uint16_t ext4_superblock_get_minor_rev_level(ext4_superblock_t *sb)
547{
548 return uint16_t_le2host(sb->minor_rev_level);
549}
550
551/** Set minor revision level of the filesystem.
552 *
553 * @param sb Superblock
554 * @param level Minor revision level
555 *
556 */
557void ext4_superblock_set_minor_rev_level(ext4_superblock_t *sb, uint16_t level)
558{
559 sb->minor_rev_level = host2uint16_t_le(level);
560}
561
562/** Get time of the last filesystem check.
563 *
564 * @param sb Superblock
565 *
566 * @return Time of the last check (POSIX)
567 *
568 */
569uint32_t ext4_superblock_get_last_check_time(ext4_superblock_t *sb)
570{
571 return uint32_t_le2host(sb->last_check_time);
572}
573
574/** Set time of the last filesystem check.
575 *
576 * @param sb Superblock
577 * @param time Time of the last check (POSIX)
578 *
579 */
580void ext4_superblock_set_last_check_time(ext4_superblock_t *sb, uint32_t time)
581{
582 sb->state = host2uint32_t_le(time);
583}
584
585/** Get maximum time interval between two filesystem checks.
586 *
587 * @param sb Superblock
588 *
589 * @return Time interval between two check (POSIX)
590 *
591 */
592uint32_t ext4_superblock_get_check_interval(ext4_superblock_t *sb)
593{
594 return uint32_t_le2host(sb->check_interval);
595}
596
597/** Set maximum time interval between two filesystem checks.
598 *
599 * @param sb Superblock
600 * @param interval Time interval between two check (POSIX)
601 *
602 */
603void ext4_superblock_set_check_interval(ext4_superblock_t *sb, uint32_t interval)
604{
605 sb->check_interval = host2uint32_t_le(interval);
606}
607
608/** Get operation system identifier, on which the filesystem was created.
609 *
610 * @param sb Superblock
611 *
612 * @return Operation system identifier
613 *
614 */
615uint32_t ext4_superblock_get_creator_os(ext4_superblock_t *sb)
616{
617 return uint32_t_le2host(sb->creator_os);
618}
619
620/** Set operation system identifier, on which the filesystem was created.
621 *
622 * @param sb Superblock
623 * @param os Operation system identifier
624 *
625 */
626void ext4_superblock_set_creator_os(ext4_superblock_t *sb, uint32_t os)
627{
628 sb->creator_os = host2uint32_t_le(os);
629}
630
631/** Get revision level of the filesystem.
632 *
633 * @param sb Superblock
634 *
635 * @return Revision level
636 *
637 */
638uint32_t ext4_superblock_get_rev_level(ext4_superblock_t *sb)
639{
640 return uint32_t_le2host(sb->rev_level);
641}
642
643/** Set revision level of the filesystem.
644 *
645 * @param sb Superblock
646 * @param level Revision level
647 *
648 */
649void ext4_superblock_set_rev_level(ext4_superblock_t *sb, uint32_t level)
650{
651 sb->rev_level = host2uint32_t_le(level);
652}
653
654/** Get default user id for reserved blocks.
655 *
656 * @param sb Superblock
657 *
658 * @return Default user id for reserved blocks.
659 *
660 */
661uint16_t ext4_superblock_get_def_resuid(ext4_superblock_t *sb)
662{
663 return uint16_t_le2host(sb->def_resuid);
664}
665
666/** Set default user id for reserved blocks.
667 *
668 * @param sb Superblock
669 * @param uid Default user id for reserved blocks.
670 *
671 */
672void ext4_superblock_set_def_resuid(ext4_superblock_t *sb, uint16_t uid)
673{
674 sb->def_resuid = host2uint16_t_le(uid);
675}
676
677/** Get default group id for reserved blocks.
678 *
679 * @param sb Superblock
680 *
681 * @return Default group id for reserved blocks.
682 *
683 */
684uint16_t ext4_superblock_get_def_resgid(ext4_superblock_t *sb)
685{
686 return uint16_t_le2host(sb->def_resgid);
687}
688
689/** Set default group id for reserved blocks.
690 *
691 * @param sb Superblock
692 * @param gid Default group id for reserved blocks.
693 *
694 */
695void ext4_superblock_set_def_resgid(ext4_superblock_t *sb, uint16_t gid)
696{
697 sb->def_resgid = host2uint16_t_le(gid);
698}
699
700/** Get index of the first i-node, which can be used for allocation.
701 *
702 * @param sb Superblock
703 *
704 * @return I-node index
705 *
706 */
707uint32_t ext4_superblock_get_first_inode(ext4_superblock_t *sb)
708{
709 return uint32_t_le2host(sb->first_inode);
710}
711
712/** Set index of the first i-node, which can be used for allocation.
713 *
714 * @param sb Superblock
715 * @param first_inode I-node index
716 *
717 */
718void ext4_superblock_set_first_inode(ext4_superblock_t *sb,
719 uint32_t first_inode)
720{
721 sb->first_inode = host2uint32_t_le(first_inode);
722}
723
724/** Get size of i-node structure.
725 *
726 * For the oldest revision return constant number.
727 *
728 * @param sb Superblock
729 *
730 * @return Size of i-node structure
731 *
732 */
733uint16_t ext4_superblock_get_inode_size(ext4_superblock_t *sb)
734{
735 if (ext4_superblock_get_rev_level(sb) == 0)
736 return EXT4_REV0_INODE_SIZE;
737
738 return uint16_t_le2host(sb->inode_size);
739}
740
741/** Set size of i-node structure.
742 *
743 * @param sb Superblock
744 * @param size Size of i-node structure
745 *
746 */
747void ext4_superblock_set_inode_size(ext4_superblock_t *sb, uint16_t size)
748{
749 sb->inode_size = host2uint16_t_le(size);
750}
751
752/** Get index of block group, where superblock copy is located.
753 *
754 * @param sb Superblock
755 *
756 * @return Block group index
757 *
758 */
759uint16_t ext4_superblock_get_block_group_index(ext4_superblock_t *sb)
760{
761 return uint16_t_le2host(sb->block_group_index);
762}
763
764/** Set index of block group, where superblock copy is located.
765 *
766 * @param sb Superblock
767 * @param bgid Block group index
768 *
769 */
770void ext4_superblock_set_block_group_index(ext4_superblock_t *sb, uint16_t bgid)
771{
772 sb->block_group_index = host2uint16_t_le(bgid);
773}
774
775/** Get compatible features supported by the filesystem.
776 *
777 * @param sb Superblock
778 *
779 * @return Compatible features bitmap
780 *
781 */
782uint32_t ext4_superblock_get_features_compatible(ext4_superblock_t *sb)
783{
784 return uint32_t_le2host(sb->features_compatible);
785}
786
787/** Set compatible features supported by the filesystem.
788 *
789 * @param sb Superblock
790 * @param features Compatible features bitmap
791 *
792 */
793void ext4_superblock_set_features_compatible(ext4_superblock_t *sb,
794 uint32_t features)
795{
796 sb->features_compatible = host2uint32_t_le(features);
797}
798
799/** Get incompatible features supported by the filesystem.
800 *
801 * @param sb Superblock
802 *
803 * @return Incompatible features bitmap
804 *
805 */
806uint32_t ext4_superblock_get_features_incompatible(ext4_superblock_t *sb)
807{
808 return uint32_t_le2host(sb->features_incompatible);
809}
810
811/** Set incompatible features supported by the filesystem.
812 *
813 * @param sb Superblock
814 * @param features Incompatible features bitmap
815 *
816 */
817void ext4_superblock_set_features_incompatible(ext4_superblock_t *sb,
818 uint32_t features)
819{
820 sb->features_incompatible = host2uint32_t_le(features);
821}
822
823/** Get compatible features supported by the filesystem.
824 *
825 * @param sb Superblock
826 *
827 * @return Read-only compatible features bitmap
828 *
829 */
830uint32_t ext4_superblock_get_features_read_only(ext4_superblock_t *sb)
831{
832 return uint32_t_le2host(sb->features_read_only);
833}
834
835/** Set compatible features supported by the filesystem.
836 *
837 * @param sb Superblock
838 * @param feature Read-only compatible features bitmap
839 *
840 */
841void ext4_superblock_set_features_read_only(ext4_superblock_t *sb,
842 uint32_t features)
843{
844 sb->features_read_only = host2uint32_t_le(features);
845}
846
847/** Get UUID of the filesystem.
848 *
849 * @param sb superblock
850 *
851 * @return Pointer to UUID array
852 *
853 */
854const uint8_t *ext4_superblock_get_uuid(ext4_superblock_t *sb)
855{
856 return sb->uuid;
857}
858
859/** Set UUID of the filesystem.
860 *
861 * @param sb Superblock
862 * @param uuid Pointer to UUID array
863 *
864 */
865void ext4_superblock_set_uuid(ext4_superblock_t *sb, const uint8_t *uuid)
866{
867 memcpy(sb->uuid, uuid, sizeof(sb->uuid));
868}
869
870/** Get name of the filesystem volume.
871 *
872 * @param sb Superblock
873 *
874 * @return Name of the volume
875 *
876 */
877const char *ext4_superblock_get_volume_name(ext4_superblock_t *sb)
878{
879 return sb->volume_name;
880}
881
882/** Set name of the filesystem volume.
883 *
884 * @param sb Superblock
885 * @param name New name of the volume
886 */
887void ext4_superblock_set_volume_name(ext4_superblock_t *sb, const char *name)
888{
889 memcpy(sb->volume_name, name, sizeof(sb->volume_name));
890}
891
892/** Get name of the directory, where this filesystem was mounted at last.
893 *
894 * @param sb Superblock
895 *
896 * @return Directory name
897 *
898 */
899const char *ext4_superblock_get_last_mounted(ext4_superblock_t *sb)
900{
901 return sb->last_mounted;
902}
903
904/** Set name of the directory, where this filesystem was mounted at last.
905 *
906 * @param sb Superblock
907 * @param last Directory name
908 *
909 */
910void ext4_superblock_set_last_mounted(ext4_superblock_t *sb, const char *last)
911{
912 memcpy(sb->last_mounted, last, sizeof(sb->last_mounted));
913}
914
915/** Get last orphaned i-node index.
916 *
917 * Orphans are stored in linked list.
918 *
919 * @param sb Superblock
920 *
921 * @return Last orphaned i-node index
922 *
923 */
924uint32_t ext4_superblock_get_last_orphan(ext4_superblock_t *sb)
925{
926 return uint32_t_le2host(sb->last_orphan);
927}
928
929/** Set last orphaned i-node index.
930 *
931 * Orphans are stored in linked list.
932 *
933 * @param sb Superblock
934 * @param last_orphan Last orphaned i-node index
935 *
936 */
937void ext4_superblock_set_last_orphan(ext4_superblock_t *sb,
938 uint32_t last_orphan)
939{
940 sb->last_orphan = host2uint32_t_le(last_orphan);
941}
942
943/** Get hash seed for directory index hash function.
944 *
945 * @param sb Superblock
946 *
947 * @return Hash seed pointer
948 *
949 */
950const uint32_t *ext4_superblock_get_hash_seed(ext4_superblock_t *sb)
951{
952 return sb->hash_seed;
953}
954
955/** Set hash seed for directory index hash function.
956 *
957 * @param sb Superblock
958 * @param seed Hash seed pointer
959 *
960 */
961void ext4_superblock_set_hash_seed(ext4_superblock_t *sb, const uint32_t *seed)
962{
963 memcpy(sb->hash_seed, seed, sizeof(sb->hash_seed));
964}
965
966/** Get default version of the hash algorithm version for directory index.
967 *
968 * @param sb Superblock
969 *
970 * @return Default hash version
971 *
972 */
973uint8_t ext4_superblock_get_default_hash_version(ext4_superblock_t *sb)
974{
975 return sb->default_hash_version;
976}
977
978/** Set default version of the hash algorithm version for directory index.
979 *
980 * @param sb Superblock
981 * @param version Default hash version
982 *
983 */
984void ext4_superblock_set_default_hash_version(ext4_superblock_t *sb,
985 uint8_t version)
986{
987 sb->default_hash_version = version;
988}
989
990/** Get size of block group descriptor structure.
991 *
992 * Output value is checked for minimal size.
993 *
994 * @param sb Superblock
995 *
996 * @return Size of block group descriptor
997 *
998 */
999uint16_t ext4_superblock_get_desc_size(ext4_superblock_t *sb)
1000{
1001 uint16_t size = uint16_t_le2host(sb->desc_size);
1002
1003 if (size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
1004 size = EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE;
1005
1006 return size;
1007}
1008
1009/** Set size of block group descriptor structure.
1010 *
1011 * Input value is checked for minimal size.
1012 *
1013 * @param sb Superblock
1014 * @param size Size of block group descriptor
1015 *
1016 */
1017void ext4_superblock_set_desc_size(ext4_superblock_t *sb, uint16_t size)
1018{
1019 if (size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
1020 sb->desc_size =
1021 host2uint16_t_le(EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE);
1022
1023 sb->desc_size = host2uint16_t_le(size);
1024}
1025
1026/** Get superblock flags.
1027 *
1028 * @param sb Superblock
1029 *
1030 * @return Flags from the superblock
1031 *
1032 */
1033uint32_t ext4_superblock_get_flags(ext4_superblock_t *sb)
1034{
1035 return uint32_t_le2host(sb->flags);
1036}
1037
1038/** Set superblock flags.
1039 *
1040 * @param sb Superblock
1041 * @param flags Flags for the superblock
1042 *
1043 */
1044void ext4_superblock_set_flags(ext4_superblock_t *sb, uint32_t flags)
1045{
1046 sb->flags = host2uint32_t_le(flags);
1047}
1048
1049/*
1050 * More complex superblock operations
1051 */
1052
1053/** Check if superblock has specified flag.
1054 *
1055 * @param sb Superblock
1056 * @param flag Flag to be checked
1057 *
1058 * @return True, if superblock has the flag
1059 *
1060 */
1061bool ext4_superblock_has_flag(ext4_superblock_t *sb, uint32_t flag)
1062{
1063 if (ext4_superblock_get_flags(sb) & flag)
1064 return true;
1065
1066 return false;
1067}
1068
1069/** Check if filesystem supports compatible feature.
1070 *
1071 * @param sb Superblock
1072 * @param feature Feature to be checked
1073 *
1074 * @return True, if filesystem supports the feature
1075 *
1076 */
1077bool ext4_superblock_has_feature_compatible(ext4_superblock_t *sb,
1078 uint32_t feature)
1079{
1080 if (ext4_superblock_get_features_compatible(sb) & feature)
1081 return true;
1082
1083 return false;
1084}
1085
1086/** Check if filesystem supports incompatible feature.
1087 *
1088 * @param sb Superblock
1089 * @param feature Feature to be checked
1090 *
1091 * @return True, if filesystem supports the feature
1092 *
1093 */
1094bool ext4_superblock_has_feature_incompatible(ext4_superblock_t *sb,
1095 uint32_t feature)
1096{
1097 if (ext4_superblock_get_features_incompatible(sb) & feature)
1098 return true;
1099
1100 return false;
1101}
1102
1103/** Check if filesystem supports read-only compatible feature.
1104 *
1105 * @param sb Superblock
1106 * @param feature Feature to be checked
1107 *
1108 * @return True, if filesystem supports the feature
1109 *
1110 */
1111bool ext4_superblock_has_feature_read_only(ext4_superblock_t *sb,
1112 uint32_t feature)
1113{
1114 if (ext4_superblock_get_features_read_only(sb) & feature)
1115 return true;
1116
1117 return false;
1118}
1119
1120/** Read superblock directly from block device.
1121 *
1122 * @param service_id Block device identifier
1123 * @param sb Output pointer to memory structure
1124 *
1125 * @return Eerror code.
1126 *
1127 */
1128int ext4_superblock_read_direct(service_id_t service_id, ext4_superblock_t **sb)
1129{
1130 /* Allocated memory for superblock structure */
1131 void *data = malloc(EXT4_SUPERBLOCK_SIZE);
1132 if (data == NULL)
1133 return ENOMEM;
1134
1135 /* Read data from block device */
1136 int rc = block_read_bytes_direct(service_id, EXT4_SUPERBLOCK_OFFSET,
1137 EXT4_SUPERBLOCK_SIZE, data);
1138
1139 if (rc != EOK) {
1140 free(data);
1141 return rc;
1142 }
1143
1144 /* Set output value */
1145 (*sb) = data;
1146
1147 return EOK;
1148}
1149
1150/** Write superblock structure directly to block device.
1151 *
1152 * @param service_id Block device identifier
1153 * @param sb Superblock to be written
1154 *
1155 * @return Error code
1156 *
1157 */
1158int ext4_superblock_write_direct(service_id_t service_id, ext4_superblock_t *sb)
1159{
1160 /* Load physical block size from block device */
1161 size_t phys_block_size;
1162 int rc = block_get_bsize(service_id, &phys_block_size);
1163 if (rc != EOK)
1164 return rc;
1165
1166 /* Compute address of the first block */
1167 uint64_t first_block = EXT4_SUPERBLOCK_OFFSET / phys_block_size;
1168
1169 /* Compute number of block to write */
1170 size_t block_count = EXT4_SUPERBLOCK_SIZE / phys_block_size;
1171
1172 /* Check alignment */
1173 if (EXT4_SUPERBLOCK_SIZE % phys_block_size)
1174 block_count++;
1175
1176 /* Write data */
1177 return block_write_direct(service_id, first_block, block_count, sb);
1178}
1179
1180/** Release the memory allocated for the superblock structure
1181 *
1182 * @param sb Superblock to be freed
1183 *
1184 */
1185void ext4_superblock_release(ext4_superblock_t *sb)
1186{
1187 free(sb);
1188}
1189
1190/** Check sanity of the superblock.
1191 *
1192 * This check is performed at mount time.
1193 * Checks are described by one-line comments in the code.
1194 *
1195 * @param sb Superblock to check
1196 *
1197 * @return Error code
1198 *
1199 */
1200int ext4_superblock_check_sanity(ext4_superblock_t *sb)
1201{
1202 if (ext4_superblock_get_magic(sb) != EXT4_SUPERBLOCK_MAGIC)
1203 return ENOTSUP;
1204
1205 if (ext4_superblock_get_inodes_count(sb) == 0)
1206 return ENOTSUP;
1207
1208 if (ext4_superblock_get_blocks_count(sb) == 0)
1209 return ENOTSUP;
1210
1211 if (ext4_superblock_get_blocks_per_group(sb) == 0)
1212 return ENOTSUP;
1213
1214 if (ext4_superblock_get_inodes_per_group(sb) == 0)
1215 return ENOTSUP;
1216
1217 if (ext4_superblock_get_inode_size(sb) < 128)
1218 return ENOTSUP;
1219
1220 if (ext4_superblock_get_first_inode(sb) < 11)
1221 return ENOTSUP;
1222
1223 if (ext4_superblock_get_desc_size(sb) <
1224 EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
1225 return ENOTSUP;
1226
1227 if (ext4_superblock_get_desc_size(sb) >
1228 EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE)
1229 return ENOTSUP;
1230
1231 return EOK;
1232}
1233
1234/** Compute number of block groups in the filesystem.
1235 *
1236 * @param sb Superblock
1237 *
1238 * @return Number of block groups
1239 *
1240 */
1241uint32_t ext4_superblock_get_block_group_count(ext4_superblock_t *sb)
1242{
1243 uint64_t blocks_count = ext4_superblock_get_blocks_count(sb);
1244 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
1245
1246 uint32_t block_groups_count = blocks_count / blocks_per_group;
1247
1248 if (blocks_count % blocks_per_group)
1249 block_groups_count++;
1250
1251 return block_groups_count;
1252}
1253
1254/** Compute number of blocks in specified block group.
1255 *
1256 * @param sb Superblock
1257 * @param bgid Block group index
1258 *
1259 * @return Number of blocks
1260 *
1261 */
1262uint32_t ext4_superblock_get_blocks_in_group(ext4_superblock_t *sb, uint32_t bgid)
1263{
1264 uint32_t block_group_count =
1265 ext4_superblock_get_block_group_count(sb);
1266 uint32_t blocks_per_group =
1267 ext4_superblock_get_blocks_per_group(sb);
1268 uint64_t total_blocks =
1269 ext4_superblock_get_blocks_count(sb);
1270
1271 if (bgid < block_group_count - 1)
1272 return blocks_per_group;
1273 else
1274 return (total_blocks - ((block_group_count - 1) * blocks_per_group));
1275}
1276
1277/** Compute number of i-nodes in specified block group.
1278 *
1279 * @param sb Superblock
1280 * @param bgid Block group index
1281 *
1282 * @return Number of i-nodes
1283 *
1284 */
1285uint32_t ext4_superblock_get_inodes_in_group(ext4_superblock_t *sb, uint32_t bgid)
1286{
1287 uint32_t block_group_count =
1288 ext4_superblock_get_block_group_count(sb);
1289 uint32_t inodes_per_group =
1290 ext4_superblock_get_inodes_per_group(sb);
1291 uint32_t total_inodes =
1292 ext4_superblock_get_inodes_count(sb);
1293
1294 if (bgid < block_group_count - 1)
1295 return inodes_per_group;
1296 else
1297 return (total_inodes - ((block_group_count - 1) * inodes_per_group));
1298}
1299
1300/**
1301 * @}
1302 */
Note: See TracBrowser for help on using the repository browser.