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