source: mainline/uspace/lib/ext2/libext2_filesystem.c@ b65cae22

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b65cae22 was a2a1792, checked in by Martin Sucha <sucha14@…>, 14 years ago

Fixed locating of inodes

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Sucha
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 libext2
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include "libext2_filesystem.h"
37#include "libext2_superblock.h"
38#include "libext2_block_group.h"
39#include "libext2_inode.h"
40#include <errno.h>
41#include <libblock.h>
42#include <malloc.h>
43
44/**
45 * Initialize an instance of filesystem on the device.
46 * This function reads superblock from the device and
47 * initializes libblock cache with appropriate logical block size.
48 *
49 * @param fs Pointer to ext2_filesystem_t to initialize
50 * @param devmap_handle Device handle of the block device
51 *
52 * @return EOK on success or negative error code on failure
53 */
54int ext2_filesystem_init(ext2_filesystem_t *fs, devmap_handle_t devmap_handle)
55{
56 int rc;
57 ext2_superblock_t *temp_superblock;
58 size_t block_size;
59
60 fs->device = devmap_handle;
61
62 rc = block_init(fs->device, 2048);
63 if (rc != EOK) {
64 return rc;
65 }
66
67 rc = ext2_superblock_read_direct(fs->device, &temp_superblock);
68 if (rc != EOK) {
69 block_fini(fs->device);
70 return rc;
71 }
72
73 block_size = ext2_superblock_get_block_size(temp_superblock);
74
75 if (block_size > EXT2_MAX_BLOCK_SIZE) {
76 block_fini(fs->device);
77 return ENOTSUP;
78 }
79
80 rc = block_cache_init(devmap_handle, block_size, 0, CACHE_MODE_WT);
81 if (rc != EOK) {
82 block_fini(fs->device);
83 return rc;
84 }
85
86 fs->superblock = temp_superblock;
87
88 return EOK;
89}
90
91/**
92 * Check filesystem for sanity
93 *
94 * @param fs Pointer to ext2_filesystem_t to check
95 * @return EOK on success or negative error code on failure
96 */
97int ext2_filesystem_check_sanity(ext2_filesystem_t *fs)
98{
99 int rc;
100
101 rc = ext2_superblock_check_sanity(fs->superblock);
102 if (rc != EOK) {
103 return rc;
104 }
105
106 return EOK;
107}
108
109/**
110 * Get a reference to block descriptor
111 *
112 * @param fs Pointer to filesystem information
113 * @param bgid Index of block group to find
114 * @param ref Pointer where to store pointer to block group reference
115 *
116 * @return EOK on success or negative error code on failure
117 */
118int ext2_filesystem_get_block_group_ref(ext2_filesystem_t *fs, uint32_t bgid,
119 ext2_block_group_ref_t **ref)
120{
121 int rc;
122 aoff64_t block_id;
123 uint32_t descriptors_per_block;
124 size_t offset;
125 ext2_block_group_ref_t *newref;
126
127 newref = malloc(sizeof(ext2_block_group_ref_t));
128 if (newref == NULL) {
129 return ENOMEM;
130 }
131
132 descriptors_per_block = ext2_superblock_get_block_size(fs->superblock)
133 / EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE;
134
135 // Block group descriptor table starts at the next block after superblock
136 block_id = ext2_superblock_get_first_block(fs->superblock) + 1;
137
138 // Find the block containing the descriptor we are looking for
139 block_id += bgid / descriptors_per_block;
140 offset = (bgid % descriptors_per_block) * EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE;
141
142 rc = block_get(&newref->block, fs->device, block_id, 0);
143 if (rc != EOK) {
144 free(newref);
145 return rc;
146 }
147
148 newref->block_group = newref->block->data + offset;
149
150 *ref = newref;
151
152 return EOK;
153}
154
155/**
156 * Free a reference to block group
157 *
158 * @param ref Pointer to block group reference to free
159 *
160 * @return EOK on success or negative error code on failure
161 */
162int ext2_filesystem_put_block_group_ref(ext2_block_group_ref_t *ref)
163{
164 int rc;
165
166 rc = block_put(ref->block);
167 free(ref);
168
169 return rc;
170}
171
172/**
173 * Get a reference to inode
174 *
175 * @param fs Pointer to filesystem information
176 * @param index The index number of the inode
177 * @param ref Pointer where to store pointer to inode reference
178 *
179 * @return EOK on success or negative error code on failure
180 */
181int ext2_filesystem_get_inode_ref(ext2_filesystem_t *fs, uint32_t index,
182 ext2_inode_ref_t **ref)
183{
184 int rc;
185 aoff64_t block_id;
186 uint32_t block_group;
187 uint32_t offset_in_group;
188 uint32_t byte_offset_in_group;
189 size_t offset_in_block;
190 uint32_t inodes_per_group;
191 uint32_t inode_table_start;
192 uint16_t inode_size;
193 uint32_t block_size;
194 ext2_block_group_ref_t *bg_ref;
195 ext2_inode_ref_t *newref;
196
197 newref = malloc(sizeof(ext2_inode_ref_t));
198 if (newref == NULL) {
199 return ENOMEM;
200 }
201
202 inodes_per_group = ext2_superblock_get_inodes_per_group(fs->superblock);
203
204 // inode numbers are 1-based
205 index -= 1;
206 block_group = index / inodes_per_group;
207 offset_in_group = index % inodes_per_group;
208
209 rc = ext2_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
210 if (rc != EOK) {
211 free(newref);
212 return rc;
213 }
214
215 inode_table_start = ext2_block_group_get_inode_table_first_block(
216 bg_ref->block_group);
217
218 inode_size = ext2_superblock_get_inode_size(fs->superblock);
219 block_size = ext2_superblock_get_block_size(fs->superblock);
220
221 byte_offset_in_group = offset_in_group * inode_size;
222
223 block_id = inode_table_start + (byte_offset_in_group / block_size);
224 offset_in_block = byte_offset_in_group % block_size;
225
226 rc = block_get(&newref->block, fs->device, block_id, 0);
227 if (rc != EOK) {
228 free(newref);
229 return rc;
230 }
231
232 newref->inode = newref->block->data + offset_in_block;
233
234 *ref = newref;
235
236 return EOK;
237}
238
239/**
240 * Free a reference to inode
241 *
242 * @param ref Pointer to inode reference to free
243 *
244 * @return EOK on success or negative error code on failure
245 */
246int ext2_filesystem_put_inode_ref(ext2_inode_ref_t *ref)
247{
248 int rc;
249
250 rc = block_put(ref->block);
251 free(ref);
252
253 return rc;
254}
255
256/**
257 * Finalize an instance of filesystem
258 *
259 * @param fs Pointer to ext2_filesystem_t to finalize
260 */
261void ext2_filesystem_fini(ext2_filesystem_t *fs)
262{
263 free(fs->superblock);
264 block_fini(fs->device);
265}
266
267
268/** @}
269 */
Note: See TracBrowser for help on using the repository browser.