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