1/* 2** Copyright 2003, Axel D��rfler, axeld@pinc-software.de. All rights reserved. 3** Distributed under the terms of the OpenBeOS License. 4*/ 5#ifndef AMIGA_FFS_H 6#define AMIGA_FFS_H 7 8 9#include <SupportDefs.h> 10#include <ByteOrder.h> 11 12 13namespace FFS { 14 15/** The base class for all FFS blocks */ 16 17class 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 60class 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 84class 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 105class 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 126class 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 142class 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 161enum primary_types { 162 PT_SHORT = 2, 163 PT_DATA = 8, 164 PT_LIST = 16, 165}; 166 167enum 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 176enum 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 183enum 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 194enum name_lengths { 195 FFS_NAME_LENGTH = 30, 196 COMMENT_LENGTH = 79, 197}; 198 199status_t get_root_block(int fDevice, char *buffer, int32 blockSize, off_t partitionSize); 200 201// inline methods 202 203inline bool 204BaseBlock::IsRootBlock() const 205{ 206 return PrimaryType() == PT_SHORT && SecondaryType() == ST_ROOT; 207} 208 209 210inline bool 211BaseBlock::IsDirectory() const 212{ 213 return PrimaryType() == PT_SHORT && SecondaryType() == ST_DIRECTORY; 214} 215 216 217inline bool 218BaseBlock::IsFile() const 219{ 220 return PrimaryType() == PT_SHORT && SecondaryType() == ST_FILE; 221} 222 223 224inline bool 225BaseBlock::IsExtensionBlock() const 226{ 227 return PrimaryType() == PT_LIST && SecondaryType() == ST_FILE; 228} 229 230 231inline bool 232BaseBlock::IsDirectoryLink() const 233{ 234 return PrimaryType() == PT_SHORT && SecondaryType() == ST_DIRECTORY_LINK; 235} 236 237 238inline bool 239BaseBlock::IsFileLink() const 240{ 241 return PrimaryType() == PT_SHORT && SecondaryType() == ST_FILE_LINK; 242} 243 244 245inline bool 246BaseBlock::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