- Added getMountTableMTime() and getMountEntries()
[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/Mount.h>
15 //#include <zypp/media/Hal.h>
16 #include <zypp/thread/Mutex.h>
17 #include <zypp/thread/MutexLock.h>
18
19 #include <zypp/base/String.h>
20 #include <zypp/base/Logger.h>
21 #include <zypp/Pathname.h>
22 #include <zypp/PathInfo.h>
23
24 #include <map>
25 #include <list>
26 #include <iostream>
27
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()
74         {
75           if( !handler->isAttached())
76           {
77             desired = false;
78             ZYPP_THROW(MediaNotAttachedException(
79               handler->url()
80             ));
81           }
82         }
83
84         inline void
85         checkDesired()
86         {
87           checkAttached();
88
89           if( !desired)
90           {
91             try {
92               desired = verifier->isDesiredMedia(handler);
93             }
94             catch(const zypp::Exception &e) {
95               ZYPP_CAUGHT(e);
96               desired = false;
97             }
98
99             if( !desired)
100             {
101               ZYPP_THROW(MediaNotDesiredException(
102                 handler->url()
103               ));
104             }
105
106             DBG << "checkDesired(): desired (report)" << std::endl;
107           } else {
108             DBG << "checkDesired(): desired (cached)" << std::endl;
109           }
110         }
111
112         bool             desired;
113         MediaAccessRef   handler;
114         MediaVerifierRef verifier;
115       };
116
117
118       // -------------------------------------------------------------
119       typedef std::map<MediaAccessId, ManagedMedia> ManagedMediaMap;
120
121
122       ////////////////////////////////////////////////////////////////
123     } // anonymous
124     //////////////////////////////////////////////////////////////////
125
126
127     //////////////////////////////////////////////////////////////////
128     class MediaManager::Impl
129     {
130     private:
131       time_t        mtab_mtime;
132       MountEntries  mtab_table;
133       MediaAccessId last_accessid;
134
135     public:
136       ManagedMediaMap mediaMap;
137
138       Impl()
139         : mtab_mtime(0)
140         , mtab_table()
141         , last_accessid(0)
142       {}
143
144       ~Impl()
145       {
146         try
147         {
148           mtab_table.clear();
149           mediaMap.clear();
150         }
151         catch( ... )
152         {}
153       }
154
155       inline MediaAccessId
156       nextAccessId()
157       {
158         return ++last_accessid;
159       }
160
161       inline bool
162       hasId(MediaAccessId accessId) const
163       {
164         return mediaMap.find(accessId) != mediaMap.end();
165       }
166
167       inline ManagedMedia &
168       findMM(MediaAccessId accessId)
169       {
170         ManagedMediaMap::iterator it( mediaMap.find(accessId));
171         if( it == mediaMap.end())
172         {
173           ZYPP_THROW(MediaNotOpenException(
174             "Invalid media access id " + str::numstring(accessId)
175           ));
176         }
177         return it->second;
178       }
179
180       inline time_t
181       getMountTableMTime() const
182       {
183         return zypp::PathInfo("/etc/mtab").mtime();
184       }
185
186       inline MountEntries
187       getMountEntries()
188       {
189         time_t old = mtab_mtime;
190         mtab_mtime = getMountTableMTime();
191         if( old <= 0 || mtab_mtime != old)
192         {
193           mtab_table = Mount::getEntries("/etc/mtab");
194         }
195         return mtab_table;
196       }
197
198     };
199
200
201     //////////////////////////////////////////////////////////////////
202     // STATIC
203     zypp::RW_pointer<MediaManager::Impl> MediaManager::m_impl(NULL);
204
205
206     //////////////////////////////////////////////////////////////////
207     MediaManager::MediaManager()
208     {
209       MutexLock glock(g_Mutex);
210       if( !m_impl)
211       {
212         m_impl.reset( new MediaManager::Impl());
213       }
214     }
215
216     // ---------------------------------------------------------------
217     MediaManager::~MediaManager()
218     {
219     }
220
221     // ---------------------------------------------------------------
222     MediaAccessId
223     MediaManager::open(const Url &url, const Pathname &preferred_attach_point)
224     {
225       MutexLock glock(g_Mutex);
226
227       // create new access handler for it
228       MediaAccessRef handler( new MediaAccess());
229       MediaVerifierRef verifier( new NoVerifier());
230       ManagedMedia tmp( handler, verifier);
231
232       tmp.handler->open(url, preferred_attach_point);
233
234       MediaAccessId nextId = m_impl->nextAccessId();
235
236       m_impl->mediaMap[nextId] = tmp;
237
238       DBG << "Opened new media access using id " << nextId
239           << " to " << url.asString() << std::endl;
240       return nextId;
241     }
242
243     // ---------------------------------------------------------------
244     void
245     MediaManager::close(MediaAccessId accessId)
246     {
247       MutexLock glock(g_Mutex);
248
249       ManagedMedia &ref( m_impl->findMM(accessId));
250
251       ref.handler->close();
252       m_impl->mediaMap.erase(accessId);
253     }
254
255     // ---------------------------------------------------------------
256     bool
257     MediaManager::isOpen(MediaAccessId accessId) const
258     {
259       MutexLock glock(g_Mutex);
260
261       ManagedMediaMap::iterator it( m_impl->mediaMap.find(accessId));
262       return it != m_impl->mediaMap.end() &&
263              it->second.handler->isOpen();
264     }
265
266     // ---------------------------------------------------------------
267     std::string
268     MediaManager::protocol(MediaAccessId accessId) const
269     {
270       MutexLock glock(g_Mutex);
271
272       ManagedMedia &ref( m_impl->findMM(accessId));
273
274       return ref.handler->protocol();
275     }
276
277     // ---------------------------------------------------------------
278     Url
279     MediaManager::url(MediaAccessId accessId) const
280     {
281       MutexLock glock(g_Mutex);
282
283       ManagedMedia &ref( m_impl->findMM(accessId));
284
285       return ref.handler->url();
286     }
287
288     // ---------------------------------------------------------------
289     void
290     MediaManager::addVerifier(MediaAccessId           accessId,
291                               const MediaVerifierRef &verifier)
292     {
293       MutexLock glock(g_Mutex);
294
295       if( !verifier)
296         ZYPP_THROW(MediaException("Invalid verifier reference"));
297
298       ManagedMedia &ref( m_impl->findMM(accessId));
299
300       MediaVerifierRef(verifier).swap(ref.verifier);
301       ref.desired = false;
302     }
303
304     // ---------------------------------------------------------------
305     void
306     MediaManager::delVerifier(MediaAccessId accessId)
307     {
308       MutexLock glock(g_Mutex);
309
310       ManagedMedia &ref( m_impl->findMM(accessId));
311
312       MediaVerifierRef verifier( new NoVerifier());
313       ref.verifier.swap(verifier);
314       ref.desired  = false;
315     }
316
317     // ---------------------------------------------------------------
318     void
319     MediaManager::attach(MediaAccessId accessId, bool next)
320     {
321       MutexLock glock(g_Mutex);
322
323       ManagedMedia &ref( m_impl->findMM(accessId));
324
325       return ref.handler->attach(next);
326     }
327
328     // ---------------------------------------------------------------
329     void
330     MediaManager::release(MediaAccessId accessId, bool eject)
331     {
332       MutexLock glock(g_Mutex);
333
334       ManagedMedia &ref( m_impl->findMM(accessId));
335
336       ref.handler->release(eject);
337       ref.desired  = false;
338     }
339
340     // ---------------------------------------------------------------
341     void
342     MediaManager::disconnect(MediaAccessId accessId)
343     {
344       MutexLock glock(g_Mutex);
345
346       ManagedMedia &ref( m_impl->findMM(accessId));
347
348       ref.handler->disconnect();
349     }
350
351     // ---------------------------------------------------------------
352     bool
353     MediaManager::isAttached(MediaAccessId accessId) const
354     {
355       MutexLock glock(g_Mutex);
356
357       ManagedMedia &ref( m_impl->findMM(accessId));
358
359       return ref.handler->isAttached();
360     }
361
362     // ---------------------------------------------------------------
363     bool
364     MediaManager::isDesiredMedia(MediaAccessId accessId) const
365     {
366       MutexLock glock(g_Mutex);
367
368       ManagedMedia &ref( m_impl->findMM(accessId));
369
370       if( !ref.handler->isAttached())
371       {
372         ref.desired = false;
373       }
374       else
375       {
376         try {
377           ref.desired = ref.verifier->isDesiredMedia(ref.handler);
378         }
379         catch(const zypp::Exception &e) {
380           ZYPP_CAUGHT(e);
381           ref.desired = false;
382         }
383       }
384       return ref.desired;
385     }
386
387     // ---------------------------------------------------------------
388     bool
389     MediaManager::isDesiredMedia(MediaAccessId           accessId,
390                                  const MediaVerifierRef &verifier) const
391     {
392       MutexLock glock(g_Mutex);
393
394       MediaVerifierRef v(verifier);
395       if( !v)
396         ZYPP_THROW(MediaException("Invalid verifier reference"));
397
398       ManagedMedia &ref( m_impl->findMM(accessId));
399
400       bool desired = false;
401       if( ref.handler->isAttached())
402       {
403         try {
404           desired = v->isDesiredMedia(ref.handler);
405         }
406         catch(const zypp::Exception &e) {
407           ZYPP_CAUGHT(e);
408           desired = false;
409         }
410       }
411       return desired;
412     }
413
414     // ---------------------------------------------------------------
415     Pathname
416     MediaManager::localRoot(MediaAccessId accessId) const
417     {
418       MutexLock glock(g_Mutex);
419
420       ManagedMedia &ref( m_impl->findMM(accessId));
421
422       Pathname path;
423       path = ref.handler->localRoot();
424       return path;
425     }
426
427     // ---------------------------------------------------------------
428     Pathname
429     MediaManager::localPath(MediaAccessId accessId,
430                             const Pathname & pathname) const
431     {
432       MutexLock glock(g_Mutex);
433
434       ManagedMedia &ref( m_impl->findMM(accessId));
435
436       Pathname path;
437       path = ref.handler->localPath(pathname);
438       return path;
439     }
440
441     // ---------------------------------------------------------------
442     void
443     MediaManager::provideFile(MediaAccessId   accessId,
444                               const Pathname &filename,
445                               bool            cached,
446                               bool            checkonly) const
447     {
448       MutexLock glock(g_Mutex);
449
450       ManagedMedia &ref( m_impl->findMM(accessId));
451
452       ref.checkDesired();
453
454       ref.handler->provideFile(filename, cached, checkonly);
455     }
456
457     // ---------------------------------------------------------------
458     void
459     MediaManager::provideDir(MediaAccessId   accessId,
460                              const Pathname &dirname) const
461     {
462       MutexLock glock(g_Mutex);
463
464       ManagedMedia &ref( m_impl->findMM(accessId));
465
466       ref.checkDesired();
467
468       ref.handler->provideDir(dirname);
469     }
470
471     // ---------------------------------------------------------------
472     void
473     MediaManager::provideDirTree(MediaAccessId   accessId,
474                                  const Pathname &dirname) const
475     {
476       MutexLock glock(g_Mutex);
477
478       ManagedMedia &ref( m_impl->findMM(accessId));
479
480       ref.checkDesired();
481
482       ref.handler->provideDirTree(dirname);
483     }
484
485     // ---------------------------------------------------------------
486     void
487     MediaManager::releaseFile(MediaAccessId   accessId,
488                               const Pathname &filename) const
489     {
490       MutexLock glock(g_Mutex);
491
492       ManagedMedia &ref( m_impl->findMM(accessId));
493
494       ref.checkAttached();
495
496       ref.handler->releaseFile(filename);
497     }
498
499     // ---------------------------------------------------------------
500     void
501     MediaManager::releaseDir(MediaAccessId   accessId,
502                              const Pathname &dirname) const
503     {
504       MutexLock glock(g_Mutex);
505
506       ManagedMedia &ref( m_impl->findMM(accessId));
507
508       ref.checkAttached();
509
510       ref.handler->releaseDir(dirname);
511     }
512
513
514     // ---------------------------------------------------------------
515     void
516     MediaManager::releasePath(MediaAccessId   accessId,
517                               const Pathname &pathname) const
518     {
519       MutexLock glock(g_Mutex);
520
521       ManagedMedia &ref( m_impl->findMM(accessId));
522
523       ref.checkAttached();
524
525       ref.handler->releasePath(pathname);
526     }
527
528     // ---------------------------------------------------------------
529     void
530     MediaManager::dirInfo(MediaAccessId           accessId,
531                           std::list<std::string> &retlist,
532                           const Pathname         &dirname,
533                           bool                    dots) const
534     {
535       MutexLock glock(g_Mutex);
536
537       ManagedMedia &ref( m_impl->findMM(accessId));
538
539       // FIXME: ref.checkDesired(); ???
540       ref.checkAttached();
541
542       ref.handler->dirInfo(retlist, dirname, dots);
543     }
544
545     // ---------------------------------------------------------------
546     void
547     MediaManager::dirInfo(MediaAccessId           accessId,
548                           filesystem::DirContent &retlist,
549                           const Pathname         &dirname,
550                           bool                    dots) const
551     {
552       MutexLock glock(g_Mutex);
553
554       ManagedMedia &ref( m_impl->findMM(accessId));
555
556       // FIXME: ref.checkDesired(); ???
557       ref.checkAttached();
558
559       ref.handler->dirInfo(retlist, dirname, dots);
560     }
561
562     // ---------------------------------------------------------------
563     time_t
564     MediaManager::getMountTableMTime() const
565     {
566       MutexLock glock(g_Mutex);
567
568       return m_impl->getMountTableMTime();
569     }
570
571     // ---------------------------------------------------------------
572     MountEntries
573     MediaManager::getMountEntries() const
574     {
575       MutexLock glock(g_Mutex);
576
577       return m_impl->getMountEntries();
578     }
579
580     // ---------------------------------------------------------------
581     AttachedMedia
582     MediaManager::findAttachedMedia(const MediaSourceRef &media) const
583     {
584       MutexLock glock(g_Mutex);
585
586       if( !media || media->type.empty())
587         return AttachedMedia();
588
589       ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin());
590       for( ; m != m_impl->mediaMap.end(); ++m)
591       {
592         if( !m->second.handler->isAttached())
593           continue;
594
595         AttachedMedia ret = m->second.handler->attachedMedia();
596         if( ret.mediaSource && ret.mediaSource->equals( *media))
597             return ret;
598       }
599       return AttachedMedia();
600     }
601
602     // ---------------------------------------------------------------
603     void
604     MediaManager::forceMediaRelease(const MediaSourceRef &media)
605     {
606       MutexLock glock(g_Mutex);
607
608       if( !media || media->type.empty())
609         return;
610
611       ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
612       for( ; m != m_impl->mediaMap.end(); ++m)
613       {
614         if( !m->second.handler->isAttached())
615           continue;
616
617         AttachedMedia ret = m->second.handler->attachedMedia();
618         if( ret.mediaSource && ret.mediaSource->equals( *media))
619         {
620           m->second.handler->release(false);
621           m->second.desired  = false;
622         }
623       }
624     }
625
626     //////////////////////////////////////////////////////////////////
627   } // namespace media
628   ////////////////////////////////////////////////////////////////////
629
630   ////////////////////////////////////////////////////////////////////
631 } // namespace zypp
632 //////////////////////////////////////////////////////////////////////
633 /*
634 ** vim: set ts=2 sts=2 sw=2 ai et:
635 */