Imported Upstream version 16.6.1
[platform/upstream/libzypp.git] / zypp / media / MediaManager.cc
index 611db5c..b753b51 100644 (file)
@@ -9,22 +9,22 @@
 /** \file zypp/media/MediaManager.cc
  *
 */
-#include <zypp/media/MediaException.h>
-#include <zypp/media/MediaManager.h>
-#include <zypp/media/MediaHandler.h>
-#include <zypp/media/Mount.h>
-#include <zypp/thread/Mutex.h>
-#include <zypp/thread/MutexLock.h>
-
-#include <zypp/base/String.h>
-#include <zypp/base/Logger.h>
-#include <zypp/Pathname.h>
-#include <zypp/PathInfo.h>
-
 #include <map>
 #include <list>
 #include <iostream>
+#include <typeinfo>
+
+#include "zypp/media/MediaException.h"
+#include "zypp/media/MediaManager.h"
+#include "zypp/media/MediaHandler.h"
+#include "zypp/media/Mount.h"
+#include "zypp/thread/Mutex.h"
+#include "zypp/thread/MutexLock.h"
 
+#include "zypp/base/String.h"
+#include "zypp/base/Logger.h"
+#include "zypp/Pathname.h"
+#include "zypp/PathInfo.h"
 
 //////////////////////////////////////////////////////////////////////
 namespace zypp
@@ -82,30 +82,21 @@ namespace zypp
           }
         }
 
-        inline void
-        checkDesired(MediaAccessId id)
+        inline void checkDesired( MediaAccessId id )
         {
-          checkAttached(id);
+          checkAttached( id );
 
-          if( !desired)
+          if ( !desired )
           {
-            try {
-              desired = verifier->isDesiredMedia(handler);
-            }
-            catch(const zypp::Exception &e) {
-              ZYPP_CAUGHT(e);
-              desired = false;
-            }
+           desired = verifier->isDesiredMedia(handler);
 
-            if( !desired)
+            if( !desired )
             {
-              DBG << "checkDesired(" << id << "): not desired" << std::endl;
-              ZYPP_THROW(MediaNotDesiredException(
-                handler->url()
-              ));
+              DBG << "checkDesired(" << id << "): not desired (report by " << verifier->info() << ")" << std::endl;
+              ZYPP_THROW( MediaNotDesiredException( handler->url() ) );
             }
 
-            DBG << "checkDesired(" << id << "): desired (report)" << std::endl;
+            DBG << "checkDesired(" << id << "): desired (report by " << verifier->info() << ")" << std::endl;
           } else {
             DBG << "checkDesired(" << id << "): desired (cached)" << std::endl;
           }
@@ -120,20 +111,35 @@ namespace zypp
       // -------------------------------------------------------------
       typedef std::map<MediaAccessId, ManagedMedia> ManagedMediaMap;
 
-
       ////////////////////////////////////////////////////////////////
     } // anonymous
     //////////////////////////////////////////////////////////////////
 
 
     //////////////////////////////////////////////////////////////////
+    std::string
+    MediaVerifierBase::info() const
+    {
+      return std::string(typeid((*this)).name());
+    }
+
+
+    //////////////////////////////////////////////////////////////////
+    std::string
+    NoVerifier::info() const
+    {
+      return std::string("zypp::media::NoVerifier");
+    }
+
+
+    //////////////////////////////////////////////////////////////////
     class MediaManager_Impl
     {
     private:
       friend class MediaManager;
 
-      MediaAccessId   last_accessid;
-      ManagedMediaMap mediaMap;
+      MediaAccessId       last_accessid;
+      ManagedMediaMap     mediaMap;
 
       MediaManager_Impl()
         : last_accessid(0)
@@ -202,13 +208,19 @@ namespace zypp
       static inline time_t
       getMountTableMTime()
       {
-        return zypp::PathInfo("/etc/mtab").mtime();
+        time_t mtime = zypp::PathInfo("/etc/mtab").mtime();
+        if( mtime <= 0)
+        {
+          WAR << "Failed to retrieve modification time of '/etc/mtab'"
+              << std::endl;
+        }
+        return mtime;
       }
 
       static inline MountEntries
       getMountEntries()
       {
-        return Mount::getEntries("/etc/mtab");
+        return Mount::getEntries();
       }
 
     };
@@ -216,7 +228,7 @@ namespace zypp
 
     //////////////////////////////////////////////////////////////////
     // STATIC
-    zypp::RW_pointer<MediaManager_Impl> MediaManager::m_impl(NULL);
+    zypp::RW_pointer<MediaManager_Impl> MediaManager::m_impl;
 
 
     //////////////////////////////////////////////////////////////////
