libzypp: zypp/HistoryLog.cc Source File

libzypp 17.25.10

HistoryLog.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <fstream>
14 #include <unistd.h>
15
16 #include <zypp/ZConfig.h>
17 #include <zypp/base/String.h>
18 #include <zypp/base/Logger.h>
19 #include <zypp/base/IOStream.h>
20
21 #include <zypp/PathInfo.h>
22 #include <zypp/Date.h>
23
24 #include <zypp/PoolItem.h>
25 #include <zypp/Package.h>
26 #include <zypp/RepoInfo.h>
27
28 #include <zypp/HistoryLog.h>
29 #include <zypp/HistoryLogData.h>
30
31 using std::endl;
32 using std::string;
33
34 namespace zypp
35 {
36 namespace
37 {
38 inline string timestamp()
39 { return zypp::Date::now().form( HISTORY_LOG_DATE_FORMAT ); }
40
41 inline string userAtHostname()
42 {
43 static char buf[256];
44 string result;
45 char * tmp = ::cuserid(buf);
46 if (tmp)
47 {
48 result = string(tmp);
49 if (!::gethostname(buf, 255))
50 result += "@" + string(buf);
51 }
52 return result;
53 }
54
55 static std::string pidAndAppname()
56 {
57 static std::string _val;
58 if ( _val.empty() )
59 {
60 pid_t mypid = getpid();
61 zypp::Pathname p( "/proc/"+zypp::str::numstring(mypid)+"/exe" );
62 zypp::Pathname myname( zypp::filesystem::readlink( p ) );
63
64 _val += zypp::str::numstring(mypid);
65 _val += ":";
66 _val += myname.basename();
67 }
68 return _val;
69 }
70
71 static std::string cmdline()
72 {
73 static std::string _val;
74 if ( _val.empty() )
75 {
76 pid_t mypid = getpid();
77 {
78 std::ifstream cmdlineStr( Pathname("/proc/"+zypp::str::numstring(mypid)+"/cmdline").c_str() );
79 char ch;
80 const char * sep = "'";
81 while ( cmdlineStr && cmdlineStr.get( ch ) )
82 {
83 if ( sep )
84 {
85 _val += sep;
86 sep = nullptr;
87 }
88 switch ( ch )
89 {
90 case '\0': _val += '\''; sep = " '"; break;
91 case '\n': _val += ' '; break;
92 case '\\': _val += '\\'; _val += '\\'; break;
93 case '|': _val += '\\'; _val += '|'; break;
94 default: _val += ch; break;
95 }
96 }
97 }
98 }
99 return _val;
100 }
101 } // namespace
102
103 namespace
104 {
105 const char _sep = '|';
106 std::ofstream _log;
107 unsigned _refcnt = 0;
108 Pathname _fname;
109 Pathname _fnameLastFail;
110
111 inline void openLog()
112 {
113 if ( _fname.empty() )
114 _fname = ZConfig::instance().historyLogFile();
115
116 _log.clear();
117 _log.open( _fname.asString().c_str(), std::ios::out|std::ios::app );
118 if( !_log && _fnameLastFail != _fname )
119 {
120 ERR << "Could not open logfile '" << _fname << "'" << endl;
121 _fnameLastFail = _fname;
122 }
123 }
124
125 inline void closeLog()
126 {
127 _log.clear();
128 _log.close();
129 }
130
131 inline void refUp()
132 {
133 if ( !_refcnt )
134 openLog();
135 ++_refcnt;
136 }
137
138 inline void refDown()
139 {
140 --_refcnt;
141 if ( !_refcnt )
142 closeLog();
143 }
144 } // namespace
145
147 //
148 // CLASS NAME : HistoryLog
149 //
151
152 HistoryLog::HistoryLog( const Pathname & rootdir )
153 {
154 setRoot( rootdir );
155 refUp();
156 }
157
158 HistoryLog::~HistoryLog()
159 {
160 refDown();
161 }
162
163 void HistoryLog::setRoot( const Pathname & rootdir )
164 {
165 if ( ! rootdir.absolute() )
166 return;
167
168 if ( _refcnt )
169 closeLog();
170
171 _fname = rootdir / ZConfig::instance().historyLogFile();
172 filesystem::assert_dir( _fname.dirname() );
173 MIL << "installation log file " << _fname << endl;
174
175 if ( _refcnt )
176 openLog();
177 }
178
179 const Pathname & HistoryLog::fname()
180 {
181 if ( _fname.empty() )
182 _fname = ZConfig::instance().historyLogFile();
183 return _fname;
184 }
185
187
188 void HistoryLog::comment( const string & comment, bool timestamp_r )
189 {
190 if (comment.empty())
191 return;
192
193 _log << "# ";
194 if ( timestamp_r )
195 _log << timestamp() << " ";
196
197 const char * s = comment.c_str();
198 const char * c = s;
199 unsigned size = comment.size();
200
201 // ignore the last newline
202 if (comment[size-1] == '\n')
203 --size;
204
205 for ( unsigned i = 0; i < size; ++i, ++c )
206 if ( *c == '\n' )
207 {
208 _log << string( s, c + 1 - s ) << "# ";
209 s = c + 1;
210 }
211
212 if ( s < c )
213 _log << std::string( s, c-s );
214
215 _log << endl;
216 }
217
219
220 void HistoryLog::stampCommand()
221 {
222 _log
223 << timestamp() // 1 timestamp
224 << _sep << HistoryActionID::STAMP_COMMAND.asString(true) // 2 action
225 << _sep << userAtHostname() // 3 requested by
226 << _sep << cmdline() // 4 command
227 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 6 userdata
228 << endl;
229
230 }
231
232 void HistoryLog::install( const PoolItem & pi )
233 {
234 if ( ! pi.isKind<Package>() ) return;
235 const Package::constPtr p = asKind<Package>(pi.resolvable());
236
237 _log
238 << timestamp() // 1 timestamp
239 << _sep << HistoryActionID::INSTALL.asString(true) // 2 action
240 << _sep << p->name() // 3 name
241 << _sep << p->edition() // 4 evr
242 << _sep << p->arch(); // 5 arch
243
244 // ApplLow is what the solver selected on behalf of the user.
245 if (pi.status().isByUser() || pi.status().isByApplLow() )
246 _log << _sep << userAtHostname(); // 6 requested by
247 else if (pi.status().isByApplHigh())
248 _log << _sep << pidAndAppname();
249 else
250 _log << _sep;
251
252 _log
253 << _sep << p->repoInfo().alias() // 7 repo alias
254 << _sep << p->checksum().checksum() // 8 checksum
255 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 9 userdata
256 << endl;
257 }
258
259
260 void HistoryLog::remove( const PoolItem & pi )
261 {
262 if ( ! pi.isKind<Package>() ) return;
263 const Package::constPtr p = asKind<Package>(pi.resolvable());
264
265 _log
266 << timestamp() // 1 timestamp
267 << _sep << HistoryActionID::REMOVE.asString(true) // 2 action
268 << _sep << p->name() // 3 name
269 << _sep << p->edition() // 4 evr
270 << _sep << p->arch(); // 5 arch
271
272 // ApplLow is what the solver selected on behalf of the user.
273 if ( pi.status().isByUser() || pi.status().isByApplLow() )
274 _log << _sep << userAtHostname(); // 6 requested by
275 else if (pi.status().isByApplHigh())
276 _log << _sep << pidAndAppname();
277 else
278 _log << _sep;
279
280 _log
281 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 7 userdata
282 << endl;
283 }
284
286
287 void HistoryLog::addRepository(const RepoInfo & repo)
288 {
289 _log
290 << timestamp() // 1 timestamp
291 << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action
292 << _sep << str::escape(repo.alias(), _sep) // 3 alias
293 << _sep << str::escape(repo.url().asString(), _sep) // 4 primary URL
294 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
295 << endl;
296 }
297
298
299 void HistoryLog::removeRepository(const RepoInfo & repo)
300 {
301 _log
302 << timestamp() // 1 timestamp
303 << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action
304 << _sep << str::escape(repo.alias(), _sep) // 3 alias
305 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 4 userdata
306 << endl;
307 }
308
309
310 void HistoryLog::modifyRepository(
311 const RepoInfo & oldrepo, const RepoInfo & newrepo)
312 {
313 if (oldrepo.alias() != newrepo.alias())
314 {
315 _log
316 << timestamp() // 1 timestamp
317 << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action
318 << _sep << str::escape(oldrepo.alias(), _sep) // 3 old alias
319 << _sep << str::escape(newrepo.alias(), _sep) // 4 new alias
320 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
321 << endl;
322 }
323 if ( oldrepo.url() != newrepo.url() )
324 {
325 _log
326 << timestamp() // 1 timestamp
327 << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action
328 << _sep << str::escape(oldrepo.url().asString(), _sep) // 3 old url
329 << _sep << str::escape(newrepo.url().asString(), _sep) // 4 new url
330 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
331 << endl;
332 }
333 }
334
335 void HistoryLog::patchStateChange( const PoolItem & pi, ResStatus::ValidateValue oldstate )
336 {
337 if ( ! pi.isKind<Patch>() ) return;
338 const Patch::constPtr p = asKind<Patch>(pi.resolvable());
339
340 _log
341 << timestamp() // 1 timestamp
342 << _sep << HistoryActionID::PATCH_STATE_CHANGE.asString(true) // 2 action
343 << _sep << p->name() // 3 name
344 << _sep << p->edition() // 4 evr
345 << _sep << p->arch() // 5 arch
346 << _sep << p->repoInfo().alias() // 6 repo alias
347 << _sep << p->severity() // 7 severity
348 << _sep << p->category() // 8 category
349 << _sep << ResStatus::validateValueAsString( oldstate ) // 9 old state
350 << _sep << pi.status().validateValueAsString() // 10 new state
351 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 11 userdata
352 << endl;
353 }
354
356
357 } // namespace zypp
Date.h
HistoryLogData.h
HISTORY_LOG_DATE_FORMAT
#define HISTORY_LOG_DATE_FORMAT
Definition: HistoryLogData.h:26
HistoryLog.h
IOStream.h
Logger.h
MIL
#define MIL
Definition: Logger.h:91
ERR
#define ERR
Definition: Logger.h:93
Package.h
PathInfo.h
PoolItem.h
RepoInfo.h
String.h
ZConfig.h
zypp::Date::form
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
Definition: Date.h:112
zypp::Date::now
static Date now()
Return the current time.
Definition: Date.h:78
zypp::HistoryLog::~HistoryLog
~HistoryLog()
Definition: HistoryLog.cc:158
zypp::HistoryLog::HistoryLog
HistoryLog(const HistoryLog &)
zypp::HistoryLog::stampCommand
void stampCommand()
Log info about the current process.
Definition: HistoryLog.cc:220
zypp::HistoryLog::setRoot
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
Definition: HistoryLog.cc:163
zypp::HistoryLog::modifyRepository
void modifyRepository(const RepoInfo &oldrepo, const RepoInfo &newrepo)
Log certain modifications to a repository.
Definition: HistoryLog.cc:310
zypp::HistoryLog::remove
void remove(const PoolItem &pi)
Log removal of a package.
Definition: HistoryLog.cc:260
zypp::HistoryLog::addRepository
void addRepository(const RepoInfo &repo)
Log a newly added repository.
Definition: HistoryLog.cc:287
zypp::HistoryLog::removeRepository
void removeRepository(const RepoInfo &repo)
Log recently removed repository.
Definition: HistoryLog.cc:299
zypp::HistoryLog::fname
static const Pathname & fname()
Get the current log file path.
Definition: HistoryLog.cc:179
zypp::HistoryLog::install
void install(const PoolItem &pi)
Log installation (or update) of a package.
Definition: HistoryLog.cc:232
zypp::HistoryLog::patchStateChange
void patchStateChange(const PoolItem &pi, ResStatus::ValidateValue oldstate)
Log state changes in patches.
Definition: HistoryLog.cc:335
zypp::HistoryLog::comment
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Definition: HistoryLog.cc:188
zypp::Package
Package interface.
Definition: Package.h:33
zypp::Package::constPtr
TraitsType::constPtrType constPtr
Definition: Package.h:38
zypp::Patch
Class representing a patch.
Definition: Patch.h:38
zypp::Patch::constPtr
TraitsType::constPtrType constPtr
Definition: Patch.h:43
zypp::PoolItem
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:51
zypp::PoolItem::resolvable
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
Definition: PoolItem.cc:218
zypp::PoolItem::status
ResStatus & status() const
Returns the current status.
Definition: PoolItem.cc:204
zypp::RepoInfo
What is known about a repository.
Definition: RepoInfo.h:72
zypp::RepoInfo::url
Url url() const
Pars pro toto: The first repository url.
Definition: RepoInfo.h:131
zypp::ResStatus::isByApplLow
bool isByApplLow() const
Definition: ResStatus.h:293
zypp::ResStatus::isByApplHigh
bool isByApplHigh() const
Definition: ResStatus.h:296
zypp::ResStatus::ValidateValue
ValidateValue
Definition: ResStatus.h:94
zypp::ResStatus::isByUser
bool isByUser() const
Definition: ResStatus.h:299
zypp::ResStatus::validateValueAsString
std::string validateValueAsString() const
Definition: ResStatus.h:228
zypp::Url::asString
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:492
zypp::ZConfig::historyLogFile
Pathname historyLogFile() const
Path where ZYpp install history is logged.
Definition: ZConfig.cc:1174
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
zypp::filesystem::Pathname
Pathname.
Definition: Pathname.h:45
zypp::filesystem::Pathname::absolute
bool absolute() const
Test for an absolute path.
Definition: Pathname.h:116
zypp::repo::RepoInfoBase::alias
std::string alias() const
unique identifier for this source.
Definition: RepoInfoBase.cc:111
zypp::filesystem::readlink
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
Definition: PathInfo.cc:886
zypp::filesystem::assert_dir
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
zypp::str::numstring
std::string numstring(char n, int w=0)
Definition: String.h:286
zypp::str::escape
std::string escape(const C_Str &str_r, const char sep_r)
Escape desired character c using a backslash.
Definition: String.cc:371
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
zypp::HistoryActionID::REPO_REMOVE
static const HistoryActionID REPO_REMOVE
Definition: HistoryLogData.h:44
zypp::HistoryActionID::PATCH_STATE_CHANGE
static const HistoryActionID PATCH_STATE_CHANGE
Definition: HistoryLogData.h:48
zypp::HistoryActionID::asString
const std::string & asString(bool pad=false) const
Definition: HistoryLogData.cc:76
zypp::HistoryActionID::REMOVE
static const HistoryActionID REMOVE
Definition: HistoryLogData.h:42
zypp::HistoryActionID::STAMP_COMMAND
static const HistoryActionID STAMP_COMMAND
Definition: HistoryLogData.h:47
zypp::HistoryActionID::REPO_ADD
static const HistoryActionID REPO_ADD
Definition: HistoryLogData.h:43
zypp::HistoryActionID::REPO_CHANGE_ALIAS
static const HistoryActionID REPO_CHANGE_ALIAS
Definition: HistoryLogData.h:45
zypp::HistoryActionID::REPO_CHANGE_URL
static const HistoryActionID REPO_CHANGE_URL
Definition: HistoryLogData.h:46
zypp::HistoryActionID::INSTALL
static const HistoryActionID INSTALL
Definition: HistoryLogData.h:41
zypp::sat::SolvableType::isKind
bool isKind(const ResKind &kind_r) const
Definition: SolvableType.h:64