1 karl 1.23 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.20 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.12 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.20 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.21 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.23 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.2 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 kumpf 1.4 //
|
21 mike 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34
35 #include <cctype>
36 #include <fstream>
37 #include <Pegasus/Common/FileSystem.h>
38 #include <Pegasus/Common/HashTable.h>
|
39 kumpf 1.3 #include <Pegasus/Common/Tracer.h>
|
40 kumpf 1.26 #include <Pegasus/Common/Executor.h>
|
41 mike 1.2
42 #include "ConfigExceptions.h"
43 #include "ConfigFile.h"
|
44 david 1.8 #if defined(PEGASUS_OS_OS400)
45 #include "OS400ConvertChar.h"
46 #endif
|
47 mike 1.2
48
49 PEGASUS_USING_STD;
50
51 PEGASUS_NAMESPACE_BEGIN
52
53
54 ////////////////////////////////////////////////////////////////////////////////
55 //
56 // ConfigFile Class
57 //
58 ////////////////////////////////////////////////////////////////////////////////
59
60
61 ////////////////////////////////////////////////////////////////////////////////
|
62 kumpf 1.24 // ConfigTable
|
63 mike 1.2 ////////////////////////////////////////////////////////////////////////////////
64
65 typedef HashTable<String, String, EqualFunc<String>, HashFunc<String> > Table;
66
67 struct ConfigTable
68 {
69 Table table;
70 };
71
72
73 /*
74 Config file header information
75 */
76 static const char* ConfigHeader [] = {
77 "########################################################################",
78 "## ##",
79 "## CIM Server configuration file ##",
80 "## ##",
81 "########################################################################",
|
82 kumpf 1.24 " ",
|
83 mike 1.2 "########################################################################",
84 "# #",
85 "# This is the configuration file for the CIMOM. The configuration #",
86 "# properties in this file are loaded in to CIMOM at startup. #",
87 "# CIMOM updates this file with the changes in the configurations. #",
88 "# #",
89 "# It is recommended that user do not edit this file, instead use #",
90 "# CIMConfigCommand to make any changes to the CIMOM configurations. #",
91 "# #",
92 "########################################################################",
93 " "
94 };
95
96 static const int HEADER_SIZE = sizeof(ConfigHeader) / sizeof(ConfigHeader[0]);
97
98
|
99 kumpf 1.24 /**
100 Constructor.
|
101 mike 1.2 */
102 ConfigFile::ConfigFile (const String& fileName)
103 {
104 _configFile = fileName;
105
106 _configBackupFile = fileName + ".bak";
107 }
108
|
109 kumpf 1.24 /**
110 Destructor.
|
111 mike 1.2 */
112 ConfigFile::~ConfigFile ()
113 {
114 }
115
116
|
117 kumpf 1.24 /**
|
118 mike 1.2 Get the name of the configuration file.
119 */
|
120 vijay.eli 1.22 String ConfigFile::getFileName () const
|
121 mike 1.2 {
|
122 kumpf 1.24 return _configFile;
|
123 mike 1.2 }
124
125
|
126 kumpf 1.24 /**
|
127 mike 1.2 Load the properties from the config file.
128 */
|
129 kumpf 1.24 void ConfigFile::load(ConfigTable* confTable)
|
130 mike 1.2 {
131 String line;
132
133 //
134 // Delete the backup configuration file
135 //
|
136 kumpf 1.26
|
137 mike 1.2 if (FileSystem::exists(_configBackupFile))
138 {
|
139 kumpf 1.26 Executor::removeFile(_configBackupFile.getCString());
|
140 mike 1.2 }
141
142 //
143 // Open the config file
144 //
|
145 kumpf 1.26
|
146 david 1.8 #if defined(PEGASUS_OS_OS400)
|
147 david 1.18 ifstream ifs(_configFile.getCString(), PEGASUS_STD(_CCSID_T(1208)));
|
148 david 1.8 #else
|
149 david 1.18 ifstream ifs(_configFile.getCString());
|
150 david 1.8 #endif
|
151 kumpf 1.26
|
152 mike 1.2 if (!ifs)
153 {
154 return;
155 }
156
157 //
158 // Read each line of the file
159 //
160 for (Uint32 lineNumber = 1; GetLine(ifs, line); lineNumber++)
161 {
162 // Get the property name and value
163
164 //
165 // Skip leading whitespace
166 //
|
167 kumpf 1.7 const Char16* p = line.getChar16Data();
|
168 mike 1.2
169 while (*p && isspace(*p))
170 {
171 p++;
172 }
173
174 if (!*p)
175 {
176 continue;
177 }
178
179 //
180 // Skip comment lines
181 //
182 if (*p == '#')
183 {
184 continue;
185 }
186
187 //
188 // Get the property name
189 mike 1.2 //
|
190 kumpf 1.25 String name;
|
191 mike 1.2
192 if (!(isalpha(*p) || *p == '_'))
193 {
194 ifs.close();
195 throw ConfigFileSyntaxError(_configFile, lineNumber);
196 }
197
|
198 kumpf 1.5 name.append(*p++);
|
199 mike 1.2
200 while (isalnum(*p) || *p == '_')
201 {
|
202 kumpf 1.5 name.append(*p++);
|
203 mike 1.2 }
204
205 //
206 // Skip whitespace after property name
207 //
208 while (*p && isspace(*p))
209 {
210 p++;
211 }
212
213 //
214 // Expect an equal sign
215 //
216 if (*p != '=')
217 {
218 ifs.close();
219 throw ConfigFileSyntaxError(_configFile, lineNumber);
220 }
221
222 p++;
223
224 mike 1.2 //
225 // Skip whitespace after equal sign
226 //
227 while (*p && isspace(*p))
228 {
229 p++;
230 }
231
232 //
233 // Get the value
234 //
|
235 kumpf 1.25 String value;
|
236 mike 1.2
237 while (*p)
238 {
|
239 kumpf 1.5 value.append(*p++);
|
240 mike 1.2 }
241
242 //
243 // Store the property name and value in the table
244 //
245 if (!confTable->table.insert(name, value))
246 {
247 //
248 // Duplicate property, ignore the new property value.
|
249 kumpf 1.3 // FUTURE: Log this message in a log file.
|
250 mike 1.2 //
|
251 kumpf 1.3 PEG_TRACE_STRING(TRC_CONFIG, Tracer::LEVEL3,
|
252 kumpf 1.24 "Duplicate property '" + name + "', value '" + value +
253 "' is ignored.");
|
254 mike 1.2 }
255 }
256
257 ifs.close();
258 }
259
260
|
261 kumpf 1.24 /**
|
262 mike 1.2 Save the properties to the config file.
263 */
|
264 kumpf 1.24 void ConfigFile::save(ConfigTable* confTable)
|
265 mike 1.2 {
266 //
267 // Delete the backup configuration file
268 //
269 if (FileSystem::exists(_configBackupFile))
270 {
|
271 kumpf 1.26 Executor::removeFile(_configBackupFile.getCString());
|
272 mike 1.2 }
273
274 //
275 // Rename the configuration file as a backup file
276 //
|
277 kumpf 1.26
|
278 mike 1.2 if (FileSystem::exists(_configFile))
279 {
|
280 kumpf 1.26 if (Executor::renameFile(
281 _configFile.getCString(), _configBackupFile.getCString()) != 0)
|
282 mike 1.2 {
283 throw CannotRenameFile(_configFile);
284 }
285 }
286
287 //
288 // Open the config file for writing
289 //
290
|
291 kumpf 1.26 FILE* ofs = Executor::openFile(_configFile.getCString(), 'w');
292
293 if (!ofs)
|
294 kumpf 1.13 {
295 throw CannotOpenFile(_configFile);
296 }
297
298 //
|
299 mike 1.2 // Write config file header information
300 //
|
301 kumpf 1.26
|
302 mike 1.2 for (int index = 0; index < HEADER_SIZE; index++)
303 {
|
304 kumpf 1.26 fputs(ConfigHeader[index], ofs);
305 fputc('\n', ofs);
|
306 mike 1.2 }
307
308 //
309 // Save config properties and values to the file
310 //
|
311 kumpf 1.26
|
312 mike 1.2 for (Table::Iterator i = confTable->table.start(); i; i++)
313 {
|
314 kumpf 1.26 CString key = i.key().getCString();
315 CString value = i.value().getCString();
316 fprintf(ofs, "%s=%s\n", (const char*)key, (const char*)value);
|
317 mike 1.2 }
318
|
319 kumpf 1.26 fclose(ofs);
320
321 #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
322 // Note: The Executor process sets the permissions to 0644 whenever it
323 // opens a file for writing.
324 # if !defined(PEGASUS_OS_TYPE_WINDOWS)
325 //
326 // Set permissions on the config file to 0644
327 //
328 if (!FileSystem::changeFilePermissions(_configFile,
329 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) // set 0644
330 {
331 throw CannotOpenFile(_configFile);
332 }
333 # endif
334 #endif /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION */
|
335 mike 1.2 }
336
337
|
338 kumpf 1.24 /**
|
339 mike 1.2 Replace the properties in the config file with the properties from
340 the given file.
341 */
342 void ConfigFile::replace (const String& fileName)
343 {
344 //
345 // Open the given config file for reading
346 //
|
347 kumpf 1.26
348 FILE* ifs = fopen(fileName.getCString(), "rb");
349
350 if (!ifs)
351 {
352 throw CannotOpenFile(fileName);
353 }
|
354 mike 1.2
355 //
356 // Delete the backup configuration file
357 //
|
358 kumpf 1.26
|
359 mike 1.2 if (FileSystem::exists(_configBackupFile))
360 {
|
361 kumpf 1.26 Executor::removeFile(_configBackupFile.getCString());
|
362 mike 1.2 }
363
364 //
365 // Rename the existing config file as a backup file
366 //
|
367 kumpf 1.26
|
368 mike 1.2 if (FileSystem::exists(_configFile))
369 {
|
370 kumpf 1.26 if (Executor::renameFile(
371 _configFile.getCString(), _configBackupFile.getCString()) != 0)
|
372 mike 1.2 {
|
373 kumpf 1.26 fclose(ifs);
|
374 mike 1.2 throw CannotRenameFile(_configFile);
375 }
376 }
377
378 //
379 // Open the existing config file for writing
380 //
|
381 kumpf 1.13
|
382 kumpf 1.26 FILE* ofs = Executor::openFile(_configFile.getCString(), 'w');
383
384 if (!ofs)
|
385 kumpf 1.14 {
|
386 kumpf 1.26 fclose(ifs);
|
387 kumpf 1.14 throw CannotOpenFile(_configFile);
388 }
|
389 mike 1.2
390 //
391 // Read each line of the new file and write to the config file.
392 //
|
393 kumpf 1.26
394 char buffer[4096];
395
396 while ((fgets(buffer, sizeof(buffer), ifs)) != NULL)
397 fputs(buffer, ofs);
|
398 mike 1.2
|
399 kumpf 1.24 //
|
400 mike 1.2 // Close the file handles
401 //
|
402 kumpf 1.26
403 fclose(ifs);
404 fclose(ofs);
405
406 #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
407 # if !defined(PEGASUS_OS_TYPE_WINDOWS)
408 //
409 // Set permissions on the config file to 0644
410 //
411 if (!FileSystem::changeFilePermissions(_configFile,
412 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) // set 0644
413 {
414 throw CannotOpenFile(_configFile);
415 }
416 # endif
417 #endif /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION */
|
418 mike 1.2 }
419
420 PEGASUS_NAMESPACE_END
|