xref: /haiku/src/system/boot/loader/file_systems/amiga_ffs/amiga_ffs.h (revision 1a76488fc88584bf66b9751d7fb9b6527ac20d87)
1 /*
2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the MIT License.
4 */
5 #ifndef AMIGA_FFS_H
6 #define AMIGA_FFS_H
7 
8 
9 #include <SupportDefs.h>
10 #include <ByteOrder.h>
11 
12 
13 namespace FFS {
14 
15 /** The base class for all FFS blocks */
16 
17 class BaseBlock{
18 	public:
19 		BaseBlock() : fData(NULL) {}
20 		BaseBlock(void *data, int32 blockSize) { SetTo(data, blockSize); }
21 		BaseBlock(int32 blockSize) { fSize = blockSize >> 2; }
22 
23 		void SetTo(void *data, int32 blockSize) { fData = (int32 *)data; fSize = blockSize >> 2; }
24 		void SetTo(void *data) { fData = (int32 *)data; }
25 
26 		int32 *BlockData() const { return fData; }
27 		int32 BlockSize() const { return fSize << 2; }
28 		int32 LongWords() const { return fSize; }
29 
30 		int32 PrimaryType() const { return Offset(0); }
31 		int32 SecondaryType() const { return BackOffset(1); }
32 		int32 CheckSum() const { return Offset(5); }
33 
34 		inline bool IsRootBlock() const;
35 		inline bool IsDirectory() const;
36 		inline bool IsFile() const;
37 		inline bool IsExtensionBlock() const;
38 		inline bool IsDirectoryLink() const;
39 		inline bool IsFileLink() const;
40 		inline bool IsSymbolicLink() const;
41 
42 		status_t ValidateCheckSum() const;
43 
44 	protected:
45 		int32 Offset(int16 i) const { return B_BENDIAN_TO_HOST_INT32(fData[i]); }
46 		int32 BackOffset(int16 i) const { return B_BENDIAN_TO_HOST_INT32(fData[fSize - i]); }
47 
48 		status_t GetNameBackOffset(int32 offset, char *name, size_t size) const;
49 
50 	private:
51 		int32	fSize;
52 		int32	*fData;
53 };
54 
55 
56 /** The base class for all blocks that represent files and directories
57  *	(all blocks that are accessible to the user)
58  */
59 
60 class NodeBlock : public BaseBlock {
61 	public:
62 		NodeBlock() {}
63 		NodeBlock(int32 blockSize) : BaseBlock(blockSize) {}
64 		NodeBlock(void *data, int32 blockSize) : BaseBlock(data, blockSize) {}
65 
66 		int32 HeaderKey() const { return Offset(1); }
67 		int32 Protection() const { return BackOffset(48); }
68 
69 		int32 Days() const { return BackOffset(23); }
70 		int32 Minute() const { return BackOffset(22); }
71 		int32 Ticks() const { return BackOffset(21); }
72 
73 		status_t GetName(char *name, size_t size) const { return GetNameBackOffset(20, name, size); }
74 
75 		int32 LinkChain() const { return BackOffset(10); }
76 		int32 HashChain() const { return BackOffset(4); }
77 
78 		int32 Parent() const { return BackOffset(3); }
79 };
80 
81 
82 /** A standard user directory block */
83 
84 class DirectoryBlock : public NodeBlock {
85 	public:
86 		DirectoryBlock() : NodeBlock() {}
87 		DirectoryBlock(int32 blockSize) : NodeBlock(blockSize) {}
88 		DirectoryBlock(void *data, int32 blockSize) : NodeBlock(data, blockSize) {}
89 
90 		char ToUpperChar(int32 type, char c) const;
91 		int32 HashIndexFor(int32 type, const char *name) const;
92 
93 		int32 HashValueAt(int32 index) const;
94 		int32 NextHashValue(int32 &index) const;
95 		int32 FirstHashValue(int32 &index) const;
96 
97 	protected:
98 		int32 *HashTable() const { return BlockData() + 6; }
99 		int32 HashSize() const { return LongWords() - 56; }
100 };
101 
102 
103 /** The root block of the device and at the same time the root directory */
104 
105 class RootBlock : public DirectoryBlock {
106 	public:
107 		RootBlock() : DirectoryBlock() {}
108 		RootBlock(int32 blockSize) : DirectoryBlock(blockSize) {}
109 		RootBlock(void *data, int32 blockSize) : DirectoryBlock(data, blockSize) {}
110 
111 		int32 BitmapFlag() const { return BackOffset(50); }
112 		int32 BitmapExtension() const { return BackOffset(24); }
113 
114 		int32 VolumeDays() const { return BackOffset(10); }
115 		int32 VolumeMinutes() const { return BackOffset(9); }
116 		int32 VolumeTicks() const { return BackOffset(8); }
117 
118 		int32 CreationDays() const { return BackOffset(7); }
119 		int32 CreationMinutes() const { return BackOffset(6); }
120 		int32 CreationTicks() const { return BackOffset(5); }
121 };
122 
123 
124 /** A standard user file block */
125 
126 class FileBlock : public NodeBlock {
127 	public:
128 		FileBlock() : NodeBlock() {}
129 		FileBlock(int32 blockSize) : NodeBlock(blockSize) {}
130 		FileBlock(void *data, int32 blockSize) : NodeBlock(data, blockSize) {}
131 
132 		int32 BlockCount() const { return Offset(2); }
133 		int32 FirstData() const { return Offset(4); }
134 		int32 Size() const { return BackOffset(47); }
135 		int32 NextExtension() const { return BackOffset(2); }
136 			// The extension block is handled by this class as well
137 
138 		int32 DataBlock(int32 index) const { return BackOffset(51 + index); }
139 		int32 NumDataBlocks() const { return LongWords() - 56; }
140 };
141 
142 class HashIterator {
143 	public:
144 		HashIterator(int32 device, DirectoryBlock &node);
145 		~HashIterator();
146 
147 		status_t InitCheck();
148 		void Goto(int32 index);
149 		NodeBlock *GetNext(int32 &block);
150 		void Rewind();
151 
152 	private:
153 		DirectoryBlock	&fDirectory;
154 		int32		fDevice;
155 		int32		fCurrent;
156 		int32		fBlock;
157 		NodeBlock	fNode;
158 		int32		*fData;
159 };
160 
161 enum primary_types {
162 	PT_SHORT			= 2,
163 	PT_DATA				= 8,
164 	PT_LIST				= 16,
165 };
166 
167 enum secondary_types {
168 	ST_ROOT				= 1,
169 	ST_DIRECTORY		= 2,
170 	ST_FILE				= -3,
171 	ST_DIRECTORY_LINK	= 4,
172 	ST_FILE_LINK		= -4,
173 	ST_SOFT_LINK		= 3
174 };
175 
176 enum dos_types {
177 	DT_AMIGA_OFS			= 'DOS\0',
178 	DT_AMIGA_FFS			= 'DOS\1',
179 	DT_AMIGA_FFS_INTL		= 'DOS\2',
180 	DT_AMIGA_FFS_DCACHE		= 'DOS\3',
181 };
182 
183 enum protection_flags {
184 	FILE_IS_DELETABLE	= 1,
185 	FILE_IS_EXECUTABLE	= 2,
186 	FILE_IS_READABLE	= 4,
187 	FILE_IS_WRITABLE	= 8,
188 	FILE_IS_ARCHIVED	= 16,
189 	FILE_IS_PURE		= 32,
190 	FILE_IS_SCRIPT		= 64,
191 	FILE_IS_HOLD		= 128,
192 };
193 
194 enum name_lengths {
195 	FFS_NAME_LENGTH		= 30,
196 	COMMENT_LENGTH		= 79,
197 };
198 
199 status_t get_root_block(int fDevice, char *buffer, int32 blockSize, off_t partitionSize);
200 
201 //	inline methods
202 
203 inline bool
204 BaseBlock::IsRootBlock() const
205 {
206 	return PrimaryType() == PT_SHORT && SecondaryType() == ST_ROOT;
207 }
208 
209 
210 inline bool
211 BaseBlock::IsDirectory() const
212 {
213 	return PrimaryType() == PT_SHORT && SecondaryType() == ST_DIRECTORY;
214 }
215 
216 
217 inline bool
218 BaseBlock::IsFile() const
219 {
220 	return PrimaryType() == PT_SHORT && SecondaryType() == ST_FILE;
221 }
222 
223 
224 inline bool
225 BaseBlock::IsExtensionBlock() const
226 {
227 	return PrimaryType() == PT_LIST && SecondaryType() == ST_FILE;
228 }
229 
230 
231 inline bool
232 BaseBlock::IsDirectoryLink() const
233 {
234 	return PrimaryType() == PT_SHORT && SecondaryType() == ST_DIRECTORY_LINK;
235 }
236 
237 
238 inline bool
239 BaseBlock::IsFileLink() const
240 {
241 	return PrimaryType() == PT_SHORT && SecondaryType() == ST_FILE_LINK;
242 }
243 
244 
245 inline bool
246 BaseBlock::IsSymbolicLink() const
247 {
248 	return PrimaryType() == PT_SHORT && SecondaryType() == ST_SOFT_LINK;
249 }
250 
251 }	// namespace FFS
252 
253 #endif	/* AMIGA_FFS_H */
254 
255