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