Imported Upstream version 17.23.5
[platform/upstream/libzypp.git] / zypp / media / MediaManager.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaManager.cc
10  *
11 */
12 #include <map>
13 #include <list>
14 #include <iostream>
15 #include <typeinfo>
16
17 #include <zypp/media/MediaException.h>
18 #include <zypp/media/MediaManager.h>
19 #include <zypp/media/MediaHandler.h>
20 #include <zypp/media/Mount.h>
21
22 #include <zypp/base/String.h>
23 #include <zypp/base/Logger.h>
24 #include <zypp/Pathname.h>
25 #include <zypp/PathInfo.h>
26
27 //////////////////////////////////////////////////////////////////////
28 namespace zypp
29 { ////////////////////////////////////////////////////////////////////
30
31   ////////////////////////////////////////////////////////////////////
32   namespace media
33   { //////////////////////////////////////////////////////////////////
34
35     //////////////////////////////////////////////////////////////////
36     namespace // anonymous
37     { ////////////////////////////////////////////////////////////////
38
39       // -------------------------------------------------------------
40       struct ManagedMedia
41       {
42         ~ManagedMedia()
43         {}
44
45         ManagedMedia()
46           : desired (false)
47         {}
48
49         ManagedMedia(const ManagedMedia &m)
50           : desired (m.desired)
51           , handler (m.handler)
52           , verifier(m.verifier)
53         {}
54
55         ManagedMedia(const MediaAccessRef &h, const MediaVerifierRef &v)
56           : desired (false)
57           , handler (h)
58           , verifier(v)
59         {}
60
61         inline void
62         checkAttached(MediaAccessId id)
63         {
64           if( !handler->isAttached())
65           {
66             DBG << "checkAttached(" << id << ") not attached" << std::endl;
67             desired = false;
68             ZYPP_THROW(MediaNotAttachedException(
69               handler->url()
70             ));
71           }
72         }
73
74         inline void checkDesired( MediaAccessId id )
75         {
76           checkAttached( id );
77
78           if ( !desired )
79           {
80             try {
81               desired = verifier->isDesiredMedia(handler);
82             } catch ( const zypp::Exception &e ) {
83                 ZYPP_CAUGHT( e );
84
85                 media::MediaNotDesiredException newEx ( handler->url() );
86                 newEx.remember( e );
87                 ZYPP_THROW( newEx );
88             }
89
90             if( !desired )
91             {
92               DBG << "checkDesired(" << id << "): not desired (report by " << verifier->info() << ")" << std::endl;
93               ZYPP_THROW( MediaNotDesiredException( handler->url() ) );
94             }
95
96             DBG << "checkDesired(" << id << "): desired (report by " << verifier->info() << ")" << std::endl;
97           } else {
98             DBG << "checkDesired(" << id << "): desired (cached)" << std::endl;
99           }
100         }
101
102         bool             desired;
103         MediaAccessRef   handler;
104         MediaVerifierRef verifier;
105       };
106
107
108       // -------------------------------------------------------------
109       typedef std::map<MediaAccessId, ManagedMedia> ManagedMediaMap;
110
111       ////////////////////////////////////////////////////////////////
112     } // anonymous
113     //////////////////////////////////////////////////////////////////
114
115
116     //////////////////////////////////////////////////////////////////
117     std::string
118     MediaVerifierBase::info() const
119     {
120       return std::string(typeid((*this)).name());
121     }
122
123
124     //////////////////////////////////////////////////////////////////
125     std::string
126     NoVerifier::info() const
127     {
128       return std::string("zypp::media::NoVerifier");
129     }
130
131
132     //////////////////////////////////////////////////////////////////
133     class MediaManager_Impl
134     {
135     private:
136       friend class MediaManager;
137
138       MediaAccessId       last_accessid;
139       ManagedMediaMap     mediaMap;
140
141       MediaManager_Impl()
142         : last_accessid(0)
143       {}
144
145     public:
146       ~MediaManager_Impl()
147       {
148         try
149         {
150           // remove depending (iso) handlers first
151           ManagedMediaMap::iterator it;
152           bool found;
153           do
154           {
155             found = false;
156             for(it = mediaMap.begin(); it != mediaMap.end(); /**/)
157             {
158               if( it->second.handler->dependsOnParent())
159               {
160                 found = true;
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
165               } else {
166                 ++it;
167               }
168             }
169           } while(found);
170
171           // remove all other handlers
172           mediaMap.clear();
173         }
174         catch( ... )
175         {}
176       }
177
178       inline MediaAccessId
179       nextAccessId()
180       {
181         return ++last_accessid;
182       }
183
184       inline bool
185       hasId(MediaAccessId accessId) const
186       {
187         return mediaMap.find(accessId) != mediaMap.end();
188       }
189
190       inline ManagedMedia &
191       findMM(MediaAccessId accessId)
192       {
193         ManagedMediaMap::iterator it( mediaMap.find(accessId));
194         if( it == mediaMap.end())
195         {
196           ZYPP_THROW(MediaNotOpenException(
197             "Invalid media access id " + str::numstring(accessId)
198           ));
199         }
200         return it->second;
201       }
202
203       static inline time_t
204       getMountTableMTime()
205       {
206         time_t mtime = zypp::PathInfo("/etc/mtab").mtime();
207         if( mtime <= 0)
208         {
209           WAR << "Failed to retrieve modification time of '/etc/mtab'"
210               << std::endl;
211         }
212         return mtime;
213       }
214
215       static inline MountEntries
216       getMountEntries()
217       {
218         return Mount::getEntries();
219       }
220
221     };
222
223
224     //////////////////////////////////////////////////////////////////
225     // STATIC
226     zypp::RW_pointer<MediaManager_Impl> MediaManager::m_impl;
227
228
229     //////////////////////////////////////////////////////////////////
230     MediaManager::MediaManager()
231     {
232       if( !m_impl)
233       {
234         m_impl.reset( new MediaManager_Impl());
235       }
236     }
237
238     // ---------------------------------------------------------------
239     MediaManager::~MediaManager()
240     {
241     }
242
243     // ---------------------------------------------------------------
244     MediaAccessId
245     MediaManager::open(const Url &url, const Pathname &preferred_attach_point)
246     {
247       // create new access handler for it
248       MediaAccessRef handler( new MediaAccess());
249       MediaVerifierRef verifier( new NoVerifier());
250       ManagedMedia tmp( handler, verifier);
251
252       tmp.handler->open(url, preferred_attach_point);
253
254       MediaAccessId nextId = m_impl->nextAccessId();
255
256       m_impl->mediaMap[nextId] = tmp;
257
258       DBG << "Opened new media access using id " << nextId
259           << " to " << url.asString() << std::endl;
260       return nextId;
261     }
262
263     // ---------------------------------------------------------------
264     void
265     MediaManager::close(MediaAccessId accessId)
266     {
267       //
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.
276       //
277       ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
278       for( ; m != m_impl->mediaMap.end(); ++m)
279       {
280         if( m->second.handler->dependsOnParent(accessId, true))
281         {
282           ZYPP_THROW(MediaIsSharedException(
283             m->second.handler->url().asString()
284           ));
285         }
286       }
287
288       DBG << "Close to access handler using id "
289           << accessId << " requested" << std::endl;
290
291       ManagedMedia &ref( m_impl->findMM(accessId));
292       ref.handler->close();
293
294       m_impl->mediaMap.erase(accessId);
295     }
296
297     // ---------------------------------------------------------------
298     bool
299     MediaManager::isOpen(MediaAccessId accessId) const
300     {
301       ManagedMediaMap::iterator it( m_impl->mediaMap.find(accessId));
302       return it != m_impl->mediaMap.end() &&
303              it->second.handler->isOpen();
304     }
305
306     // ---------------------------------------------------------------
307     std::string
308     MediaManager::protocol(MediaAccessId accessId) const
309     {
310       ManagedMedia &ref( m_impl->findMM(accessId));
311
312       return ref.handler->protocol();
313     }
314
315     // ---------------------------------------------------------------
316           bool
317     MediaManager::downloads(MediaAccessId accessId) const
318     {
319       ManagedMedia &ref( m_impl->findMM(accessId));
320
321       return ref.handler->downloads();
322     }
323
324     // ---------------------------------------------------------------
325     Url
326     MediaManager::url(MediaAccessId accessId) const
327     {
328       ManagedMedia &ref( m_impl->findMM(accessId));
329
330       return ref.handler->url();
331     }
332
333     // ---------------------------------------------------------------
334     void
335     MediaManager::addVerifier(MediaAccessId           accessId,
336                               const MediaVerifierRef &verifier)
337     {
338       if( !verifier)
339         ZYPP_THROW(MediaException("Invalid verifier reference"));
340
341       ManagedMedia &ref( m_impl->findMM(accessId));
342
343       ref.desired = false;
344       MediaVerifierRef(verifier).swap(ref.verifier);
345
346       DBG << "MediaVerifier change: id=" << accessId << ", verifier="
347           << verifier->info() << std::endl;
348     }
349
350     // ---------------------------------------------------------------
351     void
352     MediaManager::delVerifier(MediaAccessId accessId)
353     {
354       ManagedMedia &ref( m_impl->findMM(accessId));
355
356       MediaVerifierRef verifier( new NoVerifier());
357       ref.desired  = false;
358       ref.verifier.swap(verifier);
359
360       DBG << "MediaVerifier change: id=" << accessId << ", verifier="
361           << verifier->info() << std::endl;
362     }
363
364     // ---------------------------------------------------------------
365     bool
366     MediaManager::setAttachPrefix(const Pathname &attach_prefix)
367     {
368       return MediaHandler::setAttachPrefix(attach_prefix);
369     }
370
371     // ---------------------------------------------------------------
372     void MediaManager::attach(MediaAccessId accessId)
373     {
374       ManagedMedia &ref( m_impl->findMM(accessId));
375
376       DBG << "attach(id=" << accessId << ")" << std::endl;
377
378       // try first mountable/mounted device
379       ref.handler->attach(false);
380       try
381       {
382         ref.checkDesired(accessId);
383         return;
384       }
385       catch (const MediaException & ex)
386       {
387         ZYPP_CAUGHT(ex);
388
389         if (!ref.handler->hasMoreDevices())
390           ZYPP_RETHROW(ex);
391
392         if (ref.handler->isAttached())
393           ref.handler->release();
394       }
395
396       MIL << "checkDesired(" << accessId << ") of first device failed,"
397         " going to try others with attach(true)" << std::endl;
398
399       while (ref.handler->hasMoreDevices())
400       {
401         try
402         {
403           // try to attach next device
404           ref.handler->attach(true);
405           ref.checkDesired(accessId);
406           return;
407         }
408         catch (const MediaNotDesiredException & ex)
409         {
410           ZYPP_CAUGHT(ex);
411
412           if (!ref.handler->hasMoreDevices())
413           {
414             MIL << "No desired media found after trying all detected devices." << std::endl;
415             ZYPP_RETHROW(ex);
416           }
417
418           AttachedMedia media(ref.handler->attachedMedia());
419           DBG << "Skipping " << media.mediaSource->asString() << ": not desired media." << std::endl;
420
421           ref.handler->release();
422         }
423         catch (const MediaException & ex)
424         {
425           ZYPP_CAUGHT(ex);
426
427           if (!ref.handler->hasMoreDevices())
428             ZYPP_RETHROW(ex);
429
430           AttachedMedia media(ref.handler->attachedMedia());
431           DBG << "Skipping " << media.mediaSource->asString() << " because of exception thrown by attach(true)" << std::endl;
432
433           if (ref.handler->isAttached()) ref.handler->release();
434         }
435       }
436     }
437
438     // ---------------------------------------------------------------
439     void
440     MediaManager::release(MediaAccessId accessId, const std::string & ejectDev)
441     {
442       ManagedMedia &ref( m_impl->findMM(accessId));
443
444       DBG << "release(id=" << accessId;
445       if (!ejectDev.empty())
446         DBG << ", " << ejectDev;
447       DBG << ")" << std::endl;
448
449       if(!ejectDev.empty())
450       {
451         //
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
455         // with eject).
456         //
457         ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
458         for( ; m != m_impl->mediaMap.end(); ++m)
459         {
460           if( m->second.handler->dependsOnParent(accessId, false))
461           {
462             try
463             {
464               DBG << "Forcing release of handler depending on access id "
465                   << accessId << std::endl;
466               m->second.desired  = false;
467               m->second.handler->release();
468             }
469             catch(const MediaException &e)
470             {
471               ZYPP_CAUGHT(e);
472             }
473           }
474         }
475       }
476       ref.desired  = false;
477       ref.handler->release(ejectDev);
478     }
479
480     // ---------------------------------------------------------------
481     void
482     MediaManager::releaseAll()
483     {
484       MIL << "Releasing all attached media" << std::endl;
485
486       ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
487       for( ; m != m_impl->mediaMap.end(); ++m)
488       {
489         if( m->second.handler->dependsOnParent())
490           continue;
491
492         try
493         {
494           if(m->second.handler->isAttached())
495           {
496             DBG << "Releasing media id " << m->first << std::endl;
497             m->second.desired  = false;
498             m->second.handler->release();
499           }
500           else
501           {
502             DBG << "Media id " << m->first << " not attached " << std::endl;
503           }
504         }
505         catch(const MediaException & e)
506         {
507           ZYPP_CAUGHT(e);
508           ERR << "Failed to release media id " << m->first << std::endl;
509         }
510       }
511
512       MIL << "Exit" << std::endl;
513     }
514
515     // ---------------------------------------------------------------
516     void
517     MediaManager::disconnect(MediaAccessId accessId)
518     {
519       ManagedMedia &ref( m_impl->findMM(accessId));
520
521       ref.handler->disconnect();
522     }
523
524     // ---------------------------------------------------------------
525     bool
526     MediaManager::isAttached(MediaAccessId accessId) const
527     {
528       ManagedMedia &ref( m_impl->findMM(accessId));
529
530       return ref.handler->isAttached();
531     }
532
533     // ---------------------------------------------------------------
534     bool MediaManager::isSharedMedia(MediaAccessId accessId) const
535     {
536       ManagedMedia &ref( m_impl->findMM(accessId));
537
538       return ref.handler->isSharedMedia();
539     }
540
541     // ---------------------------------------------------------------
542     bool
543     MediaManager::isDesiredMedia(MediaAccessId accessId) const
544     {
545       ManagedMedia &ref( m_impl->findMM(accessId));
546
547       if( !ref.handler->isAttached())
548       {
549         ref.desired = false;
550       }
551       else
552       {
553         try {
554           ref.desired = ref.verifier->isDesiredMedia(ref.handler);
555         }
556         catch(const zypp::Exception &e) {
557           ZYPP_CAUGHT(e);
558           ref.desired = false;
559         }
560       }
561       DBG << "isDesiredMedia(" << accessId << "): "
562           << (ref.desired ? "" : "not ")
563           << "desired (report by "
564           << ref.verifier->info() << ")" << std::endl;
565       return ref.desired;
566     }
567
568     // ---------------------------------------------------------------
569     bool
570     MediaManager::isDesiredMedia(MediaAccessId           accessId,
571                                  const MediaVerifierRef &verifier) const
572     {
573       MediaVerifierRef v(verifier);
574       if( !v)
575         ZYPP_THROW(MediaException("Invalid verifier reference"));
576
577       ManagedMedia &ref( m_impl->findMM(accessId));
578
579       bool desired = false;
580       if( ref.handler->isAttached())
581       {
582         try {
583           desired = v->isDesiredMedia(ref.handler);
584         }
585         catch(const zypp::Exception &e) {
586           ZYPP_CAUGHT(e);
587           desired = false;
588         }
589       }
590       DBG << "isDesiredMedia(" << accessId << "): "
591           << (desired ? "" : "not ")
592           << "desired (report by "
593           << v->info() << ")" << std::endl;
594       return desired;
595     }
596
597     // ---------------------------------------------------------------
598     bool
599     MediaManager::isChangeable(MediaAccessId accessId)
600     {
601       return url(accessId).getScheme() == "cd" || url(accessId).getScheme() == "dvd";
602     }
603
604     // ---------------------------------------------------------------
605     Pathname
606     MediaManager::localRoot(MediaAccessId accessId) const
607     {
608       ManagedMedia &ref( m_impl->findMM(accessId));
609
610       Pathname path;
611       path = ref.handler->localRoot();
612       return path;
613     }
614
615     // ---------------------------------------------------------------
616     Pathname
617     MediaManager::localPath(MediaAccessId accessId,
618                             const Pathname & pathname) const
619     {
620       ManagedMedia &ref( m_impl->findMM(accessId));
621
622       Pathname path;
623       path = ref.handler->localPath(pathname);
624       return path;
625     }
626
627     void
628     MediaManager::provideFile(MediaAccessId   accessId,
629                               const Pathname &filename,
630                               const ByteCount &expectedFileSize ) const
631     {
632       ManagedMedia &ref( m_impl->findMM(accessId));
633
634       ref.checkDesired(accessId);
635
636       ref.handler->provideFile(filename, expectedFileSize);
637     }
638
639     // ---------------------------------------------------------------
640     void
641     MediaManager::provideFile(MediaAccessId   accessId,
642                               const Pathname &filename ) const
643     {
644       provideFile( accessId, filename, 0);
645     }
646
647     // ---------------------------------------------------------------
648     void
649     MediaManager::setDeltafile(MediaAccessId   accessId,
650                               const Pathname &filename ) const
651     {
652       ManagedMedia &ref( m_impl->findMM(accessId));
653
654       ref.checkDesired(accessId);
655
656       ref.handler->setDeltafile(filename);
657     }
658
659     // ---------------------------------------------------------------
660     void
661     MediaManager::provideDir(MediaAccessId   accessId,
662                              const Pathname &dirname) const
663     {
664       ManagedMedia &ref( m_impl->findMM(accessId));
665
666       ref.checkDesired(accessId);
667
668       ref.handler->provideDir(dirname);
669     }
670
671     // ---------------------------------------------------------------
672     void
673     MediaManager::provideDirTree(MediaAccessId   accessId,
674                                  const Pathname &dirname) const
675     {
676       ManagedMedia &ref( m_impl->findMM(accessId));
677
678       ref.checkDesired(accessId);
679
680       ref.handler->provideDirTree(dirname);
681     }
682
683     // ---------------------------------------------------------------
684     void
685     MediaManager::releaseFile(MediaAccessId   accessId,
686                               const Pathname &filename) const
687     {
688       ManagedMedia &ref( m_impl->findMM(accessId));
689
690       ref.checkAttached(accessId);
691
692       ref.handler->releaseFile(filename);
693     }
694
695     // ---------------------------------------------------------------
696     void
697     MediaManager::releaseDir(MediaAccessId   accessId,
698                              const Pathname &dirname) const
699     {
700       ManagedMedia &ref( m_impl->findMM(accessId));
701
702       ref.checkAttached(accessId);
703
704       ref.handler->releaseDir(dirname);
705     }
706
707
708     // ---------------------------------------------------------------
709     void
710     MediaManager::releasePath(MediaAccessId   accessId,
711                               const Pathname &pathname) const
712     {
713       ManagedMedia &ref( m_impl->findMM(accessId));
714
715       ref.checkAttached(accessId);
716
717       ref.handler->releasePath(pathname);
718     }
719
720     // ---------------------------------------------------------------
721     void
722     MediaManager::dirInfo(MediaAccessId           accessId,
723                           std::list<std::string> &retlist,
724                           const Pathname         &dirname,
725                           bool                    dots) const
726     {
727       ManagedMedia &ref( m_impl->findMM(accessId));
728
729       // FIXME: ref.checkDesired(accessId); ???
730       ref.checkAttached(accessId);
731
732       ref.handler->dirInfo(retlist, dirname, dots);
733     }
734
735     // ---------------------------------------------------------------
736     void
737     MediaManager::dirInfo(MediaAccessId           accessId,
738                           filesystem::DirContent &retlist,
739                           const Pathname         &dirname,
740                           bool                    dots) const
741     {
742       ManagedMedia &ref( m_impl->findMM(accessId));
743
744       // FIXME: ref.checkDesired(accessId); ???
745       ref.checkAttached(accessId);
746
747       ref.handler->dirInfo(retlist, dirname, dots);
748     }
749
750     // ---------------------------------------------------------------
751     bool
752     MediaManager::doesFileExist(MediaAccessId  accessId, const Pathname & filename ) const
753     {
754       ManagedMedia &ref( m_impl->findMM(accessId));
755
756       // FIXME: ref.checkDesired(accessId); ???
757       ref.checkAttached(accessId);
758
759       return ref.handler->doesFileExist(filename);
760     }
761
762     // ---------------------------------------------------------------
763     void
764     MediaManager::getDetectedDevices(MediaAccessId accessId,
765                                      std::vector<std::string> & devices,
766                                      unsigned int & index) const
767     {
768       ManagedMedia &ref( m_impl->findMM(accessId));
769       return ref.handler->getDetectedDevices(devices, index);
770     }
771
772     // ---------------------------------------------------------------
773     // STATIC
774     time_t
775     MediaManager::getMountTableMTime()
776     {
777       return MediaManager_Impl::getMountTableMTime();
778     }
779
780     // ---------------------------------------------------------------
781     // STATIC
782     MountEntries
783     MediaManager::getMountEntries()
784     {
785       return MediaManager_Impl::getMountEntries();
786     }
787
788     // ---------------------------------------------------------------
789     bool
790     MediaManager::isUseableAttachPoint(const Pathname &path,
791                                        bool            mtab) const
792     {
793       if( path.empty() || path == "/" || !PathInfo(path).isDir())
794         return false;
795
796       //
797       // check against our current attach points
798       //
799       ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin());
800       for( ; m != m_impl->mediaMap.end(); ++m)
801       {
802         AttachedMedia ret = m->second.handler->attachedMedia();
803         if( ret.mediaSource && ret.attachPoint)
804         {
805           std::string mnt(ret.attachPoint->path.asString());
806           std::string our(path.asString());
807
808           if( our == mnt)
809           {
810             // already used as attach point
811             return false;
812           }
813           else
814           if( mnt.size() > our.size()   &&
815               mnt.at(our.size()) == '/' &&
816              !mnt.compare(0, our.size(), our))
817           {
818             // mountpoint is bellow of path
819             // (would hide the content)
820             return false;
821           }
822         }
823       }
824
825       if( !mtab)
826         return true;
827
828       //
829       // check against system mount entries
830       //
831       MountEntries  entries( m_impl->getMountEntries());
832       MountEntries::const_iterator e;
833       for( e = entries.begin(); e != entries.end(); ++e)
834       {
835         std::string mnt(Pathname(e->dir).asString());
836         std::string our(path.asString());
837
838         if( our == mnt)
839         {
840           // already used as mountpoint
841           return false;
842         }
843         else
844         if( mnt.size() > our.size()   &&
845             mnt.at(our.size()) == '/' &&
846            !mnt.compare(0, our.size(), our))
847         {
848           // mountpoint is bellow of path
849           // (would hide the content)
850           return false;
851         }
852       }
853
854       return true;
855     }
856
857     // ---------------------------------------------------------------
858     AttachedMedia
859     MediaManager::getAttachedMedia(MediaAccessId &accessId) const
860     {
861       ManagedMedia &ref( m_impl->findMM(accessId));
862
863       return ref.handler->attachedMedia();
864     }
865
866     // ---------------------------------------------------------------
867     AttachedMedia
868     MediaManager::findAttachedMedia(const MediaSourceRef &media) const
869     {
870       if( !media || media->type.empty())
871         return AttachedMedia();
872
873       ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin());
874       for( ; m != m_impl->mediaMap.end(); ++m)
875       {
876         if( !m->second.handler->isAttached())
877           continue;
878
879         AttachedMedia ret = m->second.handler->attachedMedia();
880         if( ret.mediaSource && ret.mediaSource->equals( *media))
881             return ret;
882       }
883       return AttachedMedia();
884     }
885
886     // ---------------------------------------------------------------
887     void
888     MediaManager::forceReleaseShared(const MediaSourceRef &media)
889     {
890       if( !media || media->type.empty())
891         return;
892
893       ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
894       for( ; m != m_impl->mediaMap.end(); ++m)
895       {
896         if( !m->second.handler->isAttached())
897           continue;
898
899         AttachedMedia ret = m->second.handler->attachedMedia();
900         if( ret.mediaSource && ret.mediaSource->equals( *media))
901         {
902           m->second.handler->release();
903           m->second.desired  = false;
904         }
905       }
906     }
907
908     //////////////////////////////////////////////////////////////////
909   } // namespace media
910   ////////////////////////////////////////////////////////////////////
911
912   ////////////////////////////////////////////////////////////////////
913 } // namespace zypp
914 //////////////////////////////////////////////////////////////////////
915 /*
916 ** vim: set ts=2 sts=2 sw=2 ai et:
917 */