Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / misc / CheckAccessDeleted.cc
index 6d63abf..8f666c4 100644 (file)
@@ -18,7 +18,9 @@
 
 #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"
 
@@ -36,7 +38,7 @@ namespace zypp
   { /////////////////////////////////////////////////////////////////
     //
     // 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
@@ -63,6 +65,7 @@ namespace zypp
       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 )
@@ -80,21 +83,21 @@ namespace zypp
             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;
     }
 
 
@@ -174,15 +177,16 @@ namespace zypp
     /// \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 )
@@ -192,32 +196,9 @@ namespace zypp
       { 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
   ///////////////////////////////////////////////////////////////////
@@ -226,9 +207,10 @@ namespace zypp
   {
     _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)
@@ -274,20 +256,12 @@ namespace zypp
     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
@@ -298,33 +272,20 @@ namespace zypp
 
   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;
   }
 
   /******************************************************************