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';
263 commandname = &*(ch+1);
265 if (!_fromLsofFileMode)
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>";