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