libzypp  16.1.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/String.h"
24 #include "zypp/media/Mount.h"
25 #include <limits.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 
29 
30 using namespace std;
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 //
54 MediaHandler::MediaHandler ( const Url & url_r,
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 
157 zypp::Pathname
158 MediaHandler::getRealPath(const Pathname &path)
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
313 MediaHandler::setAttachPrefix(const Pathname &attach_prefix)
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  ERR << "Create attach point: Can't find a writable directory to create an attach point" << std::endl;
369  }
370  else
371  {
372  MIL << "Created default attach point " << apoint << std::endl;
373  }
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;
412  filesystem::recursive_rmdir( sdir.path() );
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  }
613 
614  if( !_isAttached)
615  {
616  MIL << "Looking for " << ref << endl;
617  if( entries.empty() )
618  {
619  ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
620  }
621  else
622  {
623  dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
624  }
625  if( old_mtime > 0 )
626  {
627  ERR << "Attached media not in mount table any more - forcing reset!"
628  << std::endl;
629 
631  }
632  else
633  {
634  WAR << "Attached media not in mount table ..." << std::endl;
635  }
636 
637  // reset the mtime and force a new check to make sure,
638  // that we've found the media at least once in the mtab.
639  _attach_mtime = 0;
640  }
641  }
642  }
643  return _isAttached;
644 }
645 
647 //
648 //
649 // METHOD NAME : MediaHandler::attach
650 // METHOD TYPE : PMError
651 //
652 // DESCRIPTION :
653 //
654 void MediaHandler::attach( bool next )
655 {
656  if ( isAttached() )
657  return;
658 
659  // reset it in case of overloaded isAttached()
660  // that checks the media against /etc/mtab ...
662 
664  setAttachPoint(ap.path, ap.temp);
665 
666  try
667  {
668  attachTo( next ); // pass to concrete handler
669  }
670  catch(const MediaException &e)
671  {
673  ZYPP_RETHROW(e);
674  }
675  MIL << "Attached: " << *this << endl;
676 }
677 
678 
680 //
681 //
682 // METHOD NAME : MediaHandler::localPath
683 // METHOD TYPE : Pathname
684 //
685 Pathname MediaHandler::localPath( const Pathname & pathname ) const
686 {
687  Pathname _localRoot( localRoot());
688  if ( _localRoot.empty() )
689  return _localRoot;
690 
691  // we must check maximum file name length
692  // this is important for fetching the suseservers, the
693  // url with all parameters can get too long (bug #42021)
694 
695  return _localRoot + pathname.absolutename();
696 }
697 
698 
699 
700 
701 
703 //
704 //
705 // METHOD NAME : MediaHandler::disconnect
706 // METHOD TYPE : PMError
707 //
709 {
710  if ( !isAttached() )
711  return;
712 
713  disconnectFrom(); // pass to concrete handler
714  MIL << "Disconnected: " << *this << endl;
715 }
716 
718 //
719 //
720 // METHOD NAME : MediaHandler::release
721 // METHOD TYPE : PMError
722 //
723 // DESCRIPTION :
724 //
725 void MediaHandler::release( const std::string & ejectDev )
726 {
727  if ( !isAttached() ) {
728  DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
729  << std::endl;
730  if ( !ejectDev.empty() )
731  forceEject(ejectDev);
732  return;
733  }
734 
735  DBG << "Request to release attached media "
736  << _mediaSource->asString()
737  << ", use count=" << _mediaSource.use_count()
738  << std::endl;
739 
740  if( _mediaSource.unique())
741  {
742  DBG << "Releasing media " << _mediaSource->asString() << std::endl;
743  try {
744  releaseFrom( ejectDev ); // pass to concrete handler
745  }
746  catch(const MediaNotEjectedException &e)
747  {
748  // not ejected because the media
749  // is mounted by somebody else
750  // (if our attach point is busy,
751  // we get an umount exception)
752  _mediaSource.reset(NULL);
754  // OK, retrow now
755  ZYPP_RETHROW(e);
756  }
757  _mediaSource.reset(NULL);
759  }
760  else if( !ejectDev.empty() ) {
761  //
762  // Can't eject a shared media
763  //
764  //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
765 
767  _mediaSource.reset(NULL);
768 
769  MediaManager manager;
770  manager.forceReleaseShared(media);
771 
772  setMediaSource(media);
773  DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
774  try {
775  releaseFrom( ejectDev ); // pass to concrete handler
776  }
777  catch(const MediaNotEjectedException &e)
778  {
779  // not ejected because the media
780  // is mounted by somebody else
781  // (if our attach point is busy,
782  // we get an umount exception)
783  _mediaSource.reset(NULL);
785  // OK, retrow now
786  ZYPP_RETHROW(e);
787  }
788  _mediaSource.reset(NULL);
790  }
791  else {
792  DBG << "Releasing shared media reference only" << std::endl;
793  _mediaSource.reset(NULL);
794  setAttachPoint("", true);
795  }
796  MIL << "Released: " << *this << endl;
797 }
798 
799 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
800 {
801  forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
802 }
803 
805  bool matchMountFs)
806 {
807  if( !ref)
808  return;
809 
810  MountEntries entries( MediaManager::getMountEntries());
811  MountEntries::const_iterator e;
812  for( e = entries.begin(); e != entries.end(); ++e)
813  {
814  bool is_device = false;
815  PathInfo dev_info;
816 
817  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
818  dev_info(e->src) && dev_info.isBlk())
819  {
820  is_device = true;
821  }
822 
823  if( is_device && ref->maj_nr)
824  {
825  std::string mtype(matchMountFs ? e->type : ref->type);
826  MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
827 
828  if( ref->equals( media) && e->type != "subfs")
829  {
830  DBG << "Forcing release of media device "
831  << ref->asString()
832  << " in the mount table as "
833  << e->src << std::endl;
834  try {
835  Mount mount;
836  mount.umount(e->dir);
837  }
838  catch (const Exception &e)
839  {
840  ZYPP_CAUGHT(e);
841  }
842  }
843  }
844  else
845  if(!is_device && !ref->maj_nr)
846  {
847  std::string mtype(matchMountFs ? e->type : ref->type);
848  MediaSource media(mtype, e->src);
849  if( ref->equals( media))
850  {
851  DBG << "Forcing release of media name "
852  << ref->asString()
853  << " in the mount table as "
854  << e->src << std::endl;
855  try {
856  Mount mount;
857  mount.umount(e->dir);
858  }
859  catch (const Exception &e)
860  {
861  ZYPP_CAUGHT(e);
862  }
863  }
864  }
865  }
866 }
867 
868 bool
869 MediaHandler::checkAttachPoint(const Pathname &apoint) const
870 {
871  return MediaHandler::checkAttachPoint( apoint, true, false);
872 }
873 
874 // STATIC
875 bool
876 MediaHandler::checkAttachPoint(const Pathname &apoint,
877  bool emptydir,
878  bool writeable)
879 {
880  if( apoint.empty() || !apoint.absolute())
881  {
882  ERR << "Attach point '" << apoint << "' is not absolute"
883  << std::endl;
884  return false;
885  }
886  if( apoint == "/")
887  {
888  ERR << "Attach point '" << apoint << "' is not allowed"
889  << std::endl;
890  return false;
891  }
892 
893  PathInfo ainfo(apoint);
894  if( !ainfo.isDir())
895  {
896  ERR << "Attach point '" << apoint << "' is not a directory"
897  << std::endl;
898  return false;
899  }
900 
901  if( emptydir)
902  {
903  if( 0 != zypp::filesystem::is_empty_dir(apoint))
904  {
905  ERR << "Attach point '" << apoint << "' is not a empty directory"
906  << std::endl;
907  return false;
908  }
909  }
910 
911  if( writeable)
912  {
913  Pathname apath(apoint + "XXXXXX");
914  char *atemp = ::strdup( apath.asString().c_str());
915  char *atest = NULL;
916  if( !ainfo.userMayRWX() || atemp == NULL ||
917  (atest=::mkdtemp(atemp)) == NULL)
918  {
919  if( atemp != NULL)
920  ::free(atemp);
921 
922  ERR << "Attach point '" << ainfo.path()
923  << "' is not a writeable directory" << std::endl;
924  return false;
925  }
926  else if( atest != NULL)
927  ::rmdir(atest);
928 
929  if( atemp != NULL)
930  ::free(atemp);
931  }
932  return true;
933 }
934 
936 //
937 // METHOD NAME : MediaHandler::dependsOnParent
938 // METHOD TYPE : bool
939 //
940 // DESCRIPTION :
941 //
942 bool
944 {
945  return _parentId != 0;
946 }
947 
948 bool
949 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
950 {
951  if( _parentId != 0)
952  {
953  if(parentId == _parentId)
954  return true;
955 
956  if( !exactIdMatch)
957  {
958  MediaManager mm;
960  AttachedMedia am2 = mm.getAttachedMedia(parentId);
961  if( am1.mediaSource && am2.mediaSource)
962  {
963  return am1.mediaSource->equals( *(am2.mediaSource));
964  }
965  }
966  }
967  return false;
968 }
969 
971 //
972 //
973 // METHOD NAME : MediaHandler::provideFile
974 // METHOD TYPE : PMError
975 //
976 // DESCRIPTION :
977 //
978 void MediaHandler::provideFileCopy( Pathname srcFilename,
979  Pathname targetFilename ) const
980 {
981  if ( !isAttached() ) {
982  INT << "Media not_attached on provideFileCopy(" << srcFilename
983  << "," << targetFilename << ")" << endl;
985  }
986 
987  getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
988  DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl;
989 }
990 
991 void MediaHandler::provideFile( Pathname filename ) const
992 {
993  if ( !isAttached() ) {
994  INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
996  }
997 
998  getFile( filename ); // pass to concrete handler
999  DBG << "provideFile(" << filename << ")" << endl;
1000 }
1001 
1002 
1004 //
1005 //
1006 // METHOD NAME : MediaHandler::provideDir
1007 // METHOD TYPE : PMError
1008 //
1009 // DESCRIPTION :
1010 //
1011 void MediaHandler::provideDir( Pathname dirname ) const
1012 {
1013  if ( !isAttached() ) {
1014  INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
1016  }
1017 
1018  getDir( dirname, /*recursive*/false ); // pass to concrete handler
1019  MIL << "provideDir(" << dirname << ")" << endl;
1020 }
1021 
1023 //
1024 //
1025 // METHOD NAME : MediaHandler::provideDirTree
1026 // METHOD TYPE : PMError
1027 //
1028 // DESCRIPTION :
1029 //
1030 void MediaHandler::provideDirTree( Pathname dirname ) const
1031 {
1032  if ( !isAttached() ) {
1033  INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
1035  }
1036 
1037  getDir( dirname, /*recursive*/true ); // pass to concrete handler
1038  MIL << "provideDirTree(" << dirname << ")" << endl;
1039 }
1040 
1042 //
1043 //
1044 // METHOD NAME : MediaHandler::releasePath
1045 // METHOD TYPE : PMError
1046 //
1047 // DESCRIPTION :
1048 //
1049 void MediaHandler::releasePath( Pathname pathname ) const
1050 {
1051  if ( ! _does_download || _attachPoint->empty() )
1052  return;
1053 
1054  PathInfo info( localPath( pathname ) );
1055 
1056  if ( info.isFile() ) {
1057  unlink( info.path() );
1058  } else if ( info.isDir() ) {
1059  if ( info.path() != localRoot() ) {
1060  recursive_rmdir( info.path() );
1061  } else {
1062  clean_dir( info.path() );
1063  }
1064  }
1065 }
1066 
1068 //
1069 //
1070 // METHOD NAME : MediaHandler::dirInfo
1071 // METHOD TYPE : PMError
1072 //
1073 // DESCRIPTION :
1074 //
1075 void MediaHandler::dirInfo( std::list<std::string> & retlist,
1076  const Pathname & dirname, bool dots ) const
1077 {
1078  retlist.clear();
1079 
1080  if ( !isAttached() ) {
1081  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1083  }
1084 
1085  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1086  MIL << "dirInfo(" << dirname << ")" << endl;
1087 }
1088 
1090 //
1091 //
1092 // METHOD NAME : MediaHandler::dirInfo
1093 // METHOD TYPE : PMError
1094 //
1095 // DESCRIPTION :
1096 //
1098  const Pathname & dirname, bool dots ) const
1099 {
1100  retlist.clear();
1101 
1102  if ( !isAttached() ) {
1103  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1105  }
1106 
1107  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1108  MIL << "dirInfo(" << dirname << ")" << endl;
1109 }
1110 
1112 //
1113 //
1114 // METHOD NAME : MediaHandler::doesFileExist
1115 // METHOD TYPE : PMError
1116 //
1117 // DESCRIPTION :
1118 //
1119 bool MediaHandler::doesFileExist( const Pathname & filename ) const
1120 {
1121  // TODO do some logging
1122  if ( !isAttached() ) {
1123  INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
1125  }
1126  return getDoesFileExist( filename );
1127  MIL << "doesFileExist(" << filename << ")" << endl;
1128 }
1129 
1131 //
1132 //
1133 // METHOD NAME : MediaHandler::getDirectoryYast
1134 // METHOD TYPE : PMError
1135 //
1136 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
1137  const Pathname & dirname, bool dots ) const
1138 {
1139  retlist.clear();
1140 
1141  filesystem::DirContent content;
1142  getDirectoryYast( content, dirname, dots );
1143 
1144  // convert to std::list<std::string>
1145  for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1146  retlist.push_back( it->name );
1147  }
1148 }
1149 
1151 //
1152 //
1153 // METHOD NAME : MediaHandler::getDirectoryYast
1154 // METHOD TYPE : PMError
1155 //
1157  const Pathname & dirname, bool dots ) const
1158 {
1159  retlist.clear();
1160 
1161  // look for directory.yast
1162  Pathname dirFile = dirname + "directory.yast";
1163  getFile( dirFile );
1164  DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1165 
1166  // using directory.yast
1167  ifstream dir( localPath( dirFile ).asString().c_str() );
1168  if ( dir.fail() ) {
1169  ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl;
1171  "Unable to load '" + localPath( dirFile ).asString() + "'"));
1172  }
1173 
1174  string line;
1175  while( getline( dir, line ) ) {
1176  if ( line.empty() ) continue;
1177  if ( line == "directory.yast" ) continue;
1178 
1179  // Newer directory.yast append '/' to directory names
1180  // Remaining entries are unspecified, although most probabely files.
1182  if ( *line.rbegin() == '/' ) {
1183  line.erase( line.end()-1 );
1184  type = filesystem::FT_DIR;
1185  }
1186 
1187  if ( dots ) {
1188  if ( line == "." || line == ".." ) continue;
1189  } else {
1190  if ( *line.begin() == '.' ) continue;
1191  }
1192 
1193  retlist.push_back( filesystem::DirEntry( line, type ) );
1194  }
1195 }
1196 
1197 /******************************************************************
1198 **
1199 **
1200 ** FUNCTION NAME : operator<<
1201 ** FUNCTION TYPE : ostream &
1202 */
1203 ostream & operator<<( ostream & str, const MediaHandler & obj )
1204 {
1205  str << obj.url() << ( obj.isAttached() ? "" : " not" )
1206  << " attached; localRoot \"" << obj.localRoot() << "\"";
1207  return str;
1208 }
1209 
1211 //
1212 //
1213 // METHOD NAME : MediaHandler::getFile
1214 // METHOD TYPE : PMError
1215 //
1216 // DESCRIPTION : Asserted that media is attached.
1217 // Default implementation of pure virtual.
1218 //
1219 void MediaHandler::getFile( const Pathname & filename ) const
1220 {
1221  PathInfo info( localPath( filename ) );
1222  if( info.isFile() ) {
1223  return;
1224  }
1225 
1226  if (info.isExist())
1228  else
1230 }
1231 
1232 
1233 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
1234 {
1235  getFile(srcFilename);
1236 
1237  if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
1238  ZYPP_THROW(MediaWriteException(targetFilename));
1239  }
1240 }
1241 
1242 
1243 
1245 //
1246 //
1247 // METHOD NAME : MediaHandler::getDir
1248 // METHOD TYPE : PMError
1249 //
1250 // DESCRIPTION : Asserted that media is attached.
1251 // Default implementation of pure virtual.
1252 //
1253 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1254 {
1255  PathInfo info( localPath( dirname ) );
1256  if( info.isDir() ) {
1257  return;
1258  }
1259 
1260  if (info.isExist())
1262  else
1264 }
1265 
1267 //
1268 //
1269 // METHOD NAME : MediaHandler::getDirInfo
1270 // METHOD TYPE : PMError
1271 //
1272 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1273 // Default implementation of pure virtual.
1274 //
1275 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1276  const Pathname & dirname, bool dots ) const
1277 {
1278  PathInfo info( localPath( dirname ) );
1279  if( ! info.isDir() ) {
1281  }
1282 
1283 #if NONREMOTE_DIRECTORY_YAST
1284  // use directory.yast if available
1285  try {
1286  getDirectoryYast( retlist, dirname, dots );
1287  }
1288  catch (const MediaException & excpt_r)
1289  {
1290 #endif
1291 
1292  // readdir
1293  int res = readdir( retlist, info.path(), dots );
1294  if ( res )
1295  {
1296  MediaSystemException nexcpt(url(), "readdir failed");
1297 #if NONREMOTE_DIRECTORY_YAST
1298  nexcpt.remember(excpt_r);
1299 #endif
1300  ZYPP_THROW(nexcpt);
1301  }
1302 
1303 #if NONREMOTE_DIRECTORY_YAST
1304  }
1305 #endif
1306 
1307  return;
1308 }
1309 
1311 //
1312 //
1313 // METHOD NAME : MediaHandler::getDirInfo
1314 // METHOD TYPE : PMError
1315 //
1316 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1317 // Default implementation of pure virtual.
1318 //
1320  const Pathname & dirname, bool dots ) const
1321 {
1322  PathInfo info( localPath( dirname ) );
1323  if( ! info.isDir() ) {
1325  }
1326 
1327 #if NONREMOTE_DIRECTORY_YAST
1328  // use directory.yast if available
1329  try {
1330  getDirectoryYast( retlist, dirname, dots );
1331  }
1332  catch (const MediaException & excpt_r)
1333  {
1334 #endif
1335 
1336  // readdir
1337  int res = readdir( retlist, info.path(), dots );
1338  if ( res )
1339  {
1340  MediaSystemException nexcpt(url(), "readdir failed");
1341 #if NONREMOTE_DIRECTORY_YAST
1342  nexcpt.remember(excpt_r);
1343 #endif
1344  ZYPP_THROW(nexcpt);
1345  }
1346 #if NONREMOTE_DIRECTORY_YAST
1347  }
1348 #endif
1349 }
1350 
1352 //
1353 //
1354 // METHOD NAME : MediaHandler::getDoesFileExist
1355 // METHOD TYPE : PMError
1356 //
1357 // DESCRIPTION : Asserted that file is not a directory
1358 // Default implementation of pure virtual.
1359 //
1360 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1361 {
1362  PathInfo info( localPath( filename ) );
1363  if( info.isDir() ) {
1365  }
1366  return info.isExist();
1367 }
1368 
1370 {
1371  return false;
1372 }
1373 
1374 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
1375  unsigned int & index) const
1376 {
1377  // clear the vector by default
1378  if (!devices.empty())
1379  devices.clear();
1380  index = 0;
1381 
1382  DBG << "No devices for this medium" << endl;
1383 }
1384 
1385 void MediaHandler::setDeltafile( const Pathname & filename ) const
1386 {
1387  _deltafile = filename;
1388 }
1389 
1390 Pathname MediaHandler::deltafile() const {
1391  return _deltafile;
1392 }
1393 
1394  } // namespace media
1395 } // namespace zypp
1396 // vim: set ts=8 sts=2 sw=2 ai noet:
Attach point of a media source.
Definition: MediaSource.h:105
void resetParentId()
Called in case, where the media manager takes over the destruction of the parent id (e...
#define MIL
Definition: Logger.h:64
void provideFile(Pathname filename) const
Use concrete handler to provide file denoted by path below &#39;localRoot&#39;.
bool unique() const
Definition: PtrTypes.h:343
Listentry returned by readdir.
Definition: PathInfo.h:532
Interface to the mount program.
Definition: Mount.h:69
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:321
bool isSharedMedia() const
Returns a hint if the media is shared or not.
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:121
AttachPoint _attachPointHint
The user provided attach preferred point.
Definition: MediaHandler.h:85
Pathname _relativeRoot
The relative root directory of the data on the media.
Definition: MediaHandler.h:92
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.
Pathname path
The path name (mount point).
Definition: MediaSource.h:116
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition: MediaSource.h:124
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Check if the specified path is useable as attach point.
static std::string getRealPath(const std::string &path)
bool doesFileExist(const Pathname &filename) const
check if a file exists
#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.
virtual void disconnectFrom()
Call concrete handler to disconnect media.
Definition: MediaHandler.h:325
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:434
String related utilities and Regular expression matching.
Definition: Arch.h:339
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
void provideDirTree(Pathname dirname) const
Use concrete handler to provide directory tree denoted by path below &#39;localRoot&#39; (recursive!!).
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
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...
#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.
void dirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Return content of directory on media via retlist.
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:89
Pathname deltafile() const
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:329
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
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
Ask the media manager if specified media source is already attached.
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
MediaSourceRef mediaSource
Definition: MediaSource.h:144
AttachedMedia attachedMedia() const
Returns the attached media.
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h:170
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.
Just inherits Exception to separate media exceptions.
AttachedMedia getAttachedMedia(MediaAccessId &accessId) const
void disconnect()
Use concrete handler to isconnect media.
void attach(bool next)
Use concrete handler to attach the media.
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
long use_count() const
Definition: PtrTypes.h:346
void setDeltafile(const Pathname &filename=Pathname()) const
void releasePath(Pathname pathname) const
Remove pathname below localRoot IFF handler downloads files to the local filesystem.
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...
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
Pathname download_mediaMountdir() const
Path where media are preferably mounted or downloaded.
Definition: ZConfig.cc:996
virtual bool hasMoreDevices()
Check if the media has one more device available for attach(true).
Pathname localPath(const Pathname &pathname) const
Files provided will be available at &#39;localPath(filename)&#39;.
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 bool isAttached() const
True if media is attached.
Definition: MediaHandler.h:523
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
void removeAttachPoint()
Remove unused attach point.
void forceReleaseShared(const MediaSourceRef &media)
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:36
std::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
Definition: IOStream.h:50
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:325
virtual void forceEject(const std::string &device)
Call concrete handler to physically eject the media (i.e.
Definition: MediaHandler.h:347
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
AttachPoint attachPointHint() const
Get the actual attach point hint.
void forceRelaseAllMedia(bool matchMountFs)
Call to this function will try to release all media matching the currenlty attached media source...
void swap(RW_pointer &rhs)
Definition: PtrTypes.h:315
Pathname attachPoint() const
Return the currently used attach point.
Base class for Exception.
Definition: Exception.h:143
FileType
File type information.
Definition: PathInfo.h:55
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
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
Pathname localRoot() const
Return the local directory that corresponds to medias url, no matter if media isAttached or not...
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:527
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.
void provideDir(Pathname dirname) const
Use concrete handler to provide directory denoted by path below &#39;localRoot&#39; (not recursive!).
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1028
friend std::ostream & operator<<(std::ostream &str, const MediaHandler &obj)
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 ...
Url url() const
Url used.
Definition: MediaHandler.h:506
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.
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.
virtual bool getDoesFileExist(const Pathname &filename) const =0
check if a file exists
virtual void getFile(const Pathname &filename) const =0
Call concrete handler to provide file below attach point.