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