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