libzypp 17.38.5
econfdict.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
11#include "econfdict.h"
12
13#include <tuple> // std::ignore
14#include <optional>
15
16#include <zypp-core/APIConfig.h>
17#include <zypp-core/Pathname.h>
20
21namespace zypp::parser {
22
23 namespace econf {
24
37 {
40
44
45 ConfigurationContext( std::optional<Pathname> etcDir_r, std::optional<Pathname> usrDir_r )
46 : _etcDir( std::move(etcDir_r) )
47 , _usrDir( std::move(usrDir_r) )
48 {}
49
50 const std::optional<Pathname> & etcDir() const { return _etcDir; }
51 const std::optional<Pathname> & usrDir() const { return _usrDir; }
52
53 std::vector<Pathname> getConfigFiles( const std::string & stem_r, const Pathname & root_r = Pathname("/") ) const
54 {
55 // configStem must denote a config file below some root dir:
56 // [PROJECT/]EXAMPLE[.SUFFIX]
57 Pathname configStem { stem_r };
58 if ( configStem.relative() ) {
59 if ( configStem.relativeDotDot() )
60 ZYPP_THROW( Exception(str::sprint("Config stem must not refer to '../':", configStem)) );
61 configStem = configStem.absolutename();
62 }
63 if ( configStem.emptyOrRoot() )
64 ZYPP_THROW( Exception(str::sprint("Config stem must not be empty:", configStem)) );
65 pMIL( "getConfigFiles for stem", configStem, "below", root_r, "in", _etcDir, _usrDir );
66 Pathname configDir { configStem.extend( ".d" ) }; // [PROJECT/]EXAMPLE[.SUFFIX].d
67 std::string configSuffix { configStem.extension() }; // [.SUFFIX]
68
69 // relevant lookup dirs in order of preference:
70 std::vector<Pathname> lookupDirs;
71 if ( _etcDir )
72 takeLookupDirIf( lookupDirs, root_r / *_etcDir ); // system configuration
73 takeLookupDirIf( lookupDirs, root_r / "/run" ); // /run for ephemeral overrides
74 if ( _usrDir )
75 takeLookupDirIf( lookupDirs, root_r / *_usrDir ); // vendor configuration
76
77 // now collect base config and drop-ins to parse:
78 PathInfo basecfgToParse; // the full (base) config to parse (if any)
79 std::map<std::string,PathInfo> dropinsToParse; // drop-ins to parse (1st. wins; lex sorted)
80
81 for ( const Pathname & ldir : lookupDirs ) {
82 // base config
83 PathInfo basecfg { ldir / configStem };
84 takeOrMask( basecfg, basecfgToParse );
85
86 // dropins
87 PathInfo dropinDir { ldir / configDir };
88 if ( dropinDir.isDir() ) {
89 filesystem::dirForEachExt( dropinDir.path(), [&]( const zypp::Pathname &p, const zypp::filesystem::DirEntry &entry ) {
90 if ( entry.name[0] == '.' )
91 return true;
92 if ( not ( configSuffix.empty() || str::hasSuffix( entry.name, configSuffix ) ) )
93 return true;
94 PathInfo dropin { p / entry.name };
95 takeOrMask( dropin, dropinsToParse[entry.name] );
96 return true;
97 } );
98 }
99 }
100
101 // prepare the list to parse
102 std::vector<Pathname> ret;
103 handOutIf( ret, basecfgToParse );
104 for ( const auto & [_,p] : dropinsToParse ) {
105 std::ignore = _; // silence warning: unused variable
106 handOutIf( ret, p );
107 }
108 if ( ret.empty() )
109 pMIL( "No config files found for stem", configStem, "below", root_r );
110 return ret;
111 }
112
113 private:
115 static void takeLookupDirIf( std::vector<Pathname> & lookupDirs_r, Pathname dir_r )
116 {
117 if ( PathInfo(dir_r).isDir() )
118 lookupDirs_r.push_back( dir_r );
119 }
120
122 static bool isSet( const PathInfo & file_r )
123 { return not file_r.path().empty(); }
124
126 static void takeOrMask( const PathInfo & file_r, PathInfo & toParse_r )
127 {
128 if ( file_r.isExist() && not file_r.isDir() ) {
129 if ( isSet( toParse_r ) ) {
130 pDBG( "masked", file_r, "by", toParse_r );
131 } else {
132 toParse_r = std::move(file_r); //file_r.path();
133 }
134 }
135 }
136
138 static void handOutIf( std::vector<Pathname> & ret_r, const PathInfo & file_r )
139 {
140 if ( isSet( file_r ) ) {
141 pMIL( "take", file_r );
142 ret_r.push_back( file_r.path() );
143 }
144 }
145
146
147 private:
148 std::optional<Pathname> _etcDir;
149 std::optional<Pathname> _usrDir;
150 };
151
152 Pathname ConfigurationContext::_defaultDistconfDir { APIConfig(LIBZYPP_ZYPPCONFDIR) };
153
154 } // namespace econf
155
158
159 EconfDict::EconfDict( const std::string & stem_r, const Pathname & root_r )
160 : IniDict()
161 {
162 for ( const Pathname & file : econf::ConfigurationContext().getConfigFiles( stem_r, root_r ) ) {
163 read( file );
164 }
165 pDBG( stem_r, "below", root_r, ":", *this );
166 }
167
170
173} // namespace zypp::parser
174
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define _(MSG)
Definition Gettext.h:39
#define pMIL
Definition LogTools.h:305
#define pDBG
Definition LogTools.h:304
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const Pathname & path() const
Return current Pathname.
Definition PathInfo.h:251
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:286
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
Definition Pathname.h:182
bool relativeDotDot() const
Test for a relative path referring to ../.
Definition Pathname.h:124
bool emptyOrRoot() const
Test for "" or "/".
Definition Pathname.h:127
bool empty() const
Test for an empty path.
Definition Pathname.h:117
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
Definition Pathname.h:148
std::string extension() const
Return all of the characters in name after and including the last dot in the last element of name.
Definition Pathname.h:144
bool relative() const
Test for a relative path.
Definition Pathname.h:121
void read(const InputStream &is, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Fill a dictionary from a InputStream containing a ini structured file.
Definition inidict.cc:50
IniDict(const InputStream &is, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Creates a dictionary from a InputStream containing a ini structured file.
Definition inidict.cc:40
Definition ansi.h:855
int dirForEachExt(const Pathname &dir_r, const function< bool(const Pathname &, const DirEntry &)> &fnc_r)
Simiar to.
Definition PathInfo.cc:612
std::string sprint(Args &&... args)
Print words as string.
Definition LogTools.h:266
Listentry returned by readdir.
Definition PathInfo.h:517
static Pathname defaultDistconfDir()
Where the vendor configuration files live (APIConfig(LIBZYPP_ZYPPCONFDIR)).
Definition econfdict.cc:168
Provide access to the prioritized list of files and drop-ins to read and merge for a specific config ...
Definition econfdict.cc:37
static void takeOrMask(const PathInfo &file_r, PathInfo &toParse_r)
The 1st viable file_r is stored in toParse_r; candidates found later are masked.
Definition econfdict.cc:126
std::vector< Pathname > getConfigFiles(const std::string &stem_r, const Pathname &root_r=Pathname("/")) const
Definition econfdict.cc:53
static void handOutIf(std::vector< Pathname > &ret_r, const PathInfo &file_r)
Store set values in ret_r.
Definition econfdict.cc:138
static void takeLookupDirIf(std::vector< Pathname > &lookupDirs_r, Pathname dir_r)
Remember valid lookup dirs.
Definition econfdict.cc:115
std::optional< Pathname > _etcDir
system configuration: /etc
Definition econfdict.cc:148
const std::optional< Pathname > & usrDir() const
Definition econfdict.cc:51
static bool isSet(const PathInfo &file_r)
An empty path denotes the unset value.
Definition econfdict.cc:122
ConfigurationContext(std::optional< Pathname > etcDir_r, std::optional< Pathname > usrDir_r)
Definition econfdict.cc:45
static Pathname _defaultDistconfDir
APIConfig(LIBZYPP_ZYPPCONFDIR) but amendable for Testing.
Definition econfdict.cc:39
const std::optional< Pathname > & etcDir() const
Definition econfdict.cc:50
std::optional< Pathname > _usrDir
vendor configuration: distconfdir (APIConfig(LIBZYPP_ZYPPCONFDIR))
Definition econfdict.cc:149