//%LICENSE//////////////////////////////////////////////////////////////// // // Licensed to The Open Group (TOG) under one or more contributor license // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with // this work for additional information regarding copyright ownership. // Each contributor licenses this file to you under the OpenPegasus Open // Source License; you may not use this file except in compliance with the // License. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ////////////////////////////////////////////////////////////////////////// // //%///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "ConfigExceptions.h" #include "ConfigFile.h" PEGASUS_USING_STD; PEGASUS_NAMESPACE_BEGIN //////////////////////////////////////////////////////////////////////////////// // // ConfigFile Class // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // ConfigTable //////////////////////////////////////////////////////////////////////////////// typedef HashTable, HashFunc > Table; struct ConfigTable { Table table; }; /* Config file header information */ static const char* ConfigHeader [] = { "########################################################################", "## ##", "## CIM Server configuration file ##", "## ##", "########################################################################", "", "########################################################################", "# #", "# The configuration in this file is loaded by the CIM Server at #", "# start-up. This file is updated by the CIM Server when the #", "# configuration changes. #", "# #", "# Do not edit this file directly. Instead, use the cimconfig command #", "# to update the CIM Server configuration. #", "# #", "########################################################################", "" }; static const int HEADER_SIZE = sizeof(ConfigHeader) / sizeof(ConfigHeader[0]); /** Constructor. */ ConfigFile::ConfigFile (const String& fileName) { _configFile = fileName; _configBackupFile = fileName + ".bak"; } /** Destructor. */ ConfigFile::~ConfigFile () { } /** Get the name of the configuration file. */ String ConfigFile::getFileName () const { return _configFile; } /** Load the properties from the config file. */ void ConfigFile::load(ConfigTable* confTable) { String line; // // Delete the backup configuration file // if (FileSystem::exists(_configBackupFile)) { Executor::removeFile(_configBackupFile.getCString()); } // // Open the config file // ifstream ifs(_configFile.getCString()); if (!ifs) { return; } // // Read each line of the file // for (Uint32 lineNumber = 1; GetLine(ifs, line); lineNumber++) { // Get the property name and value // // Skip leading whitespace // const Char16* p = line.getChar16Data(); while (*p && isspace(*p)) { p++; } if (!*p) { continue; } // // Skip comment lines // if (*p == '#') { continue; } // // Get the property name // String name; if (!(isalpha(*p) || *p == '_')) { ifs.close(); throw ConfigFileSyntaxError(_configFile, lineNumber); } name.append(*p++); while (isalnum(*p) || *p == '_') { name.append(*p++); } // // Skip whitespace after property name // while (*p && isspace(*p)) { p++; } // // Expect an equal sign // if (*p != '=') { ifs.close(); throw ConfigFileSyntaxError(_configFile, lineNumber); } p++; // // Skip whitespace after equal sign // while (*p && isspace(*p)) { p++; } // // Get the value // String value; while (*p) { value.append(*p++); } // // Store the property name and value in the table // if (!confTable->table.insert(name, value)) { // // Duplicate property, ignore the new property value. // FUTURE: Log this message in a log file. // PEG_TRACE((TRC_CONFIG, Tracer::LEVEL2, "Duplicate property '%s', value '%s' is ignored.", (const char*)name.getCString(), (const char*)value.getCString())); } } ifs.close(); } /** Save the properties to the config file. */ void ConfigFile::save(ConfigTable* confTable) { // // Delete the backup configuration file // if (FileSystem::exists(_configBackupFile)) { Executor::removeFile(_configBackupFile.getCString()); } // // Rename the configuration file as a backup file // if (FileSystem::exists(_configFile)) { if (Executor::renameFile( _configFile.getCString(), _configBackupFile.getCString()) != 0) { throw CannotRenameFile(_configFile); } } // // Open the config file for writing // FILE* ofs = Executor::openFile(_configFile.getCString(), 'w'); if (!ofs) { throw CannotOpenFile(_configFile); } // // Write config file header information // for (int index = 0; index < HEADER_SIZE; index++) { fputs(ConfigHeader[index], ofs); fputc('\n', ofs); } // // Save config properties and values to the file // for (Table::Iterator i = confTable->table.start(); i; i++) { CString key = i.key().getCString(); CString value = i.value().getCString(); fprintf(ofs, "%s=%s\n", (const char*)key, (const char*)value); } fclose(ofs); #if !defined(PEGASUS_OS_TYPE_WINDOWS) // Note: The Executor process sets the permissions to 0644 when it // opens the config file for writing. if (Executor::detectExecutor() != 0) { // // Set permissions on the config file to 0644 // if (!FileSystem::changeFilePermissions( _configFile, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) // set 0644 { throw CannotChangeFilePerm(_configFile); } } #endif } /** Replace the properties in the config file with the properties from the given file. */ void ConfigFile::replace (const String& fileName) { // // Open the given config file for reading // FILE* ifs = fopen(fileName.getCString(), "r"); if (!ifs) { throw CannotOpenFile(fileName); } // // Delete the backup configuration file // if (FileSystem::exists(_configBackupFile)) { Executor::removeFile(_configBackupFile.getCString()); } // // Rename the existing config file as a backup file // if (FileSystem::exists(_configFile)) { if (Executor::renameFile( _configFile.getCString(), _configBackupFile.getCString()) != 0) { fclose(ifs); throw CannotRenameFile(_configFile); } } // // Open the existing config file for writing // FILE* ofs = Executor::openFile(_configFile.getCString(), 'w'); if (!ofs) { fclose(ifs); throw CannotOpenFile(_configFile); } // // Read each line of the new file and write to the config file. // char buffer[4096]; while ((fgets(buffer, sizeof(buffer), ifs)) != NULL) fputs(buffer, ofs); // // Close the file handles // fclose(ifs); fclose(ofs); #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION) # if !defined(PEGASUS_OS_TYPE_WINDOWS) // // Set permissions on the config file to 0644 // if (!FileSystem::changeFilePermissions(_configFile, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) // set 0644 { throw CannotChangeFilePerm(_configFile); } # endif #endif /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION */ } PEGASUS_NAMESPACE_END