- Added support to share a CD mount
authorMarius Tomaschewski <mt@suse.de>
Mon, 6 Feb 2006 01:42:39 +0000 (01:42 +0000)
committerMarius Tomaschewski <mt@suse.de>
Mon, 6 Feb 2006 01:42:39 +0000 (01:42 +0000)
zypp/media/MediaAccess.cc
zypp/media/MediaAccess.h
zypp/media/MediaCD.cc
zypp/media/MediaCD.h
zypp/media/MediaHandler.cc
zypp/media/MediaHandler.h
zypp/media/MediaManager.cc
zypp/media/MediaManager.h
zypp/media/MediaSource.h [new file with mode: 0644]

index 08f7dce..f5ebb2b 100644 (file)
@@ -55,6 +55,13 @@ MediaAccess::~MediaAccess()
   close(); // !!! make sure handler gets properly deleted.
 }
 
+AttachedMedia
+MediaAccess::attachedMedia() const
+{
+       return _handler ? _handler->attachedMedia()
+                       : AttachedMedia();
+}
+
 // open URL
 void
 MediaAccess::open (const Url& url, const Pathname & preferred_attach_point)
index d2f9775..0f01750 100644 (file)
@@ -25,6 +25,8 @@
 #include "zypp/PathInfo.h"
 
 #include "zypp/media/MediaException.h"
+#include "zypp/media/MediaSource.h"
+
 #include "zypp/Url.h"
 #include "zypp/base/Logger.h"
 
