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 ;
|
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 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