xref: /haiku/src/bin/bfs_tools/lib/bfs.h (revision 899e0ef82b5624ace2ccfa5f5a58c8ebee54aaef)
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 
20 struct __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 
33 typedef block_run inode_addr;
34 
35 //**************************************
36 
37 
38 #define BFS_DISK_NAME_LENGTH	32
39 
40 struct __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 
77 struct __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 
90 struct bfs_inode;
91 
92 struct __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 
114 struct __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 
143 enum 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 
162 inline int32
163 divide_roundup(int32 num,int32 divisor)
164 {
165 	return (num + divisor - 1) / divisor;
166 }
167 
168 inline int64
169 divide_roundup(int64 num,int32 divisor)
170 {
171 	return (num + divisor - 1) / divisor;
172 }
173 
174 inline int
175 get_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 
186 inline int32
187 round_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 
197 inline 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 
204 inline 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 
211 inline bool block_run::IsZero() const
212 {
213 	return allocation_group == 0 && start == 0 && length == 0;
214 }
215 
216 inline void block_run::SetTo(int32 _group,uint16 _start,uint16 _length)
217 {
218 	allocation_group = _group;
219 	start = _start;
220 	length = _length;
221 }
222 
223 inline 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 
237 inline char *small_data::Name()
238 {
239 	return name;
240 }
241 
242 inline uint8 *small_data::Data()
243 {
244 	return (uint8 *)name + name_size + 3;
245 }
246 
247 inline small_data *small_data::Next()
248 {
249 	return (small_data *)((uint8 *)(this + 1) + name_size + 3 + data_size + 1);
250 }
251 
252 inline 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