source: mainline/uspace/lib/ext4/src/inode.c@ 1e4a937

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1e4a937 was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

  • Property mode set to 100644
File size: 14.3 KB
RevLine 
[eb91db7]1/*
[d1538a1]2 * Copyright (c) 2011 Martin Sucha
[f22d5ef0]3 * Copyright (c) 2012 Frantisek Princ
[eb91db7]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libext4
31 * @{
[38542dc]32 */
[eb91db7]33/**
[4bfad34]34 * @file inode.c
[38542dc]35 * @brief Ext4 i-node structure operations.
[eb91db7]36 */
37
[fcb0d76]38#include <block.h>
[9c0c0e1]39#include <byteorder.h>
[1a7756a]40#include <errno.h>
[fcb0d76]41#include "ext4/inode.h"
42#include "ext4/superblock.h"
[6c501f8]43
[296ef5d6]44/** Compute number of bits for block count.
45 *
[38542dc]46 * @param block_size Filesystem block_size
47 *
48 * @return Number of bits
49 *
[296ef5d6]50 */
[b3d7277]51static uint32_t ext4_inode_block_bits_count(uint32_t block_size)
52{
53 uint32_t bits = 8;
54 uint32_t size = block_size;
[a35b458]55
[b3d7277]56 do {
57 bits++;
58 size = size >> 1;
59 } while (size > 256);
[a35b458]60
[b3d7277]61 return bits;
62}
63
[296ef5d6]64/** Get mode of the i-node.
65 *
[38542dc]66 * @param sb Superblock
67 * @param inode I-node to load mode from
68 *
69 * @return Mode of the i-node
70 *
[296ef5d6]71 */
[9b9d37bb]72uint32_t ext4_inode_get_mode(ext4_superblock_t *sb, ext4_inode_t *inode)
73{
74 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD) {
[38542dc]75 return ((uint32_t) uint16_t_le2host(inode->osd2.hurd2.mode_high)) << 16 |
76 ((uint32_t) uint16_t_le2host(inode->mode));
[9b9d37bb]77 }
[a35b458]78
[9b9d37bb]79 return uint16_t_le2host(inode->mode);
80}
81
[296ef5d6]82/** Set mode of the i-node.
83 *
[38542dc]84 * @param sb Superblock
85 * @param inode I-node to set mode to
86 * @param mode Mode to set to i-node
87 *
[296ef5d6]88 */
[fe27eb4]89void ext4_inode_set_mode(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t mode)
[9b9d37bb]90{
[fe27eb4]91 inode->mode = host2uint16_t_le((mode << 16) >> 16);
[a35b458]92
[38542dc]93 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD)
[fe27eb4]94 inode->osd2.hurd2.mode_high = host2uint16_t_le(mode >> 16);
[9b9d37bb]95}
96
[296ef5d6]97/** Get ID of the i-node owner (user id).
98 *
[38542dc]99 * @param inode I-node to load uid from
100 *
101 * @return User ID of the i-node owner
102 *
[296ef5d6]103 */
[3712434]104uint32_t ext4_inode_get_uid(ext4_inode_t *inode)
[fe27eb4]105{
106 return uint32_t_le2host(inode->uid);
107}
108
[296ef5d6]109/** Set ID of the i-node owner.
110 *
[38542dc]111 * @param inode I-node to set uid to
112 * @param uid ID of the i-node owner
113 *
[296ef5d6]114 */
[fe27eb4]115void ext4_inode_set_uid(ext4_inode_t *inode, uint32_t uid)
116{
117 inode->uid = host2uint32_t_le(uid);
118}
[3712434]119
[296ef5d6]120/** Get real i-node size.
121 *
[38542dc]122 * @param sb Superblock
123 * @param inode I-node to load size from
124 *
125 * @return Real size of i-node
126 *
[296ef5d6]127 */
[9b9d37bb]128uint64_t ext4_inode_get_size(ext4_superblock_t *sb, ext4_inode_t *inode)
[3712434]129{
[9b9d37bb]130 uint32_t major_rev = ext4_superblock_get_rev_level(sb);
[a35b458]131
[38542dc]132 if ((major_rev > 0) &&
133 (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)))
[9b9d37bb]134 return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 |
[38542dc]135 ((uint64_t)uint32_t_le2host(inode->size_lo));
[a35b458]136
[9b9d37bb]137 return uint32_t_le2host(inode->size_lo);
[3712434]138}
139
[296ef5d6]140/** Set real i-node size.
141 *
[38542dc]142 * @param inode I-node to set size to
143 * @param size Size of the i-node
144 *
[296ef5d6]145 */
[38542dc]146void ext4_inode_set_size(ext4_inode_t *inode, uint64_t size)
147{
[296ef5d6]148 inode->size_lo = host2uint32_t_le((size << 32) >> 32);
149 inode->size_hi = host2uint32_t_le(size >> 32);
[052e82d]150}
151
[2add9ec]152/** Get time, when i-node was last accessed.
153 *
[38542dc]154 * @param inode I-node
155 *
156 * @return Time of the last access (POSIX)
157 *
[2add9ec]158 */
[fe27eb4]159uint32_t ext4_inode_get_access_time(ext4_inode_t *inode)
160{
161 return uint32_t_le2host(inode->access_time);
162}
163
[2add9ec]164/** Set time, when i-node was last accessed.
[296ef5d6]165 *
[38542dc]166 * @param inode I-node
167 * @param time Time of the last access (POSIX)
168 *
[296ef5d6]169 */
[fe27eb4]170void ext4_inode_set_access_time(ext4_inode_t *inode, uint32_t time)
171{
172 inode->access_time = host2uint32_t_le(time);
173}
174
[da9f220d]175/** Get time, when i-node was last changed.
[296ef5d6]176 *
[38542dc]177 * @param inode I-node
178 *
179 * @return Time of the last change (POSIX)
180 *
[296ef5d6]181 */
[fe27eb4]182uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *inode)
183{
184 return uint32_t_le2host(inode->change_inode_time);
185}
186
[da9f220d]187/** Set time, when i-node was last changed.
[296ef5d6]188 *
[38542dc]189 * @param inode I-node
190 * @param time Time of the last change (POSIX)
191 *
[296ef5d6]192 */
[fe27eb4]193void ext4_inode_set_change_inode_time(ext4_inode_t *inode, uint32_t time)
194{
195 inode->change_inode_time = host2uint32_t_le(time);
196}
197
[da9f220d]198/** Get time, when i-node content was last modified.
[296ef5d6]199 *
[38542dc]200 * @param inode I-node
201 *
202 * @return Time of the last content modification (POSIX)
203 *
[296ef5d6]204 */
[fe27eb4]205uint32_t ext4_inode_get_modification_time(ext4_inode_t *inode)
206{
207 return uint32_t_le2host(inode->modification_time);
208}
209
[da9f220d]210/** Set time, when i-node content was last modified.
[296ef5d6]211 *
[38542dc]212 * @param inode I-node
213 * @param time Time of the last content modification (POSIX)
214 *
[296ef5d6]215 */
[fe27eb4]216void ext4_inode_set_modification_time(ext4_inode_t *inode, uint32_t time)
217{
218 inode->modification_time = host2uint32_t_le(time);
219}
220
[5b26747]221/** Get time, when i-node was deleted.
[296ef5d6]222 *
[38542dc]223 * @param inode I-node
224 *
225 * @return Time of the delete action (POSIX)
226 *
[296ef5d6]227 */
[fe27eb4]228uint32_t ext4_inode_get_deletion_time(ext4_inode_t *inode)
229{
230 return uint32_t_le2host(inode->deletion_time);
231}
232
[5b26747]233/** Set time, when i-node was deleted.
[296ef5d6]234 *
[38542dc]235 * @param inode I-node
236 * @param time Time of the delete action (POSIX)
237 *
[296ef5d6]238 */
[fe27eb4]239void ext4_inode_set_deletion_time(ext4_inode_t *inode, uint32_t time)
240{
241 inode->deletion_time = host2uint32_t_le(time);
242}
243
[296ef5d6]244/** Get ID of the i-node owner's group.
245 *
[38542dc]246 * @param inode I-node to load gid from
247 *
248 * @return Group ID of the i-node owner
249 *
[296ef5d6]250 */
[fe27eb4]251uint32_t ext4_inode_get_gid(ext4_inode_t *inode)
252{
253 return uint32_t_le2host(inode->gid);
254}
255
[296ef5d6]256/** Set ID ot the i-node owner's group.
257 *
[38542dc]258 * @param inode I-node to set gid to
259 * @param gid Group ID of the i-node owner
260 *
[296ef5d6]261 */
[fe27eb4]262void ext4_inode_set_gid(ext4_inode_t *inode, uint32_t gid)
263{
264 inode->gid = host2uint32_t_le(gid);
265}
[3712434]266
[296ef5d6]267/** Get number of links to i-node.
268 *
[38542dc]269 * @param inode I-node to load number of links from
270 *
271 * @return Number of links to i-node
272 *
[296ef5d6]273 */
[3712434]274uint16_t ext4_inode_get_links_count(ext4_inode_t *inode)
[6c501f8]275{
[9c0c0e1]276 return uint16_t_le2host(inode->links_count);
[6c501f8]277}
278
[296ef5d6]279/** Set number of links to i-node.
280 *
[38542dc]281 * @param inode I-node to set number of links to
282 * @param count Number of links to i-node
283 *
[296ef5d6]284 */
[fe27eb4]285void ext4_inode_set_links_count(ext4_inode_t *inode, uint16_t count)
286{
287 inode->links_count = host2uint16_t_le(count);
288}
[b3d7277]289
[2add9ec]290/** Get number of 512-bytes blocks used for i-node.
[296ef5d6]291 *
[38542dc]292 * @param sb Superblock
293 * @param inode I-node
294 *
295 * @return Number of 512-bytes blocks
296 *
[296ef5d6]297 */
[b3d7277]298uint64_t ext4_inode_get_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode)
299{
[38542dc]300 if (ext4_superblock_has_feature_read_only(sb,
301 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
[06d85e5]302 /* 48-bit field */
[38542dc]303 uint64_t count = ((uint64_t)
304 uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 |
305 uint32_t_le2host(inode->blocks_count_lo);
[a35b458]306
[b3d7277]307 if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {
[38542dc]308 uint32_t block_size = ext4_superblock_get_block_size(sb);
309 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
310 return count << (block_bits - 9);
311 } else
[b3d7277]312 return count;
[38542dc]313 } else
[b3d7277]314 return uint32_t_le2host(inode->blocks_count_lo);
315}
316
[2add9ec]317/** Set number of 512-bytes blocks used for i-node.
[296ef5d6]318 *
[38542dc]319 * @param sb Superblock
320 * @param inode I-node
321 * @param count Number of 512-bytes blocks
322 *
323 * @return Error code
324 *
[296ef5d6]325 */
[b7fd2a0]326errno_t ext4_inode_set_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode,
[38542dc]327 uint64_t count)
328{
329 /* 32-bit maximum */
330 uint64_t max = 0;
331 max = ~max >> 32;
[a35b458]332
[38542dc]333 if (count <= max) {
334 inode->blocks_count_lo = host2uint32_t_le(count);
335 inode->osd2.linux2.blocks_high = 0;
336 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
[a35b458]337
[38542dc]338 return EOK;
339 }
[a35b458]340
[38542dc]341 /* Check if there can be used huge files (many blocks) */
342 if (!ext4_superblock_has_feature_read_only(sb,
343 EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
344 return EINVAL;
[a35b458]345
[38542dc]346 /* 48-bit maximum */
347 max = 0;
348 max = ~max >> 16;
[a35b458]349
[38542dc]350 if (count <= max) {
351 inode->blocks_count_lo = host2uint32_t_le(count);
352 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
353 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
354 } else {
355 uint32_t block_size = ext4_superblock_get_block_size(sb);
356 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
357 ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
358 count = count >> (block_bits - 9);
359 inode->blocks_count_lo = host2uint32_t_le(count);
360 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
361 }
[a35b458]362
[38542dc]363 return EOK;
[b3d7277]364}
[eb91db7]365
[296ef5d6]366/** Get flags (features) of i-node.
[38542dc]367 *
368 * @param inode I-node to get flags from
369 *
370 * @return Flags (bitmap)
371 *
[296ef5d6]372 */
[38542dc]373uint32_t ext4_inode_get_flags(ext4_inode_t *inode)
374{
[7b9381b]375 return uint32_t_le2host(inode->flags);
376}
377
[296ef5d6]378/** Set flags (features) of i-node.
379 *
[38542dc]380 * @param inode I-node to set flags to
381 * @param flags Flags to set to i-node
382 *
[296ef5d6]383 */
[38542dc]384void ext4_inode_set_flags(ext4_inode_t *inode, uint32_t flags)
385{
[b3d7277]386 inode->flags = host2uint32_t_le(flags);
387}
388
[2add9ec]389/** Get file generation (used by NFS).
[296ef5d6]390 *
[38542dc]391 * @param inode I-node
392 *
393 * @return File generation
394 *
[296ef5d6]395 */
[fe27eb4]396uint32_t ext4_inode_get_generation(ext4_inode_t *inode)
397{
398 return uint32_t_le2host(inode->generation);
399}
400
[2add9ec]401/** Set file generation (used by NFS).
[296ef5d6]402 *
[38542dc]403 * @param inode I-node
404 * @param generation File generation
405 *
[296ef5d6]406 */
[fe27eb4]407void ext4_inode_set_generation(ext4_inode_t *inode, uint32_t generation)
408{
409 inode->generation = host2uint32_t_le(generation);
410}
411
[2add9ec]412/** Get address of block, where are extended attributes located.
[296ef5d6]413 *
[38542dc]414 * @param inode I-node
415 * @param sb Superblock
416 *
417 * @return Block address
418 *
[296ef5d6]419 */
[b191acae]420uint64_t ext4_inode_get_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb)
[343ccfd]421{
[38542dc]422 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX)
423 return ((uint32_t)
424 uint16_t_le2host(inode->osd2.linux2.file_acl_high)) << 16 |
[343ccfd]425 (uint32_t_le2host(inode->file_acl_lo));
[a35b458]426
[343ccfd]427 return uint32_t_le2host(inode->file_acl_lo);
428}
429
[2add9ec]430/** Set address of block, where are extended attributes located.
[296ef5d6]431 *
[38542dc]432 * @param inode I-node
433 * @param sb Superblock
434 * @param file_acl Block address
435 *
[296ef5d6]436 */
[b191acae]437void ext4_inode_set_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb,
[38542dc]438 uint64_t file_acl)
[343ccfd]439{
440 inode->file_acl_lo = host2uint32_t_le((file_acl << 32) >> 32);
[a35b458]441
[38542dc]442 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX)
[343ccfd]443 inode->osd2.linux2.file_acl_high = host2uint16_t_le(file_acl >> 32);
444}
445
[296ef5d6]446/** Get block address of specified direct block.
447 *
[38542dc]448 * @param inode I-node to load block from
449 * @param idx Index of logical block
450 *
451 * @return Physical block address
452 *
[296ef5d6]453 */
[1e65444]454uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]455{
456 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
[a35b458]457
[9b9d37bb]458 return uint32_t_le2host(inode->blocks[idx]);
459}
460
[296ef5d6]461/** Set block address of specified direct block.
462 *
[38542dc]463 * @param inode I-node to set block address to
464 * @param idx Index of logical block
465 * @param fblock Physical block address
466 *
[296ef5d6]467 */
[1e65444]468void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
[d5a78e28]469{
470 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
[a35b458]471
[d5a78e28]472 inode->blocks[idx] = host2uint32_t_le(fblock);
473}
474
[296ef5d6]475/** Get block address of specified indirect block.
476 *
[38542dc]477 * @param inode I-node to get block address from
[1b20da0]478 * @param idx Index of indirect block
[38542dc]479 *
480 * @return Physical block address
481 *
[296ef5d6]482 */
[1e65444]483uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]484{
485 return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
486}
487
[296ef5d6]488/** Set block address of specified indirect block.
489 *
[38542dc]490 * @param inode I-node to set block address to
491 * @param idx Index of indirect block
492 * @param fblock Physical block address
493 *
[296ef5d6]494 */
[38542dc]495void ext4_inode_set_indirect_block(ext4_inode_t *inode, uint32_t idx,
496 uint32_t fblock)
[1e65444]497{
[38542dc]498 inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] =
499 host2uint32_t_le(fblock);
[1e65444]500}
501
[296ef5d6]502/** Check if i-node has specified type.
503 *
[38542dc]504 * @param sb Superblock
505 * @param inode I-node to check type of
506 * @param type Type to check
507 *
508 * @return Result of check operation
509 *
[296ef5d6]510 */
[38542dc]511bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode,
512 uint32_t type)
[fe27eb4]513{
514 uint32_t mode = ext4_inode_get_mode(sb, inode);
515 return (mode & EXT4_INODE_MODE_TYPE_MASK) == type;
516}
517
[296ef5d6]518/** Get extent header from the root of the extent tree.
519 *
[38542dc]520 * @param inode I-node to get extent header from
521 *
522 * @return Pointer to extent header of the root node
523 *
[296ef5d6]524 */
[1433ecda]525ext4_extent_header_t *ext4_inode_get_extent_header(ext4_inode_t *inode)
[acd869e]526{
[38542dc]527 return (ext4_extent_header_t *) inode->blocks;
[acd869e]528}
[7b9381b]529
[296ef5d6]530/** Check if i-node has specified flag.
531 *
[38542dc]532 * @param inode I-node to check flags of
533 * @param flag Flag to check
534 *
535 * @return Result of check operation
536 *
[296ef5d6]537 */
[7bc4508]538bool ext4_inode_has_flag(ext4_inode_t *inode, uint32_t flag)
539{
[38542dc]540 if (ext4_inode_get_flags(inode) & flag)
[7b9381b]541 return true;
[a35b458]542
[7b9381b]543 return false;
544}
545
[296ef5d6]546/** Remove specified flag from i-node.
547 *
[38542dc]548 * @param inode I-node to clear flag on
549 * @param clear_flag Flag to be cleared
550 *
[296ef5d6]551 */
[b3d7277]552void ext4_inode_clear_flag(ext4_inode_t *inode, uint32_t clear_flag)
553{
554 uint32_t flags = ext4_inode_get_flags(inode);
555 flags = flags & (~clear_flag);
556 ext4_inode_set_flags(inode, flags);
557}
558
[296ef5d6]559/** Set specified flag to i-node.
560 *
[38542dc]561 * @param inode I-node to set flag on
562 * @param set_flag Flag to be set
563 *
[296ef5d6]564 */
[b3d7277]565void ext4_inode_set_flag(ext4_inode_t *inode, uint32_t set_flag)
566{
567 uint32_t flags = ext4_inode_get_flags(inode);
568 flags = flags | set_flag;
569 ext4_inode_set_flags(inode, flags);
570}
571
[296ef5d6]572/** Check if i-node can be truncated.
573 *
[38542dc]574 * @param sb Superblock
575 * @param inode I-node to check
576 *
577 * @return Result of the check operation
578 *
[296ef5d6]579 */
[43a9968]580bool ext4_inode_can_truncate(ext4_superblock_t *sb, ext4_inode_t *inode)
[12b4a7f]581{
[38542dc]582 if ((ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)) ||
583 (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)))
584 return false;
[a35b458]585
[38542dc]586 if ((ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) ||
587 (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)))
588 return true;
[a35b458]589
[38542dc]590 return false;
[12b4a7f]591}
592
[eb91db7]593/**
594 * @}
[38542dc]595 */
Note: See TracBrowser for help on using the repository browser.