/*
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the MIT License.
*/
#ifndef AMIGA_FFS_H
#define AMIGA_FFS_H
#include <SupportDefs.h>
#include <ByteOrder.h>
namespace FFS {
/** The base class for all FFS blocks */
class BaseBlock{
public:
BaseBlock() : fData(NULL) {}
BaseBlock(void *data, int32 blockSize) { SetTo(data, blockSize); }
BaseBlock(int32 blockSize) { fSize = blockSize >> 2; }
void SetTo(void *data, int32 blockSize) { fData = (int32 *)data; fSize = blockSize >> 2; }
void SetTo(void *data) { fData = (int32 *)data; }
int32 *BlockData() const { return fData; }
int32 BlockSize() const { return fSize << 2; }
int32 LongWords() const { return fSize; }
int32 PrimaryType() const { return Offset(0); }
int32 SecondaryType() const { return BackOffset(1); }
int32 CheckSum() const { return Offset(5); }
inline bool IsRootBlock() const;
inline bool IsDirectory() const;
inline bool IsFile() const;
inline bool IsExtensionBlock() const;
inline bool IsDirectoryLink() const;
inline bool IsFileLink() const;
inline bool IsSymbolicLink() const;
status_t ValidateCheckSum() const;
protected:
int32 Offset(int16 i) const { return B_BENDIAN_TO_HOST_INT32(fData[i]); }
int32 BackOffset(int16 i) const { return B_BENDIAN_TO_HOST_INT32(fData[fSize - i]); }
status_t GetNameBackOffset(int32 offset, char *name, size_t size) const;
private:
int32 fSize;
int32 *fData;
};
/** The base class for all blocks that represent files and directories
* (all blocks that are accessible to the user)
*/
class NodeBlock : public BaseBlock {
public:
NodeBlock() {}
NodeBlock(int32 blockSize) : BaseBlock(blockSize) {}
NodeBlock(void *data, int32 blockSize) : BaseBlock(data, blockSize) {}
int32 HeaderKey() const { return Offset(1); }
int32 Protection() const { return BackOffset(48); }
int32 Days() const { return BackOffset(23); }
int32 Minute() const { return BackOffset(22); }
int32 Ticks() const { return BackOffset(21); }
status_t GetName(char *name, size_t size) const { return GetNameBackOffset(20, name, size); }
int32 LinkChain() const { return BackOffset(10); }
int32 HashChain() const { return BackOffset(4); }
int32 Parent() const { return BackOffset(3); }
};
/** A standard user directory block */
class DirectoryBlock : public NodeBlock {
public:
DirectoryBlock() : NodeBlock() {}
DirectoryBlock(int32 blockSize) : NodeBlock(blockSize) {}
DirectoryBlock(void *data, int32 blockSize) : NodeBlock(data, blockSize) {}
char ToUpperChar(int32 type, char c) const;
int32 HashIndexFor(int32 type, const char *name) const;
int32 HashValueAt(int32 index) const;
int32 NextHashValue(int32 &index) const;
int32 FirstHashValue(int32 &index) const;
protected:
int32 *HashTable() const { return BlockData() + 6; }
int32 HashSize() const { return LongWords() - 56; }
};
/** The root block of the device and at the same time the root directory */
class RootBlock : public DirectoryBlock {
public:
RootBlock() : DirectoryBlock() {}
RootBlock(int32 blockSize) : DirectoryBlock(blockSize) {}
RootBlock(void *data, int32 blockSize) : DirectoryBlock(data, blockSize) {}
int32 BitmapFlag() const { return BackOffset(50); }
int32 BitmapExtension() const { return BackOffset(24); }
int32 VolumeDays() const { return BackOffset(10); }
int32 VolumeMinutes() const { return BackOffset(9); }
int32 VolumeTicks() const { return BackOffset(8); }
int32 CreationDays() const { return BackOffset(7); }
int32 CreationMinutes() const { return BackOffset(6); }
int32 CreationTicks() const { return BackOffset(5); }
};
/** A standard user file block */
class FileBlock : public NodeBlock {
public:
FileBlock() : NodeBlock() {}
FileBlock(int32 blockSize) : NodeBlock(blockSize) {}
FileBlock(void *data, int32 blockSize) : NodeBlock(data, blockSize) {}
int32 BlockCount() const { return Offset(2); }
int32 FirstData() const { return Offset(4); }
int32 Size() const { return BackOffset(47); }
int32 NextExtension() const { return BackOffset(2); }
// The extension block is handled by this class as well
int32 DataBlock(int32 index) const { return BackOffset(51 + index); }
int32 NumDataBlocks() const { return LongWords() - 56; }
};
class HashIterator {
public:
HashIterator(int32 device, DirectoryBlock &node);
~HashIterator();
status_t InitCheck();
void Goto(int32 index);
NodeBlock *GetNext(int32 &block);
void Rewind();
private:
DirectoryBlock &fDirectory;
int32 fDevice;
int32 fCurrent;
int32 fBlock;
NodeBlock fNode;
int32 *fData;
};
enum primary_types {
PT_SHORT = 2,
PT_DATA = 8,
PT_LIST = 16,
};
enum secondary_types {
ST_ROOT = 1,
ST_DIRECTORY = 2,
ST_FILE = -3,
ST_DIRECTORY_LINK = 4,
ST_FILE_LINK = -4,
ST_SOFT_LINK = 3
};
enum dos_types {
DT_AMIGA_OFS = 'DOS\0',
DT_AMIGA_FFS = 'DOS\1',
DT_AMIGA_FFS_INTL = 'DOS\2',
DT_AMIGA_FFS_DCACHE = 'DOS\3',
};
enum protection_flags {
FILE_IS_DELETABLE = 1,
FILE_IS_EXECUTABLE = 2,
FILE_IS_READABLE = 4,
FILE_IS_WRITABLE = 8,
FILE_IS_ARCHIVED = 16,
FILE_IS_PURE = 32,
FILE_IS_SCRIPT = 64,
FILE_IS_HOLD = 128,
};
enum name_lengths {
FFS_NAME_LENGTH = 30,
COMMENT_LENGTH = 79,
};
status_t get_root_block(int fDevice, char *buffer, int32 blockSize, off_t partitionSize);
// inline methods
inline bool
BaseBlock::IsRootBlock() const
{
return PrimaryType() == PT_SHORT && SecondaryType() == ST_ROOT;
}
inline bool
BaseBlock::IsDirectory() const
{
return PrimaryType() == PT_SHORT && SecondaryType() == ST_DIRECTORY;
}
inline bool
BaseBlock::IsFile() const
{
return PrimaryType() == PT_SHORT && SecondaryType() == ST_FILE;
}
inline bool
BaseBlock::IsExtensionBlock() const
{
return PrimaryType() == PT_LIST && SecondaryType() == ST_FILE;
}
inline bool
BaseBlock::IsDirectoryLink() const
{
return PrimaryType() == PT_SHORT && SecondaryType() == ST_DIRECTORY_LINK;
}
inline bool
BaseBlock::IsFileLink() const
{
return PrimaryType() == PT_SHORT && SecondaryType() == ST_FILE_LINK;
}
inline bool
BaseBlock::IsSymbolicLink() const
{
return PrimaryType() == PT_SHORT && SecondaryType() == ST_SOFT_LINK;
}
} // namespace FFS
#endif /* AMIGA_FFS_H */
↑ V1039 Character escape is used in multicharacter literal. This causes implementation-defined behavior. Inspect expression: ''DOS\3''.
↑ V1039 Character escape is used in multicharacter literal. This causes implementation-defined behavior. Inspect expression: ''DOS\1''.
↑ V1039 Character escape is used in multicharacter literal. This causes implementation-defined behavior. Inspect expression: ''DOS\2''.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fSize.
↑ V1039 Character escape is used in multicharacter literal. This causes implementation-defined behavior. Inspect expression: ''DOS\0''.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fData.