// SuperBlock.cpp // // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de) // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // You can alternatively use *this file* under the terms of the the MIT // license included in this package. #include #include #include #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. */ // read_super_block template 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; // allocate memory for the superblock if (error == B_OK) { superBlock = new(nothrow) super_block_t; if (!superBlock) error = B_NO_MEMORY; } // read the superblock if (error == B_OK) { size_t size = sizeof(super_block_t); if (read_pos(device, offset, superBlock, size) != (int32)size) error = B_IO_ERROR; } // check magic if (error == B_OK) { size_t len = strlen(magic); if (strncmp(superBlock->s_magic, magic, len)) error = B_ERROR; } // set result / cleanup on failure if (error == B_OK) *_superBlock = superBlock; else if (superBlock) delete superBlock; return error; } // constructor SuperBlock::SuperBlock() : fFormatVersion(REISERFS_3_6), fCurrentData(NULL) { } // destructor SuperBlock::~SuperBlock() { if (GetFormatVersion() == REISERFS_3_6) { if (fCurrentData) delete fCurrentData; } else { if (fOldData) delete fOldData; } } // Init status_t SuperBlock::Init(int device, off_t offset) { status_t error = B_OK; // try old version and old layout 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; // try old version and new layout } 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; // try new version and new layout } 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; // failure } else error = B_ERROR; // TODO: checks... return error; } // GetLabel 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; }