source: mainline/uspace/lib/ext4/libext4_inode.c@ 2add9ec

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2add9ec 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
Line 
1/*
2 * Copyright (c) 2012 Frantisek Princ
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
35 * @brief Ext4 inode structure operations.
36 */
37
38#include <byteorder.h>
39#include <errno.h>
40#include <libblock.h>
41#include "libext4.h"
42
43/** Compute number of bits for block count.
44 *
45 * @param block_size filesystem block_size
46 * @return number of bits
47 */
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
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 */
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
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 */
82void ext4_inode_set_mode(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t mode)
83{
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 }
89}
90
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 */
96uint32_t ext4_inode_get_uid(ext4_inode_t *inode)
97{
98 return uint32_t_le2host(inode->uid);
99}
100
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 */
106void ext4_inode_set_uid(ext4_inode_t *inode, uint32_t uid)
107{
108 inode->uid = host2uint32_t_le(uid);
109}
110
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 */
117uint64_t ext4_inode_get_size(ext4_superblock_t *sb, ext4_inode_t *inode)
118{
119 uint32_t major_rev = ext4_superblock_get_rev_level(sb);
120
121 if ((major_rev > 0) && ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) {
122 return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 |
123 ((uint64_t)uint32_t_le2host(inode->size_lo));
124 }
125 return uint32_t_le2host(inode->size_lo);
126}
127
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);
136}
137
138/** Get time, when i-node was last accessed.
139 *
140 * @param inode i-node
141 * @return time of the last access (POSIX)
142 */
143uint32_t ext4_inode_get_access_time(ext4_inode_t *inode)
144{
145 return uint32_t_le2host(inode->access_time);
146}
147
148/** Set time, when i-node was last accessed.
149 *
150 * @param inode i-node
151 * @param time time of the last access (POSIX)
152 */
153void ext4_inode_set_access_time(ext4_inode_t *inode, uint32_t time)
154{
155 inode->access_time = host2uint32_t_le(time);
156}
157
158/** TODO comment
159 *
160 */
161uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *inode)
162{
163 return uint32_t_le2host(inode->change_inode_time);
164}
165
166/** TODO comment
167 *
168 */
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
174/** TODO comment
175 *
176 */
177uint32_t ext4_inode_get_modification_time(ext4_inode_t *inode)
178{
179 return uint32_t_le2host(inode->modification_time);
180}
181
182/** TODO comment
183 *
184 */
185void ext4_inode_set_modification_time(ext4_inode_t *inode, uint32_t time)
186{
187 inode->modification_time = host2uint32_t_le(time);
188}
189
190/** TODO comment
191 *
192 */
193uint32_t ext4_inode_get_deletion_time(ext4_inode_t *inode)
194{
195 return uint32_t_le2host(inode->deletion_time);
196}
197
198/** TODO comment
199 *
200 */
201void ext4_inode_set_deletion_time(ext4_inode_t *inode, uint32_t time)
202{
203 inode->deletion_time = host2uint32_t_le(time);
204}
205
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 */
211uint32_t ext4_inode_get_gid(ext4_inode_t *inode)
212{
213 return uint32_t_le2host(inode->gid);
214}
215
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 */
221void ext4_inode_set_gid(ext4_inode_t *inode, uint32_t gid)
222{
223 inode->gid = host2uint32_t_le(gid);
224}
225
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 */
231uint16_t ext4_inode_get_links_count(ext4_inode_t *inode)
232{
233 return uint16_t_le2host(inode->links_count);
234}
235
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 */
241void ext4_inode_set_links_count(ext4_inode_t *inode, uint16_t count)
242{
243 inode->links_count = host2uint16_t_le(count);
244}
245
246/** Get number of 512-bytes blocks used for i-node.
247 *
248 * @param sb superblock
249 * @param inode i-node
250 * @return number of 512-bytes blocks
251 */
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
256 // 48-bit field
257 uint64_t count = ((uint64_t)uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 |
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
272/** Set number of 512-bytes blocks used for i-node.
273 *
274 * @param sb superblock
275 * @param inode i-node
276 * @param count number of 512-bytes blocks
277 * @return error code
278 */
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
293 // Check if there can be used huge files (many blocks)
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}
316
317/** Get flags (features) of i-node.
318 *
319 * @param inode i-node to get flags from
320 * @return flags (bitmap)
321 */
322uint32_t ext4_inode_get_flags(ext4_inode_t *inode) {
323 return uint32_t_le2host(inode->flags);
324}
325
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 */
331void ext4_inode_set_flags(ext4_inode_t *inode, uint32_t flags) {
332 inode->flags = host2uint32_t_le(flags);
333}
334
335/** Get file generation (used by NFS).
336 *
337 * @param inode i-node
338 * @return file generation
339 */
340uint32_t ext4_inode_get_generation(ext4_inode_t *inode)
341{
342 return uint32_t_le2host(inode->generation);
343}
344
345/** Set file generation (used by NFS).
346 *
347 * @param inode i-node
348 * @param generation file generation
349 */
350void ext4_inode_set_generation(ext4_inode_t *inode, uint32_t generation)
351{
352 inode->generation = host2uint32_t_le(generation);
353}
354
355/** Get address of block, where are extended attributes located.
356 *
357 * @param inode i-node
358 * @param sb superblock
359 * @return block address
360 */
361uint64_t ext4_inode_get_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb)
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
371/** Set address of block, where are extended attributes located.
372 *
373 * @param inode i-node
374 * @param sb superblock
375 * @param file_acl block address
376 */
377void ext4_inode_set_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb,
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
387/***********************************************************************/
388
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 */
395uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
396{
397 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
398 return uint32_t_le2host(inode->blocks[idx]);
399}
400
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 */
407void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
408{
409 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
410 inode->blocks[idx] = host2uint32_t_le(fblock);
411}
412
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 */
419uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
420{
421 return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
422}
423
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 */
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
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 */
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
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 */
453ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *inode)
454{
455 return (ext4_extent_header_t *)inode->blocks;
456}
457
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 */
464bool ext4_inode_has_flag(ext4_inode_t *inode, uint32_t flag)
465{
466 if (ext4_inode_get_flags(inode) & flag) {
467 return true;
468 }
469 return false;
470}
471
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 */
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
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 */
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
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 */
502bool ext4_inode_can_truncate(ext4_superblock_t *sb, ext4_inode_t *inode)
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
509 if (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)
510 || ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)) {
511 return true;
512 }
513
514 return false;
515}
516
517/**
518 * @}
519 */
Note: See TracBrowser for help on using the repository browser.