source: mainline/uspace/lib/ext4/libext4_inode.c@ 3169f3b0

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

some i-node comments

  • Property mode set to 100644
File size: 13.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
[2add9ec]138/** Get time, when i-node was last accessed.
139 *
140 * @param inode i-node
141 * @return time of the last access (POSIX)
142 */
[fe27eb4]143uint32_t ext4_inode_get_access_time(ext4_inode_t *inode)
144{
145 return uint32_t_le2host(inode->access_time);
146}
147
[2add9ec]148/** Set time, when i-node was last accessed.
[296ef5d6]149 *
[2add9ec]150 * @param inode i-node
151 * @param time time of the last access (POSIX)
[296ef5d6]152 */
[fe27eb4]153void ext4_inode_set_access_time(ext4_inode_t *inode, uint32_t time)
154{
155 inode->access_time = host2uint32_t_le(time);
156}
157
[296ef5d6]158/** TODO comment
159 *
160 */
[fe27eb4]161uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *inode)
162{
163 return uint32_t_le2host(inode->change_inode_time);
164}
165
[296ef5d6]166/** TODO comment
167 *
168 */
[fe27eb4]169void ext4_inode_set_change_inode_time(ext4_inode_t *inode, uint32_t time)
170{
171 inode->change_inode_time = host2uint32_t_le(time);
172}
173
[296ef5d6]174/** TODO comment
175 *
176 */
[fe27eb4]177uint32_t ext4_inode_get_modification_time(ext4_inode_t *inode)
178{
179 return uint32_t_le2host(inode->modification_time);
180}
181
[296ef5d6]182/** TODO comment
183 *
184 */
[fe27eb4]185void ext4_inode_set_modification_time(ext4_inode_t *inode, uint32_t time)
186{
187 inode->modification_time = host2uint32_t_le(time);
188}
189
[296ef5d6]190/** TODO comment
191 *
192 */
[fe27eb4]193uint32_t ext4_inode_get_deletion_time(ext4_inode_t *inode)
194{
195 return uint32_t_le2host(inode->deletion_time);
196}
197
[296ef5d6]198/** TODO comment
199 *
200 */
[fe27eb4]201void ext4_inode_set_deletion_time(ext4_inode_t *inode, uint32_t time)
202{
203 inode->deletion_time = host2uint32_t_le(time);
204}
205
[296ef5d6]206/** Get ID of the i-node owner's group.
207 *
208 * @param inode i-node to load gid from
209 * @return group ID of the i-node owner
210 */
[fe27eb4]211uint32_t ext4_inode_get_gid(ext4_inode_t *inode)
212{
213 return uint32_t_le2host(inode->gid);
214}
215
[296ef5d6]216/** Set ID ot the i-node owner's group.
217 *
218 * @param inode i-node to set gid to
219 * @param gid group ID of the i-node owner
220 */
[fe27eb4]221void ext4_inode_set_gid(ext4_inode_t *inode, uint32_t gid)
222{
223 inode->gid = host2uint32_t_le(gid);
224}
[3712434]225
[296ef5d6]226/** Get number of links to i-node.
227 *
228 * @param inode i-node to load number of links from
229 * @return number of links to i-node
230 */
[3712434]231uint16_t ext4_inode_get_links_count(ext4_inode_t *inode)
[6c501f8]232{
[9c0c0e1]233 return uint16_t_le2host(inode->links_count);
[6c501f8]234}
235
[296ef5d6]236/** Set number of links to i-node.
237 *
238 * @param inode i-node to set number of links to
239 * @param count number of links to i-node
240 */
[fe27eb4]241void ext4_inode_set_links_count(ext4_inode_t *inode, uint16_t count)
242{
243 inode->links_count = host2uint16_t_le(count);
244}
[b3d7277]245
[2add9ec]246/** Get number of 512-bytes blocks used for i-node.
[296ef5d6]247 *
[2add9ec]248 * @param sb superblock
249 * @param inode i-node
250 * @return number of 512-bytes blocks
[296ef5d6]251 */
[b3d7277]252uint64_t ext4_inode_get_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode)
253{
254 if (ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
255
[296ef5d6]256 // 48-bit field
[d9bbe45]257 uint64_t count = ((uint64_t)uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 |
[b3d7277]258 uint32_t_le2host(inode->blocks_count_lo);
259
260 if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {
261 uint32_t block_size = ext4_superblock_get_block_size(sb);
262 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
263 return count << (block_bits - 9);
264 } else {
265 return count;
266 }
267 } else {
268 return uint32_t_le2host(inode->blocks_count_lo);
269 }
270}
271
[2add9ec]272/** Set number of 512-bytes blocks used for i-node.
[296ef5d6]273 *
[2add9ec]274 * @param sb superblock
275 * @param inode i-node
276 * @param count number of 512-bytes blocks
277 * @return error code
[296ef5d6]278 */
[b3d7277]279int ext4_inode_set_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode,
280 uint64_t count)
281{
282 // 32-bit maximum
283 uint64_t max = 0;
284 max = ~max >> 32;
285
286 if (count <= max) {
287 inode->blocks_count_lo = host2uint32_t_le(count);
288 inode->osd2.linux2.blocks_high = 0;
289 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
290 return EOK;
291 }
292
[2add9ec]293 // Check if there can be used huge files (many blocks)
[b3d7277]294 if (!ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
295 return EINVAL;
296 }
297
298 // 48-bit maximum
299 max = 0;
300 max = ~max >> 16;
301
302 if (count <= max) {
303 inode->blocks_count_lo = host2uint32_t_le(count);
304 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
305 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
306 } else {
307 uint32_t block_size = ext4_superblock_get_block_size(sb);
308 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
309 ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
310 count = count >> (block_bits - 9);
311 inode->blocks_count_lo = host2uint32_t_le(count);
312 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
313 }
314 return EOK;
315}
[eb91db7]316
[296ef5d6]317/** Get flags (features) of i-node.
318 *
319 * @param inode i-node to get flags from
320 * @return flags (bitmap)
321 */
[7b9381b]322uint32_t ext4_inode_get_flags(ext4_inode_t *inode) {
323 return uint32_t_le2host(inode->flags);
324}
325
[296ef5d6]326/** Set flags (features) of i-node.
327 *
328 * @param inode i-node to set flags to
329 * @param flags flags to set to i-node
330 */
[b3d7277]331void ext4_inode_set_flags(ext4_inode_t *inode, uint32_t flags) {
332 inode->flags = host2uint32_t_le(flags);
333}
334
[2add9ec]335/** Get file generation (used by NFS).
[296ef5d6]336 *
[2add9ec]337 * @param inode i-node
338 * @return file generation
[296ef5d6]339 */
[fe27eb4]340uint32_t ext4_inode_get_generation(ext4_inode_t *inode)
341{
342 return uint32_t_le2host(inode->generation);
343}
344
[2add9ec]345/** Set file generation (used by NFS).
[296ef5d6]346 *
[2add9ec]347 * @param inode i-node
348 * @param generation file generation
[296ef5d6]349 */
[fe27eb4]350void ext4_inode_set_generation(ext4_inode_t *inode, uint32_t generation)
351{
352 inode->generation = host2uint32_t_le(generation);
353}
354
[2add9ec]355/** Get address of block, where are extended attributes located.
[296ef5d6]356 *
[2add9ec]357 * @param inode i-node
358 * @param sb superblock
359 * @return block address
[296ef5d6]360 */
[b191acae]361uint64_t ext4_inode_get_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb)
[343ccfd]362{
363 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX) {
364 return ((uint32_t)uint16_t_le2host(inode->osd2.linux2.file_acl_high)) << 16 |
365 (uint32_t_le2host(inode->file_acl_lo));
366 }
367
368 return uint32_t_le2host(inode->file_acl_lo);
369}
370
[2add9ec]371/** Set address of block, where are extended attributes located.
[296ef5d6]372 *
[2add9ec]373 * @param inode i-node
374 * @param sb superblock
375 * @param file_acl block address
[296ef5d6]376 */
[b191acae]377void ext4_inode_set_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb,
[343ccfd]378 uint64_t file_acl)
379{
380 inode->file_acl_lo = host2uint32_t_le((file_acl << 32) >> 32);
381
382 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX) {
383 inode->osd2.linux2.file_acl_high = host2uint16_t_le(file_acl >> 32);
384 }
385}
386
[fe27eb4]387/***********************************************************************/
388
[296ef5d6]389/** Get block address of specified direct block.
390 *
391 * @param inode i-node to load block from
392 * @param idx index of logical block
393 * @return physical block address
394 */
[1e65444]395uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]396{
397 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
398 return uint32_t_le2host(inode->blocks[idx]);
399}
400
[296ef5d6]401/** Set block address of specified direct block.
402 *
403 * @param inode i-node to set block address to
404 * @param idx index of logical block
405 * @param fblock physical block address
406 */
[1e65444]407void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
[d5a78e28]408{
409 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
410 inode->blocks[idx] = host2uint32_t_le(fblock);
411}
412
[296ef5d6]413/** Get block address of specified indirect block.
414 *
415 * @param inode i-node to get block address from
416 * @param idx index of indirect block
417 * @return physical block address
418 */
[1e65444]419uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]420{
421 return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
422}
423
[296ef5d6]424/** Set block address of specified indirect block.
425 *
426 * @param inode i-node to set block address to
427 * @param idx index of indirect block
428 * @param fblock physical block address
429 */
[1e65444]430void ext4_inode_set_indirect_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
431{
432 inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] = host2uint32_t_le(fblock);
433}
434
[296ef5d6]435/** Check if i-node has specified type.
436 *
437 * @param sb superblock
438 * @param inode i-node to check type of
439 * @param type type to check
440 * @return result of check operation
441 */
[fe27eb4]442bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t type)
443{
444 uint32_t mode = ext4_inode_get_mode(sb, inode);
445 return (mode & EXT4_INODE_MODE_TYPE_MASK) == type;
446}
447
[296ef5d6]448/** Get extent header from the root of the extent tree.
449 *
450 * @param inode i-node to get extent header from
451 * @return pointer to extent header of the root node
452 */
[acd869e]453ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *inode)
454{
455 return (ext4_extent_header_t *)inode->blocks;
456}
[7b9381b]457
[296ef5d6]458/** Check if i-node has specified flag.
459 *
460 * @param inode i-node to check flags of
461 * @param flag flag to check
462 * @return result of check operation
463 */
[7bc4508]464bool ext4_inode_has_flag(ext4_inode_t *inode, uint32_t flag)
465{
[7b9381b]466 if (ext4_inode_get_flags(inode) & flag) {
467 return true;
468 }
469 return false;
470}
471
[296ef5d6]472/** Remove specified flag from i-node.
473 *
474 * @param inode i-node to clear flag on
475 * @param clear_flag flag to be cleared
476 */
[b3d7277]477void ext4_inode_clear_flag(ext4_inode_t *inode, uint32_t clear_flag)
478{
479 uint32_t flags = ext4_inode_get_flags(inode);
480 flags = flags & (~clear_flag);
481 ext4_inode_set_flags(inode, flags);
482}
483
[296ef5d6]484/** Set specified flag to i-node.
485 *
486 * @param inode i-node to set flag on
487 * @param set_flag falt to be set
488 */
[b3d7277]489void ext4_inode_set_flag(ext4_inode_t *inode, uint32_t set_flag)
490{
491 uint32_t flags = ext4_inode_get_flags(inode);
492 flags = flags | set_flag;
493 ext4_inode_set_flags(inode, flags);
494}
495
[296ef5d6]496/** Check if i-node can be truncated.
497 *
498 * @param sb superblock
499 * @param inode i-node to check
500 * @return result of the check operation
501 */
[43a9968]502bool ext4_inode_can_truncate(ext4_superblock_t *sb, ext4_inode_t *inode)
[12b4a7f]503{
504 if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)
505 || ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)) {
506 return false;
507 }
508
[e31e56a1]509 if (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)
510 || ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)) {
[12b4a7f]511 return true;
512 }
513
514 return false;
515}
516
[eb91db7]517/**
518 * @}
519 */
Note: See TracBrowser for help on using the repository browser.