btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / src / add-ons / kernel / file_systems / ext2 / ext2.h
blob2e7479e7fadd9dcf69a45525c502dd2ebdcc8f0e
1 /*
2 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5 #ifndef EXT2_H
6 #define EXT2_H
9 #include <sys/stat.h>
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 {
23 uint32 num_inodes;
24 uint32 num_blocks;
25 uint32 reserved_blocks;
26 uint32 free_blocks;
27 uint32 free_inodes;
28 uint32 first_data_block;
29 uint32 block_shift;
30 uint32 fragment_shift;
31 uint32 blocks_per_group;
32 uint32 fragments_per_group;
33 uint32 inodes_per_group;
34 uint32 mount_time;
35 uint32 write_time;
36 uint16 mount_count;
37 uint16 max_mount_count;
38 uint16 magic;
39 uint16 state;
40 uint16 error_handling;
41 uint16 minor_revision_level;
42 uint32 last_check_time;
43 uint32 check_interval;
44 uint32 creator_os;
45 uint32 revision_level;
46 uint16 reserved_blocks_uid;
47 uint16 reserved_blocks_gid;
48 uint32 first_inode;
49 uint16 inode_size;
50 uint16 block_group;
51 uint32 compatible_features;
52 uint32 incompatible_features;
53 uint32 read_only_features;
54 uint8 uuid[16];
55 char name[16];
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];
64 uint32 journal_inode;
65 uint32 journal_device;
66 uint32 last_orphan;
67 uint32 hash_seed[4];
68 uint8 default_hash_version;
69 uint8 _reserved1;
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];
76 // ext4 support
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;
82 uint32 flags;
83 uint16 raid_stride;
84 uint16 mmp_interval;
85 uint64 mmp_block;
86 uint32 raid_stripe_width;
87 uint8 groups_per_flex_shift;
88 uint8 _reserved3;
89 uint16 _reserved4;
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);
100 if (has64bits)
101 blocks |= ((uint64)B_LENDIAN_TO_HOST_INT32(num_blocks_high) << 32);
102 return blocks;
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);
108 if (has64bits)
109 blocks |= ((uint64)B_LENDIAN_TO_HOST_INT32(free_blocks_high) << 32);
110 return blocks;
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);
143 if (has64bits)
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); }
151 bool IsValid();
152 // implemented in Volume.cpp
153 } _PACKED;
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
192 // states
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
199 // block group flags
200 #define EXT2_BLOCK_GROUP_INODE_UNINIT 0x1
201 #define EXT2_BLOCK_GROUP_BLOCK_UNINIT 0x2
204 struct ext2_block_group {
205 uint32 block_bitmap;
206 uint32 inode_bitmap;
207 uint32 inode_table;
208 uint16 free_blocks;
209 uint16 free_inodes;
210 uint16 used_directories;
211 uint16 flags;
212 uint32 _reserved[2];
213 uint16 unused_inodes;
214 uint16 checksum;
216 // ext4
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);
229 if (has64bits)
230 block |=
231 ((uint64)B_LENDIAN_TO_HOST_INT32(block_bitmap_high) << 32);
232 return block;
234 fsblock_t InodeBitmap(bool has64bits) const
236 uint64 bitmap = B_LENDIAN_TO_HOST_INT32(inode_bitmap);
237 if (has64bits)
238 bitmap |=
239 ((uint64)B_LENDIAN_TO_HOST_INT32(inode_bitmap_high) << 32);
240 return bitmap;
242 uint64 InodeTable(bool has64bits) const
244 uint64 table = B_LENDIAN_TO_HOST_INT32(inode_table);
245 if (has64bits)
246 table |= ((uint64)B_LENDIAN_TO_HOST_INT32(inode_table_high) << 32);
247 return table;
249 uint32 FreeBlocks(bool has64bits) const
251 uint32 blocks = B_LENDIAN_TO_HOST_INT16(free_blocks);
252 if (has64bits)
253 blocks |=
254 ((uint32)B_LENDIAN_TO_HOST_INT16(free_blocks_high) << 16);
255 return blocks;
257 uint32 FreeInodes(bool has64bits) const
259 uint32 inodes = B_LENDIAN_TO_HOST_INT16(free_inodes);
260 if (has64bits)
261 inodes |=
262 ((uint32)B_LENDIAN_TO_HOST_INT16(free_inodes_high) << 16);
263 return inodes;
265 uint32 UsedDirectories(bool has64bits) const
267 uint32 dirs = B_LENDIAN_TO_HOST_INT16(used_directories);
268 if (has64bits)
269 dirs |=
270 ((uint32)B_LENDIAN_TO_HOST_INT16(used_directories_high) << 16);
271 return dirs;
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);
277 if (has64bits)
278 inodes |=
279 ((uint32)B_LENDIAN_TO_HOST_INT16(unused_inodes_high) << 16);
280 return inodes;
284 void SetFreeBlocks(uint32 freeBlocks, bool has64bits)
286 free_blocks = B_HOST_TO_LENDIAN_INT16(freeBlocks) & 0xffff;
287 if (has64bits)
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;
294 if (has64bits)
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);
301 if (has64bits)
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;
314 if (has64bits)
315 unused_inodes_high = B_HOST_TO_LENDIAN_INT16(unusedInodes >> 16);
317 } _PACKED;
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];
325 uint32 indirect;
326 uint32 double_indirect;
327 uint32 triple_indirect;
328 } _PACKED;
330 #define EXT2_EXTENT_MAGIC 0xf30a
331 #define EXT2_EXTENT_MAX_LENGTH 0x8000
333 struct ext2_extent_header {
334 uint16 magic;
335 uint16 num_entries;
336 uint16 max_entries;
337 uint16 depth;
338 uint32 generation;
339 bool IsValid() const
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); }
355 } _PACKED;
357 struct ext2_extent_index {
358 uint32 logical_block;
359 uint32 physical_block;
360 uint16 physical_block_high;
361 uint16 _reserved;
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); }
371 } _PACKED;
373 struct ext2_extent_entry {
374 uint32 logical_block;
375 uint16 length;
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); }
391 } _PACKED;
393 struct ext2_extent_stream {
394 ext2_extent_header extent_header;
395 union {
396 ext2_extent_entry extent_entries[4];
397 ext2_extent_index extent_index[4];
399 } _PACKED;
401 #define EXT2_INODE_NORMAL_SIZE 128
402 #define EXT2_INODE_MAX_LINKS 65000
404 struct ext2_inode {
405 uint16 mode;
406 uint16 uid;
407 uint32 size;
408 uint32 access_time;
409 uint32 change_time;
410 uint32 modification_time;
411 uint32 deletion_time;
412 uint16 gid;
413 uint16 num_links;
414 uint32 num_blocks;
415 uint32 flags;
416 uint32 version;
417 union {
418 ext2_data_stream stream;
419 char symlink[EXT2_SHORT_SYMLINK_LENGTH];
420 ext2_extent_stream extent_stream;
422 uint32 generation;
423 uint32 file_access_control;
424 union {
425 // for directories vs. files
426 uint32 directory_access_control;
427 uint32 size_high;
429 uint32 fragment;
430 union {
431 struct {
432 uint8 fragment_number;
433 uint8 fragment_size;
435 uint16 num_blocks_high;
437 uint16 _padding;
438 uint16 uid_high;
439 uint16 gid_high;
440 uint32 _reserved2;
442 // extra attributes
443 uint16 extra_inode_size;
444 uint16 _padding2;
445 uint32 change_time_extra;
446 uint32 modification_time_extra;
447 uint32 access_time_extra;
448 uint32 creation_time;
449 uint32 creation_time_extra;
450 uint32 version_high;
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)
464 timespec->tv_sec |=
465 (uint64)(B_LENDIAN_TO_HOST_INT32(time_extra) & 0x2) << 32;
466 if (extra)
467 timespec->tv_nsec = B_LENDIAN_TO_HOST_INT32(time_extra) >> 2;
468 else
469 timespec->tv_nsec = 0;
472 void GetModificationTime(struct timespec *timespec, bool extra) const
473 { _DecodeTime(timespec, modification_time, modification_time_extra,
474 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
481 if (extra)
482 _DecodeTime(timespec, creation_time, creation_time_extra, extra);
483 else {
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);
502 if (extra)
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);
508 if (extra)
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);
514 if (extra)
515 change_time_extra = _EncodeTime(timespec);
517 void SetCreationTime(const struct timespec *timespec, bool extra)
519 if (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(); }
532 off_t Size() const
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);
609 if (S_ISREG(Mode()))
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);
634 } _PACKED;
636 #define EXT2_SUPER_BLOCK_MAGIC 0xef53
638 // flags
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 {
672 uint32 inode_id;
673 uint16 length;
674 uint8 name_length;
675 uint8 file_type;
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()));
693 } else {
694 length = B_HOST_TO_LENDIAN_INT16(
695 (short)(nameLength % 4 + 1 + MinimumSize()));
699 bool IsValid() const
701 return Length() > MinimumSize();
702 // There is no maximum size, as the last entry spans until the
703 // end of the block
706 static size_t MinimumSize()
708 return sizeof(ext2_dir_entry) - EXT2_NAME_LENGTH;
710 } _PACKED;
712 // file types
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 {
729 uint32 magic;
730 uint32 refcount;
731 uint32 blocks; // must be 1 for ext2
732 uint32 hash;
733 uint32 reserved[4]; // zero
735 bool IsValid() const
737 return B_LENDIAN_TO_HOST_INT32(magic) == EXT2_XATTR_MAGIC
738 && B_LENDIAN_TO_HOST_INT32(blocks) == 1
739 && refcount <= 1024;
742 void Dump() const {
743 for (unsigned int i = 0; i < Length(); i++)
744 dprintf("%02x ", ((uint8 *)this)[i]);
745 dprintf("\n");
748 static size_t Length()
750 return sizeof(ext2_xattr_header);
754 struct ext2_xattr_entry {
755 uint8 name_length;
756 uint8 name_index;
757 uint16 value_offset;
758 uint32 value_block; // must be zero for ext2
759 uint32 value_size;
760 uint32 hash;
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); }
770 // padded sizes
771 uint32 Length() const { return (MinimumSize() + NameLength()
772 + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND; }
774 bool IsValid() const
776 return NameLength() > 0 && value_block == 0;
777 // There is no maximum size, as the last entry spans until the
778 // end of the block
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]);
784 dprintf("\n");
787 static size_t MinimumSize()
789 return sizeof(ext2_xattr_entry) - EXT2_XATTR_NAME_LENGTH;
791 } _PACKED;
794 struct file_cookie {
795 bigtime_t last_notification;
796 off_t last_size;
797 int open_mode;
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;
809 #endif // EXT2_H