- Removed return in forceRelaseAllMedia (void function)
[platform/upstream/libzypp.git] / zypp / media / MediaHandler.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaHandler.cc
10  *
11 */
12
13 #include <iostream>
14 #include <fstream>
15 #include <sstream>
16
17 #include "zypp/base/Logger.h"
18 #include "zypp/base/String.h"
19 #include "zypp/media/MediaHandler.h"
20 #include "zypp/media/MediaManager.h"
21 #include "zypp/media/Mount.h"
22
23 using namespace std;
24
25 // use directory.yast on every media (not just via ftp/http)
26 #define NONREMOTE_DIRECTORY_YAST 1
27
28 namespace zypp {
29   namespace media {
30
31   Pathname MediaHandler::_attachPrefix("");
32
33 ///////////////////////////////////////////////////////////////////
34 //
35 //      CLASS NAME : MediaHandler
36 //
37 ///////////////////////////////////////////////////////////////////
38
39 ///////////////////////////////////////////////////////////////////
40 //
41 //
42 //      METHOD NAME : MediaHandler::MediaHandler
43 //      METHOD TYPE : Constructor
44 //
45 //      DESCRIPTION :
46 //
47 MediaHandler::MediaHandler ( const Url &      url_r,
48                              const Pathname & attach_point_r,
49                              const Pathname & urlpath_below_attachpoint_r,
50                              const bool       does_download_r )
51     : _mediaSource()
52     , _attachPoint( new AttachPoint())
53     , _AttachPointHint()
54     , _relativeRoot( urlpath_below_attachpoint_r)
55     , _does_download( does_download_r )
56     , _attach_mtime(0)
57     , _url( url_r )
58     , _parentId(0)
59 {
60   if ( !attach_point_r.empty() ) {
61     ///////////////////////////////////////////////////////////////////
62     // check if provided attachpoint is usable.
63     ///////////////////////////////////////////////////////////////////
64
65     PathInfo adir( attach_point_r );
66     // FIXME: verify if attach_point_r isn't a mountpoint of other device
67     if ( !adir.isDir() || !attach_point_r.absolute()) {
68       ERR << "Provided attach point is not a absolute directory: "
69           << adir << endl;
70     }
71     else {
72       attachPointHint( attach_point_r, false);
73       setAttachPoint( attach_point_r, false);
74     }
75   }
76 }
77
78 ///////////////////////////////////////////////////////////////////
79 //
80 //
81 //      METHOD NAME : MediaHandler::~MediaHandler
82 //      METHOD TYPE : Destructor
83 //
84 //      DESCRIPTION :
85 //
86 MediaHandler::~MediaHandler()
87 {
88   try
89     {
90       removeAttachPoint();
91     }
92   catch(...) {}
93 }
94
95 void
96 MediaHandler::resetParentId()
97 {
98   _parentId = 0;
99 }
100
101 ///////////////////////////////////////////////////////////////////
102 //
103 //
104 //      METHOD NAME : MediaHandler::removeAttachPoint
105 //      METHOD TYPE : void
106 //
107 //      DESCRIPTION :
108 //
109 void
110 MediaHandler::removeAttachPoint()
111 {
112   if ( _mediaSource ) {
113     INT << "MediaHandler deleted with media attached." << endl;
114     return; // no cleanup if media still mounted!
115   }
116
117   DBG << "MediaHandler - checking if to remove attach point" << endl;
118   if ( _attachPoint.unique() &&
119        _attachPoint->temp    &&
120        !_attachPoint->path.empty() &&
121        PathInfo(_attachPoint->path).isDir())
122   {
123     Pathname path(_attachPoint->path);
124
125     setAttachPoint("", true);
126
127     int res = recursive_rmdir( path );
128     if ( res == 0 ) {
129       MIL << "Deleted default attach point " << path << endl;
130     } else {
131       ERR << "Failed to Delete default attach point " << path
132         << " errno(" << res << ")" << endl;
133     }
134   }
135   else
136   {
137     if( !_attachPoint->temp)
138       DBG << "MediaHandler - attachpoint is not temporary" << endl;
139   }
140 }
141
142
143 ///////////////////////////////////////////////////////////////////
144 //
145 //
146 //      METHOD NAME : MediaHandler::attachPoint
147 //      METHOD TYPE : Pathname
148 //
149 //      DESCRIPTION :
150 //
151 Pathname
152 MediaHandler::attachPoint() const
153 {
154   return _attachPoint->path;
155 }
156
157
158 ///////////////////////////////////////////////////////////////////
159 //
160 //
161 //      METHOD NAME : MediaHandler::attachPoint
162 //      METHOD TYPE :
163 //
164 //      DESCRIPTION :
165 //
166 void
167 MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
168 {
169   _attachPoint.reset( new AttachPoint(path, temporary));
170 }
171
172 Pathname
173 MediaHandler::localRoot() const
174 {
175   if( _attachPoint->path.empty())
176     return Pathname();
177   else
178     return _attachPoint->path + _relativeRoot;
179 }
180
181 ///////////////////////////////////////////////////////////////////
182 //
183 //
184 //      METHOD NAME : MediaHandler::attachPoint
185 //      METHOD TYPE :
186 //
187 //      DESCRIPTION :
188 //
189 void
190 MediaHandler::setAttachPoint(const AttachPointRef &ref)
191 {
192   if( ref)
193     AttachPointRef(ref).swap(_attachPoint);
194   else
195     _attachPoint.reset( new AttachPoint());
196 }
197
198 ///////////////////////////////////////////////////////////////////
199 //
200 //
201 //      METHOD NAME : MediaHandler::attachPointHint
202 //      METHOD TYPE : void
203 //
204 //      DESCRIPTION :
205 //
206 void
207 MediaHandler::attachPointHint(const Pathname &path, bool temporary)
208 {
209   _AttachPointHint.path = path;
210   _AttachPointHint.temp = temporary;
211 }
212
213 ///////////////////////////////////////////////////////////////////
214 //
215 //
216 //      METHOD NAME : MediaHandler::attachPointHint
217 //      METHOD TYPE : AttachPoint
218 //
219 //      DESCRIPTION :
220 //
221 AttachPoint
222 MediaHandler::attachPointHint() const
223 {
224   return _AttachPointHint;
225 }
226
227 ///////////////////////////////////////////////////////////////////
228 //
229 //
230 //      METHOD NAME : MediaHandler::findAttachedMedia
231 //      METHOD TYPE : AttachedMedia
232 //
233 //      DESCRIPTION :
234 //
235 AttachedMedia
236 MediaHandler::findAttachedMedia(const MediaSourceRef &media) const
237 {
238         return MediaManager().findAttachedMedia(media);
239 }
240
241 ///////////////////////////////////////////////////////////////////
242 //
243 //
244 //      METHOD NAME : MediaHandler::setAttachPrefix
245 //      METHOD TYPE : void
246 //
247 //      DESCRIPTION :
248 //
249 bool
250 MediaHandler::setAttachPrefix(const Pathname &attach_prefix)
251 {
252   if( attach_prefix.empty())
253   {
254     MIL << "Reseting to built-in attach point prefixes."
255         << std::endl;
256     MediaHandler::_attachPrefix = attach_prefix;
257     return true;
258   }
259   else
260   if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
261   {
262     MIL << "Setting user defined attach point prefix: "
263         << attach_prefix << std::endl;
264     MediaHandler::_attachPrefix = attach_prefix;
265     return true;
266   }
267   return false;
268 }
269
270 ///////////////////////////////////////////////////////////////////
271 //
272 //
273 //      METHOD NAME : MediaHandler::attach
274 //      METHOD TYPE : Pathname
275 //
276 //      DESCRIPTION :
277 //
278 Pathname
279 MediaHandler::createAttachPoint() const
280 {
281   /////////////////////////////////////////////////////////////////
282   // provide a default (temporary) attachpoint
283   /////////////////////////////////////////////////////////////////
284   const char * defmounts[] = {
285       "/var/adm/mount", "/var/tmp", /**/NULL/**/
286   };
287
288   Pathname apoint;
289   Pathname aroot( MediaHandler::_attachPrefix);
290
291   if( !aroot.empty())
292   {
293     apoint = createAttachPoint(aroot);
294   }
295   for ( const char ** def = defmounts; *def && apoint.empty(); ++def ) {
296     aroot = *def;
297     if( aroot.empty())
298       continue;
299
300     apoint = createAttachPoint(aroot);
301   }
302
303   if ( aroot.empty() ) {
304     ERR << "Create attach point: Can't find a writable directory to create an attach point" << std::endl;
305     return aroot;
306   }
307
308   if ( !apoint.empty() ) {
309     MIL << "Created default attach point " << apoint << std::endl;
310   }
311   return apoint;
312 }
313
314 Pathname
315 MediaHandler::createAttachPoint(const Pathname &attach_root) const
316 {
317   Pathname apoint;
318
319   if( attach_root.empty() || !attach_root.absolute()) {
320     ERR << "Create attach point: invalid attach root: '"
321         << attach_root << "'" << std::endl;
322     return apoint;
323   }
324
325   PathInfo adir( attach_root);
326   if( !adir.isDir() || !adir.userMayRWX()) {
327     DBG << "Create attach point: attach root is not a writable directory: '"
328         << attach_root << "'" << std::endl;
329     return apoint;
330   }
331
332   DBG << "Trying to create attach point in " << attach_root << std::endl;
333
334   //
335   // FIXME: use mkdtemp?
336   //
337   Pathname abase( attach_root + "AP_" );
338   //        ma and sh need more than 42 for debugging :-)
339   //        since the readonly fs are handled now, ...
340   for ( unsigned i = 1; i < 1000; ++i ) {
341     adir( Pathname::extend( abase, str::hexstring( i ) ) );
342     if ( ! adir.isExist() ) {
343       int err = mkdir( adir.path() );
344       if (err == 0 ) {
345         apoint = adir.path();
346         break;
347       }
348       else
349       if (err != EEXIST)        // readonly fs or other, dont try further
350         break;
351     }
352   }
353
354   if ( apoint.empty()) {
355     ERR << "Unable to create an attach point below of "
356         << attach_root << std::endl;
357   }
358   return apoint;
359 }
360
361 ///////////////////////////////////////////////////////////////////
362 //
363 //
364 //      METHOD NAME : MediaHandler::isUseableAttachPoint
365 //      METHOD TYPE : bool
366 //
367 //      DESCRIPTION :
368 //
369 bool
370 MediaHandler::isUseableAttachPoint(const Pathname &path) const
371 {
372   MediaManager  manager;
373   return manager.isUseableAttachPoint(path);
374 }
375
376
377 ///////////////////////////////////////////////////////////////////
378 //
379 //
380 //      METHOD NAME : MediaHandler::setMediaSource
381 //      METHOD TYPE : void
382 //
383 //      DESCRIPTION :
384 //
385 void
386 MediaHandler::setMediaSource(const MediaSourceRef &ref)
387 {
388   _mediaSource.reset();
389   if( ref && !ref->type.empty() && !ref->name.empty())
390     _mediaSource = ref;
391 }
392
393 ///////////////////////////////////////////////////////////////////
394 //
395 //
396 //      METHOD NAME : MediaHandler::attachedMedia
397 //      METHOD TYPE : AttachedMedia
398 //
399 //      DESCRIPTION :
400 //
401 AttachedMedia
402 MediaHandler::attachedMedia() const
403 {
404   if ( _mediaSource && _attachPoint)
405     return AttachedMedia(_mediaSource, _attachPoint);
406   else
407     return AttachedMedia();
408 }
409
410 ///////////////////////////////////////////////////////////////////
411 //
412 //
413 //      METHOD NAME : MediaHandler::isSharedMedia
414 //      METHOD TYPE : bool
415 //
416 //      DESCRIPTION :
417 //
418 bool
419 MediaHandler::isSharedMedia() const
420 {
421   return !_mediaSource.unique();
422 }
423
424 ///////////////////////////////////////////////////////////////////
425 //
426 //
427 //      METHOD NAME : MediaHandler::checkAttached
428 //      METHOD TYPE : bool
429 //
430 //      DESCRIPTION :
431 //
432 bool
433 MediaHandler::checkAttached(bool matchMountFs) const
434 {
435   bool _isAttached = false;
436
437   AttachedMedia ref( attachedMedia());
438   if( ref.mediaSource)
439   {
440     time_t old_mtime = _attach_mtime;
441     _attach_mtime = MediaManager::getMountTableMTime();
442     if( !(old_mtime <= 0 || _attach_mtime != old_mtime))
443     {
444       // OK, skip the check (we've seen it at least once)
445       _isAttached = true;
446     }
447     else
448     {
449       if( old_mtime > 0)
450         DBG << "Mount table changed - rereading it" << std::endl;
451       else
452         DBG << "Forced check of the mount table" << std::endl;
453
454       MountEntries  entries( MediaManager::getMountEntries());
455       MountEntries::const_iterator e;
456       for( e = entries.begin(); e != entries.end(); ++e)
457       {
458         bool        is_device = false;
459         std::string dev_path(Pathname(e->src).asString());
460         PathInfo    dev_info;
461
462         if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
463             dev_info(e->src) && dev_info.isBlk())
464         {
465           is_device = true;
466         }
467
468         if( is_device &&  ref.mediaSource->maj_nr)
469         {
470           std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
471           MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
472
473           if( ref.mediaSource->equals( media) &&
474               ref.attachPoint->path == Pathname(e->dir))
475           {
476             DBG << "Found media device "
477                 << ref.mediaSource->asString()
478                 << " in the mount table as " << e->src << std::endl;
479             _isAttached = true;
480             break;
481           }
482           // differs
483         }
484         else
485         if(!is_device && !ref.mediaSource->maj_nr)
486         {
487           std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
488           MediaSource media(mtype, e->src);
489
490           if( ref.mediaSource->equals( media) &&
491               ref.attachPoint->path == Pathname(e->dir))
492           {
493             DBG << "Found media name "
494                 << ref.mediaSource->asString()
495                 << " in the mount table as " << e->src << std::endl;
496             _isAttached = true;
497             break;
498           }
499           // differs
500         }
501       }
502
503       if( !_isAttached)
504       {
505         if( old_mtime > 0)
506         {
507           ERR << "Attached media not in mount table any more - forcing reset!"
508               << std::endl;
509
510           _mediaSource.reset();
511         }
512         else
513         {
514           WAR << "Attached media not in mount table ..." << std::endl;
515         }
516
517         // reset the mtime and force a new check to make sure,
518         // that we've found the media at least once in the mtab.
519         _attach_mtime = 0;
520       }
521     }
522   }
523   return _isAttached;
524 }
525
526 ///////////////////////////////////////////////////////////////////
527 //
528 //
529 //      METHOD NAME : MediaHandler::attach
530 //      METHOD TYPE : PMError
531 //
532 //      DESCRIPTION :
533 //
534 void MediaHandler::attach( bool next )
535 {
536   if ( isAttached() )
537     return;
538
539   // reset it in case of overloaded isAttached()
540   // that checks the media against /etc/mtab ...
541   setMediaSource(MediaSourceRef());
542
543   AttachPoint ap( attachPointHint());
544   setAttachPoint(ap.path, ap.temp);
545
546   try
547   {
548     attachTo( next ); // pass to concrete handler
549   }
550   catch(const MediaException &e)
551   {
552     removeAttachPoint();
553     ZYPP_RETHROW(e);
554   }
555   MIL << "Attached: " << *this << endl;
556 }
557
558
559 ///////////////////////////////////////////////////////////////////
560 //
561 //
562 //      METHOD NAME : MediaHandler::localPath
563 //      METHOD TYPE : Pathname
564 //
565 Pathname MediaHandler::localPath( const Pathname & pathname ) const
566 {
567     Pathname _localRoot( localRoot());
568     if ( _localRoot.empty() )
569         return _localRoot;
570
571     // we must check maximum file name length
572     // this is important for fetching the suseservers, the
573     // url with all parameters can get too long (bug #42021)
574
575     return _localRoot + pathname.absolutename();
576 }
577
578
579
580
581
582 ///////////////////////////////////////////////////////////////////
583 //
584 //
585 //      METHOD NAME : MediaHandler::disconnect
586 //      METHOD TYPE : PMError
587 //
588 void MediaHandler::disconnect()
589 {
590   if ( !isAttached() )
591     return;
592
593   disconnectFrom(); // pass to concrete handler
594   MIL << "Disconnected: " << *this << endl;
595 }
596
597 ///////////////////////////////////////////////////////////////////
598 //
599 //
600 //      METHOD NAME : MediaHandler::release
601 //      METHOD TYPE : PMError
602 //
603 //      DESCRIPTION :
604 //
605 void MediaHandler::release( bool eject )
606 {
607   if ( !isAttached() ) {
608     DBG << "Request to release media - not attached; eject " << eject << std::endl;
609     if ( eject )
610       forceEject();
611     return;
612   }
613
614   DBG << "Request to release attached media "
615       << _mediaSource->asString()
616       << ", use count=" << _mediaSource.use_count()
617       << std::endl;
618
619   if( _mediaSource.unique())
620   {
621     DBG << "Releasing media " << _mediaSource->asString() << std::endl;
622     releaseFrom( eject ); // pass to concrete handler
623     _mediaSource.reset(NULL);
624     removeAttachPoint();
625   }
626   else if( eject) {
627     //
628     // Can't eject a shared media
629     //
630     //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
631
632     MediaSourceRef media( new MediaSource(*_mediaSource));
633     _mediaSource.reset(NULL);
634
635     MediaManager manager;
636     manager.forceReleaseShared(media);
637
638     setMediaSource(media);
639     DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
640     releaseFrom( eject ); // pass to concrete handler
641     _mediaSource.reset(NULL);
642     removeAttachPoint();
643   }
644   else {
645     DBG << "Releasing shared media reference only" << std::endl;
646     _mediaSource.reset(NULL);
647     setAttachPoint("", true);
648   }
649   MIL << "Released: " << *this << endl;
650 }
651
652 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
653 {
654   forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
655 }
656
657 void MediaHandler::forceRelaseAllMedia(const MediaSourceRef &ref,
658                                        bool                  matchMountFs)
659 {
660   if( !ref)
661     return;
662
663   MountEntries  entries( MediaManager::getMountEntries());
664   MountEntries::const_iterator e;
665   for( e = entries.begin(); e != entries.end(); ++e)
666   {
667     bool        is_device = false;
668     std::string dev_path(Pathname(e->src).asString());
669     PathInfo    dev_info;
670
671     if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 &&
672         dev_info(e->src) && dev_info.isBlk())
673     {
674       is_device = true;
675     }
676
677     if( is_device &&  ref->maj_nr)
678     {
679       std::string mtype(matchMountFs ? e->type : ref->type);
680       MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
681
682       if( ref->equals( media) && e->type != "subfs")
683       {
684         DBG << "Forcing release of media device "
685             << ref->asString()
686             << " in the mount table as "
687             << e->src << std::endl;
688         Mount mount;
689         try {
690           mount.umount(e->dir);
691         }
692         catch (const Exception &e)
693         {
694           ZYPP_CAUGHT(e);
695         }
696       }
697     }
698     else
699     if(!is_device && !ref->maj_nr)
700     {
701       std::string mtype(matchMountFs ? e->type : ref->type);
702       MediaSource media(mtype, e->src);
703       if( ref->equals( media) && e->type != "subfs")
704       {
705         DBG << "Forcing release of media name "
706             << ref->asString()
707             << " in the mount table as "
708             << e->src << std::endl;
709         Mount mount;
710         try {
711           mount.umount(e->dir);
712         }
713         catch (const Exception &e)
714         {
715           ZYPP_CAUGHT(e);
716         }
717       }
718     }
719   }
720 }
721
722 bool
723 MediaHandler::checkAttachPoint(const Pathname &apoint) const
724 {
725   return MediaHandler::checkAttachPoint( apoint, true, false);
726 }
727
728 // STATIC
729 bool
730 MediaHandler::checkAttachPoint(const Pathname &apoint,
731                                bool            emptydir,
732                                bool            writeable)
733 {
734   if( apoint.empty() || !apoint.absolute())
735   {
736     ERR << "Attach point '" << apoint << "' is not absolute"
737         << std::endl;
738     return false;
739   }
740   if( apoint == "/")
741   {
742     ERR << "Attach point '" << apoint << "' is not allowed"
743         << std::endl;
744     return false;
745   }
746
747   PathInfo ainfo(apoint);
748   if( !ainfo.isDir())
749   {
750     ERR << "Attach point '" << apoint << "' is not a directory"
751         << std::endl;
752     return false;
753   }
754
755   if( emptydir)
756   {
757     if( 0 != zypp::filesystem::is_empty_dir(apoint))
758     {
759       ERR << "Attach point '" << apoint << "' is not a empty directory"
760           << std::endl;
761       return false;
762     }
763   }
764
765   if( writeable)
766   {
767     Pathname apath(apoint + "XXXXXX");
768     char    *atemp = ::strdup( apath.asString().c_str());
769     char    *atest = NULL;
770     if( !ainfo.userMayRWX() || atemp == NULL ||
771         (atest=::mkdtemp(atemp)) == NULL)
772     {
773       if( atemp != NULL)
774         ::free(atemp);
775
776       ERR << "Attach point '" << ainfo.path()
777           << "' is not a writeable directory" << std::endl;
778       return false;
779     }
780     else if( atest != NULL)
781       ::rmdir(atest);
782
783     if( atemp != NULL)
784       ::free(atemp);
785   }
786   return true;
787 }
788
789 ///////////////////////////////////////////////////////////////////
790 //
791 //      METHOD NAME : MediaHandler::dependsOnParent
792 //      METHOD TYPE : bool
793 //
794 //      DESCRIPTION :
795 //
796 bool
797 MediaHandler::dependsOnParent()
798 {
799   return _parentId != 0;
800 }
801
802 bool
803 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
804 {
805   if( _parentId != 0)
806   {
807     if(parentId == _parentId)
808       return true;
809
810     if( !exactIdMatch)
811     {
812       MediaManager mm;
813       AttachedMedia am1 = mm.getAttachedMedia(_parentId);
814       AttachedMedia am2 = mm.getAttachedMedia(parentId);
815       if( am1.mediaSource && am2.mediaSource)
816       {
817         return am1.mediaSource->equals( *(am2.mediaSource));
818       }
819     }
820   }
821   return false;
822 }
823
824 ///////////////////////////////////////////////////////////////////
825 //
826 //
827 //      METHOD NAME : MediaHandler::provideFile
828 //      METHOD TYPE : PMError
829 //
830 //      DESCRIPTION :
831 //
832 void MediaHandler::provideFileCopy( Pathname srcFilename,
833                                        Pathname targetFilename ) const
834 {
835   if ( !isAttached() ) {
836     INT << "Media not_attached on provideFileCopy(" << srcFilename
837         << "," << targetFilename << ")" << endl;
838     ZYPP_THROW(MediaNotAttachedException(url()));
839   }
840
841   getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
842   DBG << "provideFileCopy(" << srcFilename << "," << targetFilename  << ")" << endl;
843 }
844
845 void MediaHandler::provideFile( Pathname filename ) const
846 {
847   if ( !isAttached() ) {
848     INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
849     ZYPP_THROW(MediaNotAttachedException(url()));
850   }
851
852   getFile( filename ); // pass to concrete handler
853   DBG << "provideFile(" << filename << ")" << endl;
854 }
855
856
857 ///////////////////////////////////////////////////////////////////
858 //
859 //
860 //      METHOD NAME : MediaHandler::provideDir
861 //      METHOD TYPE : PMError
862 //
863 //      DESCRIPTION :
864 //
865 void MediaHandler::provideDir( Pathname dirname ) const
866 {
867   if ( !isAttached() ) {
868     INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
869     ZYPP_THROW(MediaNotAttachedException(url()));
870   }
871
872   getDir( dirname, /*recursive*/false ); // pass to concrete handler
873   MIL << "provideDir(" << dirname << ")" << endl;
874 }
875
876 ///////////////////////////////////////////////////////////////////
877 //
878 //
879 //      METHOD NAME : MediaHandler::provideDirTree
880 //      METHOD TYPE : PMError
881 //
882 //      DESCRIPTION :
883 //
884 void MediaHandler::provideDirTree( Pathname dirname ) const
885 {
886   if ( !isAttached() ) {
887     INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
888     ZYPP_THROW(MediaNotAttachedException(url()));
889   }
890
891   getDir( dirname, /*recursive*/true ); // pass to concrete handler
892   MIL << "provideDirTree(" << dirname << ")" << endl;
893 }
894
895 ///////////////////////////////////////////////////////////////////
896 //
897 //
898 //      METHOD NAME : MediaHandler::releasePath
899 //      METHOD TYPE : PMError
900 //
901 //      DESCRIPTION :
902 //
903 void MediaHandler::releasePath( Pathname pathname ) const
904 {
905   if ( ! _does_download || _attachPoint->empty() )
906     return;
907
908   PathInfo info( localPath( pathname ) );
909
910   if ( info.isFile() ) {
911     unlink( info.path() );
912   } else if ( info.isDir() ) {
913     if ( info.path() != localRoot() ) {
914       recursive_rmdir( info.path() );
915     } else {
916       clean_dir( info.path() );
917     }
918   }
919 }
920
921 ///////////////////////////////////////////////////////////////////
922 //
923 //
924 //      METHOD NAME : MediaHandler::dirInfo
925 //      METHOD TYPE : PMError
926 //
927 //      DESCRIPTION :
928 //
929 void MediaHandler::dirInfo( list<string> & retlist,
930                                const Pathname & dirname, bool dots ) const
931 {
932   retlist.clear();
933
934   if ( !isAttached() ) {
935     INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
936     ZYPP_THROW(MediaNotAttachedException(url()));
937   }
938
939   getDirInfo( retlist, dirname, dots ); // pass to concrete handler
940   MIL << "dirInfo(" << dirname << ")" << endl;
941 }
942
943 ///////////////////////////////////////////////////////////////////
944 //
945 //
946 //      METHOD NAME : MediaHandler::dirInfo
947 //      METHOD TYPE : PMError
948 //
949 //      DESCRIPTION :
950 //
951 void MediaHandler::dirInfo( filesystem::DirContent & retlist,
952                             const Pathname & dirname, bool dots ) const
953 {
954   retlist.clear();
955
956   if ( !isAttached() ) {
957     INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
958     ZYPP_THROW(MediaNotAttachedException(url()));
959   }
960
961   getDirInfo( retlist, dirname, dots ); // pass to concrete handler
962   MIL << "dirInfo(" << dirname << ")" << endl;
963 }
964
965 ///////////////////////////////////////////////////////////////////
966 //
967 //
968 //      METHOD NAME : MediaHandler::getDirectoryYast
969 //      METHOD TYPE : PMError
970 //
971 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
972                                         const Pathname & dirname, bool dots ) const
973 {
974   retlist.clear();
975
976   filesystem::DirContent content;
977   getDirectoryYast( content, dirname, dots );
978
979   // convert to std::list<std::string>
980   for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
981     retlist.push_back( it->name );
982   }
983 }
984
985 ///////////////////////////////////////////////////////////////////
986 //
987 //
988 //      METHOD NAME : MediaHandler::getDirectoryYast
989 //      METHOD TYPE : PMError
990 //
991 void MediaHandler::getDirectoryYast( filesystem::DirContent & retlist,
992                                      const Pathname & dirname, bool dots ) const
993 {
994   retlist.clear();
995
996   // look for directory.yast
997   Pathname dirFile = dirname + "directory.yast";
998   getFile( dirFile );
999   DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1000
1001   // using directory.yast
1002   ifstream dir( localPath( dirFile ).asString().c_str() );
1003   if ( dir.fail() ) {
1004     ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl;
1005     ZYPP_THROW(MediaSystemException(url(),
1006       "Unable to load '" + localPath( dirFile ).asString() + "'"));
1007   }
1008
1009   string line;
1010   while( getline( dir, line ) ) {
1011     if ( line.empty() ) continue;
1012     if ( line == "directory.yast" ) continue;
1013
1014     // Newer directory.yast append '/' to directory names
1015     // Remaining entries are unspecified, although most probabely files.
1016     filesystem::FileType type = filesystem::FT_NOT_AVAIL;
1017     if ( *line.rbegin() == '/' ) {
1018       line.erase( line.end()-1 );
1019       type = filesystem::FT_DIR;
1020     }
1021
1022     if ( dots ) {
1023       if ( line == "." || line == ".." ) continue;
1024     } else {
1025       if ( *line.begin() == '.' ) continue;
1026     }
1027
1028     retlist.push_back( filesystem::DirEntry( line, type ) );
1029   }
1030 }
1031
1032 /******************************************************************
1033 **
1034 **
1035 **      FUNCTION NAME : operator<<
1036 **      FUNCTION TYPE : ostream &
1037 */
1038 ostream & operator<<( ostream & str, const MediaHandler & obj )
1039 {
1040   str << obj.url() << ( obj.isAttached() ? "" : " not" )
1041     << " attached; localRoot \"" << obj.localRoot() << "\"";
1042   return str;
1043 }
1044
1045 ///////////////////////////////////////////////////////////////////
1046 //
1047 //
1048 //      METHOD NAME : MediaHandler::getFile
1049 //      METHOD TYPE : PMError
1050 //
1051 //      DESCRIPTION : Asserted that media is attached.
1052 //                    Default implementation of pure virtual.
1053 //
1054 void MediaHandler::getFile( const Pathname & filename ) const
1055 {
1056     PathInfo info( localPath( filename ) );
1057     if( info.isFile() ) {
1058         return;
1059     }
1060
1061     if (info.isExist())
1062       ZYPP_THROW(MediaNotAFileException(url(), localPath(filename)));
1063     else
1064       ZYPP_THROW(MediaFileNotFoundException(url(), filename));
1065 }
1066
1067
1068 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
1069 {
1070   getFile(srcFilename);
1071
1072   if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
1073     ZYPP_THROW(MediaWriteException(targetFilename));
1074   }
1075 }
1076
1077
1078
1079 ///////////////////////////////////////////////////////////////////
1080 //
1081 //
1082 //      METHOD NAME : MediaHandler::getDir
1083 //      METHOD TYPE : PMError
1084 //
1085 //      DESCRIPTION : Asserted that media is attached.
1086 //                    Default implementation of pure virtual.
1087 //
1088 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1089 {
1090   PathInfo info( localPath( dirname ) );
1091   if( info.isDir() ) {
1092     return;
1093   }
1094
1095   if (info.isExist())
1096     ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
1097   else
1098     ZYPP_THROW(MediaFileNotFoundException(url(), dirname));
1099 }
1100
1101 ///////////////////////////////////////////////////////////////////
1102 //
1103 //
1104 //      METHOD NAME : MediaHandler::getDirInfo
1105 //      METHOD TYPE : PMError
1106 //
1107 //      DESCRIPTION : Asserted that media is attached and retlist is empty.
1108 //                    Default implementation of pure virtual.
1109 //
1110 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1111                                const Pathname & dirname, bool dots ) const
1112 {
1113   PathInfo info( localPath( dirname ) );
1114   if( ! info.isDir() ) {
1115     ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
1116   }
1117
1118 #if NONREMOTE_DIRECTORY_YAST
1119   // use directory.yast if available
1120   try {
1121     getDirectoryYast( retlist, dirname, dots );
1122   }
1123   catch (const MediaException & excpt_r)
1124   {
1125 #endif
1126
1127   // readdir
1128     int res = readdir( retlist, info.path(), dots );
1129   if ( res )
1130     ZYPP_THROW(MediaSystemException(url(), "readdir failed"));
1131
1132 #if NONREMOTE_DIRECTORY_YAST
1133   }
1134 #endif
1135
1136   return;
1137 }
1138
1139 ///////////////////////////////////////////////////////////////////
1140 //
1141 //
1142 //      METHOD NAME : MediaHandler::getDirInfo
1143 //      METHOD TYPE : PMError
1144 //
1145 //      DESCRIPTION : Asserted that media is attached and retlist is empty.
1146 //                    Default implementation of pure virtual.
1147 //
1148 void MediaHandler::getDirInfo( filesystem::DirContent & retlist,
1149                                const Pathname & dirname, bool dots ) const
1150 {
1151   PathInfo info( localPath( dirname ) );
1152   if( ! info.isDir() ) {
1153     ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
1154   }
1155
1156 #if NONREMOTE_DIRECTORY_YAST
1157   // use directory.yast if available
1158   try {
1159     getDirectoryYast( retlist, dirname, dots );
1160   }
1161   catch (const MediaException & excpt_r)
1162   {
1163 #endif
1164
1165   // readdir
1166   int res = readdir( retlist, info.path(), dots );
1167   if ( res )
1168     ZYPP_THROW(MediaSystemException(url(), "readdir failed"));
1169 #if NONREMOTE_DIRECTORY_YAST
1170   }
1171 #endif
1172 }
1173
1174   } // namespace media
1175 } // namespace zypp
1176 // vim: set ts=8 sts=2 sw=2 ai noet: