14 #include <unordered_set> 33 #undef ZYPP_BASE_LOGGER_LOGGROUP 34 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::misc" 53 typedef std::pair<std::string,std::unordered_set<std::string>> CacheEntry;
61 struct FilterRunsInContainer
76 Type in_our_root(
const Pathname &path )
const {
78 const PathInfo procInfoStat( path );
81 if ( procInfoStat.error() )
return IGNORE;
84 if ( procInfoStat.nlink() == 0 )
89 if ( linkTarget.empty() )
return IGNORE;
92 const PathInfo linkStat( linkTarget );
95 if ( !linkStat.isExist() )
99 if ( linkStat.ino() != procInfoStat.ino())
103 if ( linkStat.dev() != procInfoStat.dev() )
115 bool operator()(
const pid_t pid )
const {
118 const Pathname pidDir = Pathname(
"/proc") /
asString(pid);
119 const Pathname exeFile = pidDir /
"exe";
121 auto res = in_our_root( exeFile );
123 return res == CONTAINER;
129 std::unordered_set<std::string> tested;
132 filesystem::dirForEach( pidDir /
"map_files", [
this, &tested, &res ](
const Pathname & dir_r,
const char *
const & name_r ){
135 constexpr
bool contloop =
true;
136 constexpr
bool stoploop =
false;
138 const Pathname entryName = dir_r / name_r;
142 if ( linkTarget.empty() || !tested.insert( linkTarget.asString() ).second )
return contloop;
145 const auto mappedFileType = in_our_root( entryName );
148 if ( mappedFileType > IGNORE ) {
149 res = mappedFileType;
159 return res == CONTAINER;
162 FilterRunsInContainer() {}
173 using target::rpm::librpmDb;
178 : _wasBlocked( librpmDb::isBlocked() )
179 {
if ( _wasBlocked ) librpmDb::unblockAccess(); }
181 {
if ( _wasBlocked ) librpmDb::blockAccess(); }
186 librpmDb::db_const_iterator it;
187 return( it.findPackage(
"lsof" ) && it->tag_edition() < Edition(
"4.90") && !it->tag_provides().count( Capability(
"backported-option-Ki") ) );
198 bool addDataIf(
const CacheEntry & cache_r, std::vector<std::string> *debMap =
nullptr );
199 void addCacheIf( CacheEntry & cache_r,
const std::string & line_r, std::vector<std::string> *debMap =
nullptr );
204 std::vector<CheckAccessDeleted::ProcInfo>
_data;
224 const auto & filelist( cache_r.second );
226 if ( filelist.empty() )
232 pinfo.
files.insert( pinfo.files.begin(), filelist.begin(), filelist.end() );
234 const std::string & pline( cache_r.first );
235 std::string commandname;
236 std::ostringstream pLineStr;
237 for_( ch, pline.begin(), pline.end() )
242 pinfo.pid = &*(ch+1);
244 pLineStr <<&*(ch)<<
'\0';
247 pinfo.ppid = &*(ch+1);
249 pLineStr <<&*(ch)<<
'\0';
252 pinfo.puid = &*(ch+1);
254 pLineStr <<&*(ch)<<
'\0';
257 pinfo.login = &*(ch+1);
259 pLineStr <<&*(ch)<<
'\0';
262 if ( pinfo.command.empty() ) {
263 commandname = &*(ch+1);
265 if (!_fromLsofFileMode)
267 if ( pinfo.command.empty() )
268 pinfo.command = std::move(commandname);
270 pLineStr <<
'c'<<pinfo.command<<
'\0';
274 if ( *ch ==
'\n' )
break;
275 do { ++ch; }
while ( *ch !=
'\0' );
281 debMap->front() = pLineStr.str();
300 for_( ch, line_r.c_str(), ch+line_r.size() )
305 if ( *(ch+1) !=
'0' )
318 if ( *ch ==
'\n' )
break;
319 do { ++ch; }
while ( *ch !=
'\0' );
322 if ( !t || !f || !n )
325 if ( !( ( *t ==
'R' && *(t+1) ==
'E' && *(t+2) ==
'G' && *(t+3) ==
'\0' )
326 || ( *t ==
'D' && *(t+1) ==
'E' && *(t+2) ==
'L' && *(t+3) ==
'\0' ) ) )
329 if ( !( ( *f ==
'm' && *(f+1) ==
'e' && *(f+2) ==
'm' && *(f+3) ==
'\0' )
330 || ( *f ==
't' && *(f+1) ==
'x' && *(f+2) ==
't' && *(f+3) ==
'\0' )
331 || ( *f ==
'D' && *(f+1) ==
'E' && *(f+2) ==
'L' && *(f+3) ==
'\0' )
332 || ( *f ==
'l' && *(f+1) ==
't' && *(f+2) ==
'x' && *(f+3) ==
'\0' ) ) )
344 if ( *f ==
'm' || *f ==
'D' )
346 static const char * black[] = {
361 if ( debMap && cache_r.second.find(n) == cache_r.second.end() ) {
362 debMap->push_back(line_r);
364 cache_r.second.insert( n );
370 if ( doCheck_r )
check();
378 FILE *inFile = fopen( lsofOutput_r.
c_str(),
"r" );
393 std::map<pid_t,CacheEntry> cachemap;
398 FilterRunsInContainer runsInLXC;
399 for( std::string line = source.
receiveLine( 30 * 1000 ); ! line.empty(); line = source.
receiveLine( 30 * 1000 ) )
402 if ( line[0] ==
'p' )
406 if ( debugEnabled ) {
408 if ( pidMad.empty() )
409 debugMap[cachepid].push_back( line );
413 cachemap[cachepid].first.swap( line );
421 addCacheIf( cachemap[cachepid], line, debugEnabled ? &dbgMap :
nullptr);
429 static const char* argv[] = {
"lsof",
"-n",
"-FpcuLRftkn0",
"-K",
"i", NULL };
437 std::map<pid_t,CacheEntry> cachemap;
447 int ret = prog.
close();
464 std::ofstream debugFileOut;
465 bool debugEnabled =
false;
466 if ( !_debugFile.empty() ) {
467 debugFileOut.open( _debugFile.c_str() );
468 debugEnabled = debugFileOut.is_open();
470 if ( !debugEnabled ) {
471 ERR<<
"Unable to open debug file: "<<_debugFile<<endl;
476 for (
const auto &cached : in )
479 addDataIf( cached.second);
481 std::vector<std::string> *mapPtr =
nullptr;
483 auto dbgInfo = debugMap.find(cached.first);
484 if ( dbgInfo != debugMap.end() )
485 mapPtr = &(dbgInfo->second);
487 if( !addDataIf( cached.second, mapPtr ) )
490 for (
const std::string &dbgLine: dbgInfo->second ) {
491 debugFileOut.write( dbgLine.c_str(), dbgLine.length() );
532 static const str::regex rx(
"[0-9]+:name=systemd:/system.slice/(.*/)?(.*).service$" );
536 [&](
int num_r, std::string line_r )->
bool 567 if ( obj.
pid.empty() )
568 return str <<
"<NoProc>";
bool addDataIf(const CacheEntry &cache_r, std::vector< std::string > *debMap=nullptr)
Add cache to data if the process is accessing deleted files.
Data about one running process accessing deleted files.
Bidirectional stream to external data.
bool contains(const C_Str &str_r, const C_Str &val_r)
Locate substring case sensitive.
std::map< pid_t, CacheEntry > filterInput(externalprogram::ExternalDataSource &source)
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
std::map< pid_t, std::vector< std::string > > debugMap
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
void setDebugOutputFile(const Pathname &filename_r)
Writes all filtered process entries that make it into the final set into a file specified by filename...
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\ ", const std::string &sep="\ ", const std::string &sfx="\, const std::string &extro="}")
Print range defined by iterators (multiline style).
const char * c_str() const
String representation.
std::string command
process command name
String related utilities and Regular expression matching.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
std::string receiveLine()
Read one line from the input stream.
std::ostream & operator<<(std::ostream &str, const CheckAccessDeleted &obj)
void remember(const Exception &old_r)
Store an other Exception as history.
CheckAccessDeleted::Impl * clone() const
bool empty() const
Test for an empty path.
size_type check(bool verbose_r=false)
Check for running processes which access deleted executables or libraries.
RWCOW_pointer< Impl > _pimpl
const_iterator begin() const
int simpleParseFile(std::istream &str_r, ParseFlags flags_r, function< bool(int, std::string)> consume_r)
Simple lineparser optionally trimming and skipping comments.
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
std::string pid
process ID
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::list< PublicKeyData > _data
std::vector< CheckAccessDeleted::ProcInfo > _data
TInt strtonum(const C_Str &str)
Parsing numbers from string.
std::string puid
process user ID
const_iterator end() const
std::string numstring(char n, int w=0)
CheckAccessDeleted::size_type createProcInfo(const std::map< pid_t, CacheEntry > &in)
int close()
Wait for the progamm to complete.
#define arrayBegin(A)
Simple C-array iterator.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Regular expression match result.
Base class for Exception.
Check for running processes which access deleted executables or libraries.
CheckAccessDeleted(bool doCheck_r=true)
Default ctor performs check immediately.
std::ostream & dumpRangeLine(std::ostream &str, TIterator begin, TIterator end)
Print range defined by iterators (single line style).
int dirForEach(const Pathname &dir_r, function< bool(const Pathname &, const char *const)> fnc_r)
Invoke callback function fnc_r for each entry in directory dir_r.
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Easy-to use interface to the ZYPP dependency resolver.
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
std::vector< ProcInfo >::const_iterator const_iterator
std::string login
process login name
void addCacheIf(CacheEntry &cache_r, const std::string &line_r, std::vector< std::string > *debMap=nullptr)
Add file to cache if it refers to a deleted executable or library file:
std::vector< std::string > files
list of deleted executables or libraries accessed
std::string ppid
parent process ID
std::string service() const
Guess if command was started by a systemd service script.
static std::string findService(pid_t pid_r)
Guess if pid was started by a systemd service script.