#include "zypp/PathInfo.h"
#include "zypp/ExternalProgram.h"
-#include "zypp/target/rpm/librpmDb.h"
+#include "zypp/base/Regex.h"
+#include "zypp/base/IOStream.h"
+#include "zypp/base/InputStream.h"
#include "zypp/misc/CheckAccessDeleted.h"
{ /////////////////////////////////////////////////////////////////
//
// lsof output lines are a sequence of NUL terminated fields,
- // where the 1st char determines the fiels type.
+ // where the 1st char determines the fields type.
//
// (pcuL) pid command userid loginname
// (ftkn).filedescriptor type linkcount filename
pinfo.files.insert( pinfo.files.begin(), filelist.begin(), filelist.end() );
const std::string & pline( cache_r.first );
+ std::string commandname; // pinfo.command if still needed...
for_( ch, pline.begin(), pline.end() )
{
switch ( *ch )
pinfo.login = &*(ch+1);
break;
case 'c':
- pinfo.command = &*(ch+1);
- break;
+ if ( pinfo.command.empty() )
+ commandname = &*(ch+1);
+ break;
}
if ( *ch == '\n' ) break; // end of data
do { ++ch; } while ( *ch != '\0' ); // skip to next field
}
- if ( pinfo.command.size() == 15 )
+ if ( pinfo.command.empty() )
{
- // the command name might be truncated, so we check against /proc/<pid>/exe
- Pathname command( filesystem::readlink( Pathname("/proc")/pinfo.pid/"exe" ) );
- if ( ! command.empty() )
- pinfo.command = command.basename();
+ // the lsof command name might be truncated, so we prefer /proc/<pid>/exe
+ pinfo.command = filesystem::readlink( Pathname("/proc")/pinfo.pid/"exe" ).basename();
+ if ( pinfo.command.empty() )
+ pinfo.command = std::move(commandname);
}
- //MIL << " Take " << pinfo << endl;
}
/// \class FilterRunsInLXC
/// \brief Functor guessing whether \a PID is running in a container.
///
- /// Assumme using different \c pid namespace than \c self.
+ /// Asumme a using different \c pid/mnt namespace than \c self.
/////////////////////////////////////////////////////////////////
struct FilterRunsInLXC
{
bool operator()( pid_t pid_r ) const
- { return( nsIno( pid_r, "pid" ) != pidNS ); }
+ { return( nsIno( pid_r, "pid" ) != pidNS || nsIno( pid_r, "mnt" ) != mntNS ); }
FilterRunsInLXC()
: pidNS( nsIno( "self", "pid" ) )
+ , mntNS( nsIno( "self", "mnt" ) )
{}
static inline ino_t nsIno( const std::string & pid_r, const std::string & ns_r )
{ return nsIno( asString(pid_r), ns_r ); }
ino_t pidNS;
+ ino_t mntNS;
};
- /** bsc#1099847: Check for lsof version < 4.90 which does not support '-K i'
- * Just a quick check to allow code15 libzypp runnig in a code12 environment.
- * bsc#1036304: '-K i' was backported to older lsof versions, indicated by
- * lsof providing 'backported-option-Ki'.
- */
- bool lsofNoOptKi()
- {
- using target::rpm::librpmDb;
- // RpmDb access is blocked while the Target is not initialized.
- // Launching the Target just for this query would be an overkill.
- struct TmpUnblock {
- TmpUnblock()
- : _wasBlocked( librpmDb::isBlocked() )
- { if ( _wasBlocked ) librpmDb::unblockAccess(); }
- ~TmpUnblock()
- { if ( _wasBlocked ) librpmDb::blockAccess(); }
- private:
- bool _wasBlocked;
- } tmpUnblock;
-
- librpmDb::db_const_iterator it;
- return( it.findPackage( "lsof" ) && it->tag_edition() < Edition("4.90") && !it->tag_provides().count( Capability("backported-option-Ki") ) );
- }
-
/////////////////////////////////////////////////////////////////
} // namespace
///////////////////////////////////////////////////////////////////
{
_data.clear();
- static const char* argv[] = { "lsof", "-n", "-FpcuLRftkn0", "-K", "i", NULL };
- if ( lsofNoOptKi() )
- argv[3] = NULL;
+ static const char* argv[] =
+ {
+ "lsof", "-n", "-FpcuLRftkn0", NULL
+ };
ExternalProgram prog( argv, ExternalProgram::Discard_Stderr );
// cachemap: PID => (deleted files)
return _data.size();
}
- std::string CheckAccessDeleted::findService( const Pathname & command_r )
+ std::string CheckAccessDeleted::findService( pid_t pid_r )
{
ProcInfo p;
- p.command = command_r.basename();
+ p.pid = str::numstring( pid_r );
return p.service();
}
- std::string CheckAccessDeleted::findService( const char * command_r )
- { return findService( Pathname( command_r ) ); }
-
- std::string CheckAccessDeleted::findService( const std::string & command_r )
- { return findService( Pathname( command_r ) ); }
-
- std::string CheckAccessDeleted::findService( pid_t pid_r )
- { return findService( filesystem::readlink( Pathname("/proc")/str::numstring(pid_r)/"exe" ) ); }
///////////////////////////////////////////////////////////////////
namespace
std::string CheckAccessDeleted::ProcInfo::service() const
{
- if ( command.empty() )
- return std::string();
- // TODO: This needs to be implemented smarter... be carefull
- // as we don't know whether the target is up.
-
- static const Pathname initD( "/etc/init.d" );
- { // init.d script with same name
- PathInfo pi( initD/command );
- if ( pi.isFile() && pi.isX() )
- return command;
- }
- { // init.d script with name + 'd'
- std::string alt( command+"d" );
- PathInfo pi( initD/alt );
- if ( pi.isFile() && pi.isX() )
- return alt;
- }
- if ( *command.rbegin() == 'd' )
- { // init.d script with name - trailing'd'
- std::string alt( command );
- alt.erase( alt.size()-1 );
- PathInfo pi( initD/alt );
- WAR <<pi << endl;
- if ( pi.isFile() && pi.isX() )
- return alt;
- }
- return std::string();
+ static const str::regex rx( "[0-9]+:name=systemd:/system.slice/(.*/)?(.*).service$" );
+ str::smatch what;
+ std::string ret;
+ iostr::simpleParseFile( InputStream( Pathname("/proc")/pid/"cgroup" ),
+ [&]( int num_r, std::string line_r )->bool
+ {
+ if ( str::regex_match( line_r, what, rx ) )
+ {
+ ret = what[2];
+ return false; // stop after match
+ }
+ return true;
+ } );
+ return ret;
}
/******************************************************************