libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00012 #include <iostream> 00013 #include <fstream> 00014 #include <unistd.h> 00015 00016 #include "zypp/ZConfig.h" 00017 #include "zypp/base/String.h" 00018 #include "zypp/base/Logger.h" 00019 00020 #include "zypp/PathInfo.h" 00021 #include "zypp/Date.h" 00022 00023 #include "zypp/PoolItem.h" 00024 #include "zypp/Package.h" 00025 #include "zypp/RepoInfo.h" 00026 00027 #include "zypp/HistoryLog.h" 00028 #include "zypp/HistoryLogData.h" 00029 00030 using std::endl; 00031 using std::string; 00032 00033 namespace 00034 { 00035 inline string timestamp() 00036 { return zypp::Date::now().form( HISTORY_LOG_DATE_FORMAT ); } 00037 00038 inline string userAtHostname() 00039 { 00040 static char buf[256]; 00041 string result; 00042 char * tmp = ::cuserid(buf); 00043 if (tmp) 00044 { 00045 result = string(tmp); 00046 if (!::gethostname(buf, 255)) 00047 result += "@" + string(buf); 00048 } 00049 return result; 00050 } 00051 00052 static std::string pidAndAppname() 00053 { 00054 static std::string _val; 00055 if ( _val.empty() ) 00056 { 00057 pid_t mypid = getpid(); 00058 zypp::Pathname p( "/proc/"+zypp::str::numstring(mypid)+"/exe" ); 00059 zypp::Pathname myname( zypp::filesystem::readlink( p ) ); 00060 00061 _val += zypp::str::numstring(mypid); 00062 _val += ":"; 00063 _val += myname.basename(); 00064 } 00065 return _val; 00066 } 00067 } 00068 00069 namespace zypp 00070 { 00071 namespace 00072 { 00073 const char _sep = '|'; 00074 std::ofstream _log; 00075 unsigned _refcnt = 0; 00076 Pathname _fname; 00077 Pathname _fnameLastFail; 00078 00079 inline void openLog() 00080 { 00081 if ( _fname.empty() ) 00082 _fname = ZConfig::instance().historyLogFile(); 00083 00084 _log.clear(); 00085 _log.open( _fname.asString().c_str(), std::ios::out|std::ios::app ); 00086 if( !_log && _fnameLastFail != _fname ) 00087 { 00088 ERR << "Could not open logfile '" << _fname << "'" << endl; 00089 _fnameLastFail = _fname; 00090 } 00091 } 00092 00093 inline void closeLog() 00094 { 00095 _log.clear(); 00096 _log.close(); 00097 } 00098 00099 inline void refUp() 00100 { 00101 if ( !_refcnt ) 00102 openLog(); 00103 ++_refcnt; 00104 } 00105 00106 inline void refDown() 00107 { 00108 --_refcnt; 00109 if ( !_refcnt ) 00110 closeLog(); 00111 } 00112 } 00113 00115 // 00116 // CLASS NAME : HistoryLog 00117 // 00119 00120 HistoryLog::HistoryLog( const Pathname & rootdir ) 00121 { 00122 setRoot( rootdir ); 00123 refUp(); 00124 } 00125 00126 HistoryLog::~HistoryLog() 00127 { 00128 refDown(); 00129 } 00130 00131 void HistoryLog::setRoot( const Pathname & rootdir ) 00132 { 00133 if ( ! rootdir.absolute() ) 00134 return; 00135 00136 if ( _refcnt ) 00137 closeLog(); 00138 00139 _fname = rootdir / ZConfig::instance().historyLogFile(); 00140 filesystem::assert_dir( _fname.dirname() ); 00141 MIL << "installation log file " << _fname << endl; 00142 00143 if ( _refcnt ) 00144 openLog(); 00145 } 00146 00147 const Pathname & HistoryLog::fname() 00148 { 00149 if ( _fname.empty() ) 00150 _fname = ZConfig::instance().historyLogFile(); 00151 return _fname; 00152 } 00153 00155 00156 void HistoryLog::comment( const string & comment, bool timestamp ) 00157 { 00158 if (comment.empty()) 00159 return; 00160 00161 _log << "# "; 00162 if ( timestamp ) 00163 _log << ::timestamp() << " "; 00164 00165 const char * s = comment.c_str(); 00166 const char * c = s; 00167 unsigned size = comment.size(); 00168 00169 // ignore the last newline 00170 if (comment[size-1] == '\n') 00171 --size; 00172 00173 for ( unsigned i = 0; i < size; ++i, ++c ) 00174 if ( *c == '\n' ) 00175 { 00176 _log << string( s, c + 1 - s ) << "# "; 00177 s = c + 1; 00178 } 00179 00180 if ( s < c ) 00181 _log << std::string( s, c-s ); 00182 00183 _log << endl; 00184 } 00185 00187 00188 void HistoryLog::install( const PoolItem & pi ) 00189 { 00190 const Package::constPtr p = asKind<Package>(pi.resolvable()); 00191 if (!p) 00192 return; 00193 00194 _log 00195 << timestamp() // 1 timestamp 00196 << _sep << HistoryActionID::INSTALL.asString(true) // 2 action 00197 << _sep << p->name() // 3 name 00198 << _sep << p->edition() // 4 evr 00199 << _sep << p->arch(); // 5 arch 00200 00201 // ApplLow is what the solver selected on behalf of the user. 00202 if (pi.status().isByUser() || pi.status().isByApplLow() ) 00203 _log << _sep << userAtHostname(); // 6 reqested by 00204 else if (pi.status().isByApplHigh()) 00205 _log << _sep << pidAndAppname(); 00206 else 00207 _log << _sep; 00208 00209 _log 00210 << _sep << p->repoInfo().alias() // 7 repo alias 00211 << _sep << p->checksum().checksum(); // 8 checksum 00212 00213 _log << endl; 00214 00215 //_log << pi << endl; 00216 } 00217 00218 00219 void HistoryLog::remove( const PoolItem & pi ) 00220 { 00221 const Package::constPtr p = asKind<Package>(pi.resolvable()); 00222 if (!p) 00223 return; 00224 00225 _log 00226 << timestamp() // 1 timestamp 00227 << _sep << HistoryActionID::REMOVE.asString(true) // 2 action 00228 << _sep << p->name() // 3 name 00229 << _sep << p->edition() // 4 evr 00230 << _sep << p->arch(); // 5 arch 00231 00232 // ApplLow is what the solver selected on behalf of the user. 00233 if ( pi.status().isByUser() || pi.status().isByApplLow() ) 00234 _log << _sep << userAtHostname(); // 6 reqested by 00235 else if (pi.status().isByApplHigh()) 00236 _log << _sep << pidAndAppname(); 00237 else 00238 _log << _sep; 00239 00240 // we don't have checksum in rpm db 00241 // << _sep << p->checksum().checksum(); // x checksum 00242 00243 _log << endl; 00244 00245 //_log << pi << endl; 00246 } 00247 00249 00250 void HistoryLog::addRepository(const RepoInfo & repo) 00251 { 00252 _log 00253 << timestamp() // 1 timestamp 00254 << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action 00255 << _sep << str::escape(repo.alias(), _sep) // 3 alias 00256 // what about the rest of the URLs?? 00257 << _sep << *repo.baseUrlsBegin() // 4 primary URL 00258 << endl; 00259 } 00260 00261 00262 void HistoryLog::removeRepository(const RepoInfo & repo) 00263 { 00264 _log 00265 << timestamp() // 1 timestamp 00266 << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action 00267 << _sep << str::escape(repo.alias(), _sep) // 3 alias 00268 << endl; 00269 } 00270 00271 00272 void HistoryLog::modifyRepository( 00273 const RepoInfo & oldrepo, const RepoInfo & newrepo) 00274 { 00275 if (oldrepo.alias() != newrepo.alias()) 00276 { 00277 _log 00278 << timestamp() // 1 timestamp 00279 << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action 00280 << _sep << str::escape(oldrepo.alias(), _sep) // 3 old alias 00281 << _sep << str::escape(newrepo.alias(), _sep) // 4 new alias 00282 << endl; 00283 } 00284 00285 if (*oldrepo.baseUrlsBegin() != *newrepo.baseUrlsBegin()) 00286 { 00287 _log 00288 << timestamp() //1 timestamp 00289 << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action 00290 << _sep << str::escape(oldrepo.alias(), _sep) // 3 old url 00291 << _sep << *newrepo.baseUrlsBegin() // 4 new url 00292 << endl; 00293 } 00294 } 00295 00297 00298 } // namespace zypp