xref: /haiku/src/add-ons/kernel/file_systems/reiserfs/SuperBlock.cpp (revision 25a7b01d15612846f332751841da3579db313082)
1 // SuperBlock.cpp
2 //
3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 //
19 // You can alternatively use *this file* under the terms of the the MIT
20 // license included in this package.
21 
22 #include <new>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include "Debug.h"
27 #include "SuperBlock.h"
28 
29 using std::nothrow;
30 
31 /*!
32 	\class DirEntry
33 	\brief Represents the on-disk structure for superblock of the FS.
34 
35 	There exist two versions of the structure and this class can deal with both
36 	of them. This class can also handle a very old layout that puts the super
37 	block in a different location. The Init() methods tries to find and read
38 	the superblock from disk.
39 */
40 
41 // read_super_block
42 template<typename super_block_t>
43 static
44 status_t
read_super_block(int device,off_t offset,const char * magic,super_block_t ** _superBlock)45 read_super_block(int device, off_t offset, const char *magic,
46 				 super_block_t **_superBlock)
47 {
48 	super_block_t *superBlock = NULL;
49 	status_t error = B_OK;
50 	// allocate memory for the superblock
51 	if (error == B_OK) {
52 		superBlock = new(nothrow) super_block_t;
53 		if (!superBlock)
54 			error = B_NO_MEMORY;
55 	}
56 	// read the superblock
57 	if (error == B_OK) {
58 		size_t size = sizeof(super_block_t);
59 		if (read_pos(device, offset, superBlock, size) != (int32)size)
60 			error = B_IO_ERROR;
61 	}
62 	// check magic
63 	if (error == B_OK) {
64 		size_t len = strlen(magic);
65 		if (strncmp(superBlock->s_magic, magic, len))
66 			error = B_ERROR;
67 	}
68 	// set result / cleanup on failure
69 	if (error == B_OK)
70 		*_superBlock = superBlock;
71 	else if (superBlock)
72 		delete superBlock;
73 	return error;
74 }
75 
76 // constructor
SuperBlock()77 SuperBlock::SuperBlock()
78 	: fFormatVersion(REISERFS_3_6),
79 	  fCurrentData(NULL)
80 {
81 }
82 
83 // destructor
~SuperBlock()84 SuperBlock::~SuperBlock()
85 {
86 	if (GetFormatVersion() == REISERFS_3_6) {
87 		if (fCurrentData)
88 			delete fCurrentData;
89 	} else {
90 		if (fOldData)
91 			delete fOldData;
92 	}
93 }
94 
95 // Init
96 status_t
Init(int device,off_t offset)97 SuperBlock::Init(int device, off_t offset)
98 {
99 	status_t error = B_OK;
100 	// try old version and old layout
101 	if (read_super_block(device, REISERFS_OLD_DISK_OFFSET_IN_BYTES + offset,
102 						 REISERFS_SUPER_MAGIC_STRING, &fOldData) == B_OK) {
103 PRINT(("SuperBlock: ReiserFS 3.5 (old layout)\n"));
104 		fFormatVersion = REISERFS_3_5;
105 	// try old version and new layout
106 	} else if (read_super_block(device, REISERFS_DISK_OFFSET_IN_BYTES + offset,
107 			REISERFS_SUPER_MAGIC_STRING, &fOldData) == B_OK) {
108 PRINT(("SuperBlock: ReiserFS 3.5\n"));
109 		fFormatVersion = REISERFS_3_5;
110 	// try new version and new layout
111 	} else if (read_super_block(device, REISERFS_DISK_OFFSET_IN_BYTES + offset,
112 			REISER2FS_SUPER_MAGIC_STRING, &fCurrentData) == B_OK) {
113 PRINT(("SuperBlock: ReiserFS 3.6\n"));
114 		fFormatVersion = REISERFS_3_6;
115 	// failure
116 	} else
117 		error = B_ERROR;
118 	// TODO: checks...
119 	return error;
120 }
121 
122 
123 // GetLabel
124 status_t
GetLabel(char * buffer,size_t bufferSize) const125 SuperBlock::GetLabel(char* buffer, size_t bufferSize) const
126 {
127 	if (GetFormatVersion() == REISERFS_3_6 && fCurrentData->s_label[0]) {
128 		size_t len = MIN(sizeof(fCurrentData->s_label), bufferSize - 1);
129 		memcpy(buffer, fCurrentData->s_label, len);
130 		buffer[len] = '\0';
131 		return B_OK;
132 	}
133 	return B_ENTRY_NOT_FOUND;
134 }
135