libzypp 8.13.6
|
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 00078 inline void openLog() 00079 { 00080 if ( _fname.empty() ) 00081 _fname = ZConfig::instance().historyLogFile(); 00082 00083 _log.clear(); 00084 _log.open( _fname.asString().c_str(), std::ios::out|std::ios::app ); 00085 if( !_log ) 00086 ERR << "Could not open logfile '" << _fname << "'" << endl; 00087 } 00088 00089 inline void closeLog() 00090 { 00091 _log.clear(); 00092 _log.close(); 00093 } 00094 00095 inline void refUp() 00096 { 00097 if ( !_refcnt ) 00098 openLog(); 00099 ++_refcnt; 00100 } 00101 00102 inline void refDown() 00103 { 00104 --_refcnt; 00105 if ( !_refcnt ) 00106 closeLog(); 00107 } 00108 } 00109 00111 // 00112 // CLASS NAME : HistoryLog 00113 // 00115 00116 HistoryLog::HistoryLog( const Pathname & rootdir ) 00117 { 00118 setRoot( rootdir ); 00119 refUp(); 00120 } 00121 00122 HistoryLog::~HistoryLog() 00123 { 00124 refDown(); 00125 } 00126 00127 void HistoryLog::setRoot( const Pathname & rootdir ) 00128 { 00129 if ( ! rootdir.absolute() ) 00130 return; 00131 00132 if ( _refcnt ) 00133 closeLog(); 00134 00135 _fname = rootdir / ZConfig::instance().historyLogFile(); 00136 filesystem::assert_dir( _fname.dirname() ); 00137 MIL << "installation log file " << _fname << endl; 00138 00139 if ( _refcnt ) 00140 openLog(); 00141 } 00142 00143 const Pathname & HistoryLog::fname() 00144 { 00145 if ( _fname.empty() ) 00146 _fname = ZConfig::instance().historyLogFile(); 00147 return _fname; 00148 } 00149 00151 00152 void HistoryLog::comment( const string & comment, bool timestamp ) 00153 { 00154 if (comment.empty()) 00155 return; 00156 00157 _log << "# "; 00158 if ( timestamp ) 00159 _log << ::timestamp() << " "; 00160 00161 const char * s = comment.c_str(); 00162 const char * c = s; 00163 unsigned size = comment.size(); 00164 00165 // ignore the last newline 00166 if (comment[size-1] == '\n') 00167 --size; 00168 00169 for ( unsigned i = 0; i < size; ++i, ++c ) 00170 if ( *c == '\n' ) 00171 { 00172 _log << string( s, c + 1 - s ) << "# "; 00173 s = c + 1; 00174 } 00175 00176 if ( s < c ) 00177 _log << std::string( s, c-s ); 00178 00179 _log << endl; 00180 } 00181 00183 00184 void HistoryLog::install( const PoolItem & pi ) 00185 { 00186 const Package::constPtr p = asKind<Package>(pi.resolvable()); 00187 if (!p) 00188 return; 00189 00190 _log 00191 << timestamp() // 1 timestamp 00192 << _sep << HistoryActionID::INSTALL.asString(true) // 2 action 00193 << _sep << p->name() // 3 name 00194 << _sep << p->edition() // 4 evr 00195 << _sep << p->arch(); // 5 arch 00196 00197 // ApplLow is what the solver selected on behalf of the user. 00198 if (pi.status().isByUser() || pi.status().isByApplLow() ) 00199 _log << _sep << userAtHostname(); // 6 reqested by 00200 else if (pi.status().isByApplHigh()) 00201 _log << _sep << pidAndAppname(); 00202 else 00203 _log << _sep; 00204 00205 _log 00206 << _sep << p->repoInfo().alias() // 7 repo alias 00207 << _sep << p->checksum().checksum(); // 8 checksum 00208 00209 _log << endl; 00210 00211 //_log << pi << endl; 00212 } 00213 00214 00215 void HistoryLog::remove( const PoolItem & pi ) 00216 { 00217 const Package::constPtr p = asKind<Package>(pi.resolvable()); 00218 if (!p) 00219 return; 00220 00221 _log 00222 << timestamp() // 1 timestamp 00223 << _sep << HistoryActionID::REMOVE.asString(true) // 2 action 00224 << _sep << p->name() // 3 name 00225 << _sep << p->edition() // 4 evr 00226 << _sep << p->arch(); // 5 arch 00227 00228 // ApplLow is what the solver selected on behalf of the user. 00229 if ( pi.status().isByUser() || pi.status().isByApplLow() ) 00230 _log << _sep << userAtHostname(); // 6 reqested by 00231 else if (pi.status().isByApplHigh()) 00232 _log << _sep << pidAndAppname(); 00233 else 00234 _log << _sep; 00235 00236 // we don't have checksum in rpm db 00237 // << _sep << p->checksum().checksum(); // x checksum 00238 00239 _log << endl; 00240 00241 //_log << pi << endl; 00242 } 00243 00245 00246 void HistoryLog::addRepository(const RepoInfo & repo) 00247 { 00248 _log 00249 << timestamp() // 1 timestamp 00250 << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action 00251 << _sep << str::escape(repo.alias(), _sep) // 3 alias 00252 // what about the rest of the URLs?? 00253 << _sep << *repo.baseUrlsBegin() // 4 primary URL 00254 << endl; 00255 } 00256 00257 00258 void HistoryLog::removeRepository(const RepoInfo & repo) 00259 { 00260 _log 00261 << timestamp() // 1 timestamp 00262 << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action 00263 << _sep << str::escape(repo.alias(), _sep) // 3 alias 00264 << endl; 00265 } 00266 00267 00268 void HistoryLog::modifyRepository( 00269 const RepoInfo & oldrepo, const RepoInfo & newrepo) 00270 { 00271 if (oldrepo.alias() != newrepo.alias()) 00272 { 00273 _log 00274 << timestamp() // 1 timestamp 00275 << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action 00276 << _sep << str::escape(oldrepo.alias(), _sep) // 3 old alias 00277 << _sep << str::escape(newrepo.alias(), _sep) // 4 new alias 00278 << endl; 00279 } 00280 00281 if (*oldrepo.baseUrlsBegin() != *newrepo.baseUrlsBegin()) 00282 { 00283 _log 00284 << timestamp() //1 timestamp 00285 << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action 00286 << _sep << str::escape(oldrepo.alias(), _sep) // 3 old url 00287 << _sep << *newrepo.baseUrlsBegin() // 4 new url 00288 << endl; 00289 } 00290 } 00291 00293 00294 } // namespace zypp