1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/Sysconfig.cc
16 #include "zypp/base/Logger.h"
17 #include "zypp/base/String.h"
18 #include "zypp/base/StrMatcher.h"
19 #include "zypp/base/IOStream.h"
20 #include "zypp/base/InputStream.h"
21 #include "zypp/Pathname.h"
22 #include "zypp/PathInfo.h"
23 #include "zypp/TmpPath.h"
25 #include "zypp/base/Sysconfig.h"
28 using namespace zypp::base;
34 map<string,string> read( const Pathname & _path )
36 DBG << "Load '" << _path << "'" << endl;
37 map<string,string> ret;
40 ifstream in( _path.asString().c_str() );
42 WAR << "Unable to load '" << _path << "'" << endl;
46 while( getline( in, line ) ) {
47 if ( *line.begin() != '#' ) {
49 string::size_type pos = line.find( '=', 0 );
51 if ( pos != string::npos ) {
53 string key = str::trim( line.substr( 0, pos ) );
54 string value = str::trim( line.substr( pos + 1, line.length() - pos - 1 ) );
56 if ( value.length() >= 2
57 && *(value.begin()) == '"'
58 && *(value.rbegin()) == '"' )
60 value = value.substr( 1, value.length() - 2 );
62 if ( value.length() >= 2
63 && *(value.begin()) == '\''
64 && *(value.rbegin()) == '\'' )
66 value = value.substr( 1, value.length() - 2 );
68 XXX << "KEY: '" << key << "' VALUE: '" << value << "'" << endl;
76 MIL << "done reading '" << _path << "'" << endl;
80 bool write( const Pathname & path_r, const std::string & key_r, const std::string & val_r, const std::string & newcomment_r )
84 WAR << "Empty key in write " << path_r << endl;
88 PathInfo pi( path_r );
90 ZYPP_THROW( Exception( str::Str() << path_r << ": " << Errno(ENOENT) ) );
91 if ( ! pi.userMayRW() )
92 ZYPP_THROW( Exception( str::Str() << path_r << ": " << Errno(EACCES) ) );
95 filesystem::TmpFile tmpf( filesystem::TmpFile::makeSibling( path_r ) );
97 StrMatcher matches( "^[ \t]*"+key_r+"[ \t]*=", Match::REGEX );
98 std::ofstream o( tmpf.path().c_str() );
99 iostr::forEachLine( InputStream( path_r ),
100 [&]( int num_r, std::string line_r )->bool
102 if ( !found && matches( line_r ) )
104 o << key_r << '=' << val_r << endl;
106 MIL << path_r << ": " << key_r << '=' << val_r << " changed on line " << num_r << endl;
114 if ( newcomment_r.empty() )
116 WAR << path_r << ": " << key_r << '=' << val_r << " can not be added (no comment provided)." << endl;
120 std::vector<std::string> lines;
121 str::split( newcomment_r, std::back_inserter(lines), "\r\n" );
123 for ( auto line : lines )
125 if ( line[0] != '#' )
129 o << key_r << '=' << val_r << endl;
131 MIL << path_r << ": " << key_r << '=' << val_r << " appended. " << endl;
136 ZYPP_THROW( Exception( str::Str() << tmpf.path() << ": " << Errno(EIO) ) );
139 // If everything is fine, exchange the files:
140 int res = exchange( tmpf.path(), path_r );
143 ZYPP_THROW( Exception( str::Str() << tmpf.path() << ": " << Errno(res) ) );
148 bool writeStringVal( const Pathname & path_r, const std::string & key_r, const std::string & val_r, const std::string & newcomment_r )
150 return write( path_r, key_r, str::Str() << '"' << str::escape( val_r, '"' )<< '"', newcomment_r );
153 } // namespace sysconfig