1/* bfs - BFS definitions and helper functions 2 * 3 * Initial version by Axel D��rfler, axeld@pinc-software.de 4 * Parts of this code is based on work previously done by Marcus Overhagen 5 * 6 * Copyright 2001-2008 pinc Software. All Rights Reserved. 7 * This file may be used under the terms of the MIT License. 8 */ 9#ifndef BFS_H 10#define BFS_H 11 12 13#include <SupportDefs.h> 14 15#if !defined(BEOS_VERSION_DANO) && !defined(__HAIKU__) 16# define B_BAD_DATA B_ERROR 17#endif 18 19 20struct __attribute__((packed)) block_run { 21 int32 allocation_group; 22 uint16 start; 23 uint16 length; 24 25 inline bool operator==(const block_run &run) const; 26 inline bool operator!=(const block_run &run) const; 27 inline bool IsZero() const; 28 inline void SetTo(int32 group, uint16 start, uint16 length = 1); 29 30 inline static block_run Run(int32 group, uint16 start, uint16 length = 1); 31}; 32 33typedef block_run inode_addr; 34 35//************************************** 36 37 38#define BFS_DISK_NAME_LENGTH 32 39 40struct __attribute__((packed)) disk_super_block 41{ 42 char name[BFS_DISK_NAME_LENGTH]; 43 int32 magic1; 44 int32 fs_byte_order; 45 uint32 block_size; 46 uint32 block_shift; 47 int64 num_blocks; 48 int64 used_blocks; 49 int32 inode_size; 50 int32 magic2; 51 int32 blocks_per_ag; 52 int32 ag_shift; 53 int32 num_ags; 54 int32 flags; 55 block_run log_blocks; 56 int64 log_start; 57 int64 log_end; 58 int32 magic3; 59 inode_addr root_dir; 60 inode_addr indices; 61 int32 pad[8]; 62}; 63 64#define SUPER_BLOCK_FS_LENDIAN 'BIGE' /* BIGE */ 65 66#define SUPER_BLOCK_MAGIC1 'BFS1' /* BFS1 */ 67#define SUPER_BLOCK_MAGIC2 0xdd121031 68#define SUPER_BLOCK_MAGIC3 0x15b6830e 69 70#define SUPER_BLOCK_CLEAN 'CLEN' /* CLEN */ 71#define SUPER_BLOCK_DIRTY 'DIRT' /* DIRT */ 72 73//************************************** 74 75#define NUM_DIRECT_BLOCKS 12 76 77struct __attribute__((packed)) data_stream 78{ 79 block_run direct[NUM_DIRECT_BLOCKS]; 80 int64 max_direct_range; 81 block_run indirect; 82 int64 max_indirect_range; 83 block_run double_indirect; 84 int64 max_double_indirect_range; 85 int64 size; 86}; 87 88// ************************************** 89 90struct bfs_inode; 91 92struct __attribute__((packed)) small_data 93{ 94 uint32 type; 95 uint16 name_size; 96 uint16 data_size; 97 char name[0]; // name_size long, followed by data 98 99 inline char *Name(); 100 inline uint8 *Data(); 101 inline small_data *Next(); 102 inline bool IsLast(bfs_inode *inode); 103}; 104 105// the file name is part of the small_data structure 106#define FILE_NAME_TYPE 'CSTR' 107#define FILE_NAME_NAME 0x13 108#define FILE_NAME_NAME_LENGTH 1 109 110// ************************************** 111 112#define SHORT_SYMLINK_NAME_LENGTH 144 // length incl. terminating '\0' 113 114struct __attribute__((packed)) bfs_inode 115{ 116 int32 magic1; 117 inode_addr inode_num; 118 int32 uid; 119 int32 gid; 120 int32 mode; // see sys/stat.h 121 int32 flags; 122 int64 create_time; 123 int64 last_modified_time; 124 inode_addr parent; 125 inode_addr attributes; 126 uint32 type; // attribute type 127 128 int32 inode_size; 129 uint32 etc; // for in-memory structures (unused in Haiku' fs) 130 131 union __attribute__((packed)) { 132 data_stream data; 133 char short_symlink[SHORT_SYMLINK_NAME_LENGTH]; 134 }; 135 int32 pad[4]; 136 small_data small_data_start[0]; 137}; 138 139#define INODE_MAGIC1 0x3bbe0ad9 140#define INODE_TIME_SHIFT 16 141#define INODE_FILE_NAME_LENGTH 256 142 143enum inode_flags 144{ 145 INODE_IN_USE = 0x00000001, // always set 146 INODE_ATTR_INODE = 0x00000004, 147 INODE_LOGGED = 0x00000008, // log changes to the data stream 148 INODE_DELETED = 0x00000010, 149 INODE_EMPTY = 0x00000020, 150 INODE_LONG_SYMLINK = 0x00000040, // symlink in data stream 151 152 INODE_PERMANENT_FLAGS = 0x0000ffff, 153 154 INODE_NO_CACHE = 0x00010000, 155 INODE_WAS_WRITTEN = 0x00020000, 156 INODE_NO_TRANSACTION = 0x00040000 157}; 158 159//************************************** 160 161 162inline int32 163divide_roundup(int32 num,int32 divisor) 164{ 165 return (num + divisor - 1) / divisor; 166} 167 168inline int64 169divide_roundup(int64 num,int32 divisor) 170{ 171 return (num + divisor - 1) / divisor; 172} 173 174inline int 175get_shift(uint64 i) 176{ 177 int c; 178 c = 0; 179 while (i > 1) { 180 i >>= 1; 181 c++; 182 } 183 return c; 184} 185 186inline int32 187round_up(uint32 data) 188{ 189 // rounds up to the next off_t boundary 190 return (data + sizeof(off_t) - 1) & ~(sizeof(off_t) - 1); 191} 192 193/************************ block_run inline functions ************************/ 194// #pragma mark - 195 196 197inline bool block_run::operator==(const block_run &run) const 198{ 199 return allocation_group == run.allocation_group 200 && start == run.start 201 && length == run.length; 202} 203 204inline bool block_run::operator!=(const block_run &run) const 205{ 206 return allocation_group != run.allocation_group 207 || start != run.start 208 || length != run.length; 209} 210 211inline bool block_run::IsZero() const 212{ 213 return allocation_group == 0 && start == 0 && length == 0; 214} 215 216inline void block_run::SetTo(int32 _group,uint16 _start,uint16 _length) 217{ 218 allocation_group = _group; 219 start = _start; 220 length = _length; 221} 222 223inline block_run block_run::Run(int32 group, uint16 start, uint16 length) 224{ 225 block_run run; 226 run.allocation_group = group; 227 run.start = start; 228 run.length = length; 229 return run; 230} 231 232 233/************************ small_data inline functions ************************/ 234// #pragma mark - 235 236 237inline char *small_data::Name() 238{ 239 return name; 240} 241 242inline uint8 *small_data::Data() 243{ 244 return (uint8 *)name + name_size + 3; 245} 246 247inline small_data *small_data::Next() 248{ 249 return (small_data *)((uint8 *)(this + 1) + name_size + 3 + data_size + 1); 250} 251 252inline bool small_data::IsLast(bfs_inode *inode) 253{ 254 return (addr_t)this > (addr_t)inode + inode->inode_size - sizeof(small_data) 255 || name_size == 0; 256} 257 258#endif /* BFS_H */ 259