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