@@ -326,14 +338,6 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
-    // STATIC
-    bool
-    MediaManager::downloads(const Url &url)
-    {
-      return MediaAccess::downloads( url);
-    }
-
-    // ---------------------------------------------------------------
     Url
     MediaManager::url(MediaAccessId accessId) const
     {
@@ -358,6 +362,9 @@ namespace zypp
 
       ref.desired = false;
       MediaVerifierRef(verifier).swap(ref.verifier);
+
+      DBG << "MediaVerifier change: id=" << accessId << ", verifier="
+          << verifier->info() << std::endl;
     }
 
     // ---------------------------------------------------------------
@@ -371,6 +378,9 @@ namespace zypp
       MediaVerifierRef verifier( new NoVerifier());
       ref.desired  = false;
       ref.verifier.swap(verifier);
+
+      DBG << "MediaVerifier change: id=" << accessId << ", verifier="
+          << verifier->info() << std::endl;
     }
 
     // ---------------------------------------------------------------
@@ -383,28 +393,88 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
-    void
-    MediaManager::attach(MediaAccessId accessId, bool next)
+    void MediaManager::attach(MediaAccessId accessId)
     {
       MutexLock glock(g_Mutex);
 
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       DBG << "attach(id=" << accessId << ")" << std::endl;
-      return ref.handler->attach(next);
+
+      // try first mountable/mounted device
+      ref.handler->attach(false);
+      try
+      {
+        ref.checkDesired(accessId);
+        return;
+      }
+      catch (const MediaException & ex)
+      {
+        ZYPP_CAUGHT(ex);
+
+        if (!ref.handler->hasMoreDevices())
+          ZYPP_RETHROW(ex);
+
+        if (ref.handler->isAttached())
+          ref.handler->release();
+      }
+
+      MIL << "checkDesired(" << accessId << ") of first device failed,"
+        " going to try others with attach(true)" << std::endl;
+
+      while (ref.handler->hasMoreDevices())
+      {
+        try
+        {
+          // try to attach next device
+          ref.handler->attach(true);
+          ref.checkDesired(accessId);
+          return;
+        }
+        catch (const MediaNotDesiredException & ex)
+        {
+          ZYPP_CAUGHT(ex);
+
+          if (!ref.handler->hasMoreDevices())
+          {
+            MIL << "No desired media found after trying all detected devices." << std::endl;
+            ZYPP_RETHROW(ex);
+          }
+
+          AttachedMedia media(ref.handler->attachedMedia());
+          DBG << "Skipping " << media.mediaSource->asString() << ": not desired media." << std::endl;
+
+          ref.handler->release();
+        }
+        catch (const MediaException & ex)
+        {
+          ZYPP_CAUGHT(ex);
+
+          if (!ref.handler->hasMoreDevices())
+            ZYPP_RETHROW(ex);
+
+          AttachedMedia media(ref.handler->attachedMedia());
+          DBG << "Skipping " << media.mediaSource->asString() << " because of exception thrown by attach(true)" << std::endl;
+
+          if (ref.handler->isAttached()) ref.handler->release();
+        }
+      }
     }
 
     // ---------------------------------------------------------------
     void
-    MediaManager::release(MediaAccessId accessId, bool eject)
+    MediaManager::release(MediaAccessId accessId, const std::string & ejectDev)
     {
       MutexLock glock(g_Mutex);
 
       ManagedMedia &ref( m_impl->findMM(accessId));
 
-      DBG << "release(id=" << accessId
-          << (eject ? ", eject)" : ")") << std::endl;
-      if( eject)
+      DBG << "release(id=" << accessId;
+      if (!ejectDev.empty())
+        DBG << ", " << ejectDev;
+      DBG << ")" << std::endl;
+
+      if(!ejectDev.empty())
       {
         //
         // release MediaISO handlers, that are using the one
@@ -422,7 +492,7 @@ namespace zypp
               DBG << "Forcing release of handler depending on access id "
                   << accessId << std::endl;
               m->second.desired  = false;
-              m->second.handler->release(!eject);
+              m->second.handler->release();
             }
             catch(const MediaException &e)
             {
@@ -432,7 +502,44 @@ namespace zypp
         }
       }
       ref.desired  = false;
