2
* Copyright (c) 2011 Martin Sucha
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* - Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* - The name of the author may not be used to endorse or promote products
15
* derived from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
/** @addtogroup libext2
40
#include <byteorder.h>
43
* Return a magic number from ext2 superblock, this should be equal to
44
* EXT_SUPERBLOCK_MAGIC for valid ext2 superblock
46
* @param sb pointer to superblock
48
uint16_t ext2_superblock_get_magic(ext2_superblock_t *sb)
50
return uint16_t_le2host(sb->magic);
54
* Get the position of first ext2 data block (i.e. the block number
55
* containing main superblock)
57
* @param sb pointer to superblock
59
uint32_t ext2_superblock_get_first_block(ext2_superblock_t *sb)
61
return uint32_t_le2host(sb->first_block);
65
* Get the number of bits to shift a value of 1024 to the left necessary
66
* to get the size of a block
68
* @param sb pointer to superblock
70
uint32_t ext2_superblock_get_block_size_log2(ext2_superblock_t *sb)
72
return uint32_t_le2host(sb->block_size_log2);
76
* Get the size of a block, in bytes
78
* @param sb pointer to superblock
80
uint32_t ext2_superblock_get_block_size(ext2_superblock_t *sb)
82
return 1024 << ext2_superblock_get_block_size_log2(sb);
86
* Get the number of bits to shift a value of 1024 to the left necessary
87
* to get the size of a fragment (note that this is a signed integer and
88
* if negative, the value should be shifted to the right instead)
90
* @param sb pointer to superblock
92
int32_t ext2_superblock_get_fragment_size_log2(ext2_superblock_t *sb)
94
return uint32_t_le2host(sb->fragment_size_log2);
98
* Get the size of a fragment, in bytes
100
* @param sb pointer to superblock
102
uint32_t ext2_superblock_get_fragment_size(ext2_superblock_t *sb)
104
int32_t log = ext2_superblock_get_fragment_size_log2(sb);
114
* Get number of blocks per block group
116
* @param sb pointer to superblock
118
uint32_t ext2_superblock_get_blocks_per_group(ext2_superblock_t *sb)
120
return uint32_t_le2host(sb->blocks_per_group);
124
* Get number of fragments per block group
126
* @param sb pointer to superblock
128
uint32_t ext2_superblock_get_fragments_per_group(ext2_superblock_t *sb)
130
return uint32_t_le2host(sb->fragments_per_group);
134
* Get filesystem state
136
* @param sb pointer to superblock
138
uint16_t ext2_superblock_get_state(ext2_superblock_t *sb)
140
return uint16_t_le2host(sb->state);
144
* Get minor revision number
146
* @param sb pointer to superblock
148
uint16_t ext2_superblock_get_rev_minor(ext2_superblock_t *sb)
150
return uint16_t_le2host(sb->rev_minor);
154
* Get major revision number
156
* @param sb pointer to superblock
158
uint32_t ext2_superblock_get_rev_major(ext2_superblock_t *sb)
160
return uint32_t_le2host(sb->rev_major);
164
* Get index of first regular inode
166
* @param sb pointer to superblock
168
uint32_t ext2_superblock_get_first_inode(ext2_superblock_t *sb)
170
if (ext2_superblock_get_rev_major(sb) == 0) {
171
return EXT2_REV0_FIRST_INODE;
173
return uint32_t_le2host(sb->first_inode);
179
* @param sb pointer to superblock
181
uint16_t ext2_superblock_get_inode_size(ext2_superblock_t *sb)
183
if (ext2_superblock_get_rev_major(sb) == 0) {
184
return EXT2_REV0_INODE_SIZE;
186
return uint32_t_le2host(sb->inode_size);
190
* Get total inode count
192
* @param sb pointer to superblock
194
uint32_t ext2_superblock_get_total_inode_count(ext2_superblock_t *sb)
196
return uint32_t_le2host(sb->total_inode_count);
200
* Get total block count
202
* @param sb pointer to superblock
204
uint32_t ext2_superblock_get_total_block_count(ext2_superblock_t *sb)
206
return uint32_t_le2host(sb->total_block_count);
210
* Get amount of blocks reserved for the superuser
212
* @param sb pointer to superblock
214
uint32_t ext2_superblock_get_reserved_block_count(ext2_superblock_t *sb)
216
return uint32_t_le2host(sb->reserved_block_count);
220
* Get amount of free blocks
222
* @param sb pointer to superblock
224
uint32_t ext2_superblock_get_free_block_count(ext2_superblock_t *sb)
226
return uint32_t_le2host(sb->free_block_count);
230
* Get amount of free inodes
232
* @param sb pointer to superblock
234
uint32_t ext2_superblock_get_free_inode_count(ext2_superblock_t *sb)
236
return uint32_t_le2host(sb->free_inode_count);
240
* Get id of operating system that created the filesystem
242
* @param sb pointer to superblock
244
uint32_t ext2_superblock_get_os(ext2_superblock_t *sb)
246
return uint32_t_le2host(sb->os);
250
* Get count of inodes per block group
252
* @param sb pointer to superblock
254
uint32_t ext2_superblock_get_inodes_per_group(ext2_superblock_t *sb)
256
return uint32_t_le2host(sb->inodes_per_group);
260
* Get compatible features flags
262
* @param sb pointer to superblock
264
uint32_t ext2_superblock_get_features_compatible(ext2_superblock_t *sb)
266
return uint32_t_le2host(sb->features_compatible);
270
* Get incompatible features flags
272
* @param sb pointer to superblock
274
uint32_t ext2_superblock_get_features_incompatible(ext2_superblock_t *sb)
276
return uint32_t_le2host(sb->features_incompatible);
280
* Get read-only compatible features flags
282
* @param sb pointer to superblock
284
uint32_t ext2_superblock_get_features_read_only(ext2_superblock_t *sb)
286
return uint32_t_le2host(sb->features_read_only);
290
* Compute count of block groups present in the filesystem
292
* Note: This function works only for correct filesystem,
293
* i.e. it assumes that total block count > 0 and
294
* blocks per group > 0
297
* If there are 3 blocks per group, the result should be as follows:
298
* Total blocks Result
305
* @param sb pointer to superblock
307
uint32_t ext2_superblock_get_block_group_count(ext2_superblock_t *sb)
309
/* We add one to the result because e.g. 2/3 = 0, while to store
310
* 2 blocks in 3-block group we need one (1) block group
312
* We subtract one first because of special case that to store e.g.
313
* 3 blocks in a 3-block group we need only one group
314
* (and 3/3 yields one - this is one more that we want as we
315
* already add one at the end)
317
return ((ext2_superblock_get_total_block_count(sb)-1) /
318
ext2_superblock_get_blocks_per_group(sb))+1;
321
/** Read a superblock directly from device (i.e. no libblock cache)
323
* @param devmap_handle Device handle of the block device.
324
* @param superblock Pointer where to store pointer to new superblock
326
* @return EOK on success or negative error code on failure.
328
int ext2_superblock_read_direct(devmap_handle_t devmap_handle,
329
ext2_superblock_t **superblock)
334
data = malloc(EXT2_SUPERBLOCK_SIZE);
339
rc = block_read_bytes_direct(devmap_handle, EXT2_SUPERBLOCK_OFFSET,
340
EXT2_SUPERBLOCK_SIZE, data);
346
(*superblock) = data;
350
/** Check a superblock for sanity
352
* @param sb Pointer to superblock
354
* @return EOK on success or negative error code on failure.
356
int ext2_superblock_check_sanity(ext2_superblock_t *sb)
358
if (ext2_superblock_get_magic(sb) != EXT2_SUPERBLOCK_MAGIC) {
362
if (ext2_superblock_get_rev_major(sb) > 1) {
366
if (ext2_superblock_get_total_inode_count(sb) == 0) {
370
if (ext2_superblock_get_total_block_count(sb) == 0) {
374
if (ext2_superblock_get_blocks_per_group(sb) == 0) {
378
if (ext2_superblock_get_fragments_per_group(sb) == 0) {
382
/* We don't support fragments smaller than block */
383
if (ext2_superblock_get_block_size(sb) !=
384
ext2_superblock_get_fragment_size(sb)) {
387
if (ext2_superblock_get_blocks_per_group(sb) !=
388
ext2_superblock_get_fragments_per_group(sb)) {
392
if (ext2_superblock_get_inodes_per_group(sb) == 0) {
396
if (ext2_superblock_get_inode_size(sb) < 128) {
400
if (ext2_superblock_get_first_inode(sb) < 11) {