libzypp  17.28.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 <zypp/media/Mount.h>
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
127 
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 << "Reseting to built-in attach point prefixes."
318  << std::endl;
319  MediaHandler::_attachPrefix = attach_prefix;
320  return true;
321  }
322  else
323  if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
324  {
325  MIL << "Setting user defined attach point prefix: "
326  << attach_prefix << std::endl;
327  MediaHandler::_attachPrefix = attach_prefix;
328  return true;
329  }
330  return false;
331 }
332 
334 //
335 //
336 // METHOD NAME : MediaHandler::attach
337 // METHOD TYPE : Pathname
338 //
339 // DESCRIPTION :
340 //
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;
999  }
1000 
1001  getFileCopy( srcFile, targetFilename ); // pass to concrete handler
1002  DBG << "provideFileCopy(" << srcFile << "," << targetFilename << ")" << endl;
1003 }
1004 
1006 {
1007  if ( !isAttached() ) {
1008  INT << "Error: Not attached on provideFile(" << file << ")" << endl;
1010  }
1011 
1012  getFile( file ); // pass to concrete handler
1013  DBG << "provideFile(" << file << ")" << endl;
1014 }
1015 
1016 
1018 //
1019 //
1020 // METHOD NAME : MediaHandler::provideDir
1021 // METHOD TYPE : PMError
1022 //
1023 // DESCRIPTION :
1024 //
1025 void MediaHandler::provideDir( Pathname dirname ) const
1026 {
1027  if ( !isAttached() ) {
1028  INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
1030  }
1031 
1032  getDir( dirname, /*recursive*/false ); // pass to concrete handler
1033  MIL << "provideDir(" << dirname << ")" << endl;
1034 }
1035 
1037 //
1038 //
1039 // METHOD NAME : MediaHandler::provideDirTree
1040 // METHOD TYPE : PMError
1041 //
1042 // DESCRIPTION :
1043 //
1045 {
1046  if ( !isAttached() ) {
1047  INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
1049  }
1050 
1051  getDir( dirname, /*recursive*/true ); // pass to concrete handler
1052  MIL << "provideDirTree(" << dirname << ")" << endl;
1053 }
1054 
1056 //
1057 //
1058 // METHOD NAME : MediaHandler::releasePath
1059 // METHOD TYPE : PMError
1060 //
1061 // DESCRIPTION :
1062 //
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;
1097  }
1098 
1099  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1100  MIL << "dirInfo(" << dirname << ")" << endl;
1101 }
1102 
1104 //
1105 //
1106 // METHOD NAME : MediaHandler::dirInfo
1107 // METHOD TYPE : PMError
1108 //
1109 // DESCRIPTION :
1110 //
1112  const Pathname & dirname, bool dots ) const
1113 {
1114  retlist.clear();
1115 
1116  if ( !isAttached() ) {
1117  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1119  }
1120 
1121  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1122  MIL << "dirInfo(" << dirname << ")" << endl;
1123 }
1124 
1126 //
1127 //
1128 // METHOD NAME : MediaHandler::doesFileExist
1129 // METHOD TYPE : PMError
1130 //
1131 // DESCRIPTION :
1132 //
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;
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;
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())
1233  else
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())
1264  else
1266 }
1267 
1269 //
1270 //
1271 // METHOD NAME : MediaHandler::getDirInfo
1272 // METHOD TYPE : PMError
1273 //
1274 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1275 // Default implementation of pure virtual.
1276 //
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() ) {
1283  }
1284 
1285 #if NONREMOTE_DIRECTORY_YAST
1286  // use directory.yast if available
1287  try {
1288  getDirectoryYast( retlist, dirname, dots );
1289  }
1290  catch (const MediaException & excpt_r)
1291  {
1292 #endif
1293 
1294  // readdir
1295  int res = readdir( retlist, info.path(), dots );
1296  if ( res )
1297  {
1298  MediaSystemException nexcpt(url(), "readdir failed");
1299 #if NONREMOTE_DIRECTORY_YAST
1300  nexcpt.remember(excpt_r);
1301 #endif
1302  ZYPP_THROW(nexcpt);
1303  }
1304 
1305 #if NONREMOTE_DIRECTORY_YAST
1306  }
1307 #endif
1308 
1309  return;
1310 }
1311 
1313 //
1314 //
1315 // METHOD NAME : MediaHandler::getDirInfo
1316 // METHOD TYPE : PMError
1317 //
1318 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1319 // Default implementation of pure virtual.
1320 //
1322  const Pathname & dirname, bool dots ) const
1323 {
1324  PathInfo info( localPath( dirname ) );
1325  if( ! info.isDir() ) {
1327  }
1328 
1329 #if NONREMOTE_DIRECTORY_YAST
1330  // use directory.yast if available
1331  try {
1332  getDirectoryYast( retlist, dirname, dots );
1333  }
1334  catch (const MediaException & excpt_r)
1335  {
1336 #endif
1337 
1338  // readdir
1339  int res = readdir( retlist, info.path(), dots );
1340  if ( res )
1341  {
1342  MediaSystemException nexcpt(url(), "readdir failed");
1343 #if NONREMOTE_DIRECTORY_YAST
1344  nexcpt.remember(excpt_r);
1345 #endif
1346  ZYPP_THROW(nexcpt);
1347  }
1348 #if NONREMOTE_DIRECTORY_YAST
1349  }
1350 #endif
1351 }
1352 
1354 //
1355 //
1356 // METHOD NAME : MediaHandler::getDoesFileExist
1357 // METHOD TYPE : PMError
1358 //
1359 // DESCRIPTION : Asserted that file is not a directory
1360 // Default implementation of pure virtual.
1361 //
1362 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1363 {
1364  PathInfo info( localPath( filename ) );
1365  if( info.isDir() ) {
1367  }
1368  return info.isExist();
1369 }
1370 
1372 {
1373  return false;
1374 }
1375 
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:
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:528
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
Listentry returned by readdir.
Definition: PathInfo.h:499
#define _(MSG)
Definition: Gettext.h:37
Interface to the mount program.
Definition: Mount.h:69
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:244
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Describes a resource file located on a medium.
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
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:91
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:374
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:628
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:1083
std::ostream & operator<<(std::ostream &str, const MediaBlockList &bl)
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:400
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:640
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:279
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:514
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:396
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:576
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:53
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:218
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:351
Url manipulation class.
Definition: Url.h:91
void umount(const std::string &path)
umount device
Definition: Mount.cc:163
#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.