xref: /haiku/src/add-ons/kernel/file_systems/reiserfs/SuperBlock.cpp (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
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 super block of the FS.
34 
35 	There exist two versions of the structure and this class can deal with
36 	both of them. The Init() methods tries to find and read the super block
37 	from disk.
38 */
39 
40 // read_super_block
41 template<typename super_block_t>
42 static
43 status_t
44 read_super_block(int device, off_t offset, const char *magic,
45 				 super_block_t **_superBlock)
46 {
47 	super_block_t *superBlock = NULL;
48 	status_t error = B_OK;
49 	// allocate memory for the super block
50 	if (error == B_OK) {
51 		superBlock = new(nothrow) super_block_t;
52 		if (!superBlock)
53 			error = B_NO_MEMORY;
54 	}
55 	// read the super block
56 	if (error == B_OK) {
57 		size_t size = sizeof(super_block_t);
58 		if (read_pos(device, offset, superBlock, size) != (int32)size)
59 			error = B_IO_ERROR;
60 	}
61 	// check magic
62 	if (error == B_OK) {
63 		size_t len = strlen(magic);
64 		if (strncmp(superBlock->s_magic, magic, len))
65 			error = B_ERROR;
66 	}
67 	// set result / cleanup on failure
68 	if (error == B_OK)
69 		*_superBlock = superBlock;
70 	else if (superBlock)
71 		delete superBlock;
72 	return error;
73 }
74 
75 // constructor
76 SuperBlock::SuperBlock()
77 	: fFormatVersion(REISERFS_3_6),
78 	  fCurrentData(NULL)
79 {
80 }
81 
82 // destructor
83 SuperBlock::~SuperBlock()
84 {
85 	if (GetFormatVersion() == REISERFS_3_6) {
86 		if (fCurrentData)
87 			delete fCurrentData;
88 	} else {
89 		if (fOldData)
90 			delete fOldData;
91 	}
92 }
93 
94 // Init
95 status_t
96 SuperBlock::Init(int device, off_t offset)
97 {
98 	// Not sure, if I understand the weird versioning.
99 	status_t error = B_OK;
100 	// try old version
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\n"));
104 		fFormatVersion = REISERFS_3_5;
105 	// try new version
106 	} else if (read_super_block(device, REISERFS_DISK_OFFSET_IN_BYTES + offset,
107 			REISER2FS_SUPER_MAGIC_STRING, &fOldData) == B_OK) {
108 PRINT(("SuperBlock: ReiserFS 3.6\n"));
109 		fFormatVersion = REISERFS_3_6;
110 	// failure
111 	} else
112 		error = B_ERROR;
113 	// TODO: checks...
114 	return error;
115 }
116 
117