@@ -63,6 +65,9 @@ namespace zypp {
         **/
        MediaHandler * _handler;
 
+       friend class MediaManager;
+       AttachedMedia        attachedMedia() const;
+
     public:
 
        /**
index 40b790c..48aa504 100644 (file)
@@ -16,6 +16,7 @@
 #include "zypp/ExternalProgram.h"
 #include "zypp/media/Mount.h"
 #include "zypp/media/MediaCD.h"
+#include "zypp/media/MediaManager.h"
 #include "zypp/Url.h"
 
 #include <cstring> // strerror
@@ -147,16 +148,15 @@ namespace zypp {
     //
     void MediaCD::attachTo(bool next)
     {
+      DBG << "next " << next << " last " << _lastdev << endl;
+      if (next && _lastdev == -1)
+       ZYPP_THROW(MediaNotSupportedException(url()));
+
       Mount mount;
       string mountpoint = attachPoint().asString();
       bool mountsucceeded = false;
       int count = 0;
-    
-      DBG << "next " << next << " last " << _lastdev << " lastdevice " << _mounteddevice << endl;
-    
-      if (next && _lastdev == -1)
-       ZYPP_THROW(MediaNotSupportedException(url()));
-    
+
       string options = _url.getQueryParam("mountoptions");
       if (options.empty())
       {
@@ -183,7 +183,41 @@ namespace zypp {
                DBG << "skip" << endl;
                continue;
        }
-    
+       PathInfo dev_info( *it);
+       if( !dev_info.isBlk())
+       {
+               DBG << "skip " << *it << " - is not a block device" << endl;
+               continue;
+       }
+
+       MediaSourceRef media( new MediaSource(
+         "cdrom", *it, dev_info.major(), dev_info.minor()
+       ));
+
+       AttachedMedia ret( findAttachedMedia( media));
+
+       if( ret.attachPoint &&
+           ret.mediaSource &&
+          !ret.attachPoint->empty() &&
+           media->equals( *ret.mediaSource))
+       {
+               DBG << "Using a shared media "
+                   << ret.mediaSource->name
+                   << " attached on "
+                   << ret.attachPoint->path
+                   << endl;
+                removeAttachPoint();
+               setAttachPoint(ret.attachPoint);
+               _mediaSource = ret.mediaSource;
+               _lastdev = count;
+               mountsucceeded = true;
+               break;
+       }
+       // FIXME: hmm... we may also
+       // - check against hal/mtab if still mounted
+       // - if !ret, check if already mounted (e.g.
+       //   by automounter) and reuse (!temp) ?
+
        // close tray
        closeTray( *it );
     
@@ -193,9 +227,21 @@ namespace zypp {
            ; ++fsit)
        {
          try {
+           // FIXME: verify, if this mountpoint isn't already in use.
+           if( mountpoint.empty() || mountpoint == "/")
+           {
+             mountpoint = createAttachPoint().asString();
+             setAttachPoint( mountpoint, true);
+             if( mountpoint.empty())
+             {
+               ZYPP_THROW( MediaBadAttachPointException(url()));
+             }
+           }
+
            mount.mount (*it, mountpoint.c_str(), *fsit, options);
-           _mounteddevice = *it;
+
            _lastdev = count;
+           _mediaSource = media;
            mountsucceeded = true;
          }
          catch (const MediaException & excpt_r)
@@ -207,7 +253,6 @@ namespace zypp {
     
       if (!mountsucceeded)
       {
-       _mounteddevice.erase();
        _lastdev = -1;
         ZYPP_THROW(MediaMountException(_url.asString(), mountpoint, "Mounting media failed"));
       }
@@ -225,7 +270,13 @@ namespace zypp {
     //
     void MediaCD::releaseFrom( bool eject )
     {
-      if (_mounteddevice.empty())              // no device mounted
+      DBG << "Release CD ... use count = "
+          << _mediaSource.use_count()
+         << (_mediaSource.unique() ? ", unique" : ", not unique")
+         << std::endl;
+
+      // check if a device is mounted
+      if ( !_mediaSource)
       {
        if (eject)                      // eject wanted -> eject all devices
        {
@@ -239,17 +290,20 @@ namespace zypp {
        }
        ZYPP_THROW(MediaNotAttachedException(url()));
       }
-    
-      Mount mount;
-      mount.umount(attachPoint().asString());
-    
-      // eject device
-      if (eject)
+      else
+      if( _mediaSource.unique())
       {
-       openTray( _mounteddevice );
-      }
+        Mount mount;
+        mount.umount(attachPoint().asString());
     
-      _mounteddevice.erase();
+        // eject device
+        if (eject)
+        {
+         openTray( _mediaSource->name );
+        }
+      }
+
+      _mediaSource.reset();
     }
 
     ///////////////////////////////////////////////////////////////////
@@ -262,7 +316,7 @@ namespace zypp {
     //
     void MediaCD::forceEject()
     {
-      if ( _mounteddevice.empty() ) {  // no device mounted
+      if ( !_mediaSource) {    // no device mounted
        for ( DeviceList::iterator it = _devices.begin(); it != _devices.end(); ++it ) {
          if ( openTray( *it ) )
            break; // on 1st success
@@ -324,3 +378,4 @@ namespace zypp {
 
   } // namespace media
 } // namespace zypp
+// vim: set ts=8 sts=2 sw=2 ai noet:
index 87ff697..b1f8aea 100644 (file)
@@ -13,6 +13,7 @@
 #define ZYPP_MEDIA_MEDIACD_H
 
 #include "zypp/media/MediaHandler.h"
+#include "zypp/media/MediaManager.h"
 
 namespace zypp {
   namespace media {
@@ -28,18 +29,13 @@ namespace zypp {
     
       private:
     
-        unsigned long _mountflags;
-    
         typedef std::list<std::string> DeviceList;
         /** list of devices to try to mount */
         DeviceList _devices;
     
-        /** which device has been mounted */
-        std::string _mounteddevice;
-    
         /** number of last successful mounted device in list */
-        int _lastdev;
-    
+        int        _lastdev;
+
         static bool openTray( const std::string & device_r );
         static bool closeTray( const std::string & device_r );
     
index e4315ad..b68bcf9 100644 (file)
@@ -17,6 +17,7 @@
 #include "zypp/base/Logger.h"
 #include "zypp/base/String.h"
 #include "zypp/media/MediaHandler.h"
+#include "zypp/media/MediaManager.h"
 
 using namespace std;
 
@@ -26,6 +27,8 @@ using namespace std;
 namespace zypp {
   namespace media {
 
+
+
 ///////////////////////////////////////////////////////////////////
 //
 //     CLASS NAME : MediaHandler
@@ -44,71 +47,25 @@ MediaHandler::MediaHandler ( const Url &      url_r,
                             const Pathname & attach_point_r,
                             const Pathname & urlpath_below_attachpoint_r,
                             const bool       does_download_r )
-    : _attachPoint( attach_point_r )
-    , _tmp_attachPoint( false )
+    : _attachPoint( new AttachPoint())
+    , _relativeRoot( urlpath_below_attachpoint_r)
     , _does_download( does_download_r )
     , _isAttached( false )
     , _url( url_r )
 {
-  if ( _attachPoint.empty() ) {
-    ///////////////////////////////////////////////////////////////////
-    // provide a default attachpoint
-    ///////////////////////////////////////////////////////////////////
-
-    Pathname aroot;
-    PathInfo adir;
-    const char * defmounts[] = { "/var/adm/mount", "/var/tmp", /**/NULL/**/ };
-    for ( const char ** def = defmounts; *def; ++def ) {
-      adir( *def );
-      if ( adir.isDir() && adir.userMayRWX() ) {
-       aroot = adir.path();
-       break;
-      }
-    }
-    if ( aroot.empty() ) {
-      ERR << "Create attach point: Can't find a writable directory to create an attach point" << endl;
-      return;
-    }
-
-    Pathname abase( aroot + "AP_" );
-    Pathname apoint;
-
-    for ( unsigned i = 1; i < 1000; ++i ) {
-      adir( Pathname::extend( abase, str::hexstring( i ) ) );
-      if ( ! adir.isExist() && mkdir( adir.path() ) == 0 ) {
-       apoint = adir.path();
-       break;
-      }
-    }
-
-    if ( apoint.empty() ) {
-      ERR << "Unable to create an attach point below " << aroot << endl;
-      return;
-    }
-
-    // success
-    _attachPoint = apoint;
-    _tmp_attachPoint = true;
-    MIL << "Created default attach point " << _attachPoint << endl;
-
-  } else {
+  if ( !attach_point_r.empty() ) {
     ///////////////////////////////////////////////////////////////////
     // check if provided attachpoint is usable.
     ///////////////////////////////////////////////////////////////////
-    PathInfo adir( _attachPoint );
-    if ( !adir.isDir() ) {
+
+    PathInfo adir( attach_point_r );
+    // FIXME: verify if attach_point_r isn't a mountpoint of other device
+    if ( attach_point_r.asString() == "/" || !adir.isDir() ) {
       ERR << "Provided attach point is not a directory: " << adir << endl;
-      _attachPoint = Pathname();
     }
-
-  }
-
-  ///////////////////////////////////////////////////////////////////
-  // must init _localRoot after _attachPoint is determined.
-  ///////////////////////////////////////////////////////////////////
-
-  if ( !_attachPoint.empty() ) {
-    _localRoot = _attachPoint + urlpath_below_attachpoint_r;
+    else {
+      setAttachPoint( attach_point_r, false);
+    }
   }
 }
 
@@ -122,22 +79,180 @@ MediaHandler::MediaHandler ( const Url &      url_r,
 //
 MediaHandler::~MediaHandler()
 {
+  removeAttachPoint();
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+//     METHOD NAME : MediaHandler::removeAttachPoint
+//     METHOD TYPE : void
+//
+//     DESCRIPTION :
+//
+void
+MediaHandler::removeAttachPoint()
+{
   if ( _isAttached ) {
     INT << "MediaHandler deleted with media attached." << endl;
     return; // no cleanup if media still mounted!
   }
 
-  if ( _tmp_attachPoint ) {
-    int res = recursive_rmdir( _attachPoint );
+  if ( _attachPoint.unique() &&
+       _attachPoint->temp    &&
+       !_attachPoint->path.empty())
+  {
+    int res = recursive_rmdir( _attachPoint->path );
     if ( res == 0 ) {
-      MIL << "Deleted default attach point " << _attachPoint << endl;
+      MIL << "Deleted default attach point " << _attachPoint->path << endl;
     } else {
-      ERR << "Failed to Delete default attach point " << _attachPoint
+      ERR << "Failed to Delete default attach point " << _attachPoint->path
        << " errno(" << res << ")" << endl;
     }
   }
 }
 
+
+///////////////////////////////////////////////////////////////////
+//
+//
+//     METHOD NAME : MediaHandler::attachPoint
+//     METHOD TYPE : Pathname
+//
+//     DESCRIPTION :
+//
+Pathname
+MediaHandler::attachPoint() const
+{
+  return _attachPoint->path;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//
+//
+//     METHOD NAME : MediaHandler::attachPoint
+//     METHOD TYPE :
+//
+//     DESCRIPTION :
+//
+void
+MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
+{
+  _localRoot = Pathname();
+
+  _attachPoint.reset( new AttachPoint(path, temporary));
+
+  if( !_attachPoint->path.empty())
+    _localRoot = _attachPoint->path + _relativeRoot;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//
+//
+//     METHOD NAME : MediaHandler::attachPoint
+//     METHOD TYPE :
+//
+//     DESCRIPTION :
+//
+void
+MediaHandler::setAttachPoint(const AttachPointRef &ref)
+{
+  _localRoot = Pathname();
+
+  if( ref)
+    AttachPointRef(ref).swap(_attachPoint);
+  else
+    _attachPoint.reset( new AttachPoint());
+
+  if( !_attachPoint->path.empty())
+    _localRoot = _attachPoint->path + _relativeRoot;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//
+//
+//     METHOD NAME : MediaHandler::findAttachedMedia
+//     METHOD TYPE : AttachedMedia
+//
+//     DESCRIPTION :
+//
+AttachedMedia
+MediaHandler::findAttachedMedia(const MediaSourceRef &media) const
+{
+       return MediaManager().findAttachedMedia(media);
+}
+
+
+///////////////////////////////////////////////////////////////////
+//
+//
+//     METHOD NAME : MediaHandler::attach
+//     METHOD TYPE : Pathname
+//
+//     DESCRIPTION :
+//
+Pathname
+MediaHandler::createAttachPoint() const
+{
+  /////////////////////////////////////////////////////////////////
+  // provide a default (temporary) attachpoint
+  /////////////////////////////////////////////////////////////////
+  const char * defmounts[] = {
+      "/var/adm/mount", "/var/tmp", /**/NULL/**/
+  };
+
+  Pathname aroot;
+  PathInfo adir;
+  for ( const char ** def = defmounts; *def; ++def ) {
+    adir( *def );
+    if ( adir.isDir() && adir.userMayRWX() ) {
+      aroot = adir.path();
+      break;
+    }
+  }
+  if ( aroot.empty() ) {
+    ERR << "Create attach point: Can't find a writable directory to create an attach point" << std::endl;
+    return aroot;
+  }
+
+  Pathname abase( aroot + "AP_" );
+  Pathname apoint;
+  for ( unsigned i = 1; i < 1000; ++i ) {
+    adir( Pathname::extend( abase, str::hexstring( i ) ) );
+    if ( ! adir.isExist() && mkdir( adir.path() ) == 0 ) {
+            apoint = adir.path();
+            break;
+    }
+  }
+  if ( apoint.empty() ) {
+    ERR << "Unable to create an attach point below " << aroot << std::endl;
+  } else {
+    MIL << "Created default attach point " << apoint << std::endl;
+  }
+  return apoint;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+//
+//     METHOD NAME : MediaHandler::attachedMedia
+//     METHOD TYPE : AttachedMedia
+//
+//     DESCRIPTION :
+//
+AttachedMedia
+MediaHandler::attachedMedia() const
+{
+  if ( _isAttached && _mediaSource && _attachPoint)
+    return AttachedMedia(_mediaSource, _attachPoint);
+  else
+    return AttachedMedia();
+}
+
+
 ///////////////////////////////////////////////////////////////////
 //
 //
@@ -151,10 +266,12 @@ void MediaHandler::attach( bool next )
   if ( _isAttached )
     return;
 
-  if ( _attachPoint.empty() ) {
+/**
+  if ( _attachPoint->empty() ) {
     ERR << "Bad Attachpoint" << endl;
     ZYPP_THROW( MediaBadAttachPointException(url()));
   }
+*/
 
   attachTo( next ); // pass to concrete handler
   _isAttached = true;
@@ -302,7 +419,7 @@ void MediaHandler::provideDirTree( Pathname dirname ) const
 //
 void MediaHandler::releasePath( Pathname pathname ) const
 {
-  if ( ! _does_download || _attachPoint.empty() )
+  if ( ! _does_download || _attachPoint->empty() )
     return;
 
   PathInfo info( localPath( pathname ) );
index 8d44753..3b812de 100644 (file)
 
 #include "zypp/Pathname.h"
 #include "zypp/PathInfo.h"
+#include "zypp/base/PtrTypes.h"
 
 #include "zypp/Url.h"
 
-#include "zypp/media/MediaAccess.h"
+#include "zypp/media/MediaSource.h"
+#include "zypp/media/MediaException.h"
 
 namespace zypp {
   namespace media {
 
+
 ///////////////////////////////////////////////////////////////////
 //
 //     CLASS NAME : MediaHandler
@@ -45,23 +48,37 @@ class MediaHandler {
        typedef shared_ptr<const MediaHandler> constPtr;
 
     private:
+        /**
+        * MediaAccess (MediaManager) needs access to the
+        * attachedMedia() function to deliver a shared
+        * media source and its attach point to other
+        * media handler instances.
+        */
+       friend class MediaAccess;
+
+       /**
+        * Returns the attached media. Used by MediaManager
+        * to find other handlers using the same source.
+        */
+       AttachedMedia        attachedMedia() const;
 
        /**
         * this is where the media will be actually "mounted"
         * all files are provided 'below' this directory.
         **/
-       Pathname _attachPoint;
+       AttachPointRef _attachPoint;
 
        /**
-        * If a default attach point was created, it has to be
-        * removed on destuction.
-        **/
-       bool _tmp_attachPoint;
+        * The relative root directory of the data on the media.
+        * See also _localRoot and urlpath_below_attachpoint_r
+        * constructor argument.
+        */
+       Pathname _relativeRoot;
 
        /**
         * The local directory that corresponds to the media url.
         * With NFS it's the '_attachPoint', as the directory on the
-        * server is mounted. With CD/DVD it's 'attach point+_url.path()'
+        * server is mounted. With CD/DVD it's 'attach point+_relativeRoot'
         * because the CDs root directory is mounted. And with CIFS
         * it's '_url.path() without the shares name'.
         **/
@@ -79,6 +96,11 @@ class MediaHandler {
        bool _isAttached;
 
     protected:
+       // FIXME: private...?
+       /**
+        * The attached media source.
+        */
+        MediaSourceRef _mediaSource;
 
         /**
         * Url to handle
@@ -86,9 +108,37 @@ class MediaHandler {
        const Url _url;
 
         /**
-        * Attachpoint to use
+        * Return the currently used attach point.
         **/
-       const Pathname & attachPoint() const { return _attachPoint; }
+       Pathname         attachPoint() const;
+
+       /**
+        * Set a new attach point and update localRoot.
+        */
+       void             setAttachPoint(const Pathname &path, bool _temporary);
+
+       /**
+        * Set a (shared) attach point and update localRoot.
+        */
+       void             setAttachPoint(const AttachPointRef &ref);
+
+       /**
+        * Try to create a default / temporary attach point.
+        * \return The name of the new attach point or empty path name.
+        */
+       Pathname         createAttachPoint() const;
+
+       /**
+        * Remove unused attach point.
+        */
+       void             removeAttachPoint();
+
+       /**
+        * Ask the media manager if specified media source
+        * is already attached.
+        */
+       AttachedMedia
+       findAttachedMedia(const MediaSourceRef &media) const;
 
     protected:
 
@@ -131,7 +181,9 @@ class MediaHandler {
 
        /**
         * Call concrete handler to release the media.
-        * If eject is true, physically eject the media (i.e. CD-ROM).
+        *
+        * If eject is true, and the media is used in one handler
+        * instance only, physically eject the media (i.e. CD-ROM).
         *
         * Asserted that media is attached.
         *
@@ -274,6 +326,7 @@ class MediaHandler {
 
     public:
 
+
         ///////////////////////////////////////////////////////////////////
         //
         // MediaAccess interface. Does common checks and logging.
index 8d7f2d2..371ff10 100644 (file)
@@ -11,7 +11,7 @@
 */
 #include <zypp/media/MediaException.h>
 #include <zypp/media/MediaManager.h>
-//#include <zypp/media/Mount.h>
+#include <zypp/media/Mount.h>
 //#include <zypp/media/Hal.h>
 #include <zypp/thread/Mutex.h>
 #include <zypp/thread/MutexLock.h>
@@ -55,14 +55,12 @@ namespace zypp
     //////////////////////////////////////////////////////////////////
 
 
-    // ---------------------------------------------------------------
+    //////////////////////////////////////////////////////////////////
     class MediaManager::Impl
     {
     private:
-    /*
       time_t       mtab_mtime;
       MountEntries mtab_table;
-    */
       MediaId      last_mediaid;
 
     public:
@@ -70,8 +68,8 @@ namespace zypp
       MediaAccMap  mediaAccMap;
 
       Impl()
-        : /* mtab_mtime(0)
-        , */ last_mediaid(0)
+        : mtab_mtime(0)
+        , last_mediaid(0)
       {}
 
       ~Impl()
@@ -80,7 +78,7 @@ namespace zypp
       MediaId
       nextMediaId()
       {
-        return last_mediaid++;
+        return ++last_mediaid;
       }
 
       bool hasMediaAcc(MediaId mediaId) const
@@ -93,7 +91,6 @@ namespace zypp
         return mediaVfyMap.find(mediaId) != mediaVfyMap.end();
       }
 
-      /*
       MountEntries
       getMountEntries()
       {
@@ -104,19 +101,18 @@ namespace zypp
         }
         return mtab_table;
       }
-      */
     };
 
 
-    // ---------------------------------------------------------------
+    //////////////////////////////////////////////////////////////////
     // STATIC
     zypp::RW_pointer<MediaManager::Impl> MediaManager::m_impl(NULL);
 
 
-    // ---------------------------------------------------------------
+    //////////////////////////////////////////////////////////////////
     MediaManager::MediaManager()
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
       if( !m_impl)
       {
         m_impl.reset( new MediaManager::Impl());
@@ -132,20 +128,7 @@ namespace zypp
     MediaId
     MediaManager::open(const Url &url, const Pathname &preferred_attach_point)
     {
-      MutexLock lock(g_Mutex);
-
-      // check if we already have this url
-      MediaAccMap::const_iterator a(m_impl->mediaAccMap.begin());
-      for( ; a != m_impl->mediaAccMap.end(); ++a)
-      {
-        // FIXME: not sufficient. each handler should provide
-        //        method to compare its type of media url
-        //        and MediaAccess to choose right handler...
-        if( a->second->url().asString() == url.asString())
-        {
-          return a->first;
-        }
-      }
+      MutexLock glock(g_Mutex);
 
       // create new access handler for it
       MediaAccessRef accRef( new MediaAccess());
@@ -155,7 +138,7 @@ namespace zypp
       MediaId nextId = m_impl->nextMediaId();
 
       m_impl->mediaAccMap[nextId] = accRef;
-
+      DBG << "Opened new media access using id " << nextId << std::endl;
       return nextId;
     }
 
@@ -163,7 +146,7 @@ namespace zypp
     void
     MediaManager::close(MediaId mediaId)
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
         ZYPP_THROW(MediaException("Invalid media id"));
@@ -179,7 +162,7 @@ namespace zypp
     bool
     MediaManager::isOpen(MediaId mediaId) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       return m_impl->hasMediaAcc( mediaId);
     }
@@ -188,7 +171,7 @@ namespace zypp
     std::string
     MediaManager::protocol(MediaId mediaId) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( m_impl->hasMediaAcc( mediaId))
         return m_impl->mediaAccMap[mediaId]->protocol();
@@ -200,7 +183,7 @@ namespace zypp
     Url
     MediaManager::url(MediaId mediaId) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( m_impl->hasMediaAcc( mediaId))
         return m_impl->mediaAccMap[mediaId]->url();
@@ -212,7 +195,7 @@ namespace zypp
     void
     MediaManager::addVerifier(MediaId mediaId, const MediaVerifierRef &ref)
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !ref)
         ZYPP_THROW(MediaException("Invalid (empty) verifier reference"));
@@ -231,7 +214,7 @@ namespace zypp
     void
     MediaManager::delVerifier(MediaId mediaId)
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
         ZYPP_THROW(MediaException("Invalid media id"));
@@ -244,7 +227,7 @@ namespace zypp
     void
     MediaManager::attach(MediaId mediaId, bool next)
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -263,7 +246,7 @@ namespace zypp
     void
     MediaManager::release(MediaId mediaId, bool eject)
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -279,7 +262,7 @@ namespace zypp
     void
     MediaManager::disconnect(MediaId mediaId)
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -294,7 +277,7 @@ namespace zypp
     bool
     MediaManager::isAttached(MediaId mediaId) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -310,7 +293,7 @@ namespace zypp
     bool
     MediaManager::isDesiredMedia(MediaId mediaId, MediaNr mediaNr) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !isAttached(mediaId))
         return false;
@@ -333,7 +316,7 @@ namespace zypp
     Pathname
     MediaManager::localRoot(MediaId mediaId) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -351,7 +334,7 @@ namespace zypp
     MediaManager::localPath(MediaId mediaId,
                             const Pathname & pathname) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -370,7 +353,7 @@ namespace zypp
                               const Pathname &filename,
                               bool cached, bool checkonly) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !isDesiredMedia(mediaId, mediaNr))
       {
@@ -388,7 +371,7 @@ namespace zypp
                              MediaNr mediaNr,
                              const Pathname & dirname ) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !isDesiredMedia(mediaId, mediaNr))
       {
@@ -406,7 +389,7 @@ namespace zypp
                                  MediaNr mediaNr,
                                  const Pathname & dirname ) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !isDesiredMedia(mediaId, mediaNr))
       {
@@ -423,7 +406,7 @@ namespace zypp
     MediaManager::releaseFile(MediaId mediaId,
                               const Pathname & filename) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -440,7 +423,7 @@ namespace zypp
     MediaManager::releaseDir(MediaId mediaId,
                              const Pathname & dirname) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -458,7 +441,7 @@ namespace zypp
     MediaManager::releasePath(MediaId mediaId,
                               const Pathname & pathname) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -476,7 +459,7 @@ namespace zypp
                           std::list<std::string> & retlist,
                           const Pathname & dirname, bool dots) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -494,7 +477,7 @@ namespace zypp
                           filesystem::DirContent & retlist,
                           const Pathname & dirname, bool dots) const
     {
-      MutexLock lock(g_Mutex);
+      MutexLock glock(g_Mutex);
 
       if( !m_impl->hasMediaAcc( mediaId))
       {
@@ -506,6 +489,30 @@ namespace zypp
       m_impl->mediaAccMap[mediaId]->dirInfo(retlist, dirname, dots);
     }
 
+
+    // ---------------------------------------------------------------
+    AttachedMedia
+    MediaManager::findAttachedMedia(const MediaSourceRef &media) const
+    {
+      MutexLock glock(g_Mutex);
+
+      if( !media || media->type.empty())
+        return AttachedMedia();
+
+      MediaAccMap::const_iterator a(m_impl->mediaAccMap.begin());
+      for( ; a != m_impl->mediaAccMap.end(); ++a)
+      {
+        if( !a->second->isAttached())
+          continue;
+
+        AttachedMedia ret = a->second->attachedMedia();
+        if( ret.mediaSource && ret.mediaSource->equals( *media))
+            return ret;
+      }
+      return AttachedMedia();
+    }
+
+
     //////////////////////////////////////////////////////////////////
   } // namespace media
   ////////////////////////////////////////////////////////////////////
index 79109f1..495f2a4 100644 (file)
 #ifndef ZYPP_MEDIA_MEDIAMANAGER_H
 #define ZYPP_MEDIA_MEDIAMANAGER_H
 
-#include "zypp/media/MediaAccess.h"
-#include "zypp/base/NonCopyable.h"
-#include "zypp/base/PtrTypes.h"
-#include "zypp/Pathname.h"
-#include "zypp/Url.h"
+#include <zypp/media/MediaAccess.h>
+
+#include <zypp/base/NonCopyable.h>
+#include <zypp/base/PtrTypes.h>
+#include <zypp/Pathname.h>
+#include <zypp/Url.h>
+
+#include <list>
 
 
 //////////////////////////////////////////////////////////////////////
@@ -27,10 +30,13 @@ namespace zypp
   namespace media
   { //////////////////////////////////////////////////////////////////
 
+
+    ///////////////////////////////////////////////////////////////////
     typedef zypp::RW_pointer<MediaAccess> MediaAccessRef;
     typedef unsigned int                  MediaId;
     typedef unsigned int                  MediaNr;
 
+
     ///////////////////////////////////////////////////////////////////
     //
     // CLASS NAME : MediaVerifierBase
@@ -78,8 +84,8 @@ namespace zypp
       {}
 
       /*
-      ** Check if the specified attached media contains
-      ** the desired media number (e.g. SLES10 CD1). Always return true.
+      ** Don't check if the specified attached media contains
+      ** the desired media number. Always return true.
       */
       virtual bool
       isDesiredMedia(const MediaAccessRef &ref, MediaNr mediaNr)
@@ -287,6 +293,13 @@ namespace zypp
                    filesystem::DirContent & retlist,
                    const Pathname & dirname, bool dots = true ) const;
 
+
+    private:
+      friend class MediaHandler;
+
+      AttachedMedia
+      findAttachedMedia(const MediaSourceRef &media) const;
+
     private:
       class  Impl;
       static zypp::RW_pointer<MediaManager::Impl> m_impl;
diff --git a/zypp/media/MediaSource.h b/zypp/media/MediaSource.h
new file mode 100644 (file)
index 0000000..6051daa
--- /dev/null
@@ -0,0 +1,132 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file zypp/media/MediaSource.h
+ *
+ */
+#ifndef ZYPP_MEDIA_MEDIASOURCE_H
+#define ZYPP_MEDIA_MEDIASOURCE_H
+
+#include "zypp/Pathname.h"
+#include "zypp/base/String.h"
+#include "zypp/base/PtrTypes.h"
+
+
+namespace zypp {
+  namespace media {
+
+
+    ///////////////////////////////////////////////////////////////////
+    /**
+     * Media source internally used by MediaManager and MediaHandler.
+     */
+    class MediaSource
+    {
+    public:
+      MediaSource(const std::string &_type,  const std::string &_name,
+                  unsigned int       _maj=0, unsigned int       _min=0)
+        : maj_nr(_maj)
+        , min_nr(_min)
+        , type(_type)
+        , name(_name)
+      {}
+
+      MediaSource()
+        : maj_nr(0)
+        , min_nr(0)
+      {}
+
+      virtual
+      ~MediaSource()
+      {}
+
+      /**
+       * Check if the both sources are equal.
+       */
+      virtual bool equals(const MediaSource &src) const
+      {
+        if( type == src.type)
+        {
+          if( maj_nr == 0)
+            return name == src.name;
+          else
+            return maj_nr == src.maj_nr &&
+                   min_nr == src.min_nr;
+        }
+        return false;
+      }
+
+      /**
+       * Return media source as string for debuging purposes.
+       */
+      virtual std::string asString() const
+      {
+        return type + ":" + name      + "(" +
+               str::numstring(maj_nr) + "," +
+               str::numstring(min_nr) + ")";
+      }
+
+      unsigned int maj_nr;  //!< A major number if source is a device.
+      unsigned int min_nr;  //!< A minor number if source is a device.
+      std::string  type;    //!< A media handler specific source type.
+      std::string  name;    //!< A media handler specific source name.
+    };
+
+
+    ///////////////////////////////////////////////////////////////////
+    /**
+     * Attach point of a media source.
+     */
+    class AttachPoint
+    {
+    public:
+      AttachPoint(const Pathname &_path=Pathname(),
+                  bool            _temp=true)
+        : path(_path)
+        , temp(_temp)
+      {}
+
+      bool empty() const { return path.empty(); }
+
+      Pathname path;   //!< The path name (mount point).
+      bool     temp;    //!< If it was created temporary.
+    };
+
+
+    ///////////////////////////////////////////////////////////////////
+    typedef zypp::RW_pointer<MediaSource> MediaSourceRef;
+    typedef zypp::RW_pointer<AttachPoint> AttachPointRef;
+
+
+    ///////////////////////////////////////////////////////////////////
+    /**
+     * A simple structure containing references
+     * to a media source and its attach point.
+     */
+    struct AttachedMedia
+    {
+      AttachedMedia()
+      {}
+
+      AttachedMedia(const MediaSourceRef &_mediaSource,
+                    const AttachPointRef &_attachPoint)
+       : mediaSource( _mediaSource)
+       , attachPoint( _attachPoint)
+      {}
+
+      MediaSourceRef mediaSource;
+      AttachPointRef attachPoint;
+    };
+
+
+  } // namespace media
+} // namespace zypp
+
+
+#endif // ZYPP_MEDIA_MEDIASOURCE_H
+