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