-      ref.handler->release(eject);
+      ref.handler->release(ejectDev);
+    }
+
+    // ---------------------------------------------------------------
+    void
+    MediaManager::releaseAll()
+    {
+      MutexLock glock(g_Mutex);
+
+      MIL << "Releasing all attached media" << std::endl;
+
+      ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
+      for( ; m != m_impl->mediaMap.end(); ++m)
+      {
+        if( m->second.handler->dependsOnParent())
+          continue;
+
+        try
+        {
+          if(m->second.handler->isAttached())
+          {
+            DBG << "Releasing media id " << m->first << std::endl;
+            m->second.desired  = false;
+            m->second.handler->release();
+          }
+          else
+          {
+            DBG << "Media id " << m->first << " not attached " << std::endl;
+          }
+        }
+        catch(const MediaException & e)
+        {
+          ZYPP_CAUGHT(e);
+          ERR << "Failed to release media id " << m->first << std::endl;
+        }
+      }
+
+      MIL << "Exit" << std::endl;
     }
 
     // ---------------------------------------------------------------
@@ -489,6 +596,10 @@ namespace zypp
           ref.desired = false;
         }
       }
+      DBG << "isDesiredMedia(" << accessId << "): "
+          << (ref.desired ? "" : "not ")
+          << "desired (report by "
+          << ref.verifier->info() << ")" << std::endl;
       return ref.desired;
     }
 
@@ -516,10 +627,21 @@ namespace zypp
           desired = false;
         }
       }
+      DBG << "isDesiredMedia(" << accessId << "): "
+          << (desired ? "" : "not ")
+          << "desired (report by "
+          << v->info() << ")" << std::endl;
       return desired;
     }
 
     // ---------------------------------------------------------------
+    bool
+    MediaManager::isChangeable(MediaAccessId accessId)
+    {
+      return url(accessId).getScheme() == "cd" || url(accessId).getScheme() == "dvd";
+    }
+
+    // ---------------------------------------------------------------
     Pathname
     MediaManager::localRoot(MediaAccessId accessId) const
     {
@@ -549,9 +671,21 @@ namespace zypp
     // ---------------------------------------------------------------
     void
     MediaManager::provideFile(MediaAccessId   accessId,
-                              const Pathname &filename,
-                              bool            cached,
-                              bool            checkonly) const
+                              const Pathname &filename ) const
+    {
+      MutexLock glock(g_Mutex);
+
+      ManagedMedia &ref( m_impl->findMM(accessId));
+
+      ref.checkDesired(accessId);
+
+      ref.handler->provideFile(filename);
+    }
+
+    // ---------------------------------------------------------------
+    void
+    MediaManager::setDeltafile(MediaAccessId   accessId,
+                              const Pathname &filename ) const
     {
       MutexLock glock(g_Mutex);
 
@@ -559,7 +693,7 @@ namespace zypp
 
       ref.checkDesired(accessId);
 
-      ref.handler->provideFile(filename, cached, checkonly);
+      ref.handler->setDeltafile(filename);
     }
 
     // ---------------------------------------------------------------
@@ -668,6 +802,30 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
+    bool
+    MediaManager::doesFileExist(MediaAccessId  accessId, const Pathname & filename ) const
+    {
+      MutexLock glock(g_Mutex);
+      ManagedMedia &ref( m_impl->findMM(accessId));
+
+      // FIXME: ref.checkDesired(accessId); ???
+      ref.checkAttached(accessId);
+
+      return ref.handler->doesFileExist(filename);
+    }
+
+    // ---------------------------------------------------------------
+    void
+    MediaManager::getDetectedDevices(MediaAccessId accessId,
+                                     std::vector<std::string> & devices,
+                                     unsigned int & index) const
+    {
+      MutexLock glock(g_Mutex);
+      ManagedMedia &ref( m_impl->findMM(accessId));
+      return ref.handler->getDetectedDevices(devices, index);
+    }
+
+    // ---------------------------------------------------------------
     // STATIC
     time_t
     MediaManager::getMountTableMTime()
@@ -688,7 +846,8 @@ namespace zypp
 
     // ---------------------------------------------------------------
     bool
-    MediaManager::isUseableAttachPoint(const Pathname &path) const
+    MediaManager::isUseableAttachPoint(const Pathname &path,
+                                       bool            mtab) const
     {
       if( path.empty() || path == "/" || !PathInfo(path).isDir())
         return false;
@@ -724,6 +883,9 @@ namespace zypp
         }
       }
 
+      if( !mtab)
+        return true;
+
       //
       // check against system mount entries
       //
@@ -749,6 +911,7 @@ namespace zypp
           return false;
         }
       }
+
       return true;
     }
 
@@ -803,7 +966,7 @@ namespace zypp
         AttachedMedia ret = m->second.handler->attachedMedia();
         if( ret.mediaSource && ret.mediaSource->equals( *media))
         {
-          m->second.handler->release(false);
+          m->second.handler->release();
           m->second.desired  = false;
         }
       }