libzypp  17.31.31
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 
30 using std::endl;
31 
32 // use directory.yast on every media (not just via ftp/http)
33 #define NONREMOTE_DIRECTORY_YAST 1
34 
35 namespace 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 
114 void
116 {
117  _parentId = 0;
118 }
119 
120 std::string
121 MediaHandler::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 //
141 void
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 //
183 Pathname
185 {
186  return _attachPoint->path;
187 }
188 
189 
191 //
192 //
193 // METHOD NAME : MediaHandler::attachPoint
194 // METHOD TYPE :
195 //
196 // DESCRIPTION :
197 //
198 void
199 MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
200 {
201  _attachPoint.reset( new AttachPoint(path, temporary));
202 }
203 
204 Pathname
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 //
221 void
223 {
224  if( ref)
226  else
228 }
229 
231 //
232 //
233 // METHOD NAME : MediaHandler::attachPointHint
234 // METHOD TYPE : void
235 //
236 // DESCRIPTION :
237 //
238 void
239 MediaHandler::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 //
281 bool
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 //
310 Pathname
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 
346 Pathname
347 MediaHandler::createAttachPoint(const Pathname &attach_root) const
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 //
414 bool
415 MediaHandler::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 //
430 void
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 {
449  if ( _mediaSource && _attachPoint)
451  else
452  return AttachedMedia();
453 }
454 
456 //
457 //
458 // METHOD NAME : MediaHandler::isSharedMedia
459 // METHOD TYPE : bool
460 //
461 // DESCRIPTION :
462 //
463 bool
465 {
466  return !_mediaSource.unique();
467 }
468 
470 //
471 //
472 // METHOD NAME : MediaHandler::checkAttached
473 // METHOD TYPE : bool
474 //
475 // DESCRIPTION :
476 //
477 bool
478 MediaHandler::checkAttached(bool matchMountFs) const
479 {
480  bool _isAttached = false;
481 
482  AttachedMedia ref( attachedMedia() );
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 //
632 void 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 //
663 Pathname MediaHandler::localPath( const Pathname & pathname ) const
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 //
703 void 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 
777 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
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 
846 bool
848 {
849  return MediaHandler::checkAttachPoint( apoint, true, false);
850 }
851 
852 // STATIC
853 bool
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 //
920 bool
922 {
923  return _parentId != 0;
924 }
925 
926 bool
927 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
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 //
956 void 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 //
988 void MediaHandler::provideDir( Pathname dirname ) const
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 //
1026 void MediaHandler::releasePath( Pathname pathname ) const
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 //
1052 void 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 //
1096 bool 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 //
1113 void 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 */
1180 std::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 
1187 void MediaHandler::getFile( const OnMediaLocation &file ) const
1188 {
1189  PathInfo info( localPath( file.filename() ) );
1190  if( info.isFile() ) {
1191  return;
1192  }
1193 
1194  if (info.isExist())
1196  else
1198 }
1199 
1200 void 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 //
1218 void 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 //
1240 void 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 //
1325 bool 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 
1339 void 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 
1350 void 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:
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:533
std::string asString(const Patch::Category &obj)
Definition: Patch.cc:122
Attach point of a media source.
Definition: MediaSource.h:105
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
void resetParentId()
Called in case, where the media manager takes over the destruction of the parent id (e...
#define MIL
Definition: Logger.h:96
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:163
std::ostream & operator<<(std::ostream &str, const MediaHandler &obj)
Listentry returned by readdir.
Definition: PathInfo.h:501
#define _(MSG)
Definition: Gettext.h:37
Interface to the mount program.
Definition: mount.h:74
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:428
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:922
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:91
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.
Pathname _relativeRoot
The relative root directory of the data on the media.
Definition: MediaHandler.h:98
Pathname path
The path name (mount point).
Definition: MediaSource.h:116
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition: MediaSource.h:124
static std::string getRealPath(const std::string &path)
#define INT
Definition: Logger.h:100
static Pathname _attachPrefix
User defined default attach point prefix.
Definition: MediaHandler.h:67
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:107
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:322
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
time_t mtime() const
Definition: PathInfo.h:376
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:442
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.
static const Pathname & defaultLocation()
Definition: TmpPath.cc:157
bool temp
If it was created temporary.
Definition: MediaSource.h:117
Pathname path() const
Definition: TmpPath.cc:146
void provideDir(Pathname dirname) const
Use concrete handler to provide directory denoted by path below &#39;localRoot&#39; (not recursive!).
void releasePath(Pathname pathname) const
Remove pathname below localRoot IFF handler downloads files to the local filesystem.
long use_count() const
Definition: PtrTypes.h:346
unsigned int devMinor() const
Definition: PathInfo.cc:251
bool doesFileExist(const Pathname &filename) const
check if a file exists
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
#define ERR
Definition: Logger.h:98
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
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...
static const ValueType month
Definition: Date.h:49
int is_empty_dir(const Pathname &path_r)
Check if the specified directory is empty.
Definition: PathInfo.cc:688
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:105
Pathname download_mediaMountdir() const
Path where media are preferably mounted or downloaded.
Definition: ZConfig.cc:1203
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:440
MediaSourceRef _mediaSource
The attached media source description reference.
Definition: MediaHandler.h:73
virtual void releaseFrom(const std::string &ejectDev="")=0
Call concrete handler to release the media.
AttachPointRef attachPoint
Definition: MediaSource.h:145
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
zypp::RW_pointer< AttachPoint > AttachPointRef
Definition: MediaSource.h:125
void provideDirTree(Pathname dirname) const
Use concrete handler to provide directory tree denoted by path below &#39;localRoot&#39; (recursive!!).
MediaSourceRef mediaSource
Definition: MediaSource.h:144
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h:177
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:133
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:700
const Url _url
Url to handle.
Definition: MediaHandler.h:113
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:91
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
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.
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:412
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:97
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:518
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
AttachPoint attachPointHint() const
Get the actual attach point hint.
bool absolute() const
Test for an absolute path.
Definition: Pathname.h:116
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.
void removeAttachPoint()
Remove unused attach point.
void forceReleaseShared(const MediaSourceRef &media)
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:36
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:50
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:436
virtual void forceEject(const std::string &device)
Call concrete handler to physically eject the media (i.e.
Definition: MediaHandler.h:344
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 rmdir(const Pathname &path)
Like &#39;rmdir&#39;.
Definition: PathInfo.cc:366
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.
void swap(RW_pointer &rhs)
Definition: PtrTypes.h:315
Pathname absolutename() const
Return this path, adding a leading &#39;/&#39; if relative.
Definition: Pathname.h:139
Base class for Exception.
Definition: Exception.h:145
Pathname attachPoint() const
Return the currently used attach point.
FileType
File type information.
Definition: PathInfo.h:55
Url url() const
Url used.
Definition: MediaHandler.h:503
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:118
bool unique() const
Definition: PtrTypes.h:343
AttachPointRef _attachPoint
This is where the media will be actually attached ("mounted").
Definition: MediaHandler.h:79
time_t _attach_mtime
timestamp of the the last attach verification
Definition: MediaHandler.h:107
unsigned int devMajor() const
Definition: PathInfo.cc:241
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
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
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...
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
virtual bool isAttached() const
True if media is attached.
Definition: MediaHandler.h:520
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
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:1027
virtual void getFile(const OnMediaLocation &file) const
Call concrete handler to provide file below attach point.
bool _does_download
True if concrete handler downloads files to the local filesystem.
Definition: MediaHandler.h:104
static time_t getMountTableMTime()
Get the modification time of the /etc/mtab file.
bool userMayRWX() const
Definition: PathInfo.h:353
Url manipulation class.
Definition: Url.h:91
void umount(const std::string &path)
umount device
Definition: mount.cc:117
#define DBG
Definition: Logger.h:95
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.