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
Settings()41 Settings::Settings()
42 :
43 fDefaultVolumeName(),
44 fVolumeName(),
45 fHideEsoteric(kDefaultHideEsoteric),
46 fHiddenEntries(5)
47 {
48 }
49
50 // destructor
~Settings()51 Settings::~Settings()
52 {
53 Unset();
54 }
55
56 // SetTo
57 status_t
SetTo(const char * volumeName)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
SetTo(off_t volumeOffset,off_t volumeSize)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
Unset()98 Settings::Unset()
99 {
100 fDefaultVolumeName.Unset();
101 fVolumeName.Unset();
102 fHideEsoteric = kDefaultHideEsoteric;
103 fHiddenEntries.MakeEmpty();
104 }
105
106 // GetDefaultVolumeName
107 const char *
GetDefaultVolumeName() const108 Settings::GetDefaultVolumeName() const
109 {
110 if (fDefaultVolumeName.GetLength() > 0)
111 return fDefaultVolumeName.GetString();
112 return kDefaultDefaultVolumeName;
113 }
114
115 // GetVolumeName
116 const char *
GetVolumeName() const117 Settings::GetVolumeName() const
118 {
119 if (fVolumeName.GetLength() > 0)
120 return fVolumeName.GetString();
121 return GetDefaultVolumeName();
122 }
123
124 // GetHideEsoteric
125 bool
GetHideEsoteric() const126 Settings::GetHideEsoteric() const
127 {
128 return fHideEsoteric;
129 }
130
131 // HiddenEntryAt
132 const char *
HiddenEntryAt(int32 index) const133 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
Dump()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
_Init(const driver_settings * settings,const driver_parameter * volume)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 *
_FindVolumeParameter(const driver_settings * settings,const char * name)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 *
_FindVolumeParameter(const driver_settings * settings,off_t offset,off_t size)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
_CheckVolumeName(String & name)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
_CheckEntryName(const char * name)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