d4956d48823786b1c5dbd2bbfb86d943aeb043ce
[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 #include "zypp/target/hal/HalContext.h"
24
25 #include "zypp/base/String.h"
26 #include "zypp/base/Logger.h"
27 #include "zypp/Pathname.h"
28 #include "zypp/PathInfo.h"
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, const std::string & ejectDev)
648     {
649       MutexLock glock(g_Mutex);
650
651       ManagedMedia &ref( m_impl->findMM(accessId));
652
653       DBG << "release(id=" << accessId;
654       if (!ejectDev.empty())
655         DBG << ", " << ejectDev;
656       DBG << ")" << std::endl;
657
658       if(!ejectDev.empty())
659       {
660         //
661         // release MediaISO handlers, that are using the one
662         // specified with accessId, because it provides the
663         // iso file and it will disappear now (forced release
664         // with eject).
665         //
666         ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
667         for( ; m != m_impl->mediaMap.end(); ++m)
668         {
669           if( m->second.handler->dependsOnParent(accessId, false))
670           {
671             try
672             {
673               DBG << "Forcing release of handler depending on access id "
674                   << accessId << std::endl;
675               m->second.desired  = false;
676               m->second.handler->release();
677             }
678             catch(const MediaException &e)
679             {
680               ZYPP_CAUGHT(e);
681             }
682           }
683         }
684       }
685       ref.desired  = false;
686       ref.handler->release(ejectDev);
687     }
688
689     // ---------------------------------------------------------------
690     void
691     MediaManager::releaseAll()
692     {
693       MutexLock glock(g_Mutex);
694
695       MIL << "Releasing all attached media" << std::endl;
696
697       ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
698       for( ; m != m_impl->mediaMap.end(); ++m)
699       {
700         if( m->second.handler->dependsOnParent())
701           continue;
702
703         try
704         {
705           if(m->second.handler->isAttached())
706           {
707             DBG << "Releasing media id " << m->first << std::endl;
708             m->second.desired  = false;
709             m->second.handler->release();
710           }
711           else
712           {
713             DBG << "Media id " << m->first << " not attached " << std::endl;
714           }
715         }
716         catch(const MediaException & e)
717         {
718           ZYPP_CAUGHT(e);
719           ERR << "Failed to release media id " << m->first << std::endl;
720         }
721       }
722
723       MIL << "Exit" << std::endl;
724     }
725
726     // ---------------------------------------------------------------
727     void
728     MediaManager::disconnect(MediaAccessId accessId)
729     {
730       MutexLock glock(g_Mutex);
731
732       ManagedMedia &ref( m_impl->findMM(accessId));
733
734       ref.handler->disconnect();
735     }
736
737     // ---------------------------------------------------------------
738     bool
739     MediaManager::isAttached(MediaAccessId accessId) const
740     {
741       MutexLock glock(g_Mutex);
742
743       ManagedMedia &ref( m_impl->findMM(accessId));
744
745       return ref.handler->isAttached();
746     }
747
748     // ---------------------------------------------------------------
749     bool MediaManager::isSharedMedia(MediaAccessId accessId) const
750     {
751       MutexLock glock(g_Mutex);
752
753       ManagedMedia &ref( m_impl->findMM(accessId));
754
755       return ref.handler->isSharedMedia();
756     }
757
758     // ---------------------------------------------------------------
759     bool
760     MediaManager::isDesiredMedia(MediaAccessId accessId) const
761     {
762       MutexLock glock(g_Mutex);
763
764       ManagedMedia &ref( m_impl->findMM(accessId));
765
766       if( !ref.handler->isAttached())
767       {
768         ref.desired = false;
769       }
770       else
771       {
772         try {
773           ref.desired = ref.verifier->isDesiredMedia(ref.handler);
774         }
775         catch(const zypp::Exception &e) {
776           ZYPP_CAUGHT(e);
777           ref.desired = false;
778         }
779       }
780       DBG << "isDesiredMedia(" << accessId << "): "
781           << (ref.desired ? "" : "not ")
782           << "desired (report by "
783           << ref.verifier->info() << ")" << std::endl;
784       return ref.desired;
785     }
786
787     // ---------------------------------------------------------------
788     bool
789     MediaManager::isDesiredMedia(MediaAccessId           accessId,
790                                  const MediaVerifierRef &verifier) const
791     {
792       MutexLock glock(g_Mutex);
793
794       MediaVerifierRef v(verifier);
795       if( !v)
796         ZYPP_THROW(MediaException("Invalid verifier reference"));
797
798       ManagedMedia &ref( m_impl->findMM(accessId));
799
800       bool desired = false;
801       if( ref.handler->isAttached())
802       {
803         try {
804           desired = v->isDesiredMedia(ref.handler);
805         }
806         catch(const zypp::Exception &e) {
807           ZYPP_CAUGHT(e);
808           desired = false;
809         }
810       }
811       DBG << "isDesiredMedia(" << accessId << "): "
812           << (desired ? "" : "not ")
813           << "desired (report by "
814           << v->info() << ")" << std::endl;
815       return desired;
816     }
817
818     // ---------------------------------------------------------------
819     bool
820     MediaManager::isChangeable(MediaAccessId accessId)
821     {
822       return url(accessId).getScheme() == "cd" || url(accessId).getScheme() == "dvd";
823     }
824
825     // ---------------------------------------------------------------
826     Pathname
827     MediaManager::localRoot(MediaAccessId accessId) const
828     {
829       MutexLock glock(g_Mutex);
830
831       ManagedMedia &ref( m_impl->findMM(accessId));
832
833       Pathname path;
834       path = ref.handler->localRoot();
835       return path;
836     }
837
838     // ---------------------------------------------------------------
839     Pathname
840     MediaManager::localPath(MediaAccessId accessId,
841                             const Pathname & pathname) const
842     {
843       MutexLock glock(g_Mutex);
844
845       ManagedMedia &ref( m_impl->findMM(accessId));
846
847       Pathname path;
848       path = ref.handler->localPath(pathname);
849       return path;
850     }
851
852     // ---------------------------------------------------------------
853     void
854     MediaManager::provideFile(MediaAccessId   accessId,
855                               const Pathname &filename ) const
856     {
857       MutexLock glock(g_Mutex);
858
859       ManagedMedia &ref( m_impl->findMM(accessId));
860
861       ref.checkDesired(accessId);
862
863       ref.handler->provideFile(filename);
864     }
865
866     // ---------------------------------------------------------------
867     void
868     MediaManager::provideDir(MediaAccessId   accessId,
869                              const Pathname &dirname) const
870     {
871       MutexLock glock(g_Mutex);
872
873       ManagedMedia &ref( m_impl->findMM(accessId));
874
875       ref.checkDesired(accessId);
876
877       ref.handler->provideDir(dirname);
878     }
879
880     // ---------------------------------------------------------------
881     void
882     MediaManager::provideDirTree(MediaAccessId   accessId,
883                                  const Pathname &dirname) const
884     {
885       MutexLock glock(g_Mutex);
886
887       ManagedMedia &ref( m_impl->findMM(accessId));
888
889       ref.checkDesired(accessId);
890
891       ref.handler->provideDirTree(dirname);
892     }
893
894     // ---------------------------------------------------------------
895     void
896     MediaManager::releaseFile(MediaAccessId   accessId,
897                               const Pathname &filename) const
898     {
899       MutexLock glock(g_Mutex);
900
901       ManagedMedia &ref( m_impl->findMM(accessId));
902
903       ref.checkAttached(accessId);
904
905       ref.handler->releaseFile(filename);
906     }
907
908     // ---------------------------------------------------------------
909     void
910     MediaManager::releaseDir(MediaAccessId   accessId,
911                              const Pathname &dirname) const
912     {
913       MutexLock glock(g_Mutex);
914
915       ManagedMedia &ref( m_impl->findMM(accessId));
916
917       ref.checkAttached(accessId);
918
919       ref.handler->releaseDir(dirname);
920     }
921
922
923     // ---------------------------------------------------------------
924     void
925     MediaManager::releasePath(MediaAccessId   accessId,
926                               const Pathname &pathname) const
927     {
928       MutexLock glock(g_Mutex);
929
930       ManagedMedia &ref( m_impl->findMM(accessId));
931
932       ref.checkAttached(accessId);
933
934       ref.handler->releasePath(pathname);
935     }
936
937     // ---------------------------------------------------------------
938     void
939     MediaManager::dirInfo(MediaAccessId           accessId,
940                           std::list<std::string> &retlist,
941                           const Pathname         &dirname,
942                           bool                    dots) const
943     {
944       MutexLock glock(g_Mutex);
945
946       ManagedMedia &ref( m_impl->findMM(accessId));
947
948       // FIXME: ref.checkDesired(accessId); ???
949       ref.checkAttached(accessId);
950
951       ref.handler->dirInfo(retlist, dirname, dots);
952     }
953
954     // ---------------------------------------------------------------
955     void
956     MediaManager::dirInfo(MediaAccessId           accessId,
957                           filesystem::DirContent &retlist,
958                           const Pathname         &dirname,
959                           bool                    dots) const
960     {
961       MutexLock glock(g_Mutex);
962
963       ManagedMedia &ref( m_impl->findMM(accessId));
964
965       // FIXME: ref.checkDesired(accessId); ???
966       ref.checkAttached(accessId);
967
968       ref.handler->dirInfo(retlist, dirname, dots);
969     }
970
971     // ---------------------------------------------------------------
972     bool
973     MediaManager::doesFileExist(MediaAccessId  accessId, const Pathname & filename ) const
974     {
975       MutexLock glock(g_Mutex);
976       ManagedMedia &ref( m_impl->findMM(accessId));
977
978       // FIXME: ref.checkDesired(accessId); ???
979       ref.checkAttached(accessId);
980
981       return ref.handler->doesFileExist(filename);
982     }
983
984     // ---------------------------------------------------------------
985     void
986     MediaManager::getDetectedDevices(MediaAccessId accessId,
987                                      std::vector<std::string> & devices,
988                                      unsigned int & index) const
989     {
990       MutexLock glock(g_Mutex);
991       ManagedMedia &ref( m_impl->findMM(accessId));
992       return ref.handler->getDetectedDevices(devices, index);
993     }
994
995     // ---------------------------------------------------------------
996     // STATIC
997     time_t
998     MediaManager::getMountTableMTime()
999     {
1000       MutexLock glock(g_Mutex);
1001       return MediaManager_Impl::getMountTableMTime();
1002     }
1003
1004     // ---------------------------------------------------------------
1005     // STATIC
1006     MountEntries
1007     MediaManager::getMountEntries()
1008     {
1009       MutexLock glock(g_Mutex);
1010
1011       return MediaManager_Impl::getMountEntries();
1012     }
1013
1014     // ---------------------------------------------------------------
1015     bool
1016     MediaManager::isUseableAttachPoint(const Pathname &path,
1017                                        bool            mtab) const
1018     {
1019       if( path.empty() || path == "/" || !PathInfo(path).isDir())
1020         return false;
1021
1022       MutexLock glock(g_Mutex);
1023
1024       //
1025       // check against our current attach points
1026       //
1027       ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin());
1028       for( ; m != m_impl->mediaMap.end(); ++m)
1029       {
1030         AttachedMedia ret = m->second.handler->attachedMedia();
1031         if( ret.mediaSource && ret.attachPoint)
1032         {
1033           std::string mnt(ret.attachPoint->path.asString());
1034           std::string our(path.asString());
1035
1036           if( our == mnt)
1037           {
1038             // already used as attach point
1039             return false;
1040           }
1041           else
1042           if( mnt.size() > our.size()   &&
1043               mnt.at(our.size()) == '/' &&
1044              !mnt.compare(0, our.size(), our))
1045           {
1046             // mountpoint is bellow of path
1047             // (would hide the content)
1048             return false;
1049           }
1050         }
1051       }
1052
1053       if( !mtab)
1054         return true;
1055
1056       //
1057       // check against system mount entries
1058       //
1059       MountEntries  entries( m_impl->getMountEntries());
1060       MountEntries::const_iterator e;
1061       for( e = entries.begin(); e != entries.end(); ++e)
1062       {
1063         std::string mnt(Pathname(e->dir).asString());
1064         std::string our(path.asString());
1065
1066         if( our == mnt)
1067         {
1068           // already used as mountpoint
1069           return false;
1070         }
1071         else
1072         if( mnt.size() > our.size()   &&
1073             mnt.at(our.size()) == '/' &&
1074            !mnt.compare(0, our.size(), our))
1075         {
1076           // mountpoint is bellow of path
1077           // (would hide the content)
1078           return false;
1079         }
1080       }
1081
1082       return true;
1083     }
1084
1085     // ---------------------------------------------------------------
1086     AttachedMedia
1087     MediaManager::getAttachedMedia(MediaAccessId &accessId) const
1088     {
1089       MutexLock glock(g_Mutex);
1090
1091       ManagedMedia &ref( m_impl->findMM(accessId));
1092
1093       return ref.handler->attachedMedia();
1094     }
1095
1096     // ---------------------------------------------------------------
1097     AttachedMedia
1098     MediaManager::findAttachedMedia(const MediaSourceRef &media) const
1099     {
1100       MutexLock glock(g_Mutex);
1101
1102       if( !media || media->type.empty())
1103         return AttachedMedia();
1104
1105       ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin());
1106       for( ; m != m_impl->mediaMap.end(); ++m)
1107       {
1108         if( !m->second.handler->isAttached())
1109           continue;
1110
1111         AttachedMedia ret = m->second.handler->attachedMedia();
1112         if( ret.mediaSource && ret.mediaSource->equals( *media))
1113             return ret;
1114       }
1115       return AttachedMedia();
1116     }
1117
1118     // ---------------------------------------------------------------
1119     void
1120     MediaManager::forceReleaseShared(const MediaSourceRef &media)
1121     {
1122       MutexLock glock(g_Mutex);
1123
1124       if( !media || media->type.empty())
1125         return;
1126
1127       ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
1128       for( ; m != m_impl->mediaMap.end(); ++m)
1129       {
1130         if( !m->second.handler->isAttached())
1131           continue;
1132
1133         AttachedMedia ret = m->second.handler->attachedMedia();
1134         if( ret.mediaSource && ret.mediaSource->equals( *media))
1135         {
1136           m->second.handler->release();
1137           m->second.desired  = false;
1138         }
1139       }
1140     }
1141
1142     //////////////////////////////////////////////////////////////////
1143   } // namespace media
1144   ////////////////////////////////////////////////////////////////////
1145
1146   ////////////////////////////////////////////////////////////////////
1147 } // namespace zypp
1148 //////////////////////////////////////////////////////////////////////
1149 /*
1150 ** vim: set ts=2 sts=2 sw=2 ai et:
1151 */