source: mainline/uspace/lib/ext4/src/inode.c@ 84239b1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 84239b1 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Sucha
3 * Copyright (c) 2012 Frantisek Princ
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 * @{
32 */
33/**
34 * @file inode.c
35 * @brief Ext4 i-node structure operations.
36 */
37
38#include <block.h>
39#include <byteorder.h>
40#include <errno.h>
41#include "ext4/inode.h"
42#include "ext4/superblock.h"
43
44/** Compute number of bits for block count.
45 *
46 * @param block_size Filesystem block_size
47 *
48 * @return Number of bits
49 *
50 */
51static uint32_t ext4_inode_block_bits_count(uint32_t block_size)
52{
53 uint32_t bits = 8;
54 uint32_t size = block_size;
55
56 do {
57 bits++;
58 size = size >> 1;
59 } while (size > 256);
60
61 return bits;
62}
63
64/** Get mode of the i-node.
65 *
66 * @param sb Superblock
67 * @param inode I-node to load mode from
68 *
69 * @return Mode of the i-node
70 *
71 */
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) {
75 return ((uint32_t) uint16_t_le2host(inode->osd2.hurd2.mode_high)) << 16 |
76 ((uint32_t) uint16_t_le2host(inode->mode));
77 }
78
79 return uint16_t_le2host(inode->mode);
80}
81
82/** Set mode of the i-node.
83 *
84 * @param sb Superblock
85 * @param inode I-node to set mode to
86 * @param mode Mode to set to i-node
87 *
88 */
89void ext4_inode_set_mode(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t mode)
90{
91 inode->mode = host2uint16_t_le((mode << 16) >> 16);
92
93 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD)
94 inode->osd2.hurd2.mode_high = host2uint16_t_le(mode >> 16);
95}
96
97/** Get ID of the i-node owner (user id).
98 *
99 * @param inode I-node to load uid from
100 *
101 * @return User ID of the i-node owner
102 *
103 */
104uint32_t ext4_inode_get_uid(ext4_inode_t *inode)
105{
106 return uint32_t_le2host(inode->uid);
107}
108
109/** Set ID of the i-node owner.
110 *
111 * @param inode I-node to set uid to
112 * @param uid ID of the i-node owner
113 *
114 */
115void ext4_inode_set_uid(ext4_inode_t *inode, uint32_t uid)
116{
117 inode->uid = host2uint32_t_le(uid);
118}
119
120/** Get real i-node size.
121 *
122 * @param sb Superblock
123 * @param inode I-node to load size from
124 *
125 * @return Real size of i-node
126 *
127 */
128uint64_t ext4_inode_get_size(ext4_superblock_t *sb, ext4_inode_t *inode)
129{
130 uint32_t major_rev = ext4_superblock_get_rev_level(sb);
131
132 if ((major_rev > 0) &&
133 (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)))
134 return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 |
135 ((uint64_t)uint32_t_le2host(inode->size_lo));
136
137 return uint32_t_le2host(inode->size_lo);
138}
139
140/** Set real i-node size.
141 *
142 * @param inode I-node to set size to
143 * @param size Size of the i-node
144 *
145 */
146void ext4_inode_set_size(ext4_inode_t *inode, uint64_t size)
147{
148 inode->size_lo = host2uint32_t_le((size << 32) >> 32);
149 inode->size_hi = host2uint32_t_le(size >> 32);
150}
151
152/** Get time, when i-node was last accessed.
153 *
154 * @param inode I-node
155 *
156 * @return Time of the last access (POSIX)
157 *
158 */
159uint32_t ext4_inode_get_access_time(ext4_inode_t *inode)
160{
161 return uint32_t_le2host(inode->access_time);
162}
163
164/** Set time, when i-node was last accessed.
165 *
166 * @param inode I-node
167 * @param time Time of the last access (POSIX)
168 *
169 */
170void ext4_inode_set_access_time(ext4_inode_t *inode, uint32_t time)
171{
172 inode->access_time = host2uint32_t_le(time);
173}
174
175/** Get time, when i-node was last changed.
176 *
177 * @param inode I-node
178 *
179 * @return Time of the last change (POSIX)
180 *
181 */
182uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *inode)
183{
184 return uint32_t_le2host(inode->change_inode_time);
185}
186
187/** Set time, when i-node was last changed.
188 *
189 * @param inode I-node
190 * @param time Time of the last change (POSIX)
191 *
192 */
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
198/** Get time, when i-node content was last modified.
199 *
200 * @param inode I-node
201 *
202 * @return Time of the last content modification (POSIX)
203 *
204 */
205uint32_t ext4_inode_get_modification_time(ext4_inode_t *inode)
206{
207 return uint32_t_le2host(inode->modification_time);
208}
209
210/** Set time, when i-node content was last modified.
211 *
212 * @param inode I-node
213 * @param time Time of the last content modification (POSIX)
214 *
215 */
216void ext4_inode_set_modification_time(ext4_inode_t *inode, uint32_t time)
217{
218 inode->modification_time = host2uint32_t_le(time);
219}
220
221/** Get time, when i-node was deleted.
222 *
223 * @param inode I-node
224 *
225 * @return Time of the delete action (POSIX)
226 *
227 */
228uint32_t ext4_inode_get_deletion_time(ext4_inode_t *inode)
229{
230 return uint32_t_le2host(inode->deletion_time);
231}
232
233/** Set time, when i-node was deleted.
234 *
235 * @param inode I-node
236 * @param time Time of the delete action (POSIX)
237 *
238 */
239void ext4_inode_set_deletion_time(ext4_inode_t *inode, uint32_t time)
240{
241 inode->deletion_time = host2uint32_t_le(time);
242}
243
244/** Get ID of the i-node owner's group.
245 *
246 * @param inode I-node to load gid from
247 *
248 * @return Group ID of the i-node owner
249 *
250 */
251uint32_t ext4_inode_get_gid(ext4_inode_t *inode)
252{
253 return uint32_t_le2host(inode->gid);
254}
255
256/** Set ID ot the i-node owner's group.
257 *
258 * @param inode I-node to set gid to
259 * @param gid Group ID of the i-node owner
260 *
261 */
262void ext4_inode_set_gid(ext4_inode_t *inode, uint32_t gid)
263{
264 inode->gid = host2uint32_t_le(gid);
265}
266
267/** Get number of links to i-node.
268 *
269 * @param inode I-node to load number of links from
270 *
271 * @return Number of links to i-node
272 *
273 */
274uint16_t ext4_inode_get_links_count(ext4_inode_t *inode)
275{
276 return uint16_t_le2host(inode->links_count);
277}
278
279/** Set number of links to i-node.
280 *
281 * @param inode I-node to set number of links to
282 * @param count Number of links to i-node
283 *
284 */
285void ext4_inode_set_links_count(ext4_inode_t *inode, uint16_t count)
286{
287 inode->links_count = host2uint16_t_le(count);
288}
289
290/** Get number of 512-bytes blocks used for i-node.
291 *
292 * @param sb Superblock
293 * @param inode I-node
294 *
295 * @return Number of 512-bytes blocks
296 *
297 */
298uint64_t ext4_inode_get_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode)
299{
300 if (ext4_superblock_has_feature_read_only(sb,
301 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
302 /* 48-bit field */
303 uint64_t count = ((uint64_t)
304 uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 |
305 uint32_t_le2host(inode->blocks_count_lo);
306
307 if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {
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
312 return count;
313 } else
314 return uint32_t_le2host(inode->blocks_count_lo);
315}
316
317/** Set number of 512-bytes blocks used for i-node.
318 *
319 * @param sb Superblock
320 * @param inode I-node
321 * @param count Number of 512-bytes blocks
322 *
323 * @return Error code
324 *
325 */
326errno_t ext4_inode_set_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode,
327 uint64_t count)
328{
329 /* 32-bit maximum */
330 uint64_t max = 0;
331 max = ~max >> 32;
332
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);
337
338 return EOK;
339 }
340
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;
345
346 /* 48-bit maximum */
347 max = 0;
348 max = ~max >> 16;
349
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 }
362
363 return EOK;
364}
365
366/** Get flags (features) of i-node.
367 *
368 * @param inode I-node to get flags from
369 *
370 * @return Flags (bitmap)
371 *
372 */
373uint32_t ext4_inode_get_flags(ext4_inode_t *inode)
374{
375 return uint32_t_le2host(inode->flags);
376}
377
378/** Set flags (features) of i-node.
379 *
380 * @param inode I-node to set flags to
381 * @param flags Flags to set to i-node
382 *
383 */
384void ext4_inode_set_flags(ext4_inode_t *inode, uint32_t flags)
385{
386 inode->flags = host2uint32_t_le(flags);
387}
388
389/** Get file generation (used by NFS).
390 *
391 * @param inode I-node
392 *
393 * @return File generation
394 *
395 */
396uint32_t ext4_inode_get_generation(ext4_inode_t *inode)
397{
398 return uint32_t_le2host(inode->generation);
399}
400
401/** Set file generation (used by NFS).
402 *
403 * @param inode I-node
404 * @param generation File generation
405 *
406 */
407void ext4_inode_set_generation(ext4_inode_t *inode, uint32_t generation)
408{
409 inode->generation = host2uint32_t_le(generation);
410}
411
412/** Get address of block, where are extended attributes located.
413 *
414 * @param inode I-node
415 * @param sb Superblock
416 *
417 * @return Block address
418 *
419 */
420uint64_t ext4_inode_get_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb)
421{
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 |
425 (uint32_t_le2host(inode->file_acl_lo));
426
427 return uint32_t_le2host(inode->file_acl_lo);
428}
429
430/** Set address of block, where are extended attributes located.
431 *
432 * @param inode I-node
433 * @param sb Superblock
434 * @param file_acl Block address
435 *
436 */
437void ext4_inode_set_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb,
438 uint64_t file_acl)
439{
440 inode->file_acl_lo = host2uint32_t_le((file_acl << 32) >> 32);
441
442 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX)
443 inode->osd2.linux2.file_acl_high = host2uint16_t_le(file_acl >> 32);
444}
445
446/** Get block address of specified direct block.
447 *
448 * @param inode I-node to load block from
449 * @param idx Index of logical block
450 *
451 * @return Physical block address
452 *
453 */
454uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
455{
456 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
457
458 return uint32_t_le2host(inode->blocks[idx]);
459}
460
461/** Set block address of specified direct block.
462 *
463 * @param inode I-node to set block address to
464 * @param idx Index of logical block
465 * @param fblock Physical block address
466 *
467 */
468void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
469{
470 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
471
472 inode->blocks[idx] = host2uint32_t_le(fblock);
473}
474
475/** Get block address of specified indirect block.
476 *
477 * @param inode I-node to get block address from
478 * @param idx Index of indirect block
479 *
480 * @return Physical block address
481 *
482 */
483uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
484{
485 return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
486}
487
488/** Set block address of specified indirect block.
489 *
490 * @param inode I-node to set block address to
491 * @param idx Index of indirect block
492 * @param fblock Physical block address
493 *
494 */
495void ext4_inode_set_indirect_block(ext4_inode_t *inode, uint32_t idx,
496 uint32_t fblock)
497{
498 inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] =
499 host2uint32_t_le(fblock);
500}
501
502/** Check if i-node has specified type.
503 *
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 *
510 */
511bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode,
512 uint32_t type)
513{
514 uint32_t mode = ext4_inode_get_mode(sb, inode);
515 return (mode & EXT4_INODE_MODE_TYPE_MASK) == type;
516}
517
518/** Get extent header from the root of the extent tree.
519 *
520 * @param inode I-node to get extent header from
521 *
522 * @return Pointer to extent header of the root node
523 *
524 */
525ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *inode)
526{
527 return (ext4_extent_header_t *) inode->blocks;
528}
529
530/** Check if i-node has specified flag.
531 *
532 * @param inode I-node to check flags of
533 * @param flag Flag to check
534 *
535 * @return Result of check operation
536 *
537 */
538bool ext4_inode_has_flag(ext4_inode_t *inode, uint32_t flag)
539{
540 if (ext4_inode_get_flags(inode) & flag)
541 return true;
542
543 return false;
544}
545
546/** Remove specified flag from i-node.
547 *
548 * @param inode I-node to clear flag on
549 * @param clear_flag Flag to be cleared
550 *
551 */
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
559/** Set specified flag to i-node.
560 *
561 * @param inode I-node to set flag on
562 * @param set_flag Flag to be set
563 *
564 */
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
572/** Check if i-node can be truncated.
573 *
574 * @param sb Superblock
575 * @param inode I-node to check
576 *
577 * @return Result of the check operation
578 *
579 */
580bool ext4_inode_can_truncate(ext4_superblock_t *sb, ext4_inode_t *inode)
581{
582 if ((ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)) ||
583 (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)))
584 return false;
585
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;
589
590 return false;
591}
592
593/**
594 * @}
595 */
Note: See TracBrowser for help on using the repository browser.