xref: /haiku/src/add-ons/kernel/file_systems/reiserfs/Settings.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
1 // Settings.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 
24 #include "Settings.h"
25 #include "Debug.h"
26 
27 using std::nothrow;
28 
29 /*!
30 	\class Settings
31 	\brief Manages the ReiserFS settings.
32 */
33 
34 static const char *kFSName = "reiserfs";
35 
36 // defaults
37 static const char *kDefaultDefaultVolumeName = "ReiserFS untitled";
38 static const bool kDefaultHideEsoteric	= true;
39 
40 // constructor
41 Settings::Settings()
42 	: fDefaultVolumeName(),
43 	  fVolumeName(),
44 	  fHideEsoteric(kDefaultHideEsoteric),
45 	  fHiddenEntries(5)
46 {
47 }
48 
49 // destructor
50 Settings::~Settings()
51 {
52 	Unset();
53 }
54 
55 // SetTo
56 status_t
57 Settings::SetTo(const char *volumeName)
58 {
59 	// unset
60 	Unset();
61 	// load the driver settings and find the entry for the volume
62 	void *settings = load_driver_settings(kFSName);
63 	const driver_parameter *volume = NULL;
64 	const driver_settings *ds = get_driver_settings(settings);
65 	if (ds && volumeName)
66 		volume = _FindVolumeParameter(ds, volumeName);
67 	// init the object and unload the settings
68 	_Init(ds, volume);
69 	unload_driver_settings(settings);
70 	return B_OK;
71 }
72 
73 // SetTo
74 status_t
75 Settings::SetTo(off_t volumeOffset, off_t volumeSize)
76 {
77 PRINT(("Settings::SetTo(%Ld, %Ld)\n", volumeOffset, volumeSize));
78 	// unset
79 	Unset();
80 	// load the driver settings and find the entry for the volume
81 	void *settings = load_driver_settings(kFSName);
82 	const driver_parameter *volume = NULL;
83 	const driver_settings *ds = get_driver_settings(settings);
84 	if (ds)
85 		volume = _FindVolumeParameter(ds, volumeOffset, volumeSize);
86 	// init the object and unload the settings
87 	_Init(ds, volume);
88 	unload_driver_settings(settings);
89 PRINT(("Settings::SetTo(%Ld, %Ld) done: B_OK\n", volumeOffset, volumeSize));
90 	return B_OK;
91 }
92 
93 // Unset
94 void
95 Settings::Unset()
96 {
97 	fDefaultVolumeName.Unset();
98 	fVolumeName.Unset();
99 	fHideEsoteric = kDefaultHideEsoteric;
100 	fHiddenEntries.MakeEmpty();
101 }
102 
103 // GetDefaultVolumeName
104 const char *
105 Settings::GetDefaultVolumeName() const
106 {
107 	if (fDefaultVolumeName.GetLength() > 0)
108 		return fDefaultVolumeName.GetString();
109 	return kDefaultDefaultVolumeName;
110 }
111 
112 // GetVolumeName
113 const char *
114 Settings::GetVolumeName() const
115 {
116 	if (fVolumeName.GetLength() > 0)
117 		return fVolumeName.GetString();
118 	return GetDefaultVolumeName();
119 }
120 
121 // GetHideEsoteric
122 bool
123 Settings::GetHideEsoteric() const
124 {
125 	return fHideEsoteric;
126 }
127 
128 // HiddenEntryAt
129 const char *
130 Settings::HiddenEntryAt(int32 index) const
131 {
132 	const char *entry = NULL;
133 	if (index >= 0 && index < fHiddenEntries.CountItems())
134 		entry = fHiddenEntries.ItemAt(index).GetString();
135 	return entry;
136 }
137 
138 // Dump
139 void
140 Settings::Dump()
141 {
142 	PRINT(("Settings:\n"));
143 	PRINT(("  default volume name:   `%s'\n", GetDefaultVolumeName()));
144 	PRINT(("  volume name:           `%s'\n", GetVolumeName()));
145 	PRINT(("  hide esoteric entries: %d\n", GetHideEsoteric()));
146 	PRINT(("  %ld hidden entries:\n", fHiddenEntries.CountItems()));
147 	for (int32 i = 0; const char *entry = HiddenEntryAt(i); i++)
148 		PRINT(("    `%s'\n", entry));
149 }
150 
151 // _Init
152 status_t
153 Settings::_Init(const driver_settings *settings,
154 				const driver_parameter *volume)
155 {
156 PRINT(("Settings::_Init(%p, %p)\n", settings, volume));
157 	status_t error = B_OK;
158 	// get the global values
159 	fDefaultVolumeName.SetTo(_GetParameterValue(settings,
160 		"default_volume_name", (const char*)NULL, NULL));
161 PRINT(("  default_volume_name is: `%s'\n", fDefaultVolumeName.GetString()));
162 	fHideEsoteric = _GetParameterValue(settings, "hide_esoteric_entries",
163 									   kDefaultHideEsoteric,
164 									   kDefaultHideEsoteric);
165 PRINT(("  hide_esoteric_entries is: %d\n", fHideEsoteric));
166 	// get the per volume settings
167 	if (volume) {
168 PRINT(("  getting volume parameters:\n"));
169 		fVolumeName.SetTo(_GetParameterValue(volume, "name", (const char*)NULL,
170 											 NULL));
171 PRINT(("    name is: `%s'\n", fVolumeName.GetString()));
172 		fHideEsoteric = _GetParameterValue(volume, "hide_esoteric_entries",
173 										   fHideEsoteric, fHideEsoteric);
174 PRINT(("    hide_esoteric_entries is: %d\n", fHideEsoteric));
175 		int32 cookie = 0;
176 		while (const driver_parameter *parameter
177 				= _FindNextParameter(volume, "hide_entries", cookie)) {
178 			for (int32 i = 0; i < parameter->value_count; i++)
179 {
180 				fHiddenEntries.AddItem(parameter->values[i]);
181 PRINT(("    hidden entry: `%s'\n", parameter->values[i]));
182 }
183 		}
184 	}
185 	// check the values
186 PRINT(("  checking volume names...'\n"));
187 	_CheckVolumeName(fDefaultVolumeName);
188 	_CheckVolumeName(fVolumeName);
189 PRINT(("  checking hidden entry names...'\n"));
190 	for (int32 i = fHiddenEntries.CountItems(); i >= 0; i--) {
191 		String &entry = fHiddenEntries.ItemAt(i);
192 		if (!_CheckEntryName(entry.GetString()))
193 {
194 PRINT(("    ignoring: `%s'\n", entry.GetString()));
195 			fHiddenEntries.RemoveItem(i);
196 }
197 	}
198 PRINT(("Settings::_Init() done: %s\n", strerror(error)));
199 	return error;
200 }
201 
202 // _FindVolumeParameter
203 const driver_parameter *
204 Settings::_FindVolumeParameter(const driver_settings *settings,
205 							   const char *name)
206 {
207 	if (settings) {
208 		int32 cookie = 0;
209 		while (const driver_parameter *parameter
210 				= _FindNextParameter(settings, "volume", cookie)) {
211 			if (parameter->value_count == 1
212 				&& !strcmp(parameter->values[0], name)) {
213 				return parameter;
214 			}
215 		}
216 	}
217 	return NULL;
218 }
219 
220 // _FindVolumeParameter
221 const driver_parameter *
222 Settings::_FindVolumeParameter(const driver_settings *settings,
223 							   off_t offset, off_t size)
224 {
225 PRINT(("Settings::_FindVolumeParameter(%Ld, %Ld)\n", offset, size));
226 	if (settings) {
227 		int32 cookie = 0;
228 		while (const driver_parameter *parameter
229 				= _FindNextParameter(settings, "volume", cookie)) {
230 			if (_GetParameterValue(parameter, "offset", offset + 1, offset + 1)
231 					== offset
232 				&& _GetParameterValue(parameter, "size", size + 1, size + 1)
233 					== size) {
234 PRINT(("Settings::_FindVolumeParameter() done: found parameter: index: %ld, "
235 "(%p)\n", cookie - 1, parameter));
236 				return parameter;
237 			}
238 		}
239 	}
240 PRINT(("Settings::_FindVolumeParameter() done: failed\n"));
241 	return NULL;
242 }
243 
244 // _CheckVolumeName
245 void
246 Settings::_CheckVolumeName(String &name)
247 {
248 	// truncate, if it is too long
249 	if (name.GetLength() >= B_FILE_NAME_LENGTH) {
250 		char buffer[B_FILE_NAME_LENGTH];
251 		memcpy(buffer, name.GetString(), B_FILE_NAME_LENGTH - 1);
252 		name.SetTo(buffer, B_FILE_NAME_LENGTH - 1);
253 	}
254 	// check for bad characters
255 	bool invalid = false;
256 	const char *string = name.GetString();
257 	for (int32 i = 0; !invalid && i < name.GetLength(); i++) {
258 		if (string[i] == '/')	// others?
259 			invalid = true;
260 	}
261 	if (invalid)
262 		name.Unset();
263 }
264 
265 // _CheckEntryName
266 bool
267 Settings::_CheckEntryName(const char *name)
268 {
269 	int32 len = (name ? strlen(name) : 0);
270 	// any further restictions?
271 	return (len > 0);
272 }
273 
274