#include <new>
#include <string.h>
#include <unistd.h>
#include "Debug.h"
#include "SuperBlock.h"
using std::nothrow;
\class DirEntry
\brief Represents the on-disk structure for superblock of the FS.
There exist two versions of the structure and this class can deal with both
of them. This class can also handle a very old layout that puts the super
block in a different location. The Init() methods tries to find and read
the superblock from disk.
*/
template<typename super_block_t>
static
status_t
read_super_block(int device, off_t offset, const char *magic,
super_block_t **_superBlock)
{
super_block_t *superBlock = NULL;
status_t error = B_OK;
if (error == B_OK) {
superBlock = new(nothrow) super_block_t;
if (!superBlock)
error = B_NO_MEMORY;
}
if (error == B_OK) {
size_t size = sizeof(super_block_t);
if (read_pos(device, offset, superBlock, size) != (int32)size)
error = B_IO_ERROR;
}
if (error == B_OK) {
size_t len = strlen(magic);
if (strncmp(superBlock->s_magic, magic, len))
error = B_ERROR;
}
if (error == B_OK)
*_superBlock = superBlock;
else if (superBlock)
delete superBlock;
return error;
}
SuperBlock::SuperBlock()
: fFormatVersion(REISERFS_3_6),
fCurrentData(NULL)
{
}
SuperBlock::~SuperBlock()
{
if (GetFormatVersion() == REISERFS_3_6) {
if (fCurrentData)
delete fCurrentData;
} else {
if (fOldData)
delete fOldData;
}
}
status_t
SuperBlock::Init(int device, off_t offset)
{
status_t error = B_OK;
if (read_super_block(device, REISERFS_OLD_DISK_OFFSET_IN_BYTES + offset,
REISERFS_SUPER_MAGIC_STRING, &fOldData) == B_OK) {
PRINT(("SuperBlock: ReiserFS 3.5 (old layout)\n"));
fFormatVersion = REISERFS_3_5;
} else if (read_super_block(device, REISERFS_DISK_OFFSET_IN_BYTES + offset,
REISERFS_SUPER_MAGIC_STRING, &fOldData) == B_OK) {
PRINT(("SuperBlock: ReiserFS 3.5\n"));
fFormatVersion = REISERFS_3_5;
} else if (read_super_block(device, REISERFS_DISK_OFFSET_IN_BYTES + offset,
REISER2FS_SUPER_MAGIC_STRING, &fCurrentData) == B_OK) {
PRINT(("SuperBlock: ReiserFS 3.6\n"));
fFormatVersion = REISERFS_3_6;
} else
error = B_ERROR;
return error;
}
status_t
SuperBlock::GetLabel(char* buffer, size_t bufferSize) const
{
if (GetFormatVersion() == REISERFS_3_6 && fCurrentData->s_label[0]) {
size_t len = MIN(sizeof(fCurrentData->s_label), bufferSize - 1);
memcpy(buffer, fCurrentData->s_label, len);
buffer[len] = '\0';
return B_OK;
}
return B_ENTRY_NOT_FOUND;
}