1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaManager.cc
17 #include <zypp/media/MediaException.h>
18 #include <zypp/media/MediaManager.h>
19 #include <zypp/media/MediaHandler.h>
20 #include <zypp/media/Mount.h>
22 #include <zypp/base/String.h>
23 #include <zypp/base/Logger.h>
24 #include <zypp/Pathname.h>
25 #include <zypp/PathInfo.h>
27 //////////////////////////////////////////////////////////////////////
29 { ////////////////////////////////////////////////////////////////////
31 ////////////////////////////////////////////////////////////////////
33 { //////////////////////////////////////////////////////////////////
35 //////////////////////////////////////////////////////////////////
36 namespace // anonymous
37 { ////////////////////////////////////////////////////////////////
39 // -------------------------------------------------------------
49 ManagedMedia(const ManagedMedia &m)
52 , verifier(m.verifier)
55 ManagedMedia(const MediaAccessRef &h, const MediaVerifierRef &v)
62 checkAttached(MediaAccessId id)
64 if( !handler->isAttached())
66 DBG << "checkAttached(" << id << ") not attached" << std::endl;
68 ZYPP_THROW(MediaNotAttachedException(
74 inline void checkDesired( MediaAccessId id )
81 desired = verifier->isDesiredMedia(handler);
82 } catch ( const zypp::Exception &e ) {
85 media::MediaNotDesiredException newEx ( handler->url() );
92 DBG << "checkDesired(" << id << "): not desired (report by " << verifier->info() << ")" << std::endl;
93 ZYPP_THROW( MediaNotDesiredException( handler->url() ) );
96 DBG << "checkDesired(" << id << "): desired (report by " << verifier->info() << ")" << std::endl;
98 DBG << "checkDesired(" << id << "): desired (cached)" << std::endl;
103 MediaAccessRef handler;
104 MediaVerifierRef verifier;
108 // -------------------------------------------------------------
109 typedef std::map<MediaAccessId, ManagedMedia> ManagedMediaMap;
111 ////////////////////////////////////////////////////////////////
113 //////////////////////////////////////////////////////////////////
116 //////////////////////////////////////////////////////////////////
118 MediaVerifierBase::info() const
120 return std::string(typeid((*this)).name());
124 //////////////////////////////////////////////////////////////////
126 NoVerifier::info() const
128 return std::string("zypp::media::NoVerifier");
132 //////////////////////////////////////////////////////////////////
133 class MediaManager_Impl
136 friend class MediaManager;
138 MediaAccessId last_accessid;
139 ManagedMediaMap mediaMap;
150 // remove depending (iso) handlers first
151 ManagedMediaMap::iterator it;
156 for(it = mediaMap.begin(); it != mediaMap.end(); /**/)
158 if( it->second.handler->dependsOnParent())
161 // let it forget its parent, we will
162 // destroy it later (in clear())...
163 it->second.handler->resetParentId();
164 mediaMap.erase( it++ ); // postfix! Incrementing before erase
171 // remove all other handlers
181 return ++last_accessid;
185 hasId(MediaAccessId accessId) const
187 return mediaMap.find(accessId) != mediaMap.end();
190 inline ManagedMedia &
191 findMM(MediaAccessId accessId)
193 ManagedMediaMap::iterator it( mediaMap.find(accessId));
194 if( it == mediaMap.end())
196 ZYPP_THROW(MediaNotOpenException(
197 "Invalid media access id " + str::numstring(accessId)
206 time_t mtime = zypp::PathInfo("/etc/mtab").mtime();
209 WAR << "Failed to retrieve modification time of '/etc/mtab'"
215 static inline MountEntries
218 return Mount::getEntries();
224 //////////////////////////////////////////////////////////////////
226 zypp::RW_pointer<MediaManager_Impl> MediaManager::m_impl;
229 //////////////////////////////////////////////////////////////////
230 MediaManager::MediaManager()
234 m_impl.reset( new MediaManager_Impl());
238 // ---------------------------------------------------------------
239 MediaManager::~MediaManager()
243 // ---------------------------------------------------------------
245 MediaManager::open(const Url &url, const Pathname &preferred_attach_point)
247 // create new access handler for it
248 MediaAccessRef handler( new MediaAccess());
249 MediaVerifierRef verifier( new NoVerifier());
250 ManagedMedia tmp( handler, verifier);
252 tmp.handler->open(url, preferred_attach_point);
254 MediaAccessId nextId = m_impl->nextAccessId();
256 m_impl->mediaMap[nextId] = tmp;
258 DBG << "Opened new media access using id " << nextId
259 << " to " << url.asString() << std::endl;
263 // ---------------------------------------------------------------
265 MediaManager::close(MediaAccessId accessId)
268 // The MediaISO handler internally requests an accessId
269 // of a "parent" handler providing the iso file.
270 // The parent handler accessId is private to MediaISO,
271 // but the attached media source may be shared reference.
272 // This means, that if the accessId exactly matches the
273 // parent handler id, close was used on uninitialized
274 // accessId variable (or the accessId was guessed) and
275 // the close request to this id will be rejected here.
277 ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
278 for( ; m != m_impl->mediaMap.end(); ++m)
280 if( m->second.handler->dependsOnParent(accessId, true))
282 ZYPP_THROW(MediaIsSharedException(
283 m->second.handler->url().asString()
288 DBG << "Close to access handler using id "
289 << accessId << " requested" << std::endl;
291 ManagedMedia &ref( m_impl->findMM(accessId));
292 ref.handler->close();
294 m_impl->mediaMap.erase(accessId);
297 // ---------------------------------------------------------------
299 MediaManager::isOpen(MediaAccessId accessId) const
301 ManagedMediaMap::iterator it( m_impl->mediaMap.find(accessId));
302 return it != m_impl->mediaMap.end() &&
303 it->second.handler->isOpen();
306 // ---------------------------------------------------------------
308 MediaManager::protocol(MediaAccessId accessId) const
310 ManagedMedia &ref( m_impl->findMM(accessId));
312 return ref.handler->protocol();
315 // ---------------------------------------------------------------
317 MediaManager::downloads(MediaAccessId accessId) const
319 ManagedMedia &ref( m_impl->findMM(accessId));
321 return ref.handler->downloads();
324 // ---------------------------------------------------------------
326 MediaManager::url(MediaAccessId accessId) const
328 ManagedMedia &ref( m_impl->findMM(accessId));
330 return ref.handler->url();
333 // ---------------------------------------------------------------
335 MediaManager::addVerifier(MediaAccessId accessId,
336 const MediaVerifierRef &verifier)
339 ZYPP_THROW(MediaException("Invalid verifier reference"));
341 ManagedMedia &ref( m_impl->findMM(accessId));
344 MediaVerifierRef(verifier).swap(ref.verifier);
346 DBG << "MediaVerifier change: id=" << accessId << ", verifier="
347 << verifier->info() << std::endl;
350 // ---------------------------------------------------------------
352 MediaManager::delVerifier(MediaAccessId accessId)
354 ManagedMedia &ref( m_impl->findMM(accessId));
356 MediaVerifierRef verifier( new NoVerifier());
358 ref.verifier.swap(verifier);
360 DBG << "MediaVerifier change: id=" << accessId << ", verifier="
361 << verifier->info() << std::endl;
364 // ---------------------------------------------------------------
366 MediaManager::setAttachPrefix(const Pathname &attach_prefix)
368 return MediaHandler::setAttachPrefix(attach_prefix);
371 // ---------------------------------------------------------------
372 void MediaManager::attach(MediaAccessId accessId)
374 ManagedMedia &ref( m_impl->findMM(accessId));
376 DBG << "attach(id=" << accessId << ")" << std::endl;
378 // try first mountable/mounted device
379 ref.handler->attach(false);
382 ref.checkDesired(accessId);
385 catch (const MediaException & ex)
389 if (!ref.handler->hasMoreDevices())
392 if (ref.handler->isAttached())
393 ref.handler->release();
396 MIL << "checkDesired(" << accessId << ") of first device failed,"
397 " going to try others with attach(true)" << std::endl;
399 while (ref.handler->hasMoreDevices())
403 // try to attach next device
404 ref.handler->attach(true);
405 ref.checkDesired(accessId);
408 catch (const MediaNotDesiredException & ex)
412 if (!ref.handler->hasMoreDevices())
414 MIL << "No desired media found after trying all detected devices." << std::endl;
418 AttachedMedia media(ref.handler->attachedMedia());
419 DBG << "Skipping " << media.mediaSource->asString() << ": not desired media." << std::endl;
421 ref.handler->release();
423 catch (const MediaException & ex)
427 if (!ref.handler->hasMoreDevices())
430 AttachedMedia media(ref.handler->attachedMedia());
431 DBG << "Skipping " << media.mediaSource->asString() << " because of exception thrown by attach(true)" << std::endl;
433 if (ref.handler->isAttached()) ref.handler->release();
438 // ---------------------------------------------------------------
440 MediaManager::release(MediaAccessId accessId, const std::string & ejectDev)
442 ManagedMedia &ref( m_impl->findMM(accessId));
444 DBG << "release(id=" << accessId;
445 if (!ejectDev.empty())
446 DBG << ", " << ejectDev;
447 DBG << ")" << std::endl;
449 if(!ejectDev.empty())
452 // release MediaISO handlers, that are using the one
453 // specified with accessId, because it provides the
454 // iso file and it will disappear now (forced release
457 ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
458 for( ; m != m_impl->mediaMap.end(); ++m)
460 if( m->second.handler->dependsOnParent(accessId, false))
464 DBG << "Forcing release of handler depending on access id "
465 << accessId << std::endl;
466 m->second.desired = false;
467 m->second.handler->release();
469 catch(const MediaException &e)
477 ref.handler->release(ejectDev);
480 // ---------------------------------------------------------------
482 MediaManager::releaseAll()
484 MIL << "Releasing all attached media" << std::endl;
486 ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
487 for( ; m != m_impl->mediaMap.end(); ++m)
489 if( m->second.handler->dependsOnParent())
494 if(m->second.handler->isAttached())
496 DBG << "Releasing media id " << m->first << std::endl;
497 m->second.desired = false;
498 m->second.handler->release();
502 DBG << "Media id " << m->first << " not attached " << std::endl;
505 catch(const MediaException & e)
508 ERR << "Failed to release media id " << m->first << std::endl;
512 MIL << "Exit" << std::endl;
515 // ---------------------------------------------------------------
517 MediaManager::disconnect(MediaAccessId accessId)
519 ManagedMedia &ref( m_impl->findMM(accessId));
521 ref.handler->disconnect();
524 // ---------------------------------------------------------------
526 MediaManager::isAttached(MediaAccessId accessId) const
528 ManagedMedia &ref( m_impl->findMM(accessId));
530 return ref.handler->isAttached();
533 // ---------------------------------------------------------------
534 bool MediaManager::isSharedMedia(MediaAccessId accessId) const
536 ManagedMedia &ref( m_impl->findMM(accessId));
538 return ref.handler->isSharedMedia();
541 // ---------------------------------------------------------------
543 MediaManager::isDesiredMedia(MediaAccessId accessId) const
545 ManagedMedia &ref( m_impl->findMM(accessId));
547 if( !ref.handler->isAttached())
554 ref.desired = ref.verifier->isDesiredMedia(ref.handler);
556 catch(const zypp::Exception &e) {
561 DBG << "isDesiredMedia(" << accessId << "): "
562 << (ref.desired ? "" : "not ")
563 << "desired (report by "
564 << ref.verifier->info() << ")" << std::endl;
568 // ---------------------------------------------------------------
570 MediaManager::isDesiredMedia(MediaAccessId accessId,
571 const MediaVerifierRef &verifier) const
573 MediaVerifierRef v(verifier);
575 ZYPP_THROW(MediaException("Invalid verifier reference"));
577 ManagedMedia &ref( m_impl->findMM(accessId));
579 bool desired = false;
580 if( ref.handler->isAttached())
583 desired = v->isDesiredMedia(ref.handler);
585 catch(const zypp::Exception &e) {
590 DBG << "isDesiredMedia(" << accessId << "): "
591 << (desired ? "" : "not ")
592 << "desired (report by "
593 << v->info() << ")" << std::endl;
597 // ---------------------------------------------------------------
599 MediaManager::isChangeable(MediaAccessId accessId)
601 return url(accessId).getScheme() == "cd" || url(accessId).getScheme() == "dvd";
604 // ---------------------------------------------------------------
606 MediaManager::localRoot(MediaAccessId accessId) const
608 ManagedMedia &ref( m_impl->findMM(accessId));
611 path = ref.handler->localRoot();
615 // ---------------------------------------------------------------
617 MediaManager::localPath(MediaAccessId accessId,
618 const Pathname & pathname) const
620 ManagedMedia &ref( m_impl->findMM(accessId));
623 path = ref.handler->localPath(pathname);
628 MediaManager::provideFile(MediaAccessId accessId,
629 const Pathname &filename,
630 const ByteCount &expectedFileSize ) const
632 ManagedMedia &ref( m_impl->findMM(accessId));
634 ref.checkDesired(accessId);
636 ref.handler->provideFile(filename, expectedFileSize);
639 // ---------------------------------------------------------------
641 MediaManager::provideFile(MediaAccessId accessId,
642 const Pathname &filename ) const
644 provideFile( accessId, filename, 0);
647 // ---------------------------------------------------------------
649 MediaManager::setDeltafile(MediaAccessId accessId,
650 const Pathname &filename ) const
652 ManagedMedia &ref( m_impl->findMM(accessId));
654 ref.checkDesired(accessId);
656 ref.handler->setDeltafile(filename);
659 // ---------------------------------------------------------------
661 MediaManager::provideDir(MediaAccessId accessId,
662 const Pathname &dirname) const
664 ManagedMedia &ref( m_impl->findMM(accessId));
666 ref.checkDesired(accessId);
668 ref.handler->provideDir(dirname);
671 // ---------------------------------------------------------------
673 MediaManager::provideDirTree(MediaAccessId accessId,
674 const Pathname &dirname) const
676 ManagedMedia &ref( m_impl->findMM(accessId));
678 ref.checkDesired(accessId);
680 ref.handler->provideDirTree(dirname);
683 // ---------------------------------------------------------------
685 MediaManager::releaseFile(MediaAccessId accessId,
686 const Pathname &filename) const
688 ManagedMedia &ref( m_impl->findMM(accessId));
690 ref.checkAttached(accessId);
692 ref.handler->releaseFile(filename);
695 // ---------------------------------------------------------------
697 MediaManager::releaseDir(MediaAccessId accessId,
698 const Pathname &dirname) const
700 ManagedMedia &ref( m_impl->findMM(accessId));
702 ref.checkAttached(accessId);
704 ref.handler->releaseDir(dirname);
708 // ---------------------------------------------------------------
710 MediaManager::releasePath(MediaAccessId accessId,
711 const Pathname &pathname) const
713 ManagedMedia &ref( m_impl->findMM(accessId));
715 ref.checkAttached(accessId);
717 ref.handler->releasePath(pathname);
720 // ---------------------------------------------------------------
722 MediaManager::dirInfo(MediaAccessId accessId,
723 std::list<std::string> &retlist,
724 const Pathname &dirname,
727 ManagedMedia &ref( m_impl->findMM(accessId));
729 // FIXME: ref.checkDesired(accessId); ???
730 ref.checkAttached(accessId);
732 ref.handler->dirInfo(retlist, dirname, dots);
735 // ---------------------------------------------------------------
737 MediaManager::dirInfo(MediaAccessId accessId,
738 filesystem::DirContent &retlist,
739 const Pathname &dirname,
742 ManagedMedia &ref( m_impl->findMM(accessId));
744 // FIXME: ref.checkDesired(accessId); ???
745 ref.checkAttached(accessId);
747 ref.handler->dirInfo(retlist, dirname, dots);
750 // ---------------------------------------------------------------
752 MediaManager::doesFileExist(MediaAccessId accessId, const Pathname & filename ) const
754 ManagedMedia &ref( m_impl->findMM(accessId));
756 // FIXME: ref.checkDesired(accessId); ???
757 ref.checkAttached(accessId);
759 return ref.handler->doesFileExist(filename);
762 // ---------------------------------------------------------------
764 MediaManager::getDetectedDevices(MediaAccessId accessId,
765 std::vector<std::string> & devices,
766 unsigned int & index) const
768 ManagedMedia &ref( m_impl->findMM(accessId));
769 return ref.handler->getDetectedDevices(devices, index);
772 // ---------------------------------------------------------------
775 MediaManager::getMountTableMTime()
777 return MediaManager_Impl::getMountTableMTime();
780 // ---------------------------------------------------------------
783 MediaManager::getMountEntries()
785 return MediaManager_Impl::getMountEntries();
788 // ---------------------------------------------------------------
790 MediaManager::isUseableAttachPoint(const Pathname &path,
793 if( path.empty() || path == "/" || !PathInfo(path).isDir())
797 // check against our current attach points
799 ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin());
800 for( ; m != m_impl->mediaMap.end(); ++m)
802 AttachedMedia ret = m->second.handler->attachedMedia();
803 if( ret.mediaSource && ret.attachPoint)
805 std::string mnt(ret.attachPoint->path.asString());
806 std::string our(path.asString());
810 // already used as attach point
814 if( mnt.size() > our.size() &&
815 mnt.at(our.size()) == '/' &&
816 !mnt.compare(0, our.size(), our))
818 // mountpoint is bellow of path
819 // (would hide the content)
829 // check against system mount entries
831 MountEntries entries( m_impl->getMountEntries());
832 MountEntries::const_iterator e;
833 for( e = entries.begin(); e != entries.end(); ++e)
835 std::string mnt(Pathname(e->dir).asString());
836 std::string our(path.asString());
840 // already used as mountpoint
844 if( mnt.size() > our.size() &&
845 mnt.at(our.size()) == '/' &&
846 !mnt.compare(0, our.size(), our))
848 // mountpoint is bellow of path
849 // (would hide the content)
857 // ---------------------------------------------------------------
859 MediaManager::getAttachedMedia(MediaAccessId &accessId) const
861 ManagedMedia &ref( m_impl->findMM(accessId));
863 return ref.handler->attachedMedia();
866 // ---------------------------------------------------------------
868 MediaManager::findAttachedMedia(const MediaSourceRef &media) const
870 if( !media || media->type.empty())
871 return AttachedMedia();
873 ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin());
874 for( ; m != m_impl->mediaMap.end(); ++m)
876 if( !m->second.handler->isAttached())
879 AttachedMedia ret = m->second.handler->attachedMedia();
880 if( ret.mediaSource && ret.mediaSource->equals( *media))
883 return AttachedMedia();
886 // ---------------------------------------------------------------
888 MediaManager::forceReleaseShared(const MediaSourceRef &media)
890 if( !media || media->type.empty())
893 ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
894 for( ; m != m_impl->mediaMap.end(); ++m)
896 if( !m->second.handler->isAttached())
899 AttachedMedia ret = m->second.handler->attachedMedia();
900 if( ret.mediaSource && ret.mediaSource->equals( *media))
902 m->second.handler->release();
903 m->second.desired = false;
908 //////////////////////////////////////////////////////////////////
910 ////////////////////////////////////////////////////////////////////
912 ////////////////////////////////////////////////////////////////////
914 //////////////////////////////////////////////////////////////////////
916 ** vim: set ts=2 sts=2 sw=2 ai et: