//------------------------------------------------------------------------------
//! @file Config.cc
//! @author Andreas-Joachim Peters - CERN
//------------------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2021 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#include "common/Config.hh"
#include "common/Logging.hh"
#include "common/StringConversion.hh"
#include
#include
#include
EOSCOMMONNAMESPACE_BEGIN
//----------------------------------------------------------------------------
//! Load a configuration file
//!
//! @return true if loaded successfully, otherwise set error code/msg and false
//----------------------------------------------------------------------------
bool
Config::Load(const char* service, const char* name, bool reset)
{
if (reset) {
// wipe previous configuration
conf.clear();
errcode = 0 ;
errorMessage = "";
}
std::string path = "/etc/eos/config/";
path += service;
path += "/";
path += name;
eos_static_info("loading configuration from '%s'...", path.c_str());
struct stat buf;
if (stat(path.c_str(), &buf)) {
errcode = errno;
errorMessage = "error: unable to load '" + path + "' : ";
errorMessage += strerror(errno);
return false;
}
std::string in;
eos::common::StringConversion::LoadFileIntoString(path.c_str(), in);
std::istringstream f(in);
std::string line;
std::string chapter;
while (std::getline(f, line)) {
std::string p = ParseChapter(line);
if (p.empty()) {
p = ParseSection(line);
if (!p.empty()) {
if (!chapter.empty()) {
// store in chapter
conf[chapter].push_back(p);
} else {
errcode = EINVAL;
errorMessage = "error: no chapter header in config file";
return false;
}
}
} else {
chapter = p;
conf[chapter].size();
}
}
return true;
}
//----------------------------------------------------------------------------
//! Parse and possibly return a chapter entry
//!
//! @return parsed chapter entry or NULL if not applicable
//----------------------------------------------------------------------------
std::string
Config::ParseChapter(const std::string& line)
{
std::string pline = line;
if (pline.empty()) {
return "";
}
// remove new line
if (pline.back() == '\n') {
pline.pop_back();
}
// skip comments
if (pline.front() == '#') {
return "";
}
while (pline.front() == ' ') {
pline.erase(0,1);
}
while (pline.back() == ' ') {
pline.pop_back();
}
if (line.front() == '[') {
if (line.back() == ']') {
pline.pop_back();
pline.erase(0,1);
return pline;
}
}
return "";
}
//----------------------------------------------------------------------------
//! Parse and possibly return a section entry
//!
//! @return parsed section entry or NULL if not applicable
//----------------------------------------------------------------------------
std::string
Config::ParseSection(const std::string& line)
{
std::string pline = line;
if (pline.empty()) {
return "";
}
// remove new line
if (pline.back() == '\n') {
pline.pop_back();
}
// skip comments
if (pline.front() == '#') {
return "";
}
while (pline.front() == ' ') {
pline.erase(0,1);
}
while (pline.back() == ' ') {
pline.pop_back();
}
return pline;
}
//----------------------------------------------------------------------------
//! AsMap
//!
//! return a map with the lines matching x=y
//----------------------------------------------------------------------------
std::map
Config::AsMap(const char* chapter)
{
std::map map;
if (chapter && conf.count(chapter)) {
for ( auto it : conf[chapter] ) {
if ( eos::common::StringConversion::GetKeyValueMap( it.c_str(),
map,
"="," " ) ) {
}
}
}
return map;
}
char**
Config::Env(const char* chapter)
{
std::map map = AsMap(chapter);
size_t cnt=0;
// do variable substitution
for (auto it : map) {
std::string s = it.second;
ReplaceFromChapter(s,chapter);
map[it.first]=s;
}
for (auto it : map) {
std::string kv = it.first + "=";
kv = it.first + "=" + it.second;
envv[cnt++] = strdup( kv.c_str() ) ;
}
envv[cnt] = NULL;
return envv;
}
//----------------------------------------------------------------------------
//! Get of line for a given key ' '
//----------------------------------------------------------------------------
std::string
Config::GetValueByKey(const char* chapter, const char* key)
{
if (Has(chapter)) {
for (auto it : conf[chapter]) {
if ( it.substr(0, std::string(key).length()) == key ) {
return it.substr(std::string(key).length()+1);
}
}
}
return "";
}
EOSCOMMONNAMESPACE_END