* Moved the checksum device driver to subdir "driver".
* Created a file system module and a disk system add-on. Currently only initializing and identifying/scanning is supported. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37300 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
06237dd800
commit
952d6c8cc4
@ -1,16 +1,5 @@
|
||||
SubDir HAIKU_TOP src tests system kernel file_corruption ;
|
||||
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
|
||||
KernelAddon <test_driver>checksum_device :
|
||||
checksum_device.cpp
|
||||
|
||||
# from src/kits/shared
|
||||
SHA256.cpp
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles SHA256.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src kits shared ] ;
|
||||
HaikuSubInclude disk_system ;
|
||||
HaikuSubInclude driver ;
|
||||
HaikuSubInclude fs ;
|
||||
|
41
src/tests/system/kernel/file_corruption/checksumfs.h
Normal file
41
src/tests/system/kernel/file_corruption/checksumfs.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef CHECK_SUM_FS_H
|
||||
#define CHECK_SUM_FS_H
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
|
||||
#define CHECK_SUM_FS_PRETTY_NAME "CheckSum File System"
|
||||
|
||||
|
||||
static const uint64 kCheckSumFSSuperBlockOffset = 16 * B_PAGE_SIZE;
|
||||
static const uint64 kCheckSumFSMinSize
|
||||
= kCheckSumFSSuperBlockOffset + 16 * B_PAGE_SIZE;
|
||||
|
||||
|
||||
static const uint32 kCheckSumFSNameLength = 256;
|
||||
|
||||
static const uint32 kCheckSumFSSignatureLength = 16;
|
||||
#define CHECK_SUM_FS_SIGNATURE_1 "_1!cHEcKsUmfS!1_"
|
||||
#define CHECK_SUM_FS_SIGNATURE_2 "-2@ChECkSumFs@2-"
|
||||
|
||||
static const uint32 kCheckSumFSVersion = 1;
|
||||
|
||||
struct checksumfs_super_block {
|
||||
char signature1[kCheckSumFSSignatureLength];
|
||||
uint32 version;
|
||||
uint32 pad1;
|
||||
uint64 totalBlocks;
|
||||
uint64 freeBlocks;
|
||||
uint64 rootDir;
|
||||
uint64 blockBitmap;
|
||||
char name[kCheckSumFSNameLength];
|
||||
char signature2[kCheckSumFSSignatureLength];
|
||||
} _PACKED;
|
||||
|
||||
|
||||
#endif // CHECK_SUM_FS_H
|
13
src/tests/system/kernel/file_corruption/disk_system/Jamfile
Normal file
13
src/tests/system/kernel/file_corruption/disk_system/Jamfile
Normal file
@ -0,0 +1,13 @@
|
||||
SubDir HAIKU_TOP src tests system kernel file_corruption disk_system ;
|
||||
|
||||
|
||||
UsePrivateHeaders shared storage ;
|
||||
|
||||
UseHeaders [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||
|
||||
|
||||
Addon <disk_system>checksumfs :
|
||||
checksumfs.cpp
|
||||
|
||||
: be $(TARGET_LIBSTDC++)
|
||||
;
|
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <DiskDeviceDefs.h>
|
||||
#include <DiskSystemAddOn.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <MutablePartition.h>
|
||||
|
||||
#include "checksumfs.h"
|
||||
|
||||
|
||||
static const uint32 kDiskSystemFlags =
|
||||
0
|
||||
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME
|
||||
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
|
||||
| B_DISK_SYSTEM_SUPPORTS_INITIALIZING
|
||||
| B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
|
||||
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME_WHILE_MOUNTED
|
||||
// | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS_WHILE_MOUNTED
|
||||
;
|
||||
|
||||
|
||||
class CheckSumFSAddOn : public BDiskSystemAddOn {
|
||||
public:
|
||||
CheckSumFSAddOn();
|
||||
|
||||
virtual status_t CreatePartitionHandle(
|
||||
BMutablePartition* partition,
|
||||
BPartitionHandle** _handle);
|
||||
|
||||
virtual bool CanInitialize(
|
||||
const BMutablePartition* partition);
|
||||
virtual status_t GetInitializationParameterEditor(
|
||||
const BMutablePartition* partition,
|
||||
BPartitionParameterEditor** _editor);
|
||||
virtual status_t ValidateInitialize(
|
||||
const BMutablePartition* partition,
|
||||
BString* name, const char* parameters);
|
||||
virtual status_t Initialize(BMutablePartition* partition,
|
||||
const char* name, const char* parameters,
|
||||
BPartitionHandle** _handle);
|
||||
};
|
||||
|
||||
|
||||
class CheckSumFSPartitionHandle : public BPartitionHandle {
|
||||
public:
|
||||
CheckSumFSPartitionHandle(
|
||||
BMutablePartition* partition);
|
||||
~CheckSumFSPartitionHandle();
|
||||
|
||||
status_t Init();
|
||||
|
||||
virtual uint32 SupportedOperations(uint32 mask);
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - CheckSumFSAddOn
|
||||
|
||||
|
||||
CheckSumFSAddOn::CheckSumFSAddOn()
|
||||
:
|
||||
BDiskSystemAddOn(CHECK_SUM_FS_PRETTY_NAME, kDiskSystemFlags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CheckSumFSAddOn::CreatePartitionHandle(BMutablePartition* partition,
|
||||
BPartitionHandle** _handle)
|
||||
{
|
||||
debug_printf("CheckSumFSAddOn::CreatePartitionHandle()\n");
|
||||
CheckSumFSPartitionHandle* handle
|
||||
= new(std::nothrow) CheckSumFSPartitionHandle(partition);
|
||||
if (handle == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = handle->Init();
|
||||
if (error != B_OK) {
|
||||
delete handle;
|
||||
return error;
|
||||
}
|
||||
|
||||
*_handle = handle;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CheckSumFSAddOn::CanInitialize(const BMutablePartition* partition)
|
||||
{
|
||||
debug_printf("CheckSumFSAddOn::CanInitialize()\n");
|
||||
return (uint64)partition->Size() >= kCheckSumFSMinSize;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CheckSumFSAddOn::GetInitializationParameterEditor(
|
||||
const BMutablePartition* partition, BPartitionParameterEditor** _editor)
|
||||
{
|
||||
debug_printf("CheckSumFSAddOn::GetInitializationParameterEditor()\n");
|
||||
*_editor = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CheckSumFSAddOn::ValidateInitialize(const BMutablePartition* partition,
|
||||
BString* name, const char* parameters)
|
||||
{
|
||||
debug_printf("CheckSumFSAddOn::ValidateInitialize()\n");
|
||||
if (!CanInitialize(partition) || name == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// truncate name, if too long
|
||||
if ((uint64)name->Length() >= kCheckSumFSNameLength)
|
||||
name->Truncate(kCheckSumFSNameLength - 1);
|
||||
|
||||
// replace '/' by '-'
|
||||
name->ReplaceAll('/', '-');
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CheckSumFSAddOn::Initialize(BMutablePartition* partition, const char* name,
|
||||
const char* parameters, BPartitionHandle** _handle)
|
||||
{
|
||||
debug_printf("CheckSumFSAddOn::Initialize()\n");
|
||||
if (!CanInitialize(partition) || name == NULL
|
||||
|| strlen(name) >= kCheckSumFSNameLength) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
CheckSumFSPartitionHandle* handle
|
||||
= new(std::nothrow) CheckSumFSPartitionHandle(partition);
|
||||
if (handle == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<CheckSumFSPartitionHandle> handleDeleter(handle);
|
||||
|
||||
status_t error = partition->SetContentType(Name());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
partition->SetContentName(name);
|
||||
partition->SetContentParameters(parameters);
|
||||
partition->SetBlockSize(B_PAGE_SIZE);
|
||||
partition->SetContentSize(partition->Size() / B_PAGE_SIZE * B_PAGE_SIZE);
|
||||
partition->Changed(B_PARTITION_CHANGED_INITIALIZATION);
|
||||
|
||||
*_handle = handleDeleter.Detach();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - CheckSumFSPartitionHandle
|
||||
|
||||
|
||||
CheckSumFSPartitionHandle::CheckSumFSPartitionHandle(
|
||||
BMutablePartition* partition)
|
||||
:
|
||||
BPartitionHandle(partition)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CheckSumFSPartitionHandle::~CheckSumFSPartitionHandle()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CheckSumFSPartitionHandle::Init()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
CheckSumFSPartitionHandle::SupportedOperations(uint32 mask)
|
||||
{
|
||||
return kDiskSystemFlags & mask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
get_disk_system_add_ons(BList* addOns)
|
||||
{
|
||||
debug_printf("checksumfs: get_disk_system_add_ons()\n");
|
||||
CheckSumFSAddOn* addOn = new(std::nothrow) CheckSumFSAddOn;
|
||||
if (addOn == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (!addOns->AddItem(addOn)) {
|
||||
delete addOn;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
debug_printf("checksumfs: get_disk_system_add_ons() done ok\n");
|
||||
return B_OK;
|
||||
}
|
19
src/tests/system/kernel/file_corruption/driver/Jamfile
Normal file
19
src/tests/system/kernel/file_corruption/driver/Jamfile
Normal file
@ -0,0 +1,19 @@
|
||||
SubDir HAIKU_TOP src tests system kernel file_corruption driver ;
|
||||
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
UseHeaders [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||
|
||||
|
||||
KernelAddon checksum_device :
|
||||
checksum_device.cpp
|
||||
|
||||
# from src/kits/shared
|
||||
SHA256.cpp
|
||||
;
|
||||
|
||||
|
||||
SEARCH on [ FGristFiles SHA256.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src kits shared ] ;
|
101
src/tests/system/kernel/file_corruption/fs/Block.h
Normal file
101
src/tests/system/kernel/file_corruption/fs/Block.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BLOCK_H
|
||||
#define BLOCK_H
|
||||
|
||||
|
||||
#include <fs_cache.h>
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block()
|
||||
:
|
||||
fVolume(NULL),
|
||||
fData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~Block()
|
||||
{
|
||||
Put();
|
||||
}
|
||||
|
||||
bool GetReadable(Volume* volume, uint64 blockIndex)
|
||||
{
|
||||
Put();
|
||||
|
||||
return _Init(volume, blockIndex,
|
||||
block_cache_get(volume->BlockCache(), blockIndex));
|
||||
}
|
||||
|
||||
bool GetWritable(Volume* volume, uint64 blockIndex)
|
||||
{
|
||||
Put();
|
||||
|
||||
return _Init(volume, blockIndex,
|
||||
block_cache_get_writable(volume->BlockCache(), blockIndex, -1));
|
||||
}
|
||||
|
||||
bool GetZero(Volume* volume, uint64 blockIndex)
|
||||
{
|
||||
Put();
|
||||
|
||||
return _Init(volume, blockIndex,
|
||||
block_cache_get_empty(volume->BlockCache(), blockIndex, -1));
|
||||
}
|
||||
|
||||
void Put()
|
||||
{
|
||||
if (fVolume != NULL) {
|
||||
block_cache_put(fVolume->BlockCache(), fIndex);
|
||||
fVolume = NULL;
|
||||
fData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Discard()
|
||||
{
|
||||
if (fVolume != NULL) {
|
||||
block_cache_discard(fVolume->BlockCache(), fIndex, 1);
|
||||
fVolume = NULL;
|
||||
fData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void* Data() const
|
||||
{
|
||||
return fData;
|
||||
}
|
||||
|
||||
uint64 Index() const
|
||||
{
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _Init(Volume* volume, uint64 blockIndex, const void* data)
|
||||
{
|
||||
if (data == NULL)
|
||||
return false;
|
||||
|
||||
fVolume = volume;
|
||||
fData = const_cast<void*>(data);
|
||||
fIndex = blockIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Volume* fVolume;
|
||||
void* fData;
|
||||
uint64 fIndex;
|
||||
};
|
||||
|
||||
|
||||
#endif // BLOCK_H
|
20
src/tests/system/kernel/file_corruption/fs/Jamfile
Normal file
20
src/tests/system/kernel/file_corruption/fs/Jamfile
Normal file
@ -0,0 +1,20 @@
|
||||
SubDir HAIKU_TOP src tests system kernel file_corruption fs ;
|
||||
|
||||
|
||||
UsePrivateHeaders shared ;
|
||||
|
||||
UseHeaders [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||
|
||||
|
||||
KernelAddon checksumfs :
|
||||
checksumfs.cpp
|
||||
SuperBlock.cpp
|
||||
Volume.cpp
|
||||
|
||||
# from src/kits/shared
|
||||
SHA256.cpp
|
||||
;
|
||||
|
||||
|
||||
SEARCH on [ FGristFiles SHA256.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src kits shared ] ;
|
45
src/tests/system/kernel/file_corruption/fs/SuperBlock.cpp
Normal file
45
src/tests/system/kernel/file_corruption/fs/SuperBlock.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "SuperBlock.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
bool
|
||||
SuperBlock::Check(uint64 totalBlocks) const
|
||||
{
|
||||
if (strncmp(signature1, CHECK_SUM_FS_SIGNATURE_1,
|
||||
kCheckSumFSSignatureLength) != 0
|
||||
|| strncmp(signature2, CHECK_SUM_FS_SIGNATURE_2,
|
||||
kCheckSumFSSignatureLength) != 0
|
||||
|| Version() != kCheckSumFSVersion
|
||||
|| TotalBlocks() < kCheckSumFSMinSize / B_PAGE_SIZE
|
||||
|| TotalBlocks() > totalBlocks
|
||||
|| strnlen(name, kCheckSumFSNameLength) >= kCheckSumFSNameLength) {
|
||||
return false;
|
||||
}
|
||||
// TODO: Check free blocks and location of root directory and block bitmap.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SuperBlock::Initialize(Volume* volume)
|
||||
{
|
||||
memcpy(signature1, CHECK_SUM_FS_SIGNATURE_1, kCheckSumFSSignatureLength);
|
||||
memcpy(signature2, CHECK_SUM_FS_SIGNATURE_2, kCheckSumFSSignatureLength);
|
||||
|
||||
version = kCheckSumFSVersion;
|
||||
totalBlocks = volume->TotalBlocks();
|
||||
// freeBlocks = volume->BlockAllocator()->FreeBlocks();
|
||||
// blockBitmap = volume->BlockAllocator()->BlockBitmap();
|
||||
// rootDir = volume->RootDirBlock();
|
||||
strlcpy(name, volume->Name(), kCheckSumFSNameLength);
|
||||
}
|
29
src/tests/system/kernel/file_corruption/fs/SuperBlock.h
Normal file
29
src/tests/system/kernel/file_corruption/fs/SuperBlock.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SUPER_BLOCK_H
|
||||
#define SUPER_BLOCK_H
|
||||
|
||||
|
||||
#include "checksumfs.h"
|
||||
|
||||
|
||||
class Volume;
|
||||
|
||||
|
||||
struct SuperBlock : private checksumfs_super_block {
|
||||
public:
|
||||
uint64 TotalBlocks() const { return totalBlocks; }
|
||||
uint64 FreeBlocks() const { return freeBlocks; }
|
||||
uint32 Version() const { return version; }
|
||||
const char* Name() const { return name; }
|
||||
uint64 BlockBitmap() const { return blockBitmap; }
|
||||
uint64 RootDir() const { return rootDir; }
|
||||
|
||||
bool Check(uint64 totalBlocks) const;
|
||||
void Initialize(Volume* volume);
|
||||
};
|
||||
|
||||
|
||||
#endif // SUPER_BLOCK_H
|
116
src/tests/system/kernel/file_corruption/fs/Volume.cpp
Normal file
116
src/tests/system/kernel/file_corruption/fs/Volume.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <fs_cache.h>
|
||||
|
||||
#include "Block.h"
|
||||
#include "checksumfs.h"
|
||||
#include "SuperBlock.h"
|
||||
|
||||
|
||||
Volume::Volume(uint32 flags)
|
||||
:
|
||||
fFD(-1),
|
||||
fFlags(flags),
|
||||
fBlockCache(NULL),
|
||||
fTotalBlocks(0),
|
||||
fName(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Volume::~Volume()
|
||||
{
|
||||
if (fBlockCache != NULL)
|
||||
block_cache_delete(fBlockCache, false);
|
||||
|
||||
if (fFD >= 0)
|
||||
close(fFD);
|
||||
|
||||
free(fName);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Volume::Init(const char* device)
|
||||
{
|
||||
// open the device
|
||||
fFD = open(device, IsReadOnly() ? O_RDONLY : O_RDWR);
|
||||
if (fFD < 0)
|
||||
return errno;
|
||||
|
||||
// get the size
|
||||
struct stat st;
|
||||
if (fstat(fFD, &st) < 0)
|
||||
return errno;
|
||||
|
||||
return _Init(st.st_size / B_PAGE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Volume::Init(int fd, uint64 totalBlocks)
|
||||
{
|
||||
fFD = dup(fd);
|
||||
if (fFD < 0)
|
||||
return errno;
|
||||
|
||||
return _Init(totalBlocks);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Volume::Mount()
|
||||
{
|
||||
// TODO:...
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Volume::Initialize(const char* name)
|
||||
{
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
Block block;
|
||||
if (!block.GetZero(this, kCheckSumFSSuperBlockOffset / B_PAGE_SIZE))
|
||||
return B_ERROR;
|
||||
|
||||
SuperBlock* superBlock = (SuperBlock*)block.Data();
|
||||
superBlock->Initialize(this);
|
||||
|
||||
block.Put();
|
||||
|
||||
return block_cache_sync(fBlockCache);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Volume::_Init(uint64 totalBlocks)
|
||||
{
|
||||
fTotalBlocks = totalBlocks;
|
||||
if (fTotalBlocks * B_PAGE_SIZE < kCheckSumFSMinSize)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create a block cache
|
||||
fBlockCache = block_cache_create(fFD, fTotalBlocks, B_PAGE_SIZE,
|
||||
IsReadOnly());
|
||||
if (fBlockCache == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
48
src/tests/system/kernel/file_corruption/fs/Volume.h
Normal file
48
src/tests/system/kernel/file_corruption/fs/Volume.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VOLUME_H
|
||||
#define VOLUME_H
|
||||
|
||||
|
||||
#include <fs_interface.h>
|
||||
#include <fs_volume.h>
|
||||
|
||||
|
||||
class Volume {
|
||||
public:
|
||||
Volume(uint32 flags);
|
||||
~Volume();
|
||||
|
||||
status_t Init(const char* device);
|
||||
status_t Init(int fd, uint64 totalBlocks);
|
||||
|
||||
status_t Mount();
|
||||
status_t Initialize(const char* name);
|
||||
|
||||
inline bool IsReadOnly() const;
|
||||
inline uint64 TotalBlocks() const { return fTotalBlocks; }
|
||||
inline void* BlockCache() const { return fBlockCache; }
|
||||
inline const char* Name() const { return fName; }
|
||||
|
||||
private:
|
||||
status_t _Init(uint64 totalBlocks);
|
||||
|
||||
private:
|
||||
int fFD;
|
||||
uint32 fFlags;
|
||||
void* fBlockCache;
|
||||
uint64 fTotalBlocks;
|
||||
char* fName;
|
||||
};
|
||||
|
||||
|
||||
bool
|
||||
Volume::IsReadOnly() const
|
||||
{
|
||||
return (fFlags & B_MOUNT_READ_ONLY) != 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // VOLUME_H
|
193
src/tests/system/kernel/file_corruption/fs/checksumfs.cpp
Normal file
193
src/tests/system/kernel/file_corruption/fs/checksumfs.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <fs_interface.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include "checksumfs.h"
|
||||
#include "SuperBlock.h"
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
static const char* const kCheckSumFSModuleName = "file_systems/checksumfs"
|
||||
B_CURRENT_FS_API_VERSION;
|
||||
static const char* const kCheckSumFSShortName = "checksumfs";
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
static float
|
||||
checksumfs_identify_partition(int fd, partition_data* partition,
|
||||
void** _cookie)
|
||||
{
|
||||
if ((uint64)partition->size < kCheckSumFSMinSize)
|
||||
return -1;
|
||||
|
||||
SuperBlock* superBlock = new(std::nothrow) SuperBlock;
|
||||
if (superBlock == NULL)
|
||||
return -1;
|
||||
ObjectDeleter<SuperBlock> superBlockDeleter(superBlock);
|
||||
|
||||
if (pread(fd, superBlock, sizeof(*superBlock), kCheckSumFSSuperBlockOffset)
|
||||
!= sizeof(*superBlock)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!superBlock->Check((uint64)partition->size / B_PAGE_SIZE))
|
||||
return -1;
|
||||
|
||||
*_cookie = superBlockDeleter.Detach();
|
||||
return 0.8f;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
checksumfs_scan_partition(int fd, partition_data* partition, void* cookie)
|
||||
{
|
||||
SuperBlock* superBlock = (SuperBlock*)cookie;
|
||||
|
||||
partition->status = B_PARTITION_VALID;
|
||||
partition->flags |= B_PARTITION_FILE_SYSTEM;
|
||||
partition->content_size = superBlock->TotalBlocks() * B_PAGE_SIZE;
|
||||
partition->block_size = B_PAGE_SIZE;
|
||||
partition->content_name = strdup(superBlock->Name());
|
||||
if (partition->content_name == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
checksumfs_free_identify_partition_cookie(partition_data* partition,
|
||||
void* cookie)
|
||||
{
|
||||
SuperBlock* superBlock = (SuperBlock*)cookie;
|
||||
delete superBlock;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
checksumfs_mount(fs_volume* volume, const char* device, uint32 flags,
|
||||
const char* args, ino_t* _rootVnodeID)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
checksumfs_set_content_name(int fd, partition_id partition, const char* name,
|
||||
disk_job_id job)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
checksumfs_initialize(int fd, partition_id partition, const char* name,
|
||||
const char* parameters, off_t partitionSize, disk_job_id job)
|
||||
{
|
||||
if (name == NULL || strlen(name) >= kCheckSumFSNameLength)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// TODO: Forcing a non-empty name here. Superfluous when the userland disk
|
||||
// system add-on has a parameter editor for it.
|
||||
if (*name == '\0')
|
||||
name = "Unnamed";
|
||||
|
||||
update_disk_device_job_progress(job, 0);
|
||||
|
||||
Volume volume(0);
|
||||
|
||||
status_t error = volume.Init(fd, partitionSize / B_PAGE_SIZE);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = volume.Initialize(name);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// rescan partition
|
||||
error = scan_partition(partition);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
update_disk_device_job_progress(job, 1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
checksumfs_std_ops(int32 operation, ...)
|
||||
{
|
||||
switch (operation) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static file_system_module_info sFSModule = {
|
||||
{
|
||||
kCheckSumFSModuleName,
|
||||
0,
|
||||
checksumfs_std_ops
|
||||
},
|
||||
kCheckSumFSShortName,
|
||||
CHECK_SUM_FS_PRETTY_NAME,
|
||||
// DDM flags
|
||||
B_DISK_SYSTEM_SUPPORTS_INITIALIZING
|
||||
| B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
|
||||
| B_DISK_SYSTEM_SUPPORTS_WRITING,
|
||||
|
||||
/* scanning (the device is write locked) */
|
||||
checksumfs_identify_partition,
|
||||
checksumfs_scan_partition,
|
||||
checksumfs_free_identify_partition_cookie,
|
||||
NULL, // free_partition_content_cookie
|
||||
|
||||
/* general operations */
|
||||
checksumfs_mount,
|
||||
|
||||
/* capability querying (the device is read locked) */
|
||||
NULL, // get_supported_operations
|
||||
|
||||
NULL, // validate_resize
|
||||
NULL, // validate_move
|
||||
NULL, // validate_set_content_name
|
||||
NULL, // validate_set_content_parameters
|
||||
NULL, // validate_initialize
|
||||
|
||||
/* shadow partition modification (device is write locked) */
|
||||
NULL, // shadow_changed
|
||||
|
||||
/* writing (the device is NOT locked) */
|
||||
NULL, // defragment
|
||||
NULL, // repair
|
||||
NULL, // resize
|
||||
NULL, // move
|
||||
checksumfs_set_content_name,
|
||||
NULL, // set_content_parameters
|
||||
checksumfs_initialize
|
||||
};
|
||||
|
||||
|
||||
const module_info* modules[] = {
|
||||
(module_info*)&sFSModule,
|
||||
NULL
|
||||
};
|
Loading…
Reference in New Issue
Block a user