source: mainline/uspace/lib/ext4/libext4_inode.c@ 296ef5d6

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

Part of inode comments

  • Property mode set to 100644
File size: 12.7 KB
RevLine 
[eb91db7]1/*
[f22d5ef0]2 * Copyright (c) 2012 Frantisek Princ
[eb91db7]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_inode.c
[c25e39b]35 * @brief Ext4 inode structure operations.
[eb91db7]36 */
37
[9c0c0e1]38#include <byteorder.h>
[1a7756a]39#include <errno.h>
40#include <libblock.h>
[3711e7e]41#include "libext4.h"
[6c501f8]42
[296ef5d6]43/** Compute number of bits for block count.
44 *
45 * @param block_size filesystem block_size
46 * @return number of bits
47 */
[b3d7277]48static uint32_t ext4_inode_block_bits_count(uint32_t block_size)
49{
50 uint32_t bits = 8;
51 uint32_t size = block_size;
52
53 do {
54 bits++;
55 size = size >> 1;
56 } while (size > 256);
57
58 return bits;
59}
60
[296ef5d6]61/** Get mode of the i-node.
62 *
63 * @param sb superblock
64 * @param inode i-node to load mode from
65 * @return mode of the i-node
66 */
[9b9d37bb]67uint32_t ext4_inode_get_mode(ext4_superblock_t *sb, ext4_inode_t *inode)
68{
69 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD) {
70 return ((uint32_t)uint16_t_le2host(inode->osd2.hurd2.mode_high)) << 16 |
71 ((uint32_t)uint16_t_le2host(inode->mode));
72 }
73 return uint16_t_le2host(inode->mode);
74}
75
[296ef5d6]76/** Set mode of the i-node.
77 *
78 * @param sb superblock
79 * @param inode i-node to set mode to
80 * @param mode mode to set to i-node
81 */
[fe27eb4]82void ext4_inode_set_mode(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t mode)
[9b9d37bb]83{
[fe27eb4]84 inode->mode = host2uint16_t_le((mode << 16) >> 16);
85
86 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD) {
87 inode->osd2.hurd2.mode_high = host2uint16_t_le(mode >> 16);
88 }
[9b9d37bb]89}
90
[296ef5d6]91/** Get ID of the i-node owner (user id).
92 *
93 * @param inode i-node to load uid from
94 * @return user ID of the i-node owner
95 */
[3712434]96uint32_t ext4_inode_get_uid(ext4_inode_t *inode)
[fe27eb4]97{
98 return uint32_t_le2host(inode->uid);
99}
100
[296ef5d6]101/** Set ID of the i-node owner.
102 *
103 * @param inode i-node to set uid to
104 * @param uid ID of the i-node owner
105 */
[fe27eb4]106void ext4_inode_set_uid(ext4_inode_t *inode, uint32_t uid)
107{
108 inode->uid = host2uint32_t_le(uid);
109}
[3712434]110
[296ef5d6]111/** Get real i-node size.
112 *
113 * @param sb superblock
114 * @param inode i-node to load size from
115 * @return real size of i-node
116 */
[9b9d37bb]117uint64_t ext4_inode_get_size(ext4_superblock_t *sb, ext4_inode_t *inode)
[3712434]118{
[9b9d37bb]119 uint32_t major_rev = ext4_superblock_get_rev_level(sb);
120
[acd869e]121 if ((major_rev > 0) && ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) {
[9b9d37bb]122 return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 |
123 ((uint64_t)uint32_t_le2host(inode->size_lo));
[052e82d]124 }
[9b9d37bb]125 return uint32_t_le2host(inode->size_lo);
[3712434]126}
127
[296ef5d6]128/** Set real i-node size.
129 *
130 * @param inode inode to set size to
131 * @param size size of the i-node
132 */
133void ext4_inode_set_size(ext4_inode_t *inode, uint64_t size) {
134 inode->size_lo = host2uint32_t_le((size << 32) >> 32);
135 inode->size_hi = host2uint32_t_le(size >> 32);
[052e82d]136}
137
[fe27eb4]138uint32_t ext4_inode_get_access_time(ext4_inode_t *inode)
139{
140 return uint32_t_le2host(inode->access_time);
141}
142
[296ef5d6]143/** TODO comment
144 *
145 */
[fe27eb4]146void ext4_inode_set_access_time(ext4_inode_t *inode, uint32_t time)
147{
148 inode->access_time = host2uint32_t_le(time);
149}
150
[296ef5d6]151/** TODO comment
152 *
153 */
[fe27eb4]154uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *inode)
155{
156 return uint32_t_le2host(inode->change_inode_time);
157}
158
[296ef5d6]159/** TODO comment
160 *
161 */
[fe27eb4]162void ext4_inode_set_change_inode_time(ext4_inode_t *inode, uint32_t time)
163{
164 inode->change_inode_time = host2uint32_t_le(time);
165}
166
[296ef5d6]167/** TODO comment
168 *
169 */
[fe27eb4]170uint32_t ext4_inode_get_modification_time(ext4_inode_t *inode)
171{
172 return uint32_t_le2host(inode->modification_time);
173}
174
[296ef5d6]175/** TODO comment
176 *
177 */
[fe27eb4]178void ext4_inode_set_modification_time(ext4_inode_t *inode, uint32_t time)
179{
180 inode->modification_time = host2uint32_t_le(time);
181}
182
[296ef5d6]183/** TODO comment
184 *
185 */
[fe27eb4]186uint32_t ext4_inode_get_deletion_time(ext4_inode_t *inode)
187{
188 return uint32_t_le2host(inode->deletion_time);
189}
190
[296ef5d6]191/** TODO comment
192 *
193 */
[fe27eb4]194void ext4_inode_set_deletion_time(ext4_inode_t *inode, uint32_t time)
195{
196 inode->deletion_time = host2uint32_t_le(time);
197}
198
[296ef5d6]199/** Get ID of the i-node owner's group.
200 *
201 * @param inode i-node to load gid from
202 * @return group ID of the i-node owner
203 */
[fe27eb4]204uint32_t ext4_inode_get_gid(ext4_inode_t *inode)
205{
206 return uint32_t_le2host(inode->gid);
207}
208
[296ef5d6]209/** Set ID ot the i-node owner's group.
210 *
211 * @param inode i-node to set gid to
212 * @param gid group ID of the i-node owner
213 */
[fe27eb4]214void ext4_inode_set_gid(ext4_inode_t *inode, uint32_t gid)
215{
216 inode->gid = host2uint32_t_le(gid);
217}
[3712434]218
[296ef5d6]219/** Get number of links to i-node.
220 *
221 * @param inode i-node to load number of links from
222 * @return number of links to i-node
223 */
[3712434]224uint16_t ext4_inode_get_links_count(ext4_inode_t *inode)
[6c501f8]225{
[9c0c0e1]226 return uint16_t_le2host(inode->links_count);
[6c501f8]227}
228
[296ef5d6]229/** Set number of links to i-node.
230 *
231 * @param inode i-node to set number of links to
232 * @param count number of links to i-node
233 */
[fe27eb4]234void ext4_inode_set_links_count(ext4_inode_t *inode, uint16_t count)
235{
236 inode->links_count = host2uint16_t_le(count);
237}
[b3d7277]238
[296ef5d6]239/** TODO comment
240 *
241 */
[b3d7277]242uint64_t ext4_inode_get_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode)
243{
244 if (ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
245
[296ef5d6]246 // 48-bit field
[d9bbe45]247 uint64_t count = ((uint64_t)uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 |
[b3d7277]248 uint32_t_le2host(inode->blocks_count_lo);
249
250 if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {
251 uint32_t block_size = ext4_superblock_get_block_size(sb);
252 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
253 return count << (block_bits - 9);
254 } else {
255 return count;
256 }
257 } else {
258 return uint32_t_le2host(inode->blocks_count_lo);
259 }
260
261}
262
[296ef5d6]263
264/** TODO comment
265 *
266 */
[b3d7277]267int ext4_inode_set_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode,
268 uint64_t count)
269{
270 // 32-bit maximum
271 uint64_t max = 0;
272 max = ~max >> 32;
273
274 if (count <= max) {
275 inode->blocks_count_lo = host2uint32_t_le(count);
276 inode->osd2.linux2.blocks_high = 0;
277 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
278 return EOK;
279 }
280
281 if (!ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
282 return EINVAL;
283 }
284
285 // 48-bit maximum
286 max = 0;
287 max = ~max >> 16;
288
289 if (count <= max) {
290 inode->blocks_count_lo = host2uint32_t_le(count);
291 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
292 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
293 } else {
294 uint32_t block_size = ext4_superblock_get_block_size(sb);
295 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
296 ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
297 count = count >> (block_bits - 9);
298 inode->blocks_count_lo = host2uint32_t_le(count);
299 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
300 }
301 return EOK;
302}
[eb91db7]303
[296ef5d6]304/** Get flags (features) of i-node.
305 *
306 * @param inode i-node to get flags from
307 * @return flags (bitmap)
308 */
[7b9381b]309uint32_t ext4_inode_get_flags(ext4_inode_t *inode) {
310 return uint32_t_le2host(inode->flags);
311}
312
[296ef5d6]313/** Set flags (features) of i-node.
314 *
315 * @param inode i-node to set flags to
316 * @param flags flags to set to i-node
317 */
[b3d7277]318void ext4_inode_set_flags(ext4_inode_t *inode, uint32_t flags) {
319 inode->flags = host2uint32_t_le(flags);
320}
321
[296ef5d6]322/** TODO comment
323 *
324 */
[fe27eb4]325uint32_t ext4_inode_get_generation(ext4_inode_t *inode)
326{
327 return uint32_t_le2host(inode->generation);
328}
329
[296ef5d6]330/** TODO comment
331 *
332 */
[fe27eb4]333void ext4_inode_set_generation(ext4_inode_t *inode, uint32_t generation)
334{
335 inode->generation = host2uint32_t_le(generation);
336}
337
[296ef5d6]338/** TODO comment
339 *
340 */
[b191acae]341uint64_t ext4_inode_get_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb)
[343ccfd]342{
343 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX) {
344 return ((uint32_t)uint16_t_le2host(inode->osd2.linux2.file_acl_high)) << 16 |
345 (uint32_t_le2host(inode->file_acl_lo));
346 }
347
348 return uint32_t_le2host(inode->file_acl_lo);
349}
350
[296ef5d6]351/** TODO comment
352 *
353 */
[b191acae]354void ext4_inode_set_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb,
[343ccfd]355 uint64_t file_acl)
356{
357 inode->file_acl_lo = host2uint32_t_le((file_acl << 32) >> 32);
358
359 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX) {
360 inode->osd2.linux2.file_acl_high = host2uint16_t_le(file_acl >> 32);
361 }
362}
363
[fe27eb4]364/***********************************************************************/
365
[296ef5d6]366/** Get block address of specified direct block.
367 *
368 * @param inode i-node to load block from
369 * @param idx index of logical block
370 * @return physical block address
371 */
[1e65444]372uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]373{
374 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
375 return uint32_t_le2host(inode->blocks[idx]);
376}
377
[296ef5d6]378/** Set block address of specified direct block.
379 *
380 * @param inode i-node to set block address to
381 * @param idx index of logical block
382 * @param fblock physical block address
383 */
[1e65444]384void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
[d5a78e28]385{
386 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
387 inode->blocks[idx] = host2uint32_t_le(fblock);
388}
389
[296ef5d6]390/** Get block address of specified indirect block.
391 *
392 * @param inode i-node to get block address from
393 * @param idx index of indirect block
394 * @return physical block address
395 */
[1e65444]396uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]397{
398 return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
399}
400
[296ef5d6]401/** Set block address of specified indirect block.
402 *
403 * @param inode i-node to set block address to
404 * @param idx index of indirect block
405 * @param fblock physical block address
406 */
[1e65444]407void ext4_inode_set_indirect_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
408{
409 inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] = host2uint32_t_le(fblock);
410}
411
[296ef5d6]412/** Check if i-node has specified type.
413 *
414 * @param sb superblock
415 * @param inode i-node to check type of
416 * @param type type to check
417 * @return result of check operation
418 */
[fe27eb4]419bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t type)
420{
421 uint32_t mode = ext4_inode_get_mode(sb, inode);
422 return (mode & EXT4_INODE_MODE_TYPE_MASK) == type;
423}
424
[296ef5d6]425/** Get extent header from the root of the extent tree.
426 *
427 * @param inode i-node to get extent header from
428 * @return pointer to extent header of the root node
429 */
[acd869e]430ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *inode)
431{
432 return (ext4_extent_header_t *)inode->blocks;
433}
[7b9381b]434
[296ef5d6]435/** Check if i-node has specified flag.
436 *
437 * @param inode i-node to check flags of
438 * @param flag flag to check
439 * @return result of check operation
440 */
[7bc4508]441bool ext4_inode_has_flag(ext4_inode_t *inode, uint32_t flag)
442{
[7b9381b]443 if (ext4_inode_get_flags(inode) & flag) {
444 return true;
445 }
446 return false;
447}
448
[296ef5d6]449/** Remove specified flag from i-node.
450 *
451 * @param inode i-node to clear flag on
452 * @param clear_flag flag to be cleared
453 */
[b3d7277]454void ext4_inode_clear_flag(ext4_inode_t *inode, uint32_t clear_flag)
455{
456 uint32_t flags = ext4_inode_get_flags(inode);
457 flags = flags & (~clear_flag);
458 ext4_inode_set_flags(inode, flags);
459}
460
[296ef5d6]461/** Set specified flag to i-node.
462 *
463 * @param inode i-node to set flag on
464 * @param set_flag falt to be set
465 */
[b3d7277]466void ext4_inode_set_flag(ext4_inode_t *inode, uint32_t set_flag)
467{
468 uint32_t flags = ext4_inode_get_flags(inode);
469 flags = flags | set_flag;
470 ext4_inode_set_flags(inode, flags);
471}
472
[296ef5d6]473/** Check if i-node can be truncated.
474 *
475 * @param sb superblock
476 * @param inode i-node to check
477 * @return result of the check operation
478 */
[43a9968]479bool ext4_inode_can_truncate(ext4_superblock_t *sb, ext4_inode_t *inode)
[12b4a7f]480{
481 if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)
482 || ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)) {
483 return false;
484 }
485
[e31e56a1]486 if (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)
487 || ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)) {
[12b4a7f]488 return true;
489 }
490
491 return false;
492}
493
[eb91db7]494/**
495 * @}
496 */
Note: See TracBrowser for help on using the repository browser.