2 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
11 #include <ByteOrder.h>
12 #include <fs_interface.h>
13 #include <KernelExport.h>
16 typedef uint64 fileblock_t
; // file block number
17 typedef uint64 fsblock_t
; // filesystem block number
20 #define EXT2_SUPER_BLOCK_OFFSET 1024
22 struct ext2_super_block
{
25 uint32 reserved_blocks
;
28 uint32 first_data_block
;
30 uint32 fragment_shift
;
31 uint32 blocks_per_group
;
32 uint32 fragments_per_group
;
33 uint32 inodes_per_group
;
37 uint16 max_mount_count
;
40 uint16 error_handling
;
41 uint16 minor_revision_level
;
42 uint32 last_check_time
;
43 uint32 check_interval
;
45 uint32 revision_level
;
46 uint16 reserved_blocks_uid
;
47 uint16 reserved_blocks_gid
;
51 uint32 compatible_features
;
52 uint32 incompatible_features
;
53 uint32 read_only_features
;
56 char last_mount_point
[64];
57 uint32 algorithm_usage_bitmap
;
58 uint8 preallocated_blocks
;
59 uint8 preallocated_directory_blocks
;
60 uint16 reserved_gdt_blocks
;
62 // journaling ext3 support
63 uint8 journal_uuid
[16];
65 uint32 journal_device
;
68 uint8 default_hash_version
;
70 uint16 group_descriptor_size
;
71 uint32 default_mount_options
;
72 uint32 first_meta_block_group
;
73 uint32 fs_creation_time
;
74 uint32 journal_inode_backup
[17];
77 uint32 num_blocks_high
;
78 uint32 reserved_blocks_high
;
79 uint32 free_blocks_high
;
80 uint16 min_inode_size
;
81 uint16 want_inode_size
;
86 uint32 raid_stripe_width
;
87 uint8 groups_per_flex_shift
;
90 uint32 _reserved5
[162];
92 uint16
Magic() const { return B_LENDIAN_TO_HOST_INT16(magic
); }
93 uint16
State() const { return B_LENDIAN_TO_HOST_INT16(state
); }
94 uint32
RevisionLevel() const { return B_LENDIAN_TO_HOST_INT16(revision_level
); }
95 uint32
BlockShift() const { return B_LENDIAN_TO_HOST_INT32(block_shift
) + 10; }
96 uint32
NumInodes() const { return B_LENDIAN_TO_HOST_INT32(num_inodes
); }
97 uint64
NumBlocks(bool has64bits
) const
99 uint64 blocks
= B_LENDIAN_TO_HOST_INT32(num_blocks
);
101 blocks
|= ((uint64
)B_LENDIAN_TO_HOST_INT32(num_blocks_high
) << 32);
104 uint32
FreeInodes() const { return B_LENDIAN_TO_HOST_INT32(free_inodes
); }
105 uint64
FreeBlocks(bool has64bits
) const
107 uint64 blocks
= B_LENDIAN_TO_HOST_INT32(free_blocks
);
109 blocks
|= ((uint64
)B_LENDIAN_TO_HOST_INT32(free_blocks_high
) << 32);
112 uint16
InodeSize() const { return B_LENDIAN_TO_HOST_INT16(inode_size
); }
113 uint32
FirstDataBlock() const
114 { return B_LENDIAN_TO_HOST_INT32(first_data_block
); }
115 uint32
BlocksPerGroup() const
116 { return B_LENDIAN_TO_HOST_INT32(blocks_per_group
); }
117 uint32
InodesPerGroup() const
118 { return B_LENDIAN_TO_HOST_INT32(inodes_per_group
); }
119 uint32
FirstMetaBlockGroup() const
120 { return B_LENDIAN_TO_HOST_INT32(first_meta_block_group
); }
121 uint32
CompatibleFeatures() const
122 { return B_LENDIAN_TO_HOST_INT32(compatible_features
); }
123 uint32
ReadOnlyFeatures() const
124 { return B_LENDIAN_TO_HOST_INT32(read_only_features
); }
125 uint32
IncompatibleFeatures() const
126 { return B_LENDIAN_TO_HOST_INT32(incompatible_features
); }
127 uint16
ReservedGDTBlocks() const
128 { return B_LENDIAN_TO_HOST_INT16(reserved_gdt_blocks
); }
129 ino_t
JournalInode() const
130 { return B_LENDIAN_TO_HOST_INT32(journal_inode
); }
131 ino_t
LastOrphan() const
132 { return (ino_t
)B_LENDIAN_TO_HOST_INT32(last_orphan
); }
133 uint32
HashSeed(uint8 i
) const
134 { return B_LENDIAN_TO_HOST_INT32(hash_seed
[i
]); }
135 uint16
GroupDescriptorSize() const
136 { return B_LENDIAN_TO_HOST_INT16(group_descriptor_size
); }
138 void SetFreeInodes(uint32 freeInodes
)
139 { free_inodes
= B_HOST_TO_LENDIAN_INT32(freeInodes
); }
140 void SetFreeBlocks(uint64 freeBlocks
, bool has64bits
)
142 free_blocks
= B_HOST_TO_LENDIAN_INT32(freeBlocks
& 0xffffffff);
144 free_blocks_high
= B_HOST_TO_LENDIAN_INT32(freeBlocks
>> 32);
146 void SetLastOrphan(ino_t id
)
147 { last_orphan
= B_HOST_TO_LENDIAN_INT32((uint32
)id
); }
148 void SetReadOnlyFeatures(uint32 readOnlyFeatures
) const
149 { readOnlyFeatures
= B_HOST_TO_LENDIAN_INT32(readOnlyFeatures
); }
152 // implemented in Volume.cpp
155 #define EXT2_OLD_REVISION 0
156 #define EXT2_DYNAMIC_REVISION 1
158 #define EXT2_MAX_REVISION EXT2_DYNAMIC_REVISION
160 #define EXT2_FS_STATE_VALID 1 // File system was cleanly unmounted
161 #define EXT2_FS_STATE_ERROR 2 // File system has errors
162 #define EXT2_FS_STATE_ORPHAN 3 // Orphans are being recovered
164 // compatible features
165 #define EXT2_FEATURE_DIRECTORY_PREALLOCATION 0x0001
166 #define EXT2_FEATURE_IMAGIC_INODES 0x0002
167 #define EXT2_FEATURE_HAS_JOURNAL 0x0004
168 #define EXT2_FEATURE_EXT_ATTR 0x0008
169 #define EXT2_FEATURE_RESIZE_INODE 0x0010
170 #define EXT2_FEATURE_DIRECTORY_INDEX 0x0020
172 // read-only compatible features
173 #define EXT2_READ_ONLY_FEATURE_SPARSE_SUPER 0x0001
174 #define EXT2_READ_ONLY_FEATURE_LARGE_FILE 0x0002
175 #define EXT2_READ_ONLY_FEATURE_BTREE_DIRECTORY 0x0004
176 #define EXT2_READ_ONLY_FEATURE_HUGE_FILE 0x0008
177 #define EXT2_READ_ONLY_FEATURE_GDT_CSUM 0x0010
178 #define EXT2_READ_ONLY_FEATURE_DIR_NLINK 0x0020
179 #define EXT2_READ_ONLY_FEATURE_EXTRA_ISIZE 0x0040
181 // incompatible features
182 #define EXT2_INCOMPATIBLE_FEATURE_COMPRESSION 0x0001
183 #define EXT2_INCOMPATIBLE_FEATURE_FILE_TYPE 0x0002
184 #define EXT2_INCOMPATIBLE_FEATURE_RECOVER 0x0004
185 #define EXT2_INCOMPATIBLE_FEATURE_JOURNAL 0x0008
186 #define EXT2_INCOMPATIBLE_FEATURE_META_GROUP 0x0010
187 #define EXT2_INCOMPATIBLE_FEATURE_EXTENTS 0x0040
188 #define EXT2_INCOMPATIBLE_FEATURE_64BIT 0x0080
189 #define EXT2_INCOMPATIBLE_FEATURE_MMP 0x0100
190 #define EXT2_INCOMPATIBLE_FEATURE_FLEX_GROUP 0x0200
193 #define EXT2_STATE_VALID 0x01
194 #define EXT2_STATE_INVALID 0x02
196 #define EXT2_BLOCK_GROUP_NORMAL_SIZE 32
197 #define EXT2_BLOCK_GROUP_64BIT_SIZE 64
200 #define EXT2_BLOCK_GROUP_INODE_UNINIT 0x1
201 #define EXT2_BLOCK_GROUP_BLOCK_UNINIT 0x2
204 struct ext2_block_group
{
210 uint16 used_directories
;
213 uint16 unused_inodes
;
217 uint32 block_bitmap_high
;
218 uint32 inode_bitmap_high
;
219 uint32 inode_table_high
;
220 uint16 free_blocks_high
;
221 uint16 free_inodes_high
;
222 uint16 used_directories_high
;
223 uint16 unused_inodes_high
;
224 uint32 _reserved2
[3];
226 fsblock_t
BlockBitmap(bool has64bits
) const
228 uint64 block
= B_LENDIAN_TO_HOST_INT32(block_bitmap
);
231 ((uint64
)B_LENDIAN_TO_HOST_INT32(block_bitmap_high
) << 32);
234 fsblock_t
InodeBitmap(bool has64bits
) const
236 uint64 bitmap
= B_LENDIAN_TO_HOST_INT32(inode_bitmap
);
239 ((uint64
)B_LENDIAN_TO_HOST_INT32(inode_bitmap_high
) << 32);
242 uint64
InodeTable(bool has64bits
) const
244 uint64 table
= B_LENDIAN_TO_HOST_INT32(inode_table
);
246 table
|= ((uint64
)B_LENDIAN_TO_HOST_INT32(inode_table_high
) << 32);
249 uint32
FreeBlocks(bool has64bits
) const
251 uint32 blocks
= B_LENDIAN_TO_HOST_INT16(free_blocks
);
254 ((uint32
)B_LENDIAN_TO_HOST_INT16(free_blocks_high
) << 16);
257 uint32
FreeInodes(bool has64bits
) const
259 uint32 inodes
= B_LENDIAN_TO_HOST_INT16(free_inodes
);
262 ((uint32
)B_LENDIAN_TO_HOST_INT16(free_inodes_high
) << 16);
265 uint32
UsedDirectories(bool has64bits
) const
267 uint32 dirs
= B_LENDIAN_TO_HOST_INT16(used_directories
);
270 ((uint32
)B_LENDIAN_TO_HOST_INT16(used_directories_high
) << 16);
273 uint16
Flags() const { return B_LENDIAN_TO_HOST_INT16(flags
); }
274 uint32
UnusedInodes(bool has64bits
) const
276 uint32 inodes
= B_LENDIAN_TO_HOST_INT16(unused_inodes
);
279 ((uint32
)B_LENDIAN_TO_HOST_INT16(unused_inodes_high
) << 16);
284 void SetFreeBlocks(uint32 freeBlocks
, bool has64bits
)
286 free_blocks
= B_HOST_TO_LENDIAN_INT16(freeBlocks
) & 0xffff;
288 free_blocks_high
= B_HOST_TO_LENDIAN_INT16(freeBlocks
>> 16);
291 void SetFreeInodes(uint32 freeInodes
, bool has64bits
)
293 free_inodes
= B_HOST_TO_LENDIAN_INT16(freeInodes
) & 0xffff;
295 free_inodes_high
= B_HOST_TO_LENDIAN_INT16(freeInodes
>> 16);
298 void SetUsedDirectories(uint16 usedDirectories
, bool has64bits
)
300 used_directories
= B_HOST_TO_LENDIAN_INT16(usedDirectories
& 0xffff);
302 used_directories_high
=
303 B_HOST_TO_LENDIAN_INT16(usedDirectories
>> 16);
306 void SetFlags(uint16 newFlags
)
308 flags
= B_HOST_TO_LENDIAN_INT16(newFlags
);
311 void SetUnusedInodes(uint32 unusedInodes
, bool has64bits
)
313 unused_inodes
= B_HOST_TO_LENDIAN_INT16(unusedInodes
) & 0xffff;
315 unused_inodes_high
= B_HOST_TO_LENDIAN_INT16(unusedInodes
>> 16);
319 #define EXT2_DIRECT_BLOCKS 12
320 #define EXT2_ROOT_NODE 2
321 #define EXT2_SHORT_SYMLINK_LENGTH 60
323 struct ext2_data_stream
{
324 uint32 direct
[EXT2_DIRECT_BLOCKS
];
326 uint32 double_indirect
;
327 uint32 triple_indirect
;
330 #define EXT2_EXTENT_MAGIC 0xf30a
331 #define EXT2_EXTENT_MAX_LENGTH 0x8000
333 struct ext2_extent_header
{
341 return B_LENDIAN_TO_HOST_INT16(magic
) == EXT2_EXTENT_MAGIC
;
343 uint16
NumEntries() const { return B_LENDIAN_TO_HOST_INT16(num_entries
); }
344 uint16
MaxEntries() const { return B_LENDIAN_TO_HOST_INT16(max_entries
); }
345 uint16
Depth() const { return B_LENDIAN_TO_HOST_INT16(depth
); }
346 uint32
Generation() const { return B_LENDIAN_TO_HOST_INT32(generation
); }
347 void SetNumEntries(uint16 num
)
348 { num_entries
= B_HOST_TO_LENDIAN_INT16(num
); }
349 void SetMaxEntries(uint16 max
)
350 { max_entries
= B_HOST_TO_LENDIAN_INT16(max
); }
351 void SetDepth(uint16 _depth
)
352 { depth
= B_HOST_TO_LENDIAN_INT16(_depth
); }
353 void SetGeneration(uint32 _generation
)
354 { generation
= B_HOST_TO_LENDIAN_INT32(_generation
); }
357 struct ext2_extent_index
{
358 uint32 logical_block
;
359 uint32 physical_block
;
360 uint16 physical_block_high
;
362 uint32
LogicalBlock() const
363 { return B_LENDIAN_TO_HOST_INT32(logical_block
); }
364 uint64
PhysicalBlock() const { return B_LENDIAN_TO_HOST_INT32(physical_block
)
365 | ((uint64
)B_LENDIAN_TO_HOST_INT16(physical_block_high
) << 32); }
366 void SetLogicalBlock(uint32 block
) {
367 logical_block
= B_HOST_TO_LENDIAN_INT32(block
); }
368 void SetPhysicalBlock(uint64 block
) {
369 physical_block
= B_HOST_TO_LENDIAN_INT32(block
& 0xffffffff);
370 physical_block_high
= B_HOST_TO_LENDIAN_INT16((block
>> 32) & 0xffff); }
373 struct ext2_extent_entry
{
374 uint32 logical_block
;
376 uint16 physical_block_high
;
377 uint32 physical_block
;
378 uint32
LogicalBlock() const
379 { return B_LENDIAN_TO_HOST_INT32(logical_block
); }
380 uint16
Length() const { return B_LENDIAN_TO_HOST_INT16(length
) == 0x8000
381 ? 0x8000 : B_LENDIAN_TO_HOST_INT16(length
) & 0x7fff; }
382 uint64
PhysicalBlock() const { return B_LENDIAN_TO_HOST_INT32(physical_block
)
383 | ((uint64
)B_LENDIAN_TO_HOST_INT16(physical_block_high
) << 32); }
384 void SetLogicalBlock(uint32 block
) {
385 logical_block
= B_HOST_TO_LENDIAN_INT32(block
); }
386 void SetLength(uint16 _length
) {
387 length
= B_HOST_TO_LENDIAN_INT16(_length
) & 0x7fff; }
388 void SetPhysicalBlock(uint64 block
) {
389 physical_block
= B_HOST_TO_LENDIAN_INT32(block
& 0xffffffff);
390 physical_block_high
= B_HOST_TO_LENDIAN_INT16((block
>> 32) & 0xffff); }
393 struct ext2_extent_stream
{
394 ext2_extent_header extent_header
;
396 ext2_extent_entry extent_entries
[4];
397 ext2_extent_index extent_index
[4];
401 #define EXT2_INODE_NORMAL_SIZE 128
402 #define EXT2_INODE_MAX_LINKS 65000
410 uint32 modification_time
;
411 uint32 deletion_time
;
418 ext2_data_stream stream
;
419 char symlink
[EXT2_SHORT_SYMLINK_LENGTH
];
420 ext2_extent_stream extent_stream
;
423 uint32 file_access_control
;
425 // for directories vs. files
426 uint32 directory_access_control
;
432 uint8 fragment_number
;
435 uint16 num_blocks_high
;
443 uint16 extra_inode_size
;
445 uint32 change_time_extra
;
446 uint32 modification_time_extra
;
447 uint32 access_time_extra
;
448 uint32 creation_time
;
449 uint32 creation_time_extra
;
452 uint16
Mode() const { return B_LENDIAN_TO_HOST_INT16(mode
); }
453 uint32
Flags() const { return B_LENDIAN_TO_HOST_INT32(flags
); }
454 uint16
NumLinks() const { return B_LENDIAN_TO_HOST_INT16(num_links
); }
455 uint32
NumBlocks() const { return B_LENDIAN_TO_HOST_INT32(num_blocks
); }
456 uint64
NumBlocks64() const { return B_LENDIAN_TO_HOST_INT32(num_blocks
)
457 | ((uint64
)B_LENDIAN_TO_HOST_INT32(num_blocks_high
) << 32); }
459 static void _DecodeTime(struct timespec
*timespec
, uint32 time
,
460 uint32 time_extra
, bool extra
)
462 timespec
->tv_sec
= B_LENDIAN_TO_HOST_INT32(time
);
463 if (extra
&& sizeof(timespec
->tv_sec
) > 4)
465 (uint64
)(B_LENDIAN_TO_HOST_INT32(time_extra
) & 0x2) << 32;
467 timespec
->tv_nsec
= B_LENDIAN_TO_HOST_INT32(time_extra
) >> 2;
469 timespec
->tv_nsec
= 0;
472 void GetModificationTime(struct timespec
*timespec
, bool extra
) const
473 { _DecodeTime(timespec
, modification_time
, modification_time_extra
,
475 void GetAccessTime(struct timespec
*timespec
, bool extra
) const
476 { _DecodeTime(timespec
, access_time
, access_time_extra
, extra
); }
477 void GetChangeTime(struct timespec
*timespec
, bool extra
) const
478 { _DecodeTime(timespec
, change_time
, change_time_extra
, extra
); }
479 void GetCreationTime(struct timespec
*timespec
, bool extra
) const
482 _DecodeTime(timespec
, creation_time
, creation_time_extra
, extra
);
484 timespec
->tv_sec
= 0;
485 timespec
->tv_nsec
= 0;
488 time_t DeletionTime() const
489 { return B_LENDIAN_TO_HOST_INT32(deletion_time
); }
491 static uint32
_EncodeTime(const struct timespec
*timespec
)
493 uint32 time
= (timespec
->tv_nsec
<< 2) & 0xfffffffc;
494 if (sizeof(timespec
->tv_sec
) > 4)
495 time
|= (uint64
)timespec
->tv_sec
>> 32;
496 return B_HOST_TO_LENDIAN_INT32(time
);
499 void SetModificationTime(const struct timespec
*timespec
, bool extra
)
501 modification_time
= B_HOST_TO_LENDIAN_INT32((uint32
)timespec
->tv_sec
);
503 modification_time_extra
= _EncodeTime(timespec
);
505 void SetAccessTime(const struct timespec
*timespec
, bool extra
)
507 access_time
= B_HOST_TO_LENDIAN_INT32((uint32
)timespec
->tv_sec
);
509 access_time_extra
= _EncodeTime(timespec
);
511 void SetChangeTime(const struct timespec
*timespec
, bool extra
)
513 change_time
= B_HOST_TO_LENDIAN_INT32((uint32
)timespec
->tv_sec
);
515 change_time_extra
= _EncodeTime(timespec
);
517 void SetCreationTime(const struct timespec
*timespec
, bool extra
)
520 creation_time
= B_HOST_TO_LENDIAN_INT32((uint32
)timespec
->tv_sec
);
521 creation_time_extra
=
522 B_HOST_TO_LENDIAN_INT32((uint32
)timespec
->tv_nsec
);
525 void SetDeletionTime(time_t deletionTime
)
527 deletion_time
= B_HOST_TO_LENDIAN_INT32((uint32
)deletionTime
);
530 ino_t
NextOrphan() const { return (ino_t
)DeletionTime(); }
534 if (S_ISREG(Mode())) {
535 return B_LENDIAN_TO_HOST_INT32(size
)
536 | ((off_t
)B_LENDIAN_TO_HOST_INT32(size_high
) << 32);
539 return B_LENDIAN_TO_HOST_INT32(size
);
542 uint32
ExtendedAttributesBlock() const
543 { return B_LENDIAN_TO_HOST_INT32(file_access_control
);}
545 uint16
ExtraInodeSize() const
546 { return B_LENDIAN_TO_HOST_INT16(extra_inode_size
); }
548 uint32
UserID() const
550 return B_LENDIAN_TO_HOST_INT16(uid
)
551 | (B_LENDIAN_TO_HOST_INT16(uid_high
) << 16);
554 uint32
GroupID() const
556 return B_LENDIAN_TO_HOST_INT16(gid
)
557 | (B_LENDIAN_TO_HOST_INT16(gid_high
) << 16);
560 void SetMode(uint16 newMode
)
562 mode
= B_LENDIAN_TO_HOST_INT16(newMode
);
565 void UpdateMode(uint16 newMode
, uint16 mask
)
567 SetMode((Mode() & ~mask
) | (newMode
& mask
));
570 void ClearFlag(uint32 mask
)
572 flags
&= ~B_HOST_TO_LENDIAN_INT32(mask
);
575 void SetFlag(uint32 mask
)
577 flags
|= B_HOST_TO_LENDIAN_INT32(mask
);
580 void SetFlags(uint32 newFlags
)
582 flags
= B_HOST_TO_LENDIAN_INT32(newFlags
);
585 void SetNumLinks(uint16 numLinks
)
587 num_links
= B_HOST_TO_LENDIAN_INT16(numLinks
);
590 void SetNumBlocks(uint32 numBlocks
)
592 num_blocks
= B_HOST_TO_LENDIAN_INT32(numBlocks
);
595 void SetNumBlocks64(uint64 numBlocks
)
597 num_blocks
= B_HOST_TO_LENDIAN_INT32(numBlocks
& 0xffffffff);
598 num_blocks_high
= B_HOST_TO_LENDIAN_INT32(numBlocks
>> 32);
601 void SetNextOrphan(ino_t id
)
603 deletion_time
= B_HOST_TO_LENDIAN_INT32((uint32
)id
);
606 void SetSize(off_t newSize
)
608 size
= B_HOST_TO_LENDIAN_INT32(newSize
& 0xFFFFFFFF);
610 size_high
= B_HOST_TO_LENDIAN_INT32(newSize
>> 32);
613 void SetUserID(uint32 newUID
)
615 uid
= B_HOST_TO_LENDIAN_INT16(newUID
& 0xFFFF);
616 uid_high
= B_HOST_TO_LENDIAN_INT16(newUID
>> 16);
619 void SetGroupID(uint32 newGID
)
621 gid
= B_HOST_TO_LENDIAN_INT16(newGID
& 0xFFFF);
622 gid_high
= B_HOST_TO_LENDIAN_INT16(newGID
>> 16);
625 void SetExtendedAttributesBlock(uint32 block
)
627 file_access_control
= B_HOST_TO_LENDIAN_INT32(block
);
630 void SetExtraInodeSize(uint16 newSize
)
632 extra_inode_size
= B_HOST_TO_LENDIAN_INT16(newSize
);
636 #define EXT2_SUPER_BLOCK_MAGIC 0xef53
639 #define EXT2_INODE_SECURE_DELETION 0x00000001
640 #define EXT2_INODE_UNDELETE 0x00000002
641 #define EXT2_INODE_COMPRESSED 0x00000004
642 #define EXT2_INODE_SYNCHRONOUS 0x00000008
643 #define EXT2_INODE_IMMUTABLE 0x00000010
644 #define EXT2_INODE_APPEND_ONLY 0x00000020
645 #define EXT2_INODE_NO_DUMP 0x00000040
646 #define EXT2_INODE_NO_ACCESS_TIME 0x00000080
647 #define EXT2_INODE_DIRTY 0x00000100
648 #define EXT2_INODE_COMPRESSED_BLOCKS 0x00000200
649 #define EXT2_INODE_DO_NOT_COMPRESS 0x00000400
650 #define EXT2_INODE_COMPRESSION_ERROR 0x00000800
651 #define EXT2_INODE_BTREE 0x00001000
652 #define EXT2_INODE_INDEXED 0x00001000
653 #define EXT2_INODE_JOURNAL_DATA 0x00004000
654 #define EXT2_INODE_NO_MERGE_TAIL 0x00008000
655 #define EXT2_INODE_DIR_SYNCH 0x00010000
656 #define EXT2_INODE_HUGE_FILE 0x00040000
657 #define EXT2_INODE_EXTENTS 0x00080000
658 #define EXT2_INODE_LARGE_EA 0x00200000
659 #define EXT2_INODE_EOF_BLOCKS 0x00400000
660 #define EXT2_INODE_INLINE_DATA 0x10000000
661 #define EXT2_INODE_RESERVED 0x80000000
663 #define EXT2_INODE_INHERITED (EXT2_INODE_SECURE_DELETION | EXT2_INODE_UNDELETE \
664 | EXT2_INODE_COMPRESSED | EXT2_INODE_SYNCHRONOUS | EXT2_INODE_IMMUTABLE \
665 | EXT2_INODE_APPEND_ONLY | EXT2_INODE_NO_DUMP | EXT2_INODE_NO_ACCESS_TIME \
666 | EXT2_INODE_DO_NOT_COMPRESS | EXT2_INODE_JOURNAL_DATA \
667 | EXT2_INODE_NO_MERGE_TAIL | EXT2_INODE_DIR_SYNCH)
669 #define EXT2_NAME_LENGTH 255
671 struct ext2_dir_entry
{
676 char name
[EXT2_NAME_LENGTH
];
678 uint32
InodeID() const { return B_LENDIAN_TO_HOST_INT32(inode_id
); }
679 uint16
Length() const { return B_LENDIAN_TO_HOST_INT16(length
); }
680 uint8
NameLength() const { return name_length
; }
681 uint8
FileType() const { return file_type
; }
683 void SetInodeID(uint32 id
) { inode_id
= B_HOST_TO_LENDIAN_INT32(id
); }
685 void SetLength(uint16 newLength
/*uint8 nameLength*/)
687 length
= B_HOST_TO_LENDIAN_INT16(newLength
);
688 /*name_length = nameLength;
690 if (nameLength % 4 == 0) {
691 length = B_HOST_TO_LENDIAN_INT16(
692 (short)(nameLength + MinimumSize()));
694 length = B_HOST_TO_LENDIAN_INT16(
695 (short)(nameLength % 4 + 1 + MinimumSize()));
701 return Length() > MinimumSize();
702 // There is no maximum size, as the last entry spans until the
706 static size_t MinimumSize()
708 return sizeof(ext2_dir_entry
) - EXT2_NAME_LENGTH
;
713 #define EXT2_TYPE_UNKNOWN 0
714 #define EXT2_TYPE_FILE 1
715 #define EXT2_TYPE_DIRECTORY 2
716 #define EXT2_TYPE_CHAR_DEVICE 3
717 #define EXT2_TYPE_BLOCK_DEVICE 4
718 #define EXT2_TYPE_FIFO 5
719 #define EXT2_TYPE_SOCKET 6
720 #define EXT2_TYPE_SYMLINK 7
722 #define EXT2_XATTR_MAGIC 0xea020000
723 #define EXT2_XATTR_ROUND ((1 << 2) - 1)
724 #define EXT2_XATTR_NAME_LENGTH 255
726 #define EXT2_XATTR_INDEX_USER 1
728 struct ext2_xattr_header
{
731 uint32 blocks
; // must be 1 for ext2
733 uint32 reserved
[4]; // zero
737 return B_LENDIAN_TO_HOST_INT32(magic
) == EXT2_XATTR_MAGIC
738 && B_LENDIAN_TO_HOST_INT32(blocks
) == 1
743 for (unsigned int i
= 0; i
< Length(); i
++)
744 dprintf("%02x ", ((uint8
*)this)[i
]);
748 static size_t Length()
750 return sizeof(ext2_xattr_header
);
754 struct ext2_xattr_entry
{
758 uint32 value_block
; // must be zero for ext2
761 char name
[EXT2_XATTR_NAME_LENGTH
];
763 uint8
NameLength() const { return name_length
; }
764 uint8
NameIndex() const { return name_index
; }
765 uint16
ValueOffset() const { return
766 B_LENDIAN_TO_HOST_INT16(value_offset
); }
767 uint32
ValueSize() const { return
768 B_LENDIAN_TO_HOST_INT32(value_size
); }
771 uint32
Length() const { return (MinimumSize() + NameLength()
772 + EXT2_XATTR_ROUND
) & ~EXT2_XATTR_ROUND
; }
776 return NameLength() > 0 && value_block
== 0;
777 // There is no maximum size, as the last entry spans until the
781 void Dump(bool full
=false) const {
782 for (unsigned int i
= 0; i
< (full
? sizeof(this) : MinimumSize()); i
++)
783 dprintf("%02x ", ((uint8
*)this)[i
]);
787 static size_t MinimumSize()
789 return sizeof(ext2_xattr_entry
) - EXT2_XATTR_NAME_LENGTH
;
795 bigtime_t last_notification
;
801 #define EXT2_OPEN_MODE_USER_MASK 0x7fffffff
803 #define INODE_NOTIFICATION_INTERVAL 10000000LL
806 extern fs_volume_ops gExt2VolumeOps
;
807 extern fs_vnode_ops gExt2VnodeOps
;