libzypp  17.30.2
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  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 //
172 void
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 //
214 Pathname
216 {
217  return _attachPoint->path;
218 }
219 
220 
222 //
223 //
224 // METHOD NAME : MediaHandler::attachPoint
225 // METHOD TYPE :
226 //
227 // DESCRIPTION :
228 //
229 void
230 MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
231 {
232  _attachPoint.reset( new AttachPoint(path, temporary));
233 }
234 
235 Pathname
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 //
252 void
254 {
255  if( ref)
257  else
259 }
260 
262 //
263 //
264 // METHOD NAME : MediaHandler::attachPointHint
265 // METHOD TYPE : void
266 //
267 // DESCRIPTION :
268 //
269 void
270 MediaHandler::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 //
312 bool
314 {
315  if( attach_prefix.empty())
316  {
317  MIL << "Resetting 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 //
341 Pathname
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 
377 Pathname
378 MediaHandler::createAttachPoint(const Pathname &attach_root) const
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 //
445 bool
446 MediaHandler::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 //
461 void
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 {
480  if ( _mediaSource && _attachPoint)
482  else
483  return AttachedMedia();
484 }
485 
487 //
488 //
489 // METHOD NAME : MediaHandler::isSharedMedia
490 // METHOD TYPE : bool
491 //
492 // DESCRIPTION :
493 //
494 bool
496 {
497  return !_mediaSource.unique();
498 }
499 
501 //
502 //
503 // METHOD NAME : MediaHandler::checkAttached
504 // METHOD TYPE : bool
505 //
506 // DESCRIPTION :
507 //
508 bool
509 MediaHandler::checkAttached(bool matchMountFs) const
510 {
511  bool _isAttached = false;
512 
513  AttachedMedia ref( attachedMedia() );
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 //
669 void 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 //
700 Pathname MediaHandler::localPath( const Pathname & pathname ) const
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 //
740 void 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 
814 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
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 
883 bool
885 {
886  return MediaHandler::checkAttachPoint( apoint, true, false);
887 }
888 
889 // STATIC
890 bool
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 //
957 bool
959 {
960  return _parentId != 0;
961 }
962 
963 bool
964 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
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 //
993 void MediaHandler::provideFileCopy( const OnMediaLocation &srcFile, Pathname targetFilename ) const
994 {
995  if ( !isAttached() ) {
996  INT << "Media not_attached on provideFileCopy(" << srcFile
997  << "," << targetFilename << ")" << endl;
998  ZYPP_THROW(MediaNotAttachedException(url()));
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;
1009  ZYPP_THROW(MediaNotAttachedException(url()));
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 //
1025 void MediaHandler::provideDir( Pathname dirname ) const
1026 {
1027  if ( !isAttached() ) {
1028  INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
1029  ZYPP_THROW(MediaNotAttachedException(url()));
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;
1048  ZYPP_THROW(MediaNotAttachedException(url()));
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 //
1063 void MediaHandler::releasePath( Pathname pathname ) const
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 //
1089 void 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;
1096  ZYPP_THROW(MediaNotAttachedException(url()));
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;
1118  ZYPP_THROW(MediaNotAttachedException(url()));
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 //
1133 bool MediaHandler::doesFileExist( const Pathname & filename ) const
1134 {
1135  // TODO do some logging
1136  if ( !isAttached() ) {
1137  INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
1138  ZYPP_THROW(MediaNotAttachedException(url()));
1139  }
1140  return getDoesFileExist( filename );
1141  MIL << "doesFileExist(" << filename << ")" << endl;
1142 }
1143 
1145 //
1146 //
1147 // METHOD NAME : MediaHandler::getDirectoryYast
1148 // METHOD TYPE : PMError
1149 //
1150 void 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;
1184  ZYPP_THROW(MediaSystemException(url(),
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 */
1217 std::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 
1224 void MediaHandler::getFile( const OnMediaLocation &file ) const
1225 {
1226  PathInfo info( localPath( file.filename() ) );
1227  if( info.isFile() ) {
1228  return;
1229  }
1230 
1231  if (info.isExist())
1232  ZYPP_THROW(MediaNotAFileException(url(), localPath(file.filename())));
1233  else
1234  ZYPP_THROW(MediaFileNotFoundException(url(), file.filename()));
1235 }
1236 
1237 void 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 //
1255 void 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())
1263  ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
1264  else
1265  ZYPP_THROW(MediaFileNotFoundException(url(), dirname));
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 //
1277 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1278  const Pathname & dirname, bool dots ) const
1279 {
1280  PathInfo info( localPath( dirname ) );
1281  if( ! info.isDir() ) {
1282  ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
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() ) {
1326  ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
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 //
1362 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1363 {
1364  PathInfo info( localPath( filename ) );
1365  if( info.isDir() ) {
1366  ZYPP_THROW(MediaNotAFileException(url(), localPath(filename)));
1367  }
1368  return info.isExist();
1369 }
1370 
1372 {
1373  return false;
1374 }
1375 
1376 void 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 
1387 void 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
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:1092
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:823
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
time_t mtime() const
Definition: PathInfo.h:376
bool userMayRWX() const
Definition: PathInfo.h:353
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
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
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
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
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::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
Definition: IOStream.h:50
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition: MediaSource.h:124
std::ostream & operator<<(std::ostream &str, const MediaHandler &obj)
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
zypp::RW_pointer< AttachPoint > AttachPointRef
Definition: MediaSource.h:125
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1027
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\n ", const std::string &sep="\n ", const std::string &sfx="\n", const std::string &extro="}")
Print range defined by iterators (multiline style).
Definition: LogTools.h: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:440
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:436
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:428
#define _(MSG)
Definition: Gettext.h:37
#define DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96
#define ERR
Definition: Logger.h:98
#define WAR
Definition: Logger.h:97
#define INT
Definition: Logger.h:100