libzypp 17.37.17
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//
56 const Pathname & attach_point_r,
57 Pathname urlpath_below_attachpoint_r,
58 const bool does_download_r )
59 : _mediaSource()
62 , _relativeRoot(std::move( urlpath_below_attachpoint_r))
63 , _does_download( does_download_r )
64 , _attach_mtime(0)
65 , _origin(std::move( origin_r ))
66 , _parentId(0)
67{
68 Pathname real_attach_point( getRealPath(attach_point_r.asString()));
69
70 if ( !real_attach_point.empty() ) {
72 // check if provided attachpoint is usable.
74
75 PathInfo adir( real_attach_point );
76 //
77 // The verify if attach_point_r isn't a mountpoint of another
78 // device is done in the particular media handler (if needed).
79 //
80 // We just verify, if attach_point_r is a directory and for
81 // schemes other than "file" and "dir", if it is absolute.
82 //
83 if ( !adir.isDir()
84 || ( _origin.scheme() != "file"
85 && _origin.scheme() != "dir"
86 && !real_attach_point.absolute()) )
87 {
88 ERR << "Provided attach point is not a absolute directory: "
89 << adir << endl;
90 }
91 else {
92 attachPointHint( real_attach_point, false);
93 setAttachPoint( real_attach_point, false);
94 }
95 }
96}
97
99//
100//
101// METHOD NAME : MediaHandler::~MediaHandler
102// METHOD TYPE : Destructor
103//
104// DESCRIPTION :
105//
107{
108 try
109 {
111 }
112 catch(...) {}
113}
114
115void
120
121std::string
122MediaHandler::getRealPath(const std::string &path)
123{
124 return getRealPath(zypp::Pathname(path)).asString();
125}
126
129{
130 return path.realpath();
131}
132
133
135//
136//
137// METHOD NAME : MediaHandler::removeAttachPoint
138// METHOD TYPE : void
139//
140// DESCRIPTION :
141//
142void
144{
145 if ( _mediaSource ) {
146 INT << "MediaHandler deleted with media attached." << endl;
147 return; // no cleanup if media still mounted!
148 }
149
150 DBG << "MediaHandler - checking if to remove attach point" << endl;
151 if ( _attachPoint.unique() &&
152 _attachPoint->temp &&
153 !_attachPoint->path.empty() &&
154 PathInfo(_attachPoint->path).isDir())
155 {
156 Pathname path(_attachPoint->path);
157
158 setAttachPoint("", true);
159
160 int res = recursive_rmdir( path );
161 if ( res == 0 ) {
162 MIL << "Deleted default attach point " << path << endl;
163 } else {
164 ERR << "Failed to Delete default attach point " << path
165 << " errno(" << res << ")" << endl;
166 }
167 }
168 else
169 {
170 if( !_attachPoint->path.empty() && !_attachPoint->temp)
171 DBG << "MediaHandler - attachpoint is not temporary" << endl;
172 }
173}
174
175
177//
178//
179// METHOD NAME : MediaHandler::attachPoint
180// METHOD TYPE : Pathname
181//
182// DESCRIPTION :
183//
186{
187 return _attachPoint->path;
188}
189
190
192//
193//
194// METHOD NAME : MediaHandler::attachPoint
195// METHOD TYPE :
196//
197// DESCRIPTION :
198//
199void
200MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
201{
202 _attachPoint.reset( new AttachPoint(path, temporary));
203}
204
207{
208 if( _attachPoint->path.empty())
209 return Pathname();
210 else
211 return _attachPoint->path + _relativeRoot;
212}
213
215//
216//
217// METHOD NAME : MediaHandler::attachPoint
218// METHOD TYPE :
219//
220// DESCRIPTION :
221//
222void
224{
225 if( ref)
227 else
228 _attachPoint.reset( new AttachPoint());
229}
230
232//
233//
234// METHOD NAME : MediaHandler::attachPointHint
235// METHOD TYPE : void
236//
237// DESCRIPTION :
238//
239void
240MediaHandler::attachPointHint(const Pathname &path, bool temporary)
241{
242 _attachPointHint.path = path;
243 _attachPointHint.temp = temporary;
244}
245
247//
248//
249// METHOD NAME : MediaHandler::attachPointHint
250// METHOD TYPE : AttachPoint
251//
252// DESCRIPTION :
253//
259
261//
262//
263// METHOD NAME : MediaHandler::findAttachedMedia
264// METHOD TYPE : AttachedMedia
265//
266// DESCRIPTION :
267//
273
275//
276//
277// METHOD NAME : MediaHandler::setAttachPrefix
278// METHOD TYPE : void
279//
280// DESCRIPTION :
281//
282bool
284{
285 if( attach_prefix.empty())
286 {
287 MIL << "Resetting to built-in attach point prefixes."
288 << std::endl;
289 MediaHandler::_attachPrefix = attach_prefix;
290 return true;
291 }
292 else
293 if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
294 {
295 MIL << "Setting user defined attach point prefix: "
296 << attach_prefix << std::endl;
297 MediaHandler::_attachPrefix = attach_prefix;
298 return true;
299 }
300 return false;
301}
302
304//
305//
306// METHOD NAME : MediaHandler::attach
307// METHOD TYPE : Pathname
308//
309// DESCRIPTION :
310//
313{
314 Pathname aroot;
315 Pathname apoint;
316 {
317 aroot = MediaHandler::_attachPrefix; // explicit request
318 if ( ! aroot.empty() )
319 apoint = createAttachPoint( aroot );
320 }
321
322 if ( apoint.empty() ) // fallback to config value
323 {
325 if ( ! aroot.empty() )
326 apoint = createAttachPoint( aroot );
327 }
328
329 if ( apoint.empty() ) // fall back to temp space
330 {
332 if ( ! aroot.empty() )
333 apoint = createAttachPoint( aroot );
334 }
335
336 if ( apoint.empty() )
337 {
338 auto except = MediaBadAttachPointException( url() );
339 except.addHistory( _("Create attach point: Can't find a writable directory to create an attach point") );
340 ZYPP_THROW( except );
341 }
342
343 MIL << "Created default attach point " << apoint << std::endl;
344 return apoint;
345}
346
349{
350 Pathname apoint;
351
352 if( attach_root.empty() || !attach_root.absolute()) {
353 ERR << "Create attach point: invalid attach root: '"
354 << attach_root << "'" << std::endl;
355 return apoint;
356 }
357
358 PathInfo adir( attach_root );
359 if( !adir.isDir() || (geteuid() != 0 && !adir.userMayRWX())) {
360 DBG << "Create attach point: attach root is not a writable directory: '"
361 << attach_root << "'" << std::endl;
362 return apoint;
363 }
364
365 static bool cleanup_once( true );
366 if ( cleanup_once )
367 {
368 cleanup_once = false;
369 DBG << "Look for orphaned attach points in " << adir << std::endl;
370 std::list<std::string> entries;
371 filesystem::readdir( entries, attach_root, false );
372 for ( const std::string & entry : entries )
373 {
374 if ( ! str::hasPrefix( entry, "AP_0x" ) )
375 continue;
376 PathInfo sdir( attach_root + entry );
377 if ( sdir.isDir()
378 && sdir.dev() == adir.dev()
379 && ( Date::now()-sdir.mtime() > Date::month ) )
380 {
381 DBG << "Remove orphaned attach point " << sdir << std::endl;
383 }
384 }
385 }
386
387 filesystem::TmpDir tmpdir( attach_root, "AP_0x" );
388 if ( tmpdir )
389 {
390 apoint = getRealPath( tmpdir.path().asString() );
391 if ( ! apoint.empty() )
392 {
393 tmpdir.autoCleanup( false ); // Take responsibility for cleanup.
394 }
395 else
396 {
397 ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl;
398 }
399 }
400 else
401 {
402 ERR << "Unable to create attach point below " << attach_root << std::endl;
403 }
404 return apoint;
405}
406
408//
409//
410// METHOD NAME : MediaHandler::isUseableAttachPoint
411// METHOD TYPE : bool
412//
413// DESCRIPTION :
414//
415bool
416MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const
417{
418 MediaManager manager;
419 return manager.isUseableAttachPoint(path, mtab);
420}
421
422
424//
425//
426// METHOD NAME : MediaHandler::setMediaSource
427// METHOD TYPE : void
428//
429// DESCRIPTION :
430//
431void
433{
434 _mediaSource.reset();
435 if( ref && !ref->type.empty() && !ref->name.empty())
436 _mediaSource = ref;
437}
438
440//
441//
442// METHOD NAME : MediaHandler::attachedMedia
443// METHOD TYPE : AttachedMedia
444//
445// DESCRIPTION :
446//
449{
452 else
453 return AttachedMedia();
454}
455
457//
458//
459// METHOD NAME : MediaHandler::isSharedMedia
460// METHOD TYPE : bool
461//
462// DESCRIPTION :
463//
464bool
466{
467 return !_mediaSource.unique();
468}
469
471//
472//
473// METHOD NAME : MediaHandler::checkAttached
474// METHOD TYPE : bool
475//
476// DESCRIPTION :
477//
478bool
479MediaHandler::checkAttached(bool matchMountFs) const
480{
481 bool _isAttached = false;
482
484 if( ref.mediaSource )
485 {
486 time_t old_mtime = _attach_mtime;
488 if( !(old_mtime <= 0 || _attach_mtime != old_mtime) )
489 {
490 // OK, skip the check (we've seen it at least once)
491 _isAttached = true;
492 }
493 else
494 {
495 if( old_mtime > 0)
496 DBG << "Mount table changed - rereading it" << std::endl;
497 else
498 DBG << "Forced check of the mount table" << std::endl;
499
500 MountEntries entries( MediaManager::getMountEntries());
501 for_( e, entries.begin(), entries.end() )
502 {
503 if ( ref.attachPoint->path != Pathname(e->dir) )
504 continue; // at least the mount points must match
505
506 bool is_device = e->isBlockDevice();
507 if( is_device && (ref.mediaSource->maj_nr &&
508 ref.mediaSource->bdir.empty()))
509 {
510 PathInfo dev_info(e->src);
511 std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
512 MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
513
514 if( ref.mediaSource->equals( media ) )
515 {
516 DBG << "Found media device "
517 << ref.mediaSource->asString()
518 << " in the mount table as " << e->src << std::endl;
519 _isAttached = true;
520 break;
521 }
522 // differs
523 }
524 else
525 if(!is_device && (!ref.mediaSource->maj_nr ||
526 !ref.mediaSource->bdir.empty()))
527 {
528 if( ref.mediaSource->bdir.empty())
529 {
530 // bnc#710269: Type nfs may appear as nfs4 in in the mount table
531 // and maybe vice versa. Similar cifs/smb. Need to unify these types:
532 if ( matchMountFs && e->type != ref.mediaSource->type )
533 {
534 if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) )
535 matchMountFs = false;
536 else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) )
537 matchMountFs = false;
538 else
539 continue; // different types cannot match
540 }
541 // Here: Types are ok or not to check.
542 // Check the name except for nfs (bnc#804544; symlink resolution in mount path)
543 //
544 // [fibonacci]$ ls -l /Local/ma/c12.1
545 // lrwxrwxrwx /Local/ma/c12.1 -> zypp-SuSE-Code-12_1-Branch/
546 //
547 // [localhost]$ mount -t nfs4 fibonacci:/Local/ma/c12.1 /mnt
548 // [localhost]$ mount
549 // fibonacci:/Local/ma/zypp-SuSE-Code-12_1-Branch on /mnt
550
551 // std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
552 // MediaSource media(mtype, e->src);
553
554 if( ref.mediaSource->name == e->src || str::hasPrefix( ref.mediaSource->type, "nfs" ) )
555 {
556 DBG << "Found media name "
557 << ref.mediaSource->asString()
558 << " in the mount table as " << e->src << std::endl;
559 _isAttached = true;
560 break;
561 }
562 }
563 else
564 {
565 if ( ref.mediaSource->bdir == e->src )
566 {
567 DBG << "Found bound media "
568 << ref.mediaSource->asString()
569 << " in the mount table as " << e->src << std::endl;
570 _isAttached = true;
571 break;
572 }
573 }
574 // differs
575 }
576 else // mixed cases:
577 {
578 // Type ISO: Since 11.1 mtab might contain the name of
579 // the loop device instead of the iso file:
580 if ( ref.mediaSource->type == "iso"
581 && str::hasPrefix( Pathname(e->src).asString(), "/dev/loop" )
582 && ref.attachPoint->path == Pathname(e->dir) )
583 {
584 DBG << "Found bound media "
585 << ref.mediaSource->asString()
586 << " in the mount table as " << e->src << std::endl;
587 _isAttached = true;
588 break;
589 }
590 }
591 }
592
593 if( !_isAttached)
594 {
595 MIL << "Looking for " << ref << endl;
596 if( entries.empty() )
597 {
598 ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
599 }
600 else
601 {
602 dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
603 }
604 if( old_mtime > 0 )
605 {
606 ERR << "Attached media not in mount table any more - forcing reset!"
607 << std::endl;
608
609 _mediaSource.reset();
610 }
611 else
612 {
613 WAR << "Attached media not in mount table ..." << std::endl;
614 }
615
616 // reset the mtime and force a new check to make sure,
617 // that we've found the media at least once in the mtab.
618 _attach_mtime = 0;
619 }
620 }
621 }
622 return _isAttached;
623}
624
626//
627//
628// METHOD NAME : MediaHandler::attach
629// METHOD TYPE : PMError
630//
631// DESCRIPTION :
632//
633void MediaHandler::attach( bool next )
634{
635 if ( isAttached() )
636 return;
637
638 // reset it in case of overloaded isAttached()
639 // that checks the media against /etc/mtab ...
641
643 setAttachPoint(ap.path, ap.temp);
644
645 try
646 {
647 attachTo( next ); // pass to concrete handler
648 }
649 catch(const MediaException &e)
650 {
652 ZYPP_RETHROW(e);
653 }
654 MIL << "Attached: " << *this << endl;
655}
656
657
659//
660//
661// METHOD NAME : MediaHandler::localPath
662// METHOD TYPE : Pathname
663//
665{
666 Pathname _localRoot( localRoot());
667 if ( _localRoot.empty() )
668 return _localRoot;
669
670 // we must check maximum file name length
671 // this is important for fetching the suseservers, the
672 // url with all parameters can get too long (bug #42021)
673
674 return _localRoot + pathname.absolutename();
675}
676
677
678
679
680
682//
683//
684// METHOD NAME : MediaHandler::disconnect
685// METHOD TYPE : PMError
686//
688{
689 if ( !isAttached() )
690 return;
691
692 disconnectFrom(); // pass to concrete handler
693 MIL << "Disconnected: " << *this << endl;
694}
695
697//
698//
699// METHOD NAME : MediaHandler::release
700// METHOD TYPE : PMError
701//
702// DESCRIPTION :
703//
704void MediaHandler::release( const std::string & ejectDev )
705{
706 if ( !isAttached() ) {
707 DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
708 << std::endl;
709 if ( !ejectDev.empty() )
710 forceEject(ejectDev);
711 return;
712 }
713
714 DBG << "Request to release attached media "
715 << _mediaSource->asString()
716 << ", use count=" << _mediaSource.use_count()
717 << std::endl;
718
719 if( _mediaSource.unique())
720 {
721 DBG << "Releasing media " << _mediaSource->asString() << std::endl;
722 try {
723 releaseFrom( ejectDev ); // pass to concrete handler
724 }
725 catch(const MediaNotEjectedException &e)
726 {
727 // not ejected because the media
728 // is mounted by somebody else
729 // (if our attach point is busy,
730 // we get an umount exception)
731 _mediaSource.reset(NULL);
733 // OK, retrow now
734 ZYPP_RETHROW(e);
735 }
736 _mediaSource.reset(NULL);
738 }
739 else if( !ejectDev.empty() ) {
740 //
741 // Can't eject a shared media
742 //
743 //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
744
746 _mediaSource.reset(NULL);
747
748 MediaManager manager;
749 manager.forceReleaseShared(media);
750
752 DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
753 try {
754 releaseFrom( ejectDev ); // pass to concrete handler
755 }
756 catch(const MediaNotEjectedException &e)
757 {
758 // not ejected because the media
759 // is mounted by somebody else
760 // (if our attach point is busy,
761 // we get an umount exception)
762 _mediaSource.reset(NULL);
764 // OK, retrow now
765 ZYPP_RETHROW(e);
766 }
767 _mediaSource.reset(NULL);
769 }
770 else {
771 DBG << "Releasing shared media reference only" << std::endl;
772 _mediaSource.reset(NULL);
773 setAttachPoint("", true);
774 }
775 MIL << "Released: " << *this << endl;
776}
777
779{
780 forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
781}
782
784 bool matchMountFs)
785{
786 if( !ref)
787 return;
788
789 MountEntries entries( MediaManager::getMountEntries());
790 MountEntries::const_iterator e;
791 for( e = entries.begin(); e != entries.end(); ++e)
792 {
793 bool is_device = false;
794 PathInfo dev_info;
795
796 if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
797 dev_info(e->src) && dev_info.isBlk())
798 {
799 is_device = true;
800 }
801
802 if( is_device && ref->maj_nr)
803 {
804 std::string mtype(matchMountFs ? e->type : ref->type);
805 MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
806
807 if( ref->equals( media) && e->type != "subfs")
808 {
809 DBG << "Forcing release of media device "
810 << ref->asString()
811 << " in the mount table as "
812 << e->src << std::endl;
813 try {
814 Mount mount;
815 mount.umount(e->dir);
816 }
817 catch (const Exception &e)
818 {
819 ZYPP_CAUGHT(e);
820 }
821 }
822 }
823 else
824 if(!is_device && !ref->maj_nr)
825 {
826 std::string mtype(matchMountFs ? e->type : ref->type);
827 MediaSource media(mtype, e->src);
828 if( ref->equals( media))
829 {
830 DBG << "Forcing release of media name "
831 << ref->asString()
832 << " in the mount table as "
833 << e->src << std::endl;
834 try {
835 Mount mount;
836 mount.umount(e->dir);
837 }
838 catch (const Exception &e)
839 {
840 ZYPP_CAUGHT(e);
841 }
842 }
843 }
844 }
845}
846
847bool
849{
850 return MediaHandler::checkAttachPoint( apoint, true, false);
851}
852
853// STATIC
854bool
856 bool emptydir,
857 bool writeable)
858{
859 if( apoint.empty() || !apoint.absolute())
860 {
861 ERR << "Attach point '" << apoint << "' is not absolute"
862 << std::endl;
863 return false;
864 }
865 if( apoint == "/")
866 {
867 ERR << "Attach point '" << apoint << "' is not allowed"
868 << std::endl;
869 return false;
870 }
871
872 PathInfo ainfo(apoint);
873 if( !ainfo.isDir())
874 {
875 ERR << "Attach point '" << apoint << "' is not a directory"
876 << std::endl;
877 return false;
878 }
879
880 if( emptydir)
881 {
882 if( 0 != zypp::filesystem::is_empty_dir(apoint))
883 {
884 ERR << "Attach point '" << apoint << "' is not a empty directory"
885 << std::endl;
886 return false;
887 }
888 }
889
890 if( writeable)
891 {
892 Pathname apath(apoint + "XXXXXX");
893 char *atemp = ::strdup( apath.asString().c_str());
894 char *atest = NULL;
895 if( !ainfo.userMayRWX() || atemp == NULL ||
896 (atest=::mkdtemp(atemp)) == NULL)
897 {
898 if( atemp != NULL)
899 ::free(atemp);
900
901 ERR << "Attach point '" << ainfo.path()
902 << "' is not a writeable directory" << std::endl;
903 return false;
904 }
905 else if( atest != NULL)
906 ::rmdir(atest);
907
908 if( atemp != NULL)
909 ::free(atemp);
910 }
911 return true;
912}
913
915//
916// METHOD NAME : MediaHandler::dependsOnParent
917// METHOD TYPE : bool
918//
919// DESCRIPTION :
920//
921bool
923{
924 return _parentId != 0;
925}
926
927bool
929{
930 if( _parentId != 0)
931 {
932 if(parentId == _parentId)
933 return true;
934
935 if( !exactIdMatch)
936 {
937 MediaManager mm;
939 AttachedMedia am2 = mm.getAttachedMedia(parentId);
940 if( am1.mediaSource && am2.mediaSource)
941 {
942 return am1.mediaSource->equals( *(am2.mediaSource));
943 }
944 }
945 }
946 return false;
947}
948
950//
951//
952// METHOD NAME : MediaHandler::provideFile
953// METHOD TYPE : PMError
954//
955// DESCRIPTION :
956//
957void MediaHandler::provideFileCopy( const OnMediaLocation &srcFile, const Pathname& targetFilename ) const
958{
959 if ( !isAttached() ) {
960 INT << "Media not_attached on provideFileCopy(" << srcFile
961 << "," << targetFilename << ")" << endl;
963 }
964
965 getFileCopy( srcFile, targetFilename ); // pass to concrete handler
966 DBG << "provideFileCopy(" << srcFile << "," << targetFilename << ")" << endl;
967}
968
970{
971 if ( !isAttached() ) {
972 INT << "Error: Not attached on provideFile(" << file << ")" << endl;
974 }
975
976 getFile( file ); // pass to concrete handler
977 DBG << "provideFile(" << file << ")" << endl;
978}
979
980
982//
983//
984// METHOD NAME : MediaHandler::provideDir
985// METHOD TYPE : PMError
986//
987// DESCRIPTION :
988//
989void MediaHandler::provideDir( const Pathname& dirname ) const
990{
991 if ( !isAttached() ) {
992 INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
994 }
995
996 getDir( dirname, /*recursive*/false ); // pass to concrete handler
997 MIL << "provideDir(" << dirname << ")" << endl;
998}
999
1001//
1002//
1003// METHOD NAME : MediaHandler::provideDirTree
1004// METHOD TYPE : PMError
1005//
1006// DESCRIPTION :
1007//
1008void MediaHandler::provideDirTree( const Pathname& dirname ) const
1009{
1010 if ( !isAttached() ) {
1011 INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
1013 }
1014
1015 getDir( dirname, /*recursive*/true ); // pass to concrete handler
1016 MIL << "provideDirTree(" << dirname << ")" << endl;
1017}
1018
1020//
1021//
1022// METHOD NAME : MediaHandler::releasePath
1023// METHOD TYPE : PMError
1024//
1025// DESCRIPTION :
1026//
1027void MediaHandler::releasePath( const Pathname& pathname ) const
1028{
1029 if ( ! _does_download || _attachPoint->empty() )
1030 return;
1031
1032 PathInfo info( localPath( pathname ) );
1033
1034 if ( info.isFile() ) {
1035 unlink( info.path() );
1036 } else if ( info.isDir() ) {
1037 if ( info.path() != localRoot() ) {
1038 recursive_rmdir( info.path() );
1039 } else {
1040 clean_dir( info.path() );
1041 }
1042 }
1043}
1044
1046//
1047//
1048// METHOD NAME : MediaHandler::dirInfo
1049// METHOD TYPE : PMError
1050//
1051// DESCRIPTION :
1052//
1053void MediaHandler::dirInfo( std::list<std::string> & retlist,
1054 const Pathname & dirname, bool dots ) const
1055{
1056 retlist.clear();
1057
1058 if ( !isAttached() ) {
1059 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1061 }
1062
1063 getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1064 MIL << "dirInfo(" << dirname << ")" << endl;
1065}
1066
1068//
1069//
1070// METHOD NAME : MediaHandler::dirInfo
1071// METHOD TYPE : PMError
1072//
1073// DESCRIPTION :
1074//
1076 const Pathname & dirname, bool dots ) const
1077{
1078 retlist.clear();
1079
1080 if ( !isAttached() ) {
1081 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1083 }
1084
1085 getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1086 MIL << "dirInfo(" << dirname << ")" << endl;
1087}
1088
1090//
1091//
1092// METHOD NAME : MediaHandler::doesFileExist
1093// METHOD TYPE : PMError
1094//
1095// DESCRIPTION :
1096//
1097bool MediaHandler::doesFileExist( const Pathname & filename ) const
1098{
1099 // TODO do some logging
1100 if ( !isAttached() ) {
1101 INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
1103 }
1104 return getDoesFileExist( filename );
1105 MIL << "doesFileExist(" << filename << ")" << endl;
1106}
1107
1109//
1110//
1111// METHOD NAME : MediaHandler::getDirectoryYast
1112// METHOD TYPE : PMError
1113//
1114void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
1115 const Pathname & dirname, bool dots ) const
1116{
1117 retlist.clear();
1118
1119 filesystem::DirContent content;
1120 getDirectoryYast( content, dirname, dots );
1121
1122 // convert to std::list<std::string>
1123 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1124 retlist.push_back( it->name );
1125 }
1126}
1127
1129//
1130//
1131// METHOD NAME : MediaHandler::getDirectoryYast
1132// METHOD TYPE : PMError
1133//
1135 const Pathname & dirname, bool dots ) const
1136{
1137 retlist.clear();
1138
1139 // look for directory.yast
1140 auto dirFile = OnMediaLocation( dirname + "directory.yast" );
1141 getFile( dirFile );
1142 DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1143
1144 // using directory.yast
1145 std::ifstream dir( localPath( dirFile.filename() ).asString().c_str() );
1146 if ( dir.fail() ) {
1147 ERR << "Unable to load '" << localPath( dirFile.filename() ) << "'" << endl;
1149 "Unable to load '" + localPath( dirFile.filename() ).asString() + "'"));
1150 }
1151
1152 std::string line;
1153 while( getline( dir, line ) ) {
1154 if ( line.empty() ) continue;
1155 if ( line == "directory.yast" ) continue;
1156
1157 // Newer directory.yast append '/' to directory names
1158 // Remaining entries are unspecified, although most probabely files.
1160 if ( *line.rbegin() == '/' ) {
1161 line.erase( line.end()-1 );
1162 type = filesystem::FT_DIR;
1163 }
1164
1165 if ( dots ) {
1166 if ( line == "." || line == ".." ) continue;
1167 } else {
1168 if ( *line.begin() == '.' ) continue;
1169 }
1170
1171 retlist.push_back( filesystem::DirEntry( line, type ) );
1172 }
1173}
1174
1175/******************************************************************
1176**
1177**
1178** FUNCTION NAME : operator<<
1179** FUNCTION TYPE : ostream &
1180*/
1181std::ostream & operator<<( std::ostream & str, const MediaHandler & obj )
1182{
1183 str << obj.url() << ( obj.isAttached() ? "" : " not" )
1184 << " attached; localRoot \"" << obj.localRoot() << "\"";
1185 return str;
1186}
1187
1189{
1190 PathInfo info( localPath( file.filename() ) );
1191 if( info.isFile() ) {
1192 return;
1193 }
1194
1195 if (info.isExist())
1197 else
1199}
1200
1201void MediaHandler::getFileCopy( const OnMediaLocation &file, const Pathname &targetFilename ) const
1202{
1203 getFile( file );
1204 if ( copy( localPath( file.filename() ), targetFilename ) != 0 ) {
1205 ZYPP_THROW(MediaWriteException(targetFilename));
1206 }
1207}
1208
1209
1211//
1212//
1213// METHOD NAME : MediaHandler::getDir
1214// METHOD TYPE : PMError
1215//
1216// DESCRIPTION : Asserted that media is attached.
1217// Default implementation of pure virtual.
1218//
1219void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1220{
1221 PathInfo info( localPath( dirname ) );
1222 if( info.isDir() ) {
1223 return;
1224 }
1225
1226 if (info.isExist())
1228 else
1230}
1231
1233//
1234//
1235// METHOD NAME : MediaHandler::getDirInfo
1236// METHOD TYPE : PMError
1237//
1238// DESCRIPTION : Asserted that media is attached and retlist is empty.
1239// Default implementation of pure virtual.
1240//
1241void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1242 const Pathname & dirname, bool dots ) const
1243{
1244 PathInfo info( localPath( dirname ) );
1245 if( ! info.isDir() ) {
1247 }
1248
1249#if NONREMOTE_DIRECTORY_YAST
1250 // use directory.yast if available
1251 try {
1252 getDirectoryYast( retlist, dirname, dots );
1253 }
1254 catch (const MediaException & excpt_r)
1255 {
1256#endif
1257
1258 // readdir
1259 int res = readdir( retlist, info.path(), dots );
1260 if ( res )
1261 {
1262 MediaSystemException nexcpt(url(), "readdir failed");
1263#if NONREMOTE_DIRECTORY_YAST
1264 nexcpt.remember(excpt_r);
1265#endif
1266 ZYPP_THROW(nexcpt);
1267 }
1268
1269#if NONREMOTE_DIRECTORY_YAST
1270 }
1271#endif
1272
1273 return;
1274}
1275
1277//
1278//
1279// METHOD NAME : MediaHandler::getDirInfo
1280// METHOD TYPE : PMError
1281//
1282// DESCRIPTION : Asserted that media is attached and retlist is empty.
1283// Default implementation of pure virtual.
1284//
1286 const Pathname & dirname, bool dots ) const
1287{
1288 PathInfo info( localPath( dirname ) );
1289 if( ! info.isDir() ) {
1291 }
1292
1293#if NONREMOTE_DIRECTORY_YAST
1294 // use directory.yast if available
1295 try {
1296 getDirectoryYast( retlist, dirname, dots );
1297 }
1298 catch (const MediaException & excpt_r)
1299 {
1300#endif
1301
1302 // readdir
1303 int res = readdir( retlist, info.path(), dots );
1304 if ( res )
1305 {
1306 MediaSystemException nexcpt(url(), "readdir failed");
1307#if NONREMOTE_DIRECTORY_YAST
1308 nexcpt.remember(excpt_r);
1309#endif
1310 ZYPP_THROW(nexcpt);
1311 }
1312#if NONREMOTE_DIRECTORY_YAST
1313 }
1314#endif
1315}
1316
1318//
1319//
1320// METHOD NAME : MediaHandler::getDoesFileExist
1321// METHOD TYPE : PMError
1322//
1323// DESCRIPTION : Asserted that file is not a directory
1324// Default implementation of pure virtual.
1325//
1326bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1327{
1328 PathInfo info( localPath( filename ) );
1329 if( info.isDir() ) {
1331 }
1332 return info.isExist();
1333}
1334
1336{
1337 return false;
1338}
1339
1340void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
1341 unsigned int & index) const
1342{
1343 // clear the vector by default
1344 if (!devices.empty())
1345 devices.clear();
1346 index = 0;
1347
1348 DBG << "No devices for this medium" << endl;
1349}
1350
1351void MediaHandler::precacheFiles( const std::vector<OnMediaLocation> & )
1352{
1353 /* do nothing */
1354}
1355
1356 } // namespace media
1357} // namespace zypp
1358// 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
Manages a data source characterized by an authoritative URL and a list of mirror URLs.
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.
MediaHandler(MirroredOrigin origin_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 attachTo(bool next=false)=0
Call concrete handler to attach the media.
MirroredOrigin _origin
Contains the authority URL and mirrors.
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 ...
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)
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.
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.