Implemented an Amiga FFS reader for the boot loader. Can only traverse
directories right now, reading from files is not yet implemented. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4695 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
86f2640947
commit
50d9710f0d
@ -1,3 +1,4 @@
|
||||
SubDir OBOS_TOP src kernel boot loader file_systems ;
|
||||
|
||||
SubInclude OBOS_TOP src kernel boot loader file_systems bfs ;
|
||||
SubInclude OBOS_TOP src kernel boot loader file_systems amiga_ffs ;
|
||||
|
118
src/kernel/boot/loader/file_systems/amiga_ffs/Directory.cpp
Normal file
118
src/kernel/boot/loader/file_systems/amiga_ffs/Directory.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Directory.h"
|
||||
#include "Volume.h"
|
||||
#include "File.h"
|
||||
|
||||
#include <StorageDefs.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
namespace FFS {
|
||||
|
||||
Directory::Directory(Volume &volume, int32 block)
|
||||
:
|
||||
fVolume(volume)
|
||||
{
|
||||
void *data = malloc(volume.BlockSize());
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (read_pos(volume.Device(), block * volume.BlockSize(), data, volume.BlockSize()) == volume.BlockSize())
|
||||
fNode.SetTo(data, volume.BlockSize());
|
||||
}
|
||||
|
||||
|
||||
Directory::Directory(Volume &volume, RootBlock &root)
|
||||
:
|
||||
fVolume(volume)
|
||||
{
|
||||
fNode.SetTo(root.BlockData(), root.BlockSize());
|
||||
}
|
||||
|
||||
|
||||
Directory::~Directory()
|
||||
{
|
||||
free(fNode.BlockData());
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::InitCheck()
|
||||
{
|
||||
return fNode.ValidateCheckSum();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::Open(void **_cookie, int mode)
|
||||
{
|
||||
*_cookie = (void *)new HashIterator(fVolume.Device(), fNode);
|
||||
if (*_cookie == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::Close(void *cookie)
|
||||
{
|
||||
delete (HashIterator *)cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Node *
|
||||
Directory::Lookup(const char *name, bool traverseLinks)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::GetNextEntry(void *cookie, char *name, size_t size)
|
||||
{
|
||||
HashIterator *iterator = (HashIterator *)cookie;
|
||||
int32 block;
|
||||
|
||||
NodeBlock *node = iterator->GetNext(block);
|
||||
if (node == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
return node->GetName(name, size);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::GetNextNode(void *cookie, Node **_node)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::Rewind(void *cookie)
|
||||
{
|
||||
HashIterator *iterator = (HashIterator *)cookie;
|
||||
iterator->Rewind();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::GetName(char *name, size_t size) const
|
||||
{
|
||||
return fNode.GetName(name, size);
|
||||
}
|
||||
|
||||
} // namespace FFS
|
45
src/kernel/boot/loader/file_systems/amiga_ffs/Directory.h
Normal file
45
src/kernel/boot/loader/file_systems/amiga_ffs/Directory.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
#ifndef DIRECTORY_H
|
||||
#define DIRECTORY_H
|
||||
|
||||
|
||||
#include "amiga_ffs.h"
|
||||
|
||||
#include <boot/vfs.h>
|
||||
|
||||
|
||||
namespace FFS {
|
||||
|
||||
class Volume;
|
||||
|
||||
class Directory : public ::Directory {
|
||||
public:
|
||||
Directory();
|
||||
Directory(Volume &volume, RootBlock &root);
|
||||
Directory(Volume &volume, int32 block);
|
||||
virtual ~Directory();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
virtual status_t Open(void **_cookie, int mode);
|
||||
virtual status_t Close(void *cookie);
|
||||
|
||||
virtual Node *Lookup(const char *name, bool traverseLinks);
|
||||
|
||||
virtual status_t GetNextEntry(void *cookie, char *nameBuffer, size_t bufferSize);
|
||||
virtual status_t GetNextNode(void *cookie, Node **_node);
|
||||
virtual status_t Rewind(void *cookie);
|
||||
|
||||
virtual status_t GetName(char *name, size_t size) const;
|
||||
|
||||
private:
|
||||
Volume &fVolume;
|
||||
DirectoryBlock fNode;
|
||||
};
|
||||
|
||||
} // namespace FFS
|
||||
|
||||
#endif /* DIRECTORY_H */
|
71
src/kernel/boot/loader/file_systems/amiga_ffs/File.cpp
Normal file
71
src/kernel/boot/loader/file_systems/amiga_ffs/File.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "File.h"
|
||||
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace FFS {
|
||||
|
||||
File::File(Volume &volume, int32 block)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
File::~File()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
File::InitCheck()
|
||||
{
|
||||
if (!fNode.IsFile())
|
||||
return B_BAD_TYPE;
|
||||
|
||||
return fNode.ValidateCheckSum();
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
File::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
File::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
File::GetName(char *nameBuffer, size_t bufferSize) const
|
||||
{
|
||||
return fNode.GetName(nameBuffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
File::Type() const
|
||||
{
|
||||
return S_IFREG;
|
||||
}
|
||||
|
||||
|
||||
off_t
|
||||
File::Size() const
|
||||
{
|
||||
return fNode.Size();
|
||||
}
|
||||
|
||||
} // namespace FFS
|
36
src/kernel/boot/loader/file_systems/amiga_ffs/File.h
Normal file
36
src/kernel/boot/loader/file_systems/amiga_ffs/File.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
|
||||
|
||||
#include <boot/vfs.h>
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
namespace FFS {
|
||||
|
||||
class File : public Node {
|
||||
public:
|
||||
File(Volume &volume, int32 block);
|
||||
virtual ~File();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize);
|
||||
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);
|
||||
|
||||
virtual status_t GetName(char *nameBuffer, size_t bufferSize) const;
|
||||
virtual int32 Type() const;
|
||||
virtual off_t Size() const;
|
||||
|
||||
private:
|
||||
FileBlock fNode;
|
||||
};
|
||||
|
||||
} // namespace FFS
|
||||
|
||||
#endif /* FILE_H */
|
14
src/kernel/boot/loader/file_systems/amiga_ffs/Jamfile
Normal file
14
src/kernel/boot/loader/file_systems/amiga_ffs/Jamfile
Normal file
@ -0,0 +1,14 @@
|
||||
SubDir OBOS_TOP src kernel boot loader file_systems amiga_ffs ;
|
||||
|
||||
UsePrivateHeaders [ FDirName kernel boot platform $(OBOS_BOOT_PLATFORM) ] ;
|
||||
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||
UsePrivateHeaders [ FDirName storage ] ;
|
||||
|
||||
#SubDirHdrs $(OBOS_TOP) src add-ons kernel file_systems amiga_ffs ;
|
||||
|
||||
KernelStaticLibrary boot_amiga_ffs :
|
||||
amiga_ffs.cpp
|
||||
Volume.cpp
|
||||
Directory.cpp
|
||||
File.cpp
|
||||
;
|
122
src/kernel/boot/loader/file_systems/amiga_ffs/Volume.cpp
Normal file
122
src/kernel/boot/loader/file_systems/amiga_ffs/Volume.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Volume.h"
|
||||
#include "Directory.h"
|
||||
|
||||
#include <boot/partitions.h>
|
||||
#include <boot/platform.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
using namespace FFS;
|
||||
|
||||
|
||||
Volume::Volume(boot::Partition *partition)
|
||||
:
|
||||
fRoot(NULL)
|
||||
{
|
||||
if ((fDevice = open_node(partition, O_RDONLY)) < B_OK)
|
||||
return;
|
||||
|
||||
char *buffer = (char *)malloc(4096);
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
if (read_pos(fDevice, 0, buffer, sizeof(uint32)) < B_OK) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (B_BENDIAN_TO_HOST_INT32(*(uint32 *)buffer)) {
|
||||
case DT_AMIGA_FFS:
|
||||
case DT_AMIGA_FFS_INTL:
|
||||
case DT_AMIGA_FFS_DCACHE:
|
||||
break;
|
||||
|
||||
case DT_AMIGA_OFS:
|
||||
printf("The Amiga OFS is not yet supported.\n");
|
||||
default:
|
||||
// unsupported file system
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
int32 blockSize = partition->block_size;
|
||||
if (get_root_block(fDevice, buffer, blockSize, partition->size) != B_OK) {
|
||||
// try to get the root block at different sizes, if the
|
||||
// block size was incorrectly passed from the partitioning
|
||||
// system
|
||||
for (int32 size = 512; size <= 4096; size <<= 1) {
|
||||
if (get_root_block(fDevice, buffer, size, partition->size) == B_OK) {
|
||||
blockSize = size;
|
||||
break;
|
||||
} else if (size >= 4096) {
|
||||
puts("Could not find root block\n");
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *newBuffer = (char *)realloc(buffer, blockSize);
|
||||
// if reallocation fails, we keep the old buffer
|
||||
if (newBuffer != NULL)
|
||||
buffer = newBuffer;
|
||||
|
||||
fRootNode.SetTo(buffer, blockSize);
|
||||
fRoot = new Directory(*this, fRootNode);
|
||||
// fRoot will free the buffer for us upon destruction
|
||||
}
|
||||
|
||||
|
||||
Volume::~Volume()
|
||||
{
|
||||
delete fRoot;
|
||||
close(fDevice);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Volume::InitCheck()
|
||||
{
|
||||
if (fRoot != NULL)
|
||||
return fRootNode.ValidateCheckSum();
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
static status_t
|
||||
amiga_ffs_get_file_system(boot::Partition *partition, ::Directory **_root)
|
||||
{
|
||||
Volume *volume = new Volume(partition);
|
||||
if (volume == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (volume->InitCheck() < B_OK) {
|
||||
delete volume;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
*_root = volume->Root();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
file_system_module_info gAmigaFFSFileSystemModule = {
|
||||
kPartitionTypeAmigaFFS,
|
||||
amiga_ffs_get_file_system
|
||||
};
|
||||
|
41
src/kernel/boot/loader/file_systems/amiga_ffs/Volume.h
Normal file
41
src/kernel/boot/loader/file_systems/amiga_ffs/Volume.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
#ifndef VOLUME_H
|
||||
#define VOLUME_H
|
||||
|
||||
|
||||
#include "amiga_ffs.h"
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
namespace boot {
|
||||
class Partition;
|
||||
}
|
||||
|
||||
|
||||
namespace FFS {
|
||||
|
||||
class Directory;
|
||||
|
||||
class Volume {
|
||||
public:
|
||||
Volume(boot::Partition *partition);
|
||||
~Volume();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
int Device() const { return fDevice; }
|
||||
Directory *Root() { return fRoot; }
|
||||
int32 BlockSize() const { return fRootNode.BlockSize(); }
|
||||
|
||||
protected:
|
||||
int fDevice;
|
||||
RootBlock fRootNode;
|
||||
Directory *fRoot;
|
||||
};
|
||||
|
||||
} // namespace FFS
|
||||
|
||||
#endif /* VOLUME_H */
|
199
src/kernel/boot/loader/file_systems/amiga_ffs/amiga_ffs.cpp
Normal file
199
src/kernel/boot/loader/file_systems/amiga_ffs/amiga_ffs.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include "amiga_ffs.h"
|
||||
|
||||
#include <boot/partitions.h>
|
||||
#include <boot/platform.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
using namespace FFS;
|
||||
|
||||
|
||||
class BCPLString {
|
||||
public:
|
||||
uint8 Length() { return fLength; }
|
||||
const char *String() { return (const char *)(&fLength + 1); }
|
||||
int32 CopyTo(char *name, size_t size);
|
||||
|
||||
private:
|
||||
uint8 fLength;
|
||||
};
|
||||
|
||||
|
||||
int32
|
||||
BCPLString::CopyTo(char *name, size_t size)
|
||||
{
|
||||
int32 length = size - 1 > Length() ? Length() : size - 1;
|
||||
|
||||
memcpy(name, String(), length);
|
||||
name[length] = '\0';
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
BaseBlock::GetNameBackOffset(int32 offset, char *name, size_t size) const
|
||||
{
|
||||
BCPLString *string = (BCPLString *)&fData[fSize - offset];
|
||||
string->CopyTo(name, size);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BaseBlock::ValidateCheckSum() const
|
||||
{
|
||||
if (fData == NULL)
|
||||
return B_NO_INIT;
|
||||
|
||||
int32 sum = 0;
|
||||
for (int32 index = 0; index < fSize; index++) {
|
||||
sum += Offset(index);
|
||||
}
|
||||
|
||||
return sum == 0 ? B_OK : B_BAD_DATA;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
int32
|
||||
DirectoryBlock::HashIndexFor(const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
DirectoryBlock::HashValueAt(int32 index) const
|
||||
{
|
||||
return index >= HashSize() ? -1 : (int32)B_BENDIAN_TO_HOST_INT32(HashTable()[index]);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
DirectoryBlock::FirstHashValue(int32 &index) const
|
||||
{
|
||||
index = -1;
|
||||
return NextHashValue(index);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
DirectoryBlock::NextHashValue(int32 &index) const
|
||||
{
|
||||
index++;
|
||||
|
||||
int32 value;
|
||||
while ((value = HashValueAt(index)) == 0) {
|
||||
if (++index >= HashSize())
|
||||
return -1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
HashIterator::HashIterator(int32 device, DirectoryBlock &directory)
|
||||
:
|
||||
fDirectory(directory),
|
||||
fDevice(device),
|
||||
fCurrent(0),
|
||||
fBlock(-1)
|
||||
{
|
||||
fData = (int32 *)malloc(directory.BlockSize());
|
||||
fNode.SetTo(directory.BlockData(), directory.BlockSize());
|
||||
}
|
||||
|
||||
|
||||
HashIterator::~HashIterator()
|
||||
{
|
||||
free(fData);
|
||||
}
|
||||
|
||||
|
||||
NodeBlock *
|
||||
HashIterator::GetNext(int32 &block)
|
||||
{
|
||||
if (fBlock == -1) {
|
||||
// first entry
|
||||
fBlock = fDirectory.FirstHashValue(fCurrent);
|
||||
} else if (fBlock == 0) {
|
||||
fBlock = fDirectory.NextHashValue(fCurrent);
|
||||
}
|
||||
|
||||
if (fBlock == -1)
|
||||
return NULL;
|
||||
|
||||
block = fBlock;
|
||||
|
||||
if (read_pos(fDevice, fBlock * fNode.BlockSize(), fData, fNode.BlockSize()) < B_OK)
|
||||
return NULL;
|
||||
|
||||
fNode.SetTo(fData);
|
||||
if (fNode.ValidateCheckSum() != B_OK) {
|
||||
dprintf("block at %ld bad checksum.\n", fBlock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fBlock = fNode.HashChain();
|
||||
|
||||
return &fNode;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HashIterator::Rewind()
|
||||
{
|
||||
fCurrent = 0;
|
||||
fBlock = -1;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
FFS::get_root_block(int fDevice, char *buffer, int32 blockSize, off_t partitionSize)
|
||||
{
|
||||
// calculate root block position (it depends on the block size)
|
||||
|
||||
// ToDo: get the number of reserved blocks out of the disk_environment structure??
|
||||
// (from the amiga_rdb module)
|
||||
int32 reservedBlocks = 2;
|
||||
off_t offset = (((partitionSize / blockSize) - 1 - reservedBlocks) / 2) + reservedBlocks;
|
||||
// ToDo: this calculation might be incorrect for certain cases.
|
||||
|
||||
if (read_pos(fDevice, offset * blockSize, buffer, blockSize) < B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
RootBlock root(buffer, blockSize);
|
||||
if (root.ValidateCheckSum() < B_OK)
|
||||
return B_BAD_DATA;
|
||||
|
||||
//printf("primary = %ld, secondary = %ld\n", root.PrimaryType(), root.SecondaryType());
|
||||
if (!root.IsRootBlock())
|
||||
return B_BAD_TYPE;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
258
src/kernel/boot/loader/file_systems/amiga_ffs/amiga_ffs.h
Normal file
258
src/kernel/boot/loader/file_systems/amiga_ffs/amiga_ffs.h
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS 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) {}
|
||||
|
||||
int32 HashIndexFor(const char *name);
|
||||
|
||||
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 Extension() const { return BackOffset(2); }
|
||||
};
|
||||
|
||||
class ExtensionBlock : public BaseBlock {
|
||||
public:
|
||||
ExtensionBlock(int32 blockSize) : BaseBlock(blockSize) {}
|
||||
|
||||
int32 HeaderKey() const { return Offset(1); }
|
||||
int32 BlockCount() const { return Offset(2); }
|
||||
|
||||
int32 Parent() const { return BackOffset(3); }
|
||||
int32 NextExtension() const { return BackOffset(2); }
|
||||
};
|
||||
|
||||
class HashIterator {
|
||||
public:
|
||||
HashIterator(int32 device, DirectoryBlock &node);
|
||||
~HashIterator();
|
||||
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user