source: mainline/uspace/lib/ext4/libext4_filesystem.c@ 3712434

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3712434 was 3712434, checked in by Frantisek Princ <frantisek.princ@…>, 14 years ago

Added more getters on basic ext4 structures

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * Copyright (c) 2011 Frantisek Princ
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/** @addtogroup libext4
30 * @{
31 */
32
33/**
34 * @file libext4_filesystem.c
35 * @brief TODO
36 */
37
38#include <errno.h>
39#include <malloc.h>
40#include "libext4.h"
41
42/**
43 * TODO doxy
44 */
45int ext4_filesystem_init(ext4_filesystem_t *fs, service_id_t service_id)
46{
47
48 int rc;
49 ext4_superblock_t *temp_superblock;
50 size_t block_size;
51
52 fs->device = service_id;
53
54 // TODO what does constant 2048 mean?
55 rc = block_init(EXCHANGE_SERIALIZE, fs->device, 2048);
56 if (rc != EOK) {
57 return rc;
58 }
59
60 /* Read superblock from device */
61 rc = ext4_superblock_read_direct(fs->device, &temp_superblock);
62 if (rc != EOK) {
63 block_fini(fs->device);
64 return rc;
65 }
66
67 /* Read block size from superblock and check */
68 block_size = ext4_superblock_get_block_size(temp_superblock);
69 if (block_size > EXT4_MAX_BLOCK_SIZE) {
70 block_fini(fs->device);
71 return ENOTSUP;
72 }
73
74 /* Initialize block caching */
75 rc = block_cache_init(service_id, block_size, 0, CACHE_MODE_WT);
76 if (rc != EOK) {
77 block_fini(fs->device);
78 return rc;
79 }
80
81 /* Return loaded superblock */
82 fs->superblock = temp_superblock;
83
84 return EOK;
85}
86
87/**
88 * TODO doxy
89 */
90void ext4_filesystem_fini(ext4_filesystem_t *fs)
91{
92 free(fs->superblock);
93 block_fini(fs->device);
94}
95
96/**
97 * TODO doxy
98 */
99int ext4_filesystem_check_sanity(ext4_filesystem_t *fs)
100{
101 int rc;
102
103 rc = ext4_superblock_check_sanity(fs->superblock);
104 if (rc != EOK) {
105 return rc;
106 }
107
108 return EOK;
109}
110
111/**
112 * TODO doxy
113 */
114int ext4_filesystem_check_features(ext4_filesystem_t *fs, bool *o_read_only)
115{
116 /* Feature flags are present in rev 1 and later */
117 if (ext4_superblock_get_rev_level(fs->superblock) == 0) {
118 *o_read_only = false;
119 return EOK;
120 }
121
122 uint32_t incompatible_features;
123 incompatible_features = ext4_superblock_get_features_incompatible(fs->superblock);
124 incompatible_features &= ~EXT4_FEATURE_INCOMPAT_SUPP;
125 if (incompatible_features > 0) {
126 *o_read_only = true;
127 return ENOTSUP;
128 }
129
130 uint32_t compatible_read_only;
131 compatible_read_only = ext4_superblock_get_features_read_only(fs->superblock);
132 compatible_read_only &= ~EXT4_FEATURE_RO_COMPAT_SUPP;
133 if (compatible_read_only > 0) {
134 *o_read_only = true;
135 }
136
137 return EOK;
138}
139
140/**
141 * TODO doxy
142 */
143int ext4_filesystem_get_block_group_ref(ext4_filesystem_t *fs, uint32_t bgid,
144 ext4_block_group_ref_t **ref)
145{
146 int rc;
147 aoff64_t block_id;
148 uint32_t descriptors_per_block;
149 size_t offset;
150 ext4_block_group_ref_t *newref;
151
152 newref = malloc(sizeof(ext4_block_group_ref_t));
153 if (newref == NULL) {
154 return ENOMEM;
155 }
156
157 descriptors_per_block = ext4_superblock_get_block_size(fs->superblock)
158 / EXT4_BLOCK_GROUP_DESCRIPTOR_SIZE;
159
160 /* Block group descriptor table starts at the next block after superblock */
161 block_id = ext4_superblock_get_first_data_block(fs->superblock) + 1;
162
163 /* Find the block containing the descriptor we are looking for */
164 block_id += bgid / descriptors_per_block;
165 offset = (bgid % descriptors_per_block) * EXT4_BLOCK_GROUP_DESCRIPTOR_SIZE;
166
167 rc = block_get(&newref->block, fs->device, block_id, 0);
168 if (rc != EOK) {
169 free(newref);
170 return rc;
171 }
172
173 newref->block_group = newref->block->data + offset;
174
175 *ref = newref;
176
177 return EOK;
178}
179
180/**
181 * TODO doxy
182 */
183int ext4_filesystem_get_inode_ref(ext4_filesystem_t *fs, uint32_t index,
184 ext4_inode_ref_t **ref)
185{
186 int rc;
187 aoff64_t block_id;
188 uint32_t block_group;
189 uint32_t offset_in_group;
190 uint32_t byte_offset_in_group;
191 size_t offset_in_block;
192 uint32_t inodes_per_group;
193 uint32_t inode_table_start;
194 uint16_t inode_size;
195 uint32_t block_size;
196 ext4_block_group_ref_t *bg_ref;
197 ext4_inode_ref_t *newref;
198
199 newref = malloc(sizeof(ext4_inode_ref_t));
200 if (newref == NULL) {
201 return ENOMEM;
202 }
203
204 inodes_per_group = ext4_superblock_get_inodes_per_group(fs->superblock);
205
206 /* inode numbers are 1-based, but it is simpler to work with 0-based
207 * when computing indices
208 */
209 index -= 1;
210 block_group = index / inodes_per_group;
211 offset_in_group = index % inodes_per_group;
212
213 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
214 if (rc != EOK) {
215 free(newref);
216 return rc;
217 }
218
219 inode_table_start = ext4_block_group_get_inode_table_first_block(
220 bg_ref->block_group);
221
222 inode_size = ext4_superblock_get_inode_size(fs->superblock);
223 block_size = ext4_superblock_get_block_size(fs->superblock);
224
225 byte_offset_in_group = offset_in_group * inode_size;
226
227 block_id = inode_table_start + (byte_offset_in_group / block_size);
228 offset_in_block = byte_offset_in_group % block_size;
229
230 rc = block_get(&newref->block, fs->device, block_id, 0);
231 if (rc != EOK) {
232 free(newref);
233 return rc;
234 }
235
236 newref->inode = newref->block->data + offset_in_block;
237 /* we decremented index above, but need to store the original value
238 * in the reference
239 */
240 newref->index = index+1;
241
242 *ref = newref;
243
244 return EOK;
245}
246
247/**
248 * @}
249 */
Note: See TracBrowser for help on using the repository browser.