xref: /haiku/src/add-ons/kernel/file_systems/reiserfs/Settings.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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 #if DEBUG
146 	PRINT(("Settings:\n"));
147 	PRINT(("  default volume name:   `%s'\n", GetDefaultVolumeName()));
148 	PRINT(("  volume name:           `%s'\n", GetVolumeName()));
149 	PRINT(("  hide esoteric entries: %d\n", GetHideEsoteric()));
150 	PRINT(("  %" B_PRId32 " hidden entries:\n", fHiddenEntries.CountItems()));
151 	for (int32 i = 0; const char *entry = HiddenEntryAt(i); i++)
152 		PRINT(("    `%s'\n", entry));
153 #endif
154 }
155 
156 // _Init
157 status_t
158 Settings::_Init(const driver_settings *settings,
159 				const driver_parameter *volume)
160 {
161 PRINT(("Settings::_Init(%p, %p)\n", settings, volume));
162 	status_t error = B_OK;
163 	// get the global values
164 	fDefaultVolumeName.SetTo(_GetParameterValue(settings,
165 		"default_volume_name", (const char*)NULL, NULL));
166 PRINT(("  default_volume_name is: `%s'\n", fDefaultVolumeName.GetString()));
167 	fHideEsoteric = _GetParameterValue(settings, "hide_esoteric_entries",
168 										kDefaultHideEsoteric,
169 										kDefaultHideEsoteric);
170 PRINT(("  hide_esoteric_entries is: %d\n", fHideEsoteric));
171 	// get the per volume settings
172 	if (volume) {
173 PRINT(("  getting volume parameters:\n"));
174 		fVolumeName.SetTo(_GetParameterValue(volume, "name", (const char*)NULL,
175 												NULL));
176 PRINT(("    name is: `%s'\n", fVolumeName.GetString()));
177 		fHideEsoteric = _GetParameterValue(volume, "hide_esoteric_entries",
178 											fHideEsoteric, fHideEsoteric);
179 PRINT(("    hide_esoteric_entries is: %d\n", fHideEsoteric));
180 		int32 cookie = 0;
181 		while (const driver_parameter *parameter
182 				= _FindNextParameter(volume, "hide_entries", cookie)) {
183 			for (int32 i = 0; i < parameter->value_count; i++)
184 {
185 				fHiddenEntries.AddItem(parameter->values[i]);
186 PRINT(("    hidden entry: `%s'\n", parameter->values[i]));
187 }
188 		}
189 	}
190 	// check the values
191 PRINT(("  checking volume names...'\n"));
192 	_CheckVolumeName(fDefaultVolumeName);
193 	_CheckVolumeName(fVolumeName);
194 PRINT(("  checking hidden entry names...'\n"));
195 	for (int32 i = fHiddenEntries.CountItems(); i >= 0; i--) {
196 		String &entry = fHiddenEntries.ItemAt(i);
197 		if (!_CheckEntryName(entry.GetString()))
198 {
199 PRINT(("    ignoring: `%s'\n", entry.GetString()));
200 			fHiddenEntries.RemoveItem(i);
201 }
202 	}
203 PRINT(("Settings::_Init() done: %s\n", strerror(error)));
204 	return error;
205 }
206 
207 // _FindVolumeParameter
208 const driver_parameter *
209 Settings::_FindVolumeParameter(const driver_settings *settings,
210 								const char *name)
211 {
212 	if (settings) {
213 		int32 cookie = 0;
214 		while (const driver_parameter *parameter
215 				= _FindNextParameter(settings, "volume", cookie)) {
216 			if (parameter->value_count == 1
217 				&& !strcmp(parameter->values[0], name)) {
218 				return parameter;
219 			}
220 		}
221 	}
222 	return NULL;
223 }
224 
225 // _FindVolumeParameter
226 const driver_parameter *
227 Settings::_FindVolumeParameter(const driver_settings *settings,
228 								off_t offset, off_t size)
229 {
230 	PRINT(("Settings::_FindVolumeParameter(%" B_PRIdOFF ", %" B_PRIdOFF ")\n",
231 		offset, size));
232 	if (settings) {
233 		int32 cookie = 0;
234 		while (const driver_parameter *parameter
235 				= _FindNextParameter(settings, "volume", cookie)) {
236 			if (_GetParameterValue(parameter, "offset", offset + 1, offset + 1)
237 					== offset
238 				&& _GetParameterValue(parameter, "size", size + 1, size + 1)
239 					== size) {
240 				PRINT(("Settings::_FindVolumeParameter() done: found parameter:"
241 					" index: %" B_PRId32 ", (%p)\n", cookie - 1, parameter));
242 				return parameter;
243 			}
244 		}
245 	}
246 	PRINT(("Settings::_FindVolumeParameter() done: failed\n"));
247 	return NULL;
248 }
249 
250 // _CheckVolumeName
251 void
252 Settings::_CheckVolumeName(String &name)
253 {
254 	// truncate, if it is too long
255 	if (name.GetLength() >= B_FILE_NAME_LENGTH) {
256 		char buffer[B_FILE_NAME_LENGTH];
257 		memcpy(buffer, name.GetString(), B_FILE_NAME_LENGTH - 1);
258 		name.SetTo(buffer, B_FILE_NAME_LENGTH - 1);
259 	}
260 	// check for bad characters
261 	bool invalid = false;
262 	const char *string = name.GetString();
263 	for (int32 i = 0; !invalid && i < name.GetLength(); i++) {
264 		if (string[i] == '/')	// others?
265 			invalid = true;
266 	}
267 	if (invalid)
268 		name.Unset();
269 }
270 
271 // _CheckEntryName
272 bool
273 Settings::_CheckEntryName(const char *name)
274 {
275 	int32 len = (name ? strlen(name) : 0);
276 	// any further restictions?
277 	return (len > 0);
278 }
279 
280