1 /* 2 * Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de. 3 * Parts of this code is based on work previously done by Marcus Overhagen. 4 * 5 * This file may be used under the terms of the MIT License. 6 */ 7 #ifndef BFS_H 8 #define BFS_H 9 10 //! BFS definitions and helper functions 11 12 13 #include "bfs_endian.h" 14 #include "system_dependencies.h" 15 16 17 #ifdef _BOOT_MODE 18 namespace BFS { 19 #endif 20 21 #ifndef _BOOT_MODE 22 extern fs_volume_ops gBFSVolumeOps; 23 extern fs_vnode_ops gBFSVnodeOps; 24 #endif 25 26 struct block_run { 27 int32 allocation_group; 28 uint16 start; 29 uint16 length; 30 31 int32 AllocationGroup() const { return BFS_ENDIAN_TO_HOST_INT32(allocation_group); } 32 uint16 Start() const { return BFS_ENDIAN_TO_HOST_INT16(start); } 33 uint16 Length() const { return BFS_ENDIAN_TO_HOST_INT16(length); } 34 35 inline bool operator==(const block_run &run) const; 36 inline bool operator!=(const block_run &run) const; 37 inline bool IsZero() const; 38 inline bool MergeableWith(block_run run) const; 39 inline void SetTo(int32 group, uint16 start, uint16 length = 1); 40 41 inline static block_run Run(int32 group, uint16 start, uint16 length = 1); 42 // can't have a constructor because it's used in a union 43 } _PACKED; 44 45 typedef block_run inode_addr; 46 47 // Since the block_run::length field spans 16 bits, the largest number of 48 // blocks covered by a block_run is 65535 (as long as we don't want to 49 // break compatibility and take a zero length for 65536). 50 #define MAX_BLOCK_RUN_LENGTH 65535 51 52 //************************************** 53 54 55 #define BFS_DISK_NAME_LENGTH 32 56 57 struct disk_super_block { 58 char name[BFS_DISK_NAME_LENGTH]; 59 int32 magic1; 60 int32 fs_byte_order; 61 uint32 block_size; 62 uint32 block_shift; 63 off_t num_blocks; 64 off_t used_blocks; 65 int32 inode_size; 66 int32 magic2; 67 int32 blocks_per_ag; 68 int32 ag_shift; 69 int32 num_ags; 70 int32 flags; 71 block_run log_blocks; 72 off_t log_start; 73 off_t log_end; 74 int32 magic3; 75 inode_addr root_dir; 76 inode_addr indices; 77 int32 _reserved[8]; 78 int32 pad_to_block[87]; 79 // this also contains parts of the boot block 80 81 int32 Magic1() const { return BFS_ENDIAN_TO_HOST_INT32(magic1); } 82 int32 Magic2() const { return BFS_ENDIAN_TO_HOST_INT32(magic2); } 83 int32 Magic3() const { return BFS_ENDIAN_TO_HOST_INT32(magic3); } 84 int32 ByteOrder() const { return BFS_ENDIAN_TO_HOST_INT32(fs_byte_order); } 85 uint32 BlockSize() const { return BFS_ENDIAN_TO_HOST_INT32(block_size); } 86 uint32 BlockShift() const { return BFS_ENDIAN_TO_HOST_INT32(block_shift); } 87 off_t NumBlocks() const { return BFS_ENDIAN_TO_HOST_INT64(num_blocks); } 88 off_t UsedBlocks() const { return BFS_ENDIAN_TO_HOST_INT64(used_blocks); } 89 int32 InodeSize() const { return BFS_ENDIAN_TO_HOST_INT32(inode_size); } 90 int32 BlocksPerAllocationGroup() const { return BFS_ENDIAN_TO_HOST_INT32(blocks_per_ag); } 91 int32 AllocationGroups() const { return BFS_ENDIAN_TO_HOST_INT32(num_ags); } 92 int32 AllocationGroupShift() const { return BFS_ENDIAN_TO_HOST_INT32(ag_shift); } 93 int32 Flags() const { return BFS_ENDIAN_TO_HOST_INT32(flags); } 94 off_t LogStart() const { return BFS_ENDIAN_TO_HOST_INT64(log_start); } 95 off_t LogEnd() const { return BFS_ENDIAN_TO_HOST_INT64(log_end); } 96 97 // implemented in Volume.cpp: 98 bool IsValid(); 99 void Initialize(const char *name, off_t numBlocks, uint32 blockSize); 100 } _PACKED; 101 102 #define SUPER_BLOCK_FS_LENDIAN 'BIGE' /* BIGE */ 103 104 #define SUPER_BLOCK_MAGIC1 'BFS1' /* BFS1 */ 105 #define SUPER_BLOCK_MAGIC2 0xdd121031 106 #define SUPER_BLOCK_MAGIC3 0x15b6830e 107 108 #define SUPER_BLOCK_DISK_CLEAN 'CLEN' /* CLEN */ 109 #define SUPER_BLOCK_DISK_DIRTY 'DIRT' /* DIRT */ 110 111 //************************************** 112 113 #define NUM_DIRECT_BLOCKS 12 114 115 struct data_stream { 116 block_run direct[NUM_DIRECT_BLOCKS]; 117 off_t max_direct_range; 118 block_run indirect; 119 off_t max_indirect_range; 120 block_run double_indirect; 121 off_t max_double_indirect_range; 122 off_t size; 123 124 off_t MaxDirectRange() const { return BFS_ENDIAN_TO_HOST_INT64(max_direct_range); } 125 off_t MaxIndirectRange() const { return BFS_ENDIAN_TO_HOST_INT64(max_indirect_range); } 126 off_t MaxDoubleIndirectRange() const { return BFS_ENDIAN_TO_HOST_INT64(max_double_indirect_range); } 127 off_t Size() const { return BFS_ENDIAN_TO_HOST_INT64(size); } 128 } _PACKED; 129 130 // This defines the size of the indirect and double indirect 131 // blocks. Note: the code may not work correctly at some places 132 // if this value is changed (it's not tested). 133 #define NUM_ARRAY_BLOCKS 4 134 #define ARRAY_BLOCKS_SHIFT 2 135 #define INDIRECT_BLOCKS_SHIFT (ARRAY_BLOCKS_SHIFT + ARRAY_BLOCKS_SHIFT) 136 137 //************************************** 138 139 struct bfs_inode; 140 141 struct small_data { 142 uint32 type; 143 uint16 name_size; 144 uint16 data_size; 145 char name[0]; // name_size long, followed by data 146 147 uint32 Type() const { return BFS_ENDIAN_TO_HOST_INT32(type); } 148 uint16 NameSize() const { return BFS_ENDIAN_TO_HOST_INT16(name_size); } 149 uint16 DataSize() const { return BFS_ENDIAN_TO_HOST_INT16(data_size); } 150 151 inline char *Name() const; 152 inline uint8 *Data() const; 153 inline uint32 Size() const; 154 inline small_data *Next() const; 155 inline bool IsLast(const bfs_inode *inode) const; 156 } _PACKED; 157 158 // the file name is part of the small_data structure 159 #define FILE_NAME_TYPE 'CSTR' 160 #define FILE_NAME_NAME 0x13 161 #define FILE_NAME_NAME_LENGTH 1 162 163 164 //************************************** 165 166 class Volume; 167 168 #define SHORT_SYMLINK_NAME_LENGTH 144 // length incl. terminating '\0' 169 170 struct bfs_inode { 171 int32 magic1; 172 inode_addr inode_num; 173 int32 uid; 174 int32 gid; 175 int32 mode; // see sys/stat.h 176 int32 flags; 177 bigtime_t create_time; 178 bigtime_t last_modified_time; 179 inode_addr parent; 180 inode_addr attributes; 181 uint32 type; // attribute type 182 183 int32 inode_size; 184 uint32 etc; // a pointer to the Inode object during construction 185 186 union { 187 data_stream data; 188 char short_symlink[SHORT_SYMLINK_NAME_LENGTH]; 189 }; 190 int32 pad[4]; 191 192 small_data small_data_start[0]; 193 194 int32 Magic1() const { return BFS_ENDIAN_TO_HOST_INT32(magic1); } 195 int32 UserID() const { return BFS_ENDIAN_TO_HOST_INT32(uid); } 196 int32 GroupID() const { return BFS_ENDIAN_TO_HOST_INT32(gid); } 197 int32 Mode() const { return BFS_ENDIAN_TO_HOST_INT32(mode); } 198 int32 Flags() const { return BFS_ENDIAN_TO_HOST_INT32(flags); } 199 int32 Type() const { return BFS_ENDIAN_TO_HOST_INT32(type); } 200 int32 InodeSize() const { return BFS_ENDIAN_TO_HOST_INT32(inode_size); } 201 bigtime_t LastModifiedTime() const { return BFS_ENDIAN_TO_HOST_INT64(last_modified_time); } 202 bigtime_t CreateTime() const { return BFS_ENDIAN_TO_HOST_INT64(create_time); } 203 small_data *SmallDataStart() { return small_data_start; } 204 205 status_t InitCheck(Volume *volume); 206 // defined in Inode.cpp 207 } _PACKED; 208 209 #define INODE_MAGIC1 0x3bbe0ad9 210 #define INODE_TIME_SHIFT 16 211 #define INODE_TIME_MASK 0xffff 212 #define INODE_FILE_NAME_LENGTH 256 213 214 enum inode_flags { 215 INODE_IN_USE = 0x00000001, // always set 216 INODE_ATTR_INODE = 0x00000004, 217 INODE_LOGGED = 0x00000008, // log changes to the data stream 218 INODE_DELETED = 0x00000010, 219 INODE_NOT_READY = 0x00000020, // used during Inode construction 220 INODE_LONG_SYMLINK = 0x00000040, // symlink in data stream 221 222 INODE_PERMANENT_FLAGS = 0x0000ffff, 223 224 INODE_WAS_WRITTEN = 0x00020000, 225 INODE_DONT_FREE_SPACE = 0x00080000, // only used by the "chkbfs" functionality 226 INODE_CHKBFS_RUNNING = 0x00200000, 227 }; 228 229 //************************************** 230 231 struct file_cookie { 232 bigtime_t last_notification; 233 off_t last_size; 234 int open_mode; 235 }; 236 237 // notify every second if the file size has changed 238 #define INODE_NOTIFICATION_INTERVAL 1000000LL 239 240 //************************************** 241 242 243 inline int32 244 divide_roundup(int32 num,int32 divisor) 245 { 246 return (num + divisor - 1) / divisor; 247 } 248 249 inline int64 250 divide_roundup(int64 num,int32 divisor) 251 { 252 return (num + divisor - 1) / divisor; 253 } 254 255 inline int 256 get_shift(uint64 i) 257 { 258 int c; 259 c = 0; 260 while (i > 1) { 261 i >>= 1; 262 c++; 263 } 264 return c; 265 } 266 267 inline uint32 268 key_align(uint32 data) 269 { 270 // rounds up to the next off_t boundary 271 return (data + sizeof(off_t) - 1) & ~(sizeof(off_t) - 1); 272 } 273 274 275 /************************ block_run inline functions ************************/ 276 // #pragma mark - 277 278 279 inline bool 280 block_run::operator==(const block_run &run) const 281 { 282 return allocation_group == run.allocation_group 283 && start == run.start 284 && length == run.length; 285 } 286 287 288 inline bool 289 block_run::operator!=(const block_run &run) const 290 { 291 return allocation_group != run.allocation_group 292 || start != run.start 293 || length != run.length; 294 } 295 296 297 inline bool 298 block_run::IsZero() const 299 { 300 return allocation_group == 0 && start == 0 && length == 0; 301 } 302 303 304 inline bool 305 block_run::MergeableWith(block_run run) const 306 { 307 // 65535 is the maximum allowed run size for BFS 308 return allocation_group == run.allocation_group 309 && Start() + Length() == run.Start() 310 && (uint32)Length() + run.Length() <= MAX_BLOCK_RUN_LENGTH; 311 } 312 313 314 inline void 315 block_run::SetTo(int32 _group,uint16 _start,uint16 _length) 316 { 317 allocation_group = HOST_ENDIAN_TO_BFS_INT32(_group); 318 start = HOST_ENDIAN_TO_BFS_INT16(_start); 319 length = HOST_ENDIAN_TO_BFS_INT16(_length); 320 } 321 322 323 inline block_run 324 block_run::Run(int32 group, uint16 start, uint16 length) 325 { 326 block_run run; 327 run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(group); 328 run.start = HOST_ENDIAN_TO_BFS_INT16(start); 329 run.length = HOST_ENDIAN_TO_BFS_INT16(length); 330 return run; 331 } 332 333 334 /************************ small_data inline functions ************************/ 335 // #pragma mark - 336 337 338 inline char * 339 small_data::Name() const 340 { 341 return const_cast<char *>(name); 342 } 343 344 345 inline uint8 * 346 small_data::Data() const 347 { 348 return (uint8 *)Name() + NameSize() + 3; 349 } 350 351 352 inline uint32 353 small_data::Size() const 354 { 355 return sizeof(small_data) + NameSize() + 3 + DataSize() + 1; 356 } 357 358 359 inline small_data * 360 small_data::Next() const 361 { 362 return (small_data *)((uint8 *)this + Size()); 363 } 364 365 366 inline bool 367 small_data::IsLast(const bfs_inode *inode) const 368 { 369 // we need to check the location first, because if name_size is already beyond 370 // the block, we would touch invalid memory (although that can't cause wrong 371 // results) 372 return (addr_t)this > (addr_t)inode + inode->InodeSize() - sizeof(small_data) || name_size == 0; 373 } 374 375 #ifdef _BOOT_MODE 376 } // namespace BFS 377 #endif 378 379 #endif /* BFS_H */ 380