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