xref: /haiku/src/add-ons/kernel/file_systems/reiserfs/SuperBlock.cpp (revision 35ead8815b679605a9b4db8130613ea100f4b14c)
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 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 super block from disk.
39 */
40 
41 // read_super_block
42 template<typename super_block_t>
43 static
44 status_t
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 super block
51 	if (error == B_OK) {
52 		superBlock = new(nothrow) super_block_t;
53 		if (!superBlock)
54 			error = B_NO_MEMORY;
55 	}
56 	// read the super block
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
77 SuperBlock::SuperBlock()
78 	: fFormatVersion(REISERFS_3_6),
79 	  fCurrentData(NULL)
80 {
81 }
82 
83 // destructor
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
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, &fOldData) == 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