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