libzypp 17.37.4
MediaHandler.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12
13#include <iostream>
14#include <fstream>
15#include <sstream>
16
17#include <zypp/ZConfig.h>
18#include <zypp/TmpPath.h>
19#include <zypp/Date.h>
20#include <zypp/base/LogTools.h>
21#include <zypp/base/Gettext.h>
22#include <zypp/base/String.h>
25#include <utility>
26#include <zypp-media/Mount>
27#include <limits.h>
28#include <stdlib.h>
29#include <errno.h>
30
31using std::endl;
32
33// use directory.yast on every media (not just via ftp/http)
34#define NONREMOTE_DIRECTORY_YAST 1
35
36namespace zypp {
37 namespace media {
38
39 Pathname MediaHandler::_attachPrefix("");
40
42//
43// CLASS NAME : MediaHandler
44//
46
48//
49//
50// METHOD NAME : MediaHandler::MediaHandler
51// METHOD TYPE : Constructor
52//
53// DESCRIPTION :
54//
55 MediaHandler::MediaHandler (MediaUrl primaryUrl_r,
56 std::vector<MediaUrl> urls_r,
57 const Pathname & attach_point_r,
58 Pathname urlpath_below_attachpoint_r,
59 const bool does_download_r )
60 : _mediaSource()
63 , _relativeRoot(std::move( urlpath_below_attachpoint_r))
64 , _does_download( does_download_r )
65 , _attach_mtime(0)
66 , _urls(std::move( urls_r ))
67 , _url(std::move(primaryUrl_r))
68 , _parentId(0)
69{
70 Pathname real_attach_point( getRealPath(attach_point_r.asString()));
71
72 if ( !real_attach_point.empty() ) {
74 // check if provided attachpoint is usable.
76
77 PathInfo adir( real_attach_point );
78 //
79 // The verify if attach_point_r isn't a mountpoint of another
80 // device is done in the particular media handler (if needed).
81 //
82 // We just verify, if attach_point_r is a directory and for
83 // schemes other than "file" and "dir", if it is absolute.
84 //
85 if ( !adir.isDir()
86 || (_url.url().getScheme() != "file"
87 && _url.url().getScheme() != "dir"
88 && !real_attach_point.absolute()) )
89 {
90 ERR << "Provided attach point is not a absolute directory: "
91 << adir << endl;
92 }
93 else {
94 attachPointHint( real_attach_point, false);
95 setAttachPoint( real_attach_point, false);
96 }
97 }
98}
99
101//
102//
103// METHOD NAME : MediaHandler::~MediaHandler
104// METHOD TYPE : Destructor
105//
106// DESCRIPTION :
107//
109{
110 try
111 {
113 }
114 catch(...) {}
115}
116
117void
122
123std::string
124MediaHandler::getRealPath(const std::string &path)
125{
126 return getRealPath(zypp::Pathname(path)).asString();
127}
128
131{
132 return path.realpath();
133}
134
135
137//
138//
139// METHOD NAME : MediaHandler::removeAttachPoint
140// METHOD TYPE : void
141//
142// DESCRIPTION :
143//
144void
146{
147 if ( _mediaSource ) {
148 INT << "MediaHandler deleted with media attached." << endl;
149 return; // no cleanup if media still mounted!
150 }
151
152 DBG << "MediaHandler - checking if to remove attach point" << endl;
153 if ( _attachPoint.unique() &&
154 _attachPoint->temp &&
155 !_attachPoint->path.empty() &&
156 PathInfo(_attachPoint->path).isDir())
157 {
158 Pathname path(_attachPoint->path);
159
160 setAttachPoint("", true);
161
162 int res = recursive_rmdir( path );
163 if ( res == 0 ) {
164 MIL << "Deleted default attach point " << path << endl;
165 } else {
166 ERR << "Failed to Delete default attach point " << path
167 << " errno(" << res << ")" << endl;
168 }
169 }
170 else
171 {
172 if( !_attachPoint->path.empty() && !_attachPoint->temp)
173 DBG << "MediaHandler - attachpoint is not temporary" << endl;
174 }
175}
176
177
179//
180//
181// METHOD NAME : MediaHandler::attachPoint
182// METHOD TYPE : Pathname
183//
184// DESCRIPTION :
185//
188{
189 return _attachPoint->path;
190}
191
192
194//
195//
196// METHOD NAME : MediaHandler::attachPoint
197// METHOD TYPE :
198//
199// DESCRIPTION :
200//
201void
202MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
203{
204 _attachPoint.reset( new AttachPoint(path, temporary));
205}
206
209{
210 if( _attachPoint->path.empty())
211 return Pathname();
212 else
213 return _attachPoint->path + _relativeRoot;
214}
215
217//
218//
219// METHOD NAME : MediaHandler::attachPoint
220// METHOD TYPE :
221//
222// DESCRIPTION :
223//
224void
226{
227 if( ref)
229 else
230 _attachPoint.reset( new AttachPoint());
231}
232
234//
235//
236// METHOD NAME : MediaHandler::attachPointHint
237// METHOD TYPE : void
238//
239// DESCRIPTION :
240//
241void
242MediaHandler::attachPointHint(const Pathname &path, bool temporary)
243{
244 _attachPointHint.path = path;
245 _attachPointHint.temp = temporary;
246}
247
249//
250//
251// METHOD NAME : MediaHandler::attachPointHint
252// METHOD TYPE : AttachPoint
253//
254// DESCRIPTION :
255//
261
263//
264//
265// METHOD NAME : MediaHandler::findAttachedMedia
266// METHOD TYPE : AttachedMedia
267//
268// DESCRIPTION :
269//
275
277//
278//
279// METHOD NAME : MediaHandler::setAttachPrefix
280// METHOD TYPE : void
281//
282// DESCRIPTION :
283//
284bool
286{
287 if( attach_prefix.empty())
288 {
289 MIL << "Resetting to built-in attach point prefixes."
290 << std::endl;
291 MediaHandler::_attachPrefix = attach_prefix;
292 return true;
293 }
294 else
295 if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
296 {
297 MIL << "Setting user defined attach point prefix: "
298 << attach_prefix << std::endl;
299 MediaHandler::_attachPrefix = attach_prefix;
300 return true;
301 }
302 return false;
303}
304
306//
307//
308// METHOD NAME : MediaHandler::attach
309// METHOD TYPE : Pathname
310//
311// DESCRIPTION :
312//
315{
316 Pathname aroot;
317 Pathname apoint;
318 {
319 aroot = MediaHandler::_attachPrefix; // explicit request
320 if ( ! aroot.empty() )
321 apoint = createAttachPoint( aroot );
322 }
323
324 if ( apoint.empty() ) // fallback to config value
325 {
327 if ( ! aroot.empty() )
328 apoint = createAttachPoint( aroot );
329 }
330
331 if ( apoint.empty() ) // fall back to temp space
332 {
334 if ( ! aroot.empty() )
335 apoint = createAttachPoint( aroot );
336 }
337
338 if ( apoint.empty() )
339 {
340 auto except = MediaBadAttachPointException( url() );
341 except.addHistory( _("Create attach point: Can't find a writable directory to create an attach point") );
342 ZYPP_THROW( except );
343 }
344
345 MIL << "Created default attach point " << apoint << std::endl;
346 return apoint;
347}
348
351{
352 Pathname apoint;
353
354 if( attach_root.empty() || !attach_root.absolute()) {
355 ERR << "Create attach point: invalid attach root: '"
356 << attach_root << "'" << std::endl;
357 return apoint;
358 }
359
360 PathInfo adir( attach_root );
361 if( !adir.isDir() || (geteuid() != 0 && !adir.userMayRWX())) {
362 DBG << "Create attach point: attach root is not a writable directory: '"
363 << attach_root << "'" << std::endl;
364 return apoint;
365 }
366
367 static bool cleanup_once( true );
368 if ( cleanup_once )
369 {
370 cleanup_once = false;
371 DBG << "Look for orphaned attach points in " << adir << std::endl;
372 std::list<std::string> entries;
373 filesystem::readdir( entries, attach_root, false );
374 for ( const std::string & entry : entries )
375 {
376 if ( ! str::hasPrefix( entry, "AP_0x" ) )
377 continue;
378 PathInfo sdir( attach_root + entry );
379 if ( sdir.isDir()
380 && sdir.dev() == adir.dev()
381 && ( Date::now()-sdir.mtime() > Date::month ) )
382 {
383 DBG << "Remove orphaned attach point " << sdir << std::endl;
385 }
386 }
387 }
388
389 filesystem::TmpDir tmpdir( attach_root, "AP_0x" );
390 if ( tmpdir )
391 {
392 apoint = getRealPath( tmpdir.path().asString() );
393 if ( ! apoint.empty() )
394 {
395 tmpdir.autoCleanup( false ); // Take responsibility for cleanup.
396 }
397 else
398 {
399 ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl;
400 }
401 }
402 else
403 {
404 ERR << "Unable to create attach point below " << attach_root << std::endl;
405 }
406 return apoint;
407}
408
410//
411//
412// METHOD NAME : MediaHandler::isUseableAttachPoint
413// METHOD TYPE : bool
414//
415// DESCRIPTION :
416//
417bool
418MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const
419{
420 MediaManager manager;
421 return manager.isUseableAttachPoint(path, mtab);
422}
423
424
426//
427//
428// METHOD NAME : MediaHandler::setMediaSource
429// METHOD TYPE : void
430//
431// DESCRIPTION :
432//
433void
435{
436 _mediaSource.reset();
437 if( ref && !ref->type.empty() && !ref->name.empty())
438 _mediaSource = ref;
439}
440
442//
443//
444// METHOD NAME : MediaHandler::attachedMedia
445// METHOD TYPE : AttachedMedia
446//
447// DESCRIPTION :
448//
451{
454 else
455 return AttachedMedia();
456}
457
459//
460//
461// METHOD NAME : MediaHandler::isSharedMedia
462// METHOD TYPE : bool
463//
464// DESCRIPTION :
465//
466bool
468{
469 return !_mediaSource.unique();
470}
471
473//
474//
475// METHOD NAME : MediaHandler::checkAttached
476// METHOD TYPE : bool
477//
478// DESCRIPTION :
479//
480bool
481MediaHandler::checkAttached(bool matchMountFs) const
482{
483 bool _isAttached = false;
484
486 if( ref.mediaSource )
487 {
488 time_t old_mtime = _attach_mtime;
490 if( !(old_mtime <= 0 || _attach_mtime != old_mtime) )
491 {
492 // OK, skip the check (we've seen it at least once)
493 _isAttached = true;
494 }
495 else
496 {
497 if( old_mtime > 0)
498 DBG << "Mount table changed - rereading it" << std::endl;
499 else
500 DBG << "Forced check of the mount table" << std::endl;
501
502 MountEntries entries( MediaManager::getMountEntries());
503 for_( e, entries.begin(), entries.end() )
504 {
505 if ( ref.attachPoint->path != Pathname(e->dir) )
506 continue; // at least the mount points must match
507
508 bool is_device = e->isBlockDevice();
509 if( is_device && (ref.mediaSource->maj_nr &&
510 ref.mediaSource->bdir.empty()))
511 {
512 PathInfo dev_info(e->src);
513 std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
514 MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
515
516 if( ref.mediaSource->equals( media ) )
517 {
518 DBG << "Found media device "
519 << ref.mediaSource->asString()
520 << " in the mount table as " << e->src << std::endl;
521 _isAttached = true;
522 break;
523 }
524 // differs
525 }
526 else
527 if(!is_device && (!ref.mediaSource->maj_nr ||
528 !ref.mediaSource->bdir.empty()))
529 {
530 if( ref.mediaSource->bdir.empty())
531 {
532 // bnc#710269: Type nfs may appear as nfs4 in in the mount table
533 // and maybe vice versa. Similar cifs/smb. Need to unify these types:
534 if ( matchMountFs && e->type != ref.mediaSource->type )
535 {
536 if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) )
537 matchMountFs = false;
538 else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) )
539 matchMountFs = false;
540 else
541 continue; // different types cannot match
542 }
543 // Here: Types are ok or not to check.
544 // Check the name except for nfs (bnc#804544; symlink resolution in mount path)
545 //
546 // [fibonacci]$ ls -l /Local/ma/c12.1
547 // lrwxrwxrwx /Local/ma/c12.1 -> zypp-SuSE-Code-12_1-Branch/
548 //
549 // [localhost]$ mount -t nfs4 fibonacci:/Local/ma/c12.1 /mnt
550 // [localhost]$ mount
551 // fibonacci:/Local/ma/zypp-SuSE-Code-12_1-Branch on /mnt
552
553 // std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
554 // MediaSource media(mtype, e->src);
555
556 if( ref.mediaSource->name == e->src || str::hasPrefix( ref.mediaSource->type, "nfs" ) )
557 {
558 DBG << "Found media name "
559 << ref.mediaSource->asString()
560 << " in the mount table as " << e->src << std::endl;
561 _isAttached = true;
562 break;
563 }
564 }
565 else
566 {
567 if ( ref.mediaSource->bdir == e->src )
568 {
569 DBG << "Found bound media "
570 << ref.mediaSource->asString()
571 << " in the mount table as " << e->src << std::endl;
572 _isAttached = true;
573 break;
574 }
575 }
576 // differs
577 }
578 else // mixed cases:
579 {
580 // Type ISO: Since 11.1 mtab might contain the name of
581 // the loop device instead of the iso file:
582 if ( ref.mediaSource->type == "iso"
583 && str::hasPrefix( Pathname(e->src).asString(), "/dev/loop" )
584 && ref.attachPoint->path == Pathname(e->dir) )
585 {
586 DBG << "Found bound media "
587 << ref.mediaSource->asString()
588 << " in the mount table as " << e->src << std::endl;
589 _isAttached = true;
590 break;
591 }
592 }
593 }
594
595 if( !_isAttached)
596 {
597 MIL << "Looking for " << ref << endl;
598 if( entries.empty() )
599 {
600 ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
601 }
602 else
603 {
604 dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
605 }
606 if( old_mtime > 0 )
607 {
608 ERR << "Attached media not in mount table any more - forcing reset!"
609 << std::endl;
610
611 _mediaSource.reset();
612 }
613 else
614 {
615 WAR << "Attached media not in mount table ..." << std::endl;
616 }
617
618 // reset the mtime and force a new check to make sure,
619 // that we've found the media at least once in the mtab.
620 _attach_mtime = 0;
621 }
622 }
623 }
624 return _isAttached;
625}
626
628//
629//
630// METHOD NAME : MediaHandler::attach
631// METHOD TYPE : PMError
632//
633// DESCRIPTION :
634//
635void MediaHandler::attach( bool next )
636{
637 if ( isAttached() )
638 return;
639
640 // reset it in case of overloaded isAttached()
641 // that checks the media against /etc/mtab ...
643
645 setAttachPoint(ap.path, ap.temp);
646
647 try
648 {
649 attachTo( next ); // pass to concrete handler
650 }
651 catch(const MediaException &e)
652 {
654 ZYPP_RETHROW(e);
655 }
656 MIL << "Attached: " << *this << endl;
657}
658
659
661//
662//
663// METHOD NAME : MediaHandler::localPath
664// METHOD TYPE : Pathname
665//
667{
668 Pathname _localRoot( localRoot());
669 if ( _localRoot.empty() )
670 return _localRoot;
671
672 // we must check maximum file name length
673 // this is important for fetching the suseservers, the
674 // url with all parameters can get too long (bug #42021)
675
676 return _localRoot + pathname.absolutename();
677}
678
679
680
681
682
684//
685//
686// METHOD NAME : MediaHandler::disconnect
687// METHOD TYPE : PMError
688//
690{
691 if ( !isAttached() )
692 return;
693
694 disconnectFrom(); // pass to concrete handler
695 MIL << "Disconnected: " << *this << endl;
696}
697
699//
700//
701// METHOD NAME : MediaHandler::release
702// METHOD TYPE : PMError
703//
704// DESCRIPTION :
705//
706void MediaHandler::release( const std::string & ejectDev )
707{
708 if ( !isAttached() ) {
709 DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
710 << std::endl;
711 if ( !ejectDev.empty() )
712 forceEject(ejectDev);
713 return;
714 }
715
716 DBG << "Request to release attached media "
717 << _mediaSource->asString()
718 << ", use count=" << _mediaSource.use_count()
719 << std::endl;
720
721 if( _mediaSource.unique())
722 {
723 DBG << "Releasing media " << _mediaSource->asString() << std::endl;
724 try {
725 releaseFrom( ejectDev ); // pass to concrete handler
726 }
727 catch(const MediaNotEjectedException &e)
728 {
729 // not ejected because the media
730 // is mounted by somebody else
731 // (if our attach point is busy,
732 // we get an umount exception)
733 _mediaSource.reset(NULL);
735 // OK, retrow now
736 ZYPP_RETHROW(e);
737 }
738 _mediaSource.reset(NULL);
740 }
741 else if( !ejectDev.empty() ) {
742 //
743 // Can't eject a shared media
744 //
745 //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
746
748 _mediaSource.reset(NULL);
749
750 MediaManager manager;
751 manager.forceReleaseShared(media);
752
754 DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
755 try {
756 releaseFrom( ejectDev ); // pass to concrete handler
757 }
758 catch(const MediaNotEjectedException &e)
759 {
760 // not ejected because the media
761 // is mounted by somebody else
762 // (if our attach point is busy,
763 // we get an umount exception)
764 _mediaSource.reset(NULL);
766 // OK, retrow now
767 ZYPP_RETHROW(e);
768 }
769 _mediaSource.reset(NULL);
771 }
772 else {
773 DBG << "Releasing shared media reference only" << std::endl;
774 _mediaSource.reset(NULL);
775 setAttachPoint("", true);
776 }
777 MIL << "Released: " << *this << endl;
778}
779
781{
782 forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
783}
784
786 bool matchMountFs)
787{
788 if( !ref)
789 return;
790
791 MountEntries entries( MediaManager::getMountEntries());
792 MountEntries::const_iterator e;
793 for( e = entries.begin(); e != entries.end(); ++e)
794 {
795 bool is_device = false;
796 PathInfo dev_info;
797
798 if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
799 dev_info(e->src) && dev_info.isBlk())
800 {
801 is_device = true;
802 }
803
804 if( is_device && ref->maj_nr)
805 {
806 std::string mtype(matchMountFs ? e->type : ref->type);
807 MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
808
809 if( ref->equals( media) && e->type != "subfs")
810 {
811 DBG << "Forcing release of media device "
812 << ref->asString()
813 << " in the mount table as "
814 << e->src << std::endl;
815 try {
816 Mount mount;
817 mount.umount(e->dir);
818 }
819 catch (const Exception &e)
820 {
821 ZYPP_CAUGHT(e);
822 }
823 }
824 }
825 else
826 if(!is_device && !ref->maj_nr)
827 {
828 std::string mtype(matchMountFs ? e->type : ref->type);
829 MediaSource media(mtype, e->src);
830 if( ref->equals( media))
831 {
832 DBG << "Forcing release of media name "
833 << ref->asString()
834 << " in the mount table as "
835 << e->src << std::endl;
836 try {
837 Mount mount;
838 mount.umount(e->dir);
839 }
840 catch (const Exception &e)
841 {
842 ZYPP_CAUGHT(e);
843 }
844 }
845 }
846 }
847}
848
849bool
851{
852 return MediaHandler::checkAttachPoint( apoint, true, false);
853}
854
855// STATIC
856bool
858 bool emptydir,
859 bool writeable)
860{
861 if( apoint.empty() || !apoint.absolute())
862 {
863 ERR << "Attach point '" << apoint << "' is not absolute"
864 << std::endl;
865 return false;
866 }
867 if( apoint == "/")
868 {
869 ERR << "Attach point '" << apoint << "' is not allowed"
870 << std::endl;
871 return false;
872 }
873
874 PathInfo ainfo(apoint);
875 if( !ainfo.isDir())
876 {
877 ERR << "Attach point '" << apoint << "' is not a directory"
878 << std::endl;
879 return false;
880 }
881
882 if( emptydir)
883 {
884 if( 0 != zypp::filesystem::is_empty_dir(apoint))
885 {
886 ERR << "Attach point '" << apoint << "' is not a empty directory"
887 << std::endl;
888 return false;
889 }
890 }
891
892 if( writeable)
893 {
894 Pathname apath(apoint + "XXXXXX");
895 char *atemp = ::strdup( apath.asString().c_str());
896 char *atest = NULL;
897 if( !ainfo.userMayRWX() || atemp == NULL ||
898 (atest=::mkdtemp(atemp)) == NULL)
899 {
900 if( atemp != NULL)
901 ::free(atemp);
902
903 ERR << "Attach point '" << ainfo.path()
904 << "' is not a writeable directory" << std::endl;
905 return false;
906 }
907 else if( atest != NULL)
908 ::rmdir(atest);
909
910 if( atemp != NULL)
911 ::free(atemp);
912 }
913 return true;
914}
915
917//
918// METHOD NAME : MediaHandler::dependsOnParent
919// METHOD TYPE : bool
920//
921// DESCRIPTION :
922//
923bool
925{
926 return _parentId != 0;
927}
928
929bool
931{
932 if( _parentId != 0)
933 {
934 if(parentId == _parentId)
935 return true;
936
937 if( !exactIdMatch)
938 {
939 MediaManager mm;
941 AttachedMedia am2 = mm.getAttachedMedia(parentId);
942 if( am1.mediaSource && am2.mediaSource)
943 {
944 return am1.mediaSource->equals( *(am2.mediaSource));
945 }
946 }
947 }
948 return false;
949}
950
952//
953//
954// METHOD NAME : MediaHandler::provideFile
955// METHOD TYPE : PMError
956//
957// DESCRIPTION :
958//
959void MediaHandler::provideFileCopy( const OnMediaLocation &srcFile, const Pathname& targetFilename ) const
960{
961 if ( !isAttached() ) {
962 INT << "Media not_attached on provideFileCopy(" << srcFile
963 << "," << targetFilename << ")" << endl;
965 }
966
967 getFileCopy( srcFile, targetFilename ); // pass to concrete handler
968 DBG << "provideFileCopy(" << srcFile << "," << targetFilename << ")" << endl;
969}
970
972{
973 if ( !isAttached() ) {
974 INT << "Error: Not attached on provideFile(" << file << ")" << endl;
976 }
977
978 getFile( file ); // pass to concrete handler
979 DBG << "provideFile(" << file << ")" << endl;
980}
981
982
984//
985//
986// METHOD NAME : MediaHandler::provideDir
987// METHOD TYPE : PMError
988//
989// DESCRIPTION :
990//
991void MediaHandler::provideDir( const Pathname& dirname ) const
992{
993 if ( !isAttached() ) {
994 INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
996 }
997
998 getDir( dirname, /*recursive*/false ); // pass to concrete handler
999 MIL << "provideDir(" << dirname << ")" << endl;
1000}
1001
1003//
1004//
1005// METHOD NAME : MediaHandler::provideDirTree
1006// METHOD TYPE : PMError
1007//
1008// DESCRIPTION :
1009//
1010void MediaHandler::provideDirTree( const Pathname& dirname ) const
1011{
1012 if ( !isAttached() ) {
1013 INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
1015 }
1016
1017 getDir( dirname, /*recursive*/true ); // pass to concrete handler
1018 MIL << "provideDirTree(" << dirname << ")" << endl;
1019}
1020
1022//
1023//
1024// METHOD NAME : MediaHandler::releasePath
1025// METHOD TYPE : PMError
1026//
1027// DESCRIPTION :
1028//
1029void MediaHandler::releasePath( const Pathname& pathname ) const
1030{
1031 if ( ! _does_download || _attachPoint->empty() )
1032 return;
1033
1034 PathInfo info( localPath( pathname ) );
1035
1036 if ( info.isFile() ) {
1037 unlink( info.path() );
1038 } else if ( info.isDir() ) {
1039 if ( info.path() != localRoot() ) {
1040 recursive_rmdir( info.path() );
1041 } else {
1042 clean_dir( info.path() );
1043 }
1044 }
1045}
1046
1048//
1049//
1050// METHOD NAME : MediaHandler::dirInfo
1051// METHOD TYPE : PMError
1052//
1053// DESCRIPTION :
1054//
1055void MediaHandler::dirInfo( std::list<std::string> & retlist,
1056 const Pathname & dirname, bool dots ) const
1057{
1058 retlist.clear();
1059
1060 if ( !isAttached() ) {
1061 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1063 }
1064
1065 getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1066 MIL << "dirInfo(" << dirname << ")" << endl;
1067}
1068
1070//
1071//
1072// METHOD NAME : MediaHandler::dirInfo
1073// METHOD TYPE : PMError
1074//
1075// DESCRIPTION :
1076//
1078 const Pathname & dirname, bool dots ) const
1079{
1080 retlist.clear();
1081
1082 if ( !isAttached() ) {
1083 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1085 }
1086
1087 getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1088 MIL << "dirInfo(" << dirname << ")" << endl;
1089}
1090
1092//
1093//
1094// METHOD NAME : MediaHandler::doesFileExist
1095// METHOD TYPE : PMError
1096//
1097// DESCRIPTION :
1098//
1099bool MediaHandler::doesFileExist( const Pathname & filename ) const
1100{
1101 // TODO do some logging
1102 if ( !isAttached() ) {
1103 INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
1105 }
1106 return getDoesFileExist( filename );
1107 MIL << "doesFileExist(" << filename << ")" << endl;
1108}
1109
1111//
1112//
1113// METHOD NAME : MediaHandler::getDirectoryYast
1114// METHOD TYPE : PMError
1115//
1116void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
1117 const Pathname & dirname, bool dots ) const
1118{
1119 retlist.clear();
1120
1121 filesystem::DirContent content;
1122 getDirectoryYast( content, dirname, dots );
1123
1124 // convert to std::list<std::string>
1125 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1126 retlist.push_back( it->name );
1127 }
1128}
1129
1131//
1132//
1133// METHOD NAME : MediaHandler::getDirectoryYast
1134// METHOD TYPE : PMError
1135//
1137 const Pathname & dirname, bool dots ) const
1138{
1139 retlist.clear();
1140
1141 // look for directory.yast
1142 auto dirFile = OnMediaLocation( dirname + "directory.yast" );
1143 getFile( dirFile );
1144 DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1145
1146 // using directory.yast
1147 std::ifstream dir( localPath( dirFile.filename() ).asString().c_str() );
1148 if ( dir.fail() ) {
1149 ERR << "Unable to load '" << localPath( dirFile.filename() ) << "'" << endl;
1151 "Unable to load '" + localPath( dirFile.filename() ).asString() + "'"));
1152 }
1153
1154 std::string line;
1155 while( getline( dir, line ) ) {
1156 if ( line.empty() ) continue;
1157 if ( line == "directory.yast" ) continue;
1158
1159 // Newer directory.yast append '/' to directory names
1160 // Remaining entries are unspecified, although most probabely files.
1162 if ( *line.rbegin() == '/' ) {
1163 line.erase( line.end()-1 );
1164 type = filesystem::FT_DIR;
1165 }
1166
1167 if ( dots ) {
1168 if ( line == "." || line == ".." ) continue;
1169 } else {
1170 if ( *line.begin() == '.' ) continue;
1171 }
1172
1173 retlist.push_back( filesystem::DirEntry( line, type ) );
1174 }
1175}
1176
1177/******************************************************************
1178**
1179**
1180** FUNCTION NAME : operator<<
1181** FUNCTION TYPE : ostream &
1182*/
1183std::ostream & operator<<( std::ostream & str, const MediaHandler & obj )
1184{
1185 str << obj.url() << ( obj.isAttached() ? "" : " not" )
1186 << " attached; localRoot \"" << obj.localRoot() << "\"";
1187 return str;
1188}
1189
1191{
1192 PathInfo info( localPath( file.filename() ) );
1193 if( info.isFile() ) {
1194 return;
1195 }
1196
1197 if (info.isExist())
1199 else
1201}
1202
1203void MediaHandler::getFileCopy( const OnMediaLocation &file, const Pathname &targetFilename ) const
1204{
1205 getFile( file );
1206 if ( copy( localPath( file.filename() ), targetFilename ) != 0 ) {
1207 ZYPP_THROW(MediaWriteException(targetFilename));
1208 }
1209}
1210
1211
1213//
1214//
1215// METHOD NAME : MediaHandler::getDir
1216// METHOD TYPE : PMError
1217//
1218// DESCRIPTION : Asserted that media is attached.
1219// Default implementation of pure virtual.
1220//
1221void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1222{
1223 PathInfo info( localPath( dirname ) );
1224 if( info.isDir() ) {
1225 return;
1226 }
1227
1228 if (info.isExist())
1230 else
1232}
1233
1235//
1236//
1237// METHOD NAME : MediaHandler::getDirInfo
1238// METHOD TYPE : PMError
1239//
1240// DESCRIPTION : Asserted that media is attached and retlist is empty.
1241// Default implementation of pure virtual.
1242//
1243void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1244 const Pathname & dirname, bool dots ) const
1245{
1246 PathInfo info( localPath( dirname ) );
1247 if( ! info.isDir() ) {
1249 }
1250
1251#if NONREMOTE_DIRECTORY_YAST
1252 // use directory.yast if available
1253 try {
1254 getDirectoryYast( retlist, dirname, dots );
1255 }
1256 catch (const MediaException & excpt_r)
1257 {
1258#endif
1259
1260 // readdir
1261 int res = readdir( retlist, info.path(), dots );
1262 if ( res )
1263 {
1264 MediaSystemException nexcpt(url(), "readdir failed");
1265#if NONREMOTE_DIRECTORY_YAST
1266 nexcpt.remember(excpt_r);
1267#endif
1268 ZYPP_THROW(nexcpt);
1269 }
1270
1271#if NONREMOTE_DIRECTORY_YAST
1272 }
1273#endif
1274
1275 return;
1276}
1277
1279//
1280//
1281// METHOD NAME : MediaHandler::getDirInfo
1282// METHOD TYPE : PMError
1283//
1284// DESCRIPTION : Asserted that media is attached and retlist is empty.
1285// Default implementation of pure virtual.
1286//
1288 const Pathname & dirname, bool dots ) const
1289{
1290 PathInfo info( localPath( dirname ) );
1291 if( ! info.isDir() ) {
1293 }
1294
1295#if NONREMOTE_DIRECTORY_YAST
1296 // use directory.yast if available
1297 try {
1298 getDirectoryYast( retlist, dirname, dots );
1299 }
1300 catch (const MediaException & excpt_r)
1301 {
1302#endif
1303
1304 // readdir
1305 int res = readdir( retlist, info.path(), dots );
1306 if ( res )
1307 {
1308 MediaSystemException nexcpt(url(), "readdir failed");
1309#if NONREMOTE_DIRECTORY_YAST
1310 nexcpt.remember(excpt_r);
1311#endif
1312 ZYPP_THROW(nexcpt);
1313 }
1314#if NONREMOTE_DIRECTORY_YAST
1315 }
1316#endif
1317}
1318
1320//
1321//
1322// METHOD NAME : MediaHandler::getDoesFileExist
1323// METHOD TYPE : PMError
1324//
1325// DESCRIPTION : Asserted that file is not a directory
1326// Default implementation of pure virtual.
1327//
1328bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1329{
1330 PathInfo info( localPath( filename ) );
1331 if( info.isDir() ) {
1333 }
1334 return info.isExist();
1335}
1336
1338{
1339 return false;
1340}
1341
1342void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
1343 unsigned int & index) const
1344{
1345 // clear the vector by default
1346 if (!devices.empty())
1347 devices.clear();
1348 index = 0;
1349
1350 DBG << "No devices for this medium" << endl;
1351}
1352
1353void MediaHandler::precacheFiles( const std::vector<OnMediaLocation> & )
1354{
1355 /* do nothing */
1356}
1357
1358 } // namespace media
1359} // namespace zypp
1360// vim: set ts=8 sts=2 sw=2 ai noet:
static const ValueType month
Definition Date.h:49
static Date now()
Return the current time.
Definition Date.h:78
Base class for Exception.
Definition Exception.h:153
void remember(const Exception &old_r)
Store an other Exception as history.
Definition Exception.cc:154
Describes a resource file located on a medium.
const Pathname & filename() const
The path to the resource on the medium.
Pathname download_mediaMountdir() const
Path where media are preferably mounted or downloaded.
Definition ZConfig.cc:1233
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:940
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const Pathname & path() const
Return current Pathname.
Definition PathInfo.h:251
unsigned int devMinor() const
Definition PathInfo.cc:252
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:286
unsigned int devMajor() const
Definition PathInfo.cc:242
bool absolute() const
Test for an absolute path.
Definition Pathname.h:118
const std::string & asString() const
String representation.
Definition Pathname.h:93
bool empty() const
Test for an empty path.
Definition Pathname.h:116
Pathname realpath() const
Returns this path as the absolute canonical pathname.
Definition Pathname.cc:231
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
Definition Pathname.h:141
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition TmpPath.h:188
static const Pathname & defaultLocation()
Definition TmpPath.cc:163
Pathname path() const
Definition TmpPath.cc:152
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition TmpPath.cc:169
Attach point of a media source.
Pathname path
The path name (mount point).
bool temp
If it was created temporary.
Just inherits Exception to separate media exceptions.
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Ask media manager, if the specified path is already used as attach point or if there are another atta...
virtual void getFile(const OnMediaLocation &file) const
Call concrete handler to provide file below attach point.
virtual void attachTo(bool next=false)=0
Call concrete handler to attach the media.
Url url() const
Primary Url used.
void provideDirTree(const Pathname &dirname) const
Use concrete handler to provide directory tree denoted by path below 'localRoot' (recursive!
virtual bool getDoesFileExist(const Pathname &filename) const =0
check if a file exists
virtual void getDetectedDevices(std::vector< std::string > &devices, unsigned int &index) const
Fill in a vector of detected ejectable devices and the index of the currently attached device within ...
const MediaUrl _url
Primary Url.
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
void disconnect()
Use concrete handler to isconnect media.
MediaSourceRef _mediaSource
The attached media source description reference.
void attach(bool next)
Use concrete handler to attach the media.
void resetParentId()
Called in case, where the media manager takes over the destruction of the parent id (e....
time_t _attach_mtime
timestamp of the the last attach verification
virtual void precacheFiles(const std::vector< OnMediaLocation > &files)
Tries to fetch the given files and precaches them.
virtual bool isAttached() const
True if media is attached.
virtual bool hasMoreDevices()
Check if the media has one more device available for attach(true).
AttachPoint _attachPointHint
The user provided attach preferred point.
virtual void disconnectFrom()
Call concrete handler to disconnect media.
static std::string getRealPath(const std::string &path)
void dirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Return content of directory on media via retlist.
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
AttachPointRef _attachPoint
This is where the media will be actually attached ("mounted").
AttachPoint attachPointHint() const
Get the actual attach point hint.
bool doesFileExist(const Pathname &filename) const
check if a file exists
static bool setAttachPrefix(const Pathname &attach_prefix)
MediaHandler(MediaUrl primaryUrl_r, std::vector< MediaUrl > urls_r, const Pathname &attach_point_r, Pathname urlpath_below_attachpoint_r, const bool does_download_r)
If the concrete media handler provides a nonempty attach_point, it must be an existing directory.
virtual void getFileCopy(const OnMediaLocation &file, const Pathname &targetFilename) const
Call concrete handler to provide a file under a different place in the file system (usually not under...
void setMediaSource(const MediaSourceRef &ref)
Set new media source reference.
Pathname localPath(const Pathname &pathname) const
Files provided will be available at 'localPath(filename)'.
static Pathname _attachPrefix
User defined default attach point prefix.
void forceRelaseAllMedia(bool matchMountFs)
Call to this function will try to release all media matching the currenlty attached media source,...
void release(const std::string &ejectDev="")
Use concrete handler to release the media.
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
void removeAttachPoint()
Remove unused attach point.
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
Pathname attachPoint() const
Return the currently used attach point.
Pathname localRoot() const
Return the local directory that corresponds to medias url, no matter if media isAttached or not.
virtual ~MediaHandler()
Contolling MediaAccess takes care, that attached media is released prior to deleting this.
const std::vector< MediaUrl > _urls
All mirrors including the primary.
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
Pathname _relativeRoot
The relative root directory of the data on the media.
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
Ask the media manager if specified media source is already attached.
void provideDir(const Pathname &dirname) const
Use concrete handler to provide directory denoted by path below 'localRoot' (not recursive!...
bool isSharedMedia() const
Returns a hint if the media is shared or not.
void provideFileCopy(const OnMediaLocation &srcFile, const Pathname &targetFilename) const
Call concrete handler to provide a copy of a file under a different place in the file system (usually...
virtual void releaseFrom(const std::string &ejectDev="")=0
Call concrete handler to release the media.
void provideFile(const OnMediaLocation &file) const
Use concrete handler to provide file denoted by path below 'localRoot'.
AttachedMedia attachedMedia() const
Returns the attached media.
void releasePath(const Pathname &pathname) const
Remove pathname below localRoot IFF handler downloads files to the local filesystem.
virtual void forceEject(const std::string &device)
Call concrete handler to physically eject the media (i.e.
bool _does_download
True if concrete handler downloads files to the local filesystem.
virtual void getDirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const =0
Call concrete handler to provide a content list of directory on media via retlist.
MediaAccessId _parentId
Access Id of media handler we depend on.
Manages access to the 'physical' media, e.g CDROM drives, Disk volumes, directory trees,...
void forceReleaseShared(const MediaSourceRef &media)
AttachedMedia getAttachedMedia(MediaAccessId &accessId) const
static time_t getMountTableMTime()
Get the modification time of the /etc/mtab file.
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Check if the specified path is useable as attach point.
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.
Media source internally used by MediaManager and MediaHandler.
Definition MediaSource.h:38
Interface to the mount program.
Definition mount.h:76
void umount(const std::string &path)
umount device
Definition mount.cc:117
Definition Arch.h:364
String related utilities and Regular expression matching.
FileType
File type information.
Definition PathInfo.h:60
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition PathInfo.cc:417
std::list< DirEntry > DirContent
Returned by readdir.
Definition PathInfo.h:526
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition PathInfo.cc:610
int is_empty_dir(const Pathname &path_r)
Check if the specified directory is empty.
Definition PathInfo.cc:693
std::ostream & operator<<(std::ostream &str, const MediaHandler &obj)
unsigned int MediaAccessId
Media manager access Id type.
Definition MediaSource.h:30
zypp::RW_pointer< MediaSource > MediaSourceRef
zypp::RW_pointer< AttachPoint > AttachPointRef
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition String.h:1097
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\n ", const std::string &sep="\n ", const std::string &sfx="\n", const std::string &extro="}")
Print range defined by iterators (multiline style).
Definition LogTools.h:120
void swap(RW_pointer &rhs) noexcept
Definition PtrTypes.h:325
Listentry returned by readdir.
Definition PathInfo.h:509
A simple structure containing references to a media source and its attach point.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:479
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
#define _(MSG)
Definition Gettext.h:39
#define DBG
Definition Logger.h:99
#define MIL
Definition Logger.h:100
#define ERR
Definition Logger.h:102
#define WAR
Definition Logger.h:101
#define INT
Definition Logger.h:104
Interface to gettext.