14#include <unordered_set> 
   27#include <zypp-core/base/InputStream> 
   34#undef ZYPP_BASE_LOGGER_LOGGROUP 
   35#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::misc" 
   54    using CacheEntry = std::pair<std::string, std::unordered_set<std::string>>;
 
   62    struct FilterRunsInContainer
 
   77      Type in_our_root( 
const Pathname &path )
 const {
 
   79        const PathInfo procInfoStat( path );
 
   82        if ( procInfoStat.error() ) 
return IGNORE;
 
   85        if ( procInfoStat.nlink() == 0 )
 
   90        if ( linkTarget.empty() ) 
return IGNORE;
 
   94        if ( linkTarget.relative() ) 
return IGNORE;
 
  102        const PathInfo linkStat( linkTarget );
 
  105        if ( !linkStat.isExist() )
 
  109        if ( linkStat.ino() != procInfoStat.ino())
 
  113        if ( linkStat.dev() != procInfoStat.dev() )
 
  128        const Pathname pidDir  = Pathname(
"/proc") / 
asString(pid);
 
  129        const Pathname exeFile = pidDir / 
"exe";
 
  131        auto res = in_our_root( exeFile );
 
  133          return res == CONTAINER;
 
  139        std::unordered_set<std::string> tested;
 
  142        filesystem::dirForEach( pidDir / 
"map_files", [ 
this, &tested, &res ]( 
const Pathname & dir_r, 
const char *
const & name_r  ){
 
  145          constexpr bool contloop = 
true;
 
  146          constexpr bool stoploop = 
false;
 
  148          const Pathname entryName = dir_r / name_r;
 
  152          if ( linkTarget.empty() || !tested.insert( linkTarget.asString() ).second ) 
return contloop;
 
  155          const auto mappedFileType = in_our_root( entryName );
 
  158          if ( mappedFileType > IGNORE ) {
 
  159            res = mappedFileType;
 
  169        return res == CONTAINER;
 
  172      FilterRunsInContainer() {}
 
  183      using target::rpm::librpmDb;
 
  184      librpmDb::db_const_iterator it( 
"/" );
 
  185      return( it.findPackage( 
"lsof" ) && it->tag_edition() < Edition(
"4.90") && !it->tag_provides().count( Capability(
"backported-option-Ki") ) );
 
  196    bool addDataIf( 
const CacheEntry & cache_r, std::vector<std::string> *debMap = 
nullptr );
 
  197    void addCacheIf( CacheEntry & cache_r, 
const std::string & line_r, std::vector<std::string> *debMap = 
nullptr );
 
  202    std::vector<CheckAccessDeleted::ProcInfo> 
_data;
 
 
  222    const auto & filelist( cache_r.second );
 
  224    if ( filelist.empty() )
 
  230    pinfo.
files.insert( pinfo.
files.begin(), filelist.begin(), filelist.end() );
 
  232    const std::string & pline( cache_r.first );
 
  233    std::string commandname;    
 
  234    std::ostringstream pLineStr; 
 
  235    for_( ch, pline.begin(), pline.end() )
 
  240          pinfo.
pid = &*(ch+1);
 
  242            pLineStr <<&*(ch)<<
'\0';
 
  245          pinfo.
ppid = &*(ch+1);
 
  247            pLineStr <<&*(ch)<<
'\0';
 
  250          pinfo.
puid = &*(ch+1);
 
  252            pLineStr <<&*(ch)<<
'\0';
 
  255          pinfo.
login = &*(ch+1);
 
  257            pLineStr <<&*(ch)<<
'\0';
 
  261            commandname = &*(ch+1);
 
  266              pinfo.
command = std::move(commandname);
 
  268              pLineStr <<
'c'<<pinfo.
command<<
'\0';
 
  272      if ( *ch == 
'\n' ) 
break;         
 
  273      do { ++ch; } 
while ( *ch != 
'\0' );       
 
  279      debMap->front() = pLineStr.str();
 
 
  299    static const str::regex statErr(R
"(.*\(stat: [^)]+\)$)"); 
  301    for_( ch, line_r.c_str(), ch+line_r.size() ) 
  306          if ( *(ch+1) != 
'0' ) 
 
  319      if ( *ch == 
'\n' ) 
break;         
 
  320      do { ++ch; } 
while ( *ch != 
'\0' );       
 
  323    if ( !t || !f || !n )
 
  326    if ( !(    ( *t == 
'R' && *(t+1) == 
'E' && *(t+2) == 
'G' && *(t+3) == 
'\0' )
 
  327            || ( *t == 
'D' && *(t+1) == 
'E' && *(t+2) == 
'L' && *(t+3) == 
'\0' ) ) )
 
  330    if ( !(    ( *f == 
'm' && *(f+1) == 
'e' && *(f+2) == 
'm' && *(f+3) == 
'\0' )
 
  331            || ( *f == 
't' && *(f+1) == 
'x' && *(f+2) == 
't' && *(f+3) == 
'\0' )
 
  332            || ( *f == 
'D' && *(f+1) == 
'E' && *(f+2) == 
'L' && *(f+3) == 
'\0' )
 
  333            || ( *f == 
'l' && *(f+1) == 
't' && *(f+2) == 
'x' && *(f+3) == 
'\0' ) ) )
 
  347    if ( *f == 
'm' || *f == 
'D' )       
 
  349      static const char * black[] = {
 
  365    if ( debMap && cache_r.second.find(n) == cache_r.second.end() ) {
 
  366      debMap->push_back(line_r);
 
  368    cache_r.second.insert( n );
 
 
  374    if ( doCheck_r ) 
check();
 
 
  379    _pimpl->_verbose = verbose_r;
 
  380    _pimpl->_fromLsofFileMode = 
true;
 
  382    FILE *inFile = fopen( lsofOutput_r.
c_str(), 
"r" );
 
  389    auto cache = 
_pimpl->filterInput( inSource );
 
  390    return _pimpl->createProcInfo( cache );
 
 
  397    std::map<pid_t,CacheEntry> cachemap;
 
  402    FilterRunsInContainer runsInLXC;
 
  403    MIL << 
"Silently scanning lsof output..." << endl;
 
  405    for( std::string line = source.
receiveLine( 30 * 1000 ); ! line.empty(); line = source.
receiveLine(  30 * 1000  ) )
 
  408      if ( line[0] == 
'p' )
 
  412          if ( debugEnabled ) {
 
  414            if ( pidMad.empty() )
 
  415              debugMap[cachepid].push_back( line );
 
  419          cachemap[cachepid].first.swap( line );
 
  427        addCacheIf( cachemap[cachepid], line, debugEnabled ? &dbgMap : 
nullptr);
 
 
  435    static const char* argv[] = { 
"lsof", 
"-n", 
"-FpcuLRftkn0", 
"-K", 
"i", NULL };
 
  439    _pimpl->_verbose = verbose_r;
 
  440    _pimpl->_fromLsofFileMode = 
false;
 
  443    std::map<pid_t,CacheEntry> cachemap;
 
  446      cachemap = 
_pimpl->filterInput( prog );
 
  453    int ret = prog.
close();
 
  465    return _pimpl->createProcInfo( cachemap );
 
 
  470    std::ofstream debugFileOut;
 
  471    bool debugEnabled = 
false;
 
  474      debugEnabled =  debugFileOut.is_open();
 
  476      if ( !debugEnabled ) {
 
  482    for ( 
const auto &cached : in )
 
  487        std::vector<std::string> *mapPtr = 
nullptr;
 
  489        auto dbgInfo = 
debugMap.find(cached.first);
 
  491          mapPtr = &(dbgInfo->second);
 
  493        if( !
addDataIf( cached.second, mapPtr ) )
 
  496        for ( 
const std::string &dbgLine: dbgInfo->second ) {
 
  497          debugFileOut.write( dbgLine.c_str(), dbgLine.length() );
 
 
  506    return _pimpl->_data.empty();
 
 
  511    return _pimpl->_data.size();
 
 
  516    return _pimpl->_data.begin();
 
 
  521    return _pimpl->_data.end();
 
 
  526    _pimpl->_debugFile = filename_r;
 
 
  542    static const str::regex rx( 
"(0::|[0-9]+:name=systemd:)/system.slice/(.*/)?(.*).service(/.*)?$" );
 
  546                            [&]( 
int num_r, 
const std::string& line_r )->
bool 
 
  577    if ( obj.
pid.empty() )
 
  578      return str << 
"<NoProc>";
 
 
bool operator()(const zypp::Arch &lhs, const zypp::Arch &rhs) const
Default order for std::container based Arch::compare.
CheckAccessDeleted::Impl * clone() const
CheckAccessDeleted::size_type createProcInfo(const std::map< pid_t, CacheEntry > &in)
std::map< pid_t, std::vector< std::string > > debugMap
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::map< pid_t, CacheEntry > filterInput(externalprogram::ExternalDataSource &source)
bool addDataIf(const CacheEntry &cache_r, std::vector< std::string > *debMap=nullptr)
Add cache to data if the process is accessing deleted files.
std::vector< CheckAccessDeleted::ProcInfo > _data
size_type check(bool verbose_r=false)
Check for running processes which access deleted executables or libraries.
CheckAccessDeleted(bool doCheck_r=true)
Default ctor performs check immediately.
const_iterator end() const
std::ostream & operator<<(std::ostream &str, const CheckAccessDeleted &obj)
Stream output.
const_iterator begin() const
static std::string findService(pid_t pid_r)
Guess if pid was started by a systemd service script.
std::vector< ProcInfo >::const_iterator const_iterator
void setDebugOutputFile(const Pathname &filename_r)
Writes all filtered process entries that make it into the final set into a file specified by filename...
RWCOW_pointer< Impl > _pimpl
Base class for Exception.
void remember(const Exception &old_r)
Store an other Exception as history.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
int close() override
Wait for the progamm to complete.
bool kill()
Kill the program.
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
Bidirectional stream to external data.
std::string receiveLine()
Read one line from the input stream.
const char * c_str() const
String representation.
Regular expression match result.
String related utilities and Regular expression matching.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
int simpleParseFile(std::istream &str_r, ParseFlags flags_r, function< bool(int, std::string)> consume_r)
Simple lineparser optionally trimming and skipping comments.
std::string numstring(char n, int w=0)
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
\relates regex \ingroup ZYPP_STR_REGEX    \relates regex \ingroup ZYPP_STR_REGEX
TInt strtonum(const C_Str &str)
Parsing numbers from string.
bool contains(const C_Str &str_r, const C_Str &val_r)
Locate substring case sensitive.
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & dumpRangeLine(std::ostream &str, TIterator begin, TIterator end)
Print range defined by iterators (single line style).
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\n  ", const std::string &sep="\n  ", const std::string &sfx="\n", const std::string &extro="}")
Print range defined by iterators (multiline style).
std::string asString(const Patch::Category &obj)
Data about one running process accessing deleted files.
std::string service() const
Guess if command was started by a systemd service script.
std::string pid
process ID
std::string login
process login name
std::string puid
process user ID
std::string command
process command name
std::vector< std::string > files
list of deleted executables or libraries accessed
std::string ppid
parent process ID
Exchange LineWriter for the lifetime of this object.
#define arrayBegin(A)
Simple C-array iterator.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.