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