1f0bc043bSIngo Weinhold// SuperBlock.cpp
2f0bc043bSIngo Weinhold//
3f0bc043bSIngo Weinhold// Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4f0bc043bSIngo Weinhold//
5f0bc043bSIngo Weinhold// This program is free software; you can redistribute it and/or modify
6f0bc043bSIngo Weinhold// it under the terms of the GNU General Public License as published by
7f0bc043bSIngo Weinhold// the Free Software Foundation; either version 2 of the License, or
8f0bc043bSIngo Weinhold// (at your option) any later version.
9f0bc043bSIngo Weinhold//
10f0bc043bSIngo Weinhold// This program is distributed in the hope that it will be useful,
11f0bc043bSIngo Weinhold// but WITHOUT ANY WARRANTY; without even the implied warranty of
13f0bc043bSIngo Weinhold// GNU General Public License for more details.
14f0bc043bSIngo Weinhold//
15f0bc043bSIngo Weinhold// You should have received a copy of the GNU General Public License
16f0bc043bSIngo Weinhold// along with this program; if not, write to the Free Software
17f0bc043bSIngo Weinhold// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18f0bc043bSIngo Weinhold//
19f0bc043bSIngo Weinhold// You can alternatively use *this file* under the terms of the the MIT
20f0bc043bSIngo Weinhold// license included in this package.
21f0bc043bSIngo Weinhold
22f0bc043bSIngo Weinhold#include <new>
23f0bc043bSIngo Weinhold#include <string.h>
24f0bc043bSIngo Weinhold#include <unistd.h>
25f0bc043bSIngo Weinhold
26f0bc043bSIngo Weinhold#include "Debug.h"
27f0bc043bSIngo Weinhold#include "SuperBlock.h"
28f0bc043bSIngo Weinhold
29f0bc043bSIngo Weinholdusing std::nothrow;
30f0bc043bSIngo Weinhold
31f0bc043bSIngo Weinhold/*!
32f0bc043bSIngo Weinhold	\class DirEntry
3346cf7a5aSPrzemysław Buczkowski	\brief Represents the on-disk structure for superblock of the FS.
34f0bc043bSIngo Weinhold
3537b79c03SIngo Weinhold	There exist two versions of the structure and this class can deal with both
3637b79c03SIngo Weinhold	of them. This class can also handle a very old layout that puts the super
3737b79c03SIngo Weinhold	block in a different location. The Init() methods tries to find and read
3846cf7a5aSPrzemysław Buczkowski	the superblock from disk.
39f0bc043bSIngo Weinhold*/
40f0bc043bSIngo Weinhold
41f0bc043bSIngo Weinhold// read_super_block
42f0bc043bSIngo Weinholdtemplate<typename super_block_t>
43f0bc043bSIngo Weinholdstatic
44f0bc043bSIngo Weinholdstatus_t
45f0bc043bSIngo Weinholdread_super_block(int device, off_t offset, const char *magic,
46f0bc043bSIngo Weinhold				 super_block_t **_superBlock)
47f0bc043bSIngo Weinhold{
48f0bc043bSIngo Weinhold	super_block_t *superBlock = NULL;
49f0bc043bSIngo Weinhold	status_t error = B_OK;
5046cf7a5aSPrzemysław Buczkowski	// allocate memory for the superblock
51f0bc043bSIngo Weinhold	if (error == B_OK) {
52f0bc043bSIngo Weinhold		superBlock = new(nothrow) super_block_t;
53f0bc043bSIngo Weinhold		if (!superBlock)
54f0bc043bSIngo Weinhold			error = B_NO_MEMORY;
55f0bc043bSIngo Weinhold	}
5646cf7a5aSPrzemysław Buczkowski	// read the superblock
57f0bc043bSIngo Weinhold	if (error == B_OK) {
58f0bc043bSIngo Weinhold		size_t size = sizeof(super_block_t);
59f0bc043bSIngo Weinhold		if (read_pos(device, offset, superBlock, size) != (int32)size)
60f0bc043bSIngo Weinhold			error = B_IO_ERROR;
61f0bc043bSIngo Weinhold	}
62f0bc043bSIngo Weinhold	// check magic
63f0bc043bSIngo Weinhold	if (error == B_OK) {
64f0bc043bSIngo Weinhold		size_t len = strlen(magic);
65f0bc043bSIngo Weinhold		if (strncmp(superBlock->s_magic, magic, len))
66f0bc043bSIngo Weinhold			error = B_ERROR;
67f0bc043bSIngo Weinhold	}
68f0bc043bSIngo Weinhold	// set result / cleanup on failure
69f0bc043bSIngo Weinhold	if (error == B_OK)
70f0bc043bSIngo Weinhold		*_superBlock = superBlock;
71f0bc043bSIngo Weinhold	else if (superBlock)
72f0bc043bSIngo Weinhold		delete superBlock;
73f0bc043bSIngo Weinhold	return error;
74f0bc043bSIngo Weinhold}
75f0bc043bSIngo Weinhold
76f0bc043bSIngo Weinhold// constructor
77f0bc043bSIngo WeinholdSuperBlock::SuperBlock()
78f0bc043bSIngo Weinhold	: fFormatVersion(REISERFS_3_6),
79f0bc043bSIngo Weinhold	  fCurrentData(NULL)
80f0bc043bSIngo Weinhold{
81f0bc043bSIngo Weinhold}
82f0bc043bSIngo Weinhold
83f0bc043bSIngo Weinhold// destructor
84f0bc043bSIngo WeinholdSuperBlock::~SuperBlock()
85f0bc043bSIngo Weinhold{
86f0bc043bSIngo Weinhold	if (GetFormatVersion() == REISERFS_3_6) {
87f0bc043bSIngo Weinhold		if (fCurrentData)
88f0bc043bSIngo Weinhold			delete fCurrentData;
89f0bc043bSIngo Weinhold	} else {
90f0bc043bSIngo Weinhold		if (fOldData)
91f0bc043bSIngo Weinhold			delete fOldData;
92f0bc043bSIngo Weinhold	}
93f0bc043bSIngo Weinhold}
94f0bc043bSIngo Weinhold
95f0bc043bSIngo Weinhold// Init
96f0bc043bSIngo Weinholdstatus_t
97f0bc043bSIngo WeinholdSuperBlock::Init(int device, off_t offset)
98f0bc043bSIngo Weinhold{
99f0bc043bSIngo Weinhold	status_t error = B_OK;
10037b79c03SIngo Weinhold	// try old version and old layout
101f0bc043bSIngo Weinhold	if (read_super_block(device, REISERFS_OLD_DISK_OFFSET_IN_BYTES + offset,
102f0bc043bSIngo Weinhold						 REISERFS_SUPER_MAGIC_STRING, &fOldData) == B_OK) {
10337b79c03SIngo WeinholdPRINT(("SuperBlock: ReiserFS 3.5 (old layout)\n"));
10437b79c03SIngo Weinhold		fFormatVersion = REISERFS_3_5;
10537b79c03SIngo Weinhold	// try old version and new layout
10637b79c03SIngo Weinhold	} else if (read_super_block(device, REISERFS_DISK_OFFSET_IN_BYTES + offset,
10737b79c03SIngo Weinhold			REISERFS_SUPER_MAGIC_STRING, &fOldData) == B_OK) {
108f0bc043bSIngo WeinholdPRINT(("SuperBlock: ReiserFS 3.5\n"));
109f0bc043bSIngo Weinhold		fFormatVersion = REISERFS_3_5;
11037b79c03SIngo Weinhold	// try new version and new layout
111f0bc043bSIngo Weinhold	} else if (read_super_block(device, REISERFS_DISK_OFFSET_IN_BYTES + offset,
11237cfdb5dSIngo Weinhold			REISER2FS_SUPER_MAGIC_STRING, &fCurrentData) == B_OK) {
113f0bc043bSIngo WeinholdPRINT(("SuperBlock: ReiserFS 3.6\n"));
114f0bc043bSIngo Weinhold		fFormatVersion = REISERFS_3_6;
115f0bc043bSIngo Weinhold	// failure
116f0bc043bSIngo Weinhold	} else
117f0bc043bSIngo Weinhold		error = B_ERROR;
118f0bc043bSIngo Weinhold	// TODO: checks...
119f0bc043bSIngo Weinhold	return error;
120f0bc043bSIngo Weinhold}
121f0bc043bSIngo Weinhold
12237cfdb5dSIngo Weinhold
12337cfdb5dSIngo Weinhold// GetLabel
12437cfdb5dSIngo Weinholdstatus_t
12537cfdb5dSIngo WeinholdSuperBlock::GetLabel(char* buffer, size_t bufferSize) const
12637cfdb5dSIngo Weinhold{
12737cfdb5dSIngo Weinhold	if (GetFormatVersion() == REISERFS_3_6 && fCurrentData->s_label[0]) {
12837cfdb5dSIngo Weinhold		size_t len = MIN(sizeof(fCurrentData->s_label), bufferSize - 1);
12937cfdb5dSIngo Weinhold		memcpy(buffer, fCurrentData->s_label, len);
13037cfdb5dSIngo Weinhold		buffer[len] = '\0';
13137cfdb5dSIngo Weinhold		return B_OK;
13237cfdb5dSIngo Weinhold	}
13337cfdb5dSIngo Weinhold	return B_ENTRY_NOT_FOUND;
13437cfdb5dSIngo Weinhold}