libzypp  15.28.6
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/TmpPath.h"
18 #include "zypp/Date.h"
19 #include "zypp/base/LogTools.h"
20 #include "zypp/base/String.h"
23 #include "zypp/media/Mount.h"
24 #include <limits.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 
28 
29 using namespace std;
30 
31 // use directory.yast on every media (not just via ftp/http)
32 #define NONREMOTE_DIRECTORY_YAST 1
33 
34 namespace zypp {
35  namespace media {
36 
37  Pathname MediaHandler::_attachPrefix("");
38 
40 //
41 // CLASS NAME : MediaHandler
42 //
44 
46 //
47 //
48 // METHOD NAME : MediaHandler::MediaHandler
49 // METHOD TYPE : Constructor
50 //
51 // DESCRIPTION :
52 //
53 MediaHandler::MediaHandler ( const Url & url_r,
54  const Pathname & attach_point_r,
55  const Pathname & urlpath_below_attachpoint_r,
56  const bool does_download_r )
57  : _mediaSource()
58  , _attachPoint( new AttachPoint())
59  , _attachPointHint()
60  , _relativeRoot( urlpath_below_attachpoint_r)
61  , _does_download( does_download_r )
62  , _attach_mtime(0)
63  , _url( url_r )
64  , _parentId(0)
65 {
66  Pathname real_attach_point( getRealPath(attach_point_r.asString()));
67 
68  if ( !real_attach_point.empty() ) {
70  // check if provided attachpoint is usable.
72 
73  PathInfo adir( real_attach_point );
74  //
75  // The verify if attach_point_r isn't a mountpoint of another
76  // device is done in the particular media handler (if needed).
77  //
78  // We just verify, if attach_point_r is a directory and for
79  // schemes other than "file" and "dir", if it is absolute.
80  //
81  if ( !adir.isDir()
82  || (_url.getScheme() != "file"
83  && _url.getScheme() != "dir"
84  && !real_attach_point.absolute()) )
85  {
86  ERR << "Provided attach point is not a absolute directory: "
87  << adir << endl;
88  }
89  else {
90  attachPointHint( real_attach_point, false);
91  setAttachPoint( real_attach_point, false);
92  }
93  }
94 }
95 
97 //
98 //
99 // METHOD NAME : MediaHandler::~MediaHandler
100 // METHOD TYPE : Destructor
101 //
102 // DESCRIPTION :
103 //
105 {
106  try
107  {
109  }
110  catch(...) {}
111 }
112 
113 void
115 {
116  _parentId = 0;
117 }
118 
119 std::string
120 MediaHandler::getRealPath(const std::string &path)
121 {
122  std::string real;
123  if( !path.empty())
124  {
125 #if __GNUC__ > 2
126 
127  char *ptr = ::realpath(path.c_str(), NULL);
128  if( ptr != NULL)
129  {
130  real = ptr;
131  free( ptr);
132  }
133  else
135  if( EINVAL == errno)
136  {
137  char buff[PATH_MAX + 2];
138  memset(buff, '\0', sizeof(buff));
139  if( ::realpath(path.c_str(), buff) != NULL)
140  {
141  real = buff;
142  }
143  }
144 #else
145  char buff[PATH_MAX + 2];
146  memset(buff, '\0', sizeof(buff));
147  if( ::realpath(path.c_str(), buff) != NULL)
148  {
149  real = buff;
150  }
151 #endif
152  }
153  return real;
154 }
155 
156 zypp::Pathname
157 MediaHandler::getRealPath(const Pathname &path)
158 {
159  return zypp::Pathname(getRealPath(path.asString()));
160 }
161 
162 
164 //
165 //
166 // METHOD NAME : MediaHandler::removeAttachPoint
167 // METHOD TYPE : void
168 //
169 // DESCRIPTION :
170 //
171 void
173 {
174  if ( _mediaSource ) {
175  INT << "MediaHandler deleted with media attached." << endl;
176  return; // no cleanup if media still mounted!
177  }
178 
179  DBG << "MediaHandler - checking if to remove attach point" << endl;
180  if ( _attachPoint.unique() &&
181  _attachPoint->temp &&
182  !_attachPoint->path.empty() &&
183  PathInfo(_attachPoint->path).isDir())
184  {
185  Pathname path(_attachPoint->path);
186 
187  setAttachPoint("", true);
188 
189  int res = recursive_rmdir( path );
190  if ( res == 0 ) {
191  MIL << "Deleted default attach point " << path << endl;
192  } else {
193  ERR << "Failed to Delete default attach point " << path
194  << " errno(" << res << ")" << endl;
195  }
196  }
197  else
198  {
199  if( !_attachPoint->path.empty() && !_attachPoint->temp)
200  DBG << "MediaHandler - attachpoint is not temporary" << endl;
201  }
202 }
203 
204 
206 //
207 //
208 // METHOD NAME : MediaHandler::attachPoint
209 // METHOD TYPE : Pathname
210 //
211 // DESCRIPTION :
212 //
213 Pathname
215 {
216  return _attachPoint->path;
217 }
218 
219 
221 //
222 //
223 // METHOD NAME : MediaHandler::attachPoint
224 // METHOD TYPE :
225 //
226 // DESCRIPTION :
227 //
228 void
229 MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
230 {
231  _attachPoint.reset( new AttachPoint(path, temporary));
232 }
233 
234 Pathname
236 {
237  if( _attachPoint->path.empty())
238  return Pathname();
239  else
240  return _attachPoint->path + _relativeRoot;
241 }
242 
244 //
245 //
246 // METHOD NAME : MediaHandler::attachPoint
247 // METHOD TYPE :
248 //
249 // DESCRIPTION :
250 //
251 void
253 {
254  if( ref)
256  else
258 }
259 
261 //
262 //
263 // METHOD NAME : MediaHandler::attachPointHint
264 // METHOD TYPE : void
265 //
266 // DESCRIPTION :
267 //
268 void
269 MediaHandler::attachPointHint(const Pathname &path, bool temporary)
270 {
271  _attachPointHint.path = path;
272  _attachPointHint.temp = temporary;
273 }
274 
276 //
277 //
278 // METHOD NAME : MediaHandler::attachPointHint
279 // METHOD TYPE : AttachPoint
280 //
281 // DESCRIPTION :
282 //
285 {
286  return _attachPointHint;
287 }
288 
290 //
291 //
292 // METHOD NAME : MediaHandler::findAttachedMedia
293 // METHOD TYPE : AttachedMedia
294 //
295 // DESCRIPTION :
296 //
299 {
300  return MediaManager().findAttachedMedia(media);
301 }
302 
304 //
305 //
306 // METHOD NAME : MediaHandler::setAttachPrefix
307 // METHOD TYPE : void
308 //
309 // DESCRIPTION :
310 //
311 bool
312 MediaHandler::setAttachPrefix(const Pathname &attach_prefix)
313 {
314  if( attach_prefix.empty())
315  {
316  MIL << "Reseting to built-in attach point prefixes."
317  << std::endl;
318  MediaHandler::_attachPrefix = attach_prefix;
319  return true;
320  }
321  else
322  if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
323  {
324  MIL << "Setting user defined attach point prefix: "
325  << attach_prefix << std::endl;
326  MediaHandler::_attachPrefix = attach_prefix;
327  return true;
328  }
329  return false;
330 }
331 
333 //
334 //
335 // METHOD NAME : MediaHandler::attach
336 // METHOD TYPE : Pathname
337 //
338 // DESCRIPTION :
339 //
340 Pathname
342 {
344  // provide a default (temporary) attachpoint
346  const char * defmounts[] = {
347  "/var/adm/mount", filesystem::TmpPath::defaultLocation().c_str(), NULL
348  };
349 
350  Pathname apoint;
351  Pathname aroot( MediaHandler::_attachPrefix);
352 
353  if( !aroot.empty())
354  {
355  apoint = createAttachPoint(aroot);
356  }
357  for ( const char ** def = defmounts; *def && apoint.empty(); ++def ) {
358  aroot = *def;
359  if( aroot.empty())
360  continue;
361 
362  apoint = createAttachPoint(aroot);
363  }
364 
365  if ( aroot.empty() ) {
366  ERR << "Create attach point: Can't find a writable directory to create an attach point" << std::endl;
367  return aroot;
368  }
369 
370  if ( !apoint.empty() ) {
371  MIL << "Created default attach point " << apoint << std::endl;
372  }
373  return apoint;
374 }
375 
376 Pathname
377 MediaHandler::createAttachPoint(const Pathname &attach_root) const
378 {
379  Pathname apoint;
380 
381  if( attach_root.empty() || !attach_root.absolute()) {
382  ERR << "Create attach point: invalid attach root: '"
383  << attach_root << "'" << std::endl;
384  return apoint;
385  }
386 
387  PathInfo adir( attach_root );
388  if( !adir.isDir() || (geteuid() != 0 && !adir.userMayRWX())) {
389  DBG << "Create attach point: attach root is not a writable directory: '"
390  << attach_root << "'" << std::endl;
391  return apoint;
392  }
393 
394  static bool cleanup_once( true );
395  if ( cleanup_once )
396  {
397  cleanup_once = false;
398  DBG << "Look for orphaned attach points in " << adir << std::endl;
399  std::list<std::string> entries;
400  filesystem::readdir( entries, attach_root, false );
401  for ( const std::string & entry : entries )
402  {
403  if ( ! str::hasPrefix( entry, "AP_0x" ) )
404  continue;
405  PathInfo sdir( attach_root + entry );
406  if ( sdir.isDir()
407  && sdir.dev() == adir.dev()
408  && ( Date::now()-sdir.mtime() > Date::month ) )
409  {
410  DBG << "Remove orphaned attach point " << sdir << std::endl;
411  filesystem::recursive_rmdir( sdir.path() );
412  }
413  }
414  }
415 
416  filesystem::TmpDir tmpdir( attach_root, "AP_0x" );
417  if ( tmpdir )
418  {
419  apoint = getRealPath( tmpdir.path().asString() );
420  if ( ! apoint.empty() )
421  {
422  tmpdir.autoCleanup( false ); // Take responsibility for cleanup.
423  }
424  else
425  {
426  ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl;
427  }
428  }
429  else
430  {
431  ERR << "Unable to create attach point below " << attach_root << std::endl;
432  }
433  return apoint;
434 }
435 
437 //
438 //
439 // METHOD NAME : MediaHandler::isUseableAttachPoint
440 // METHOD TYPE : bool
441 //
442 // DESCRIPTION :
443 //
444 bool
445 MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const
446 {
447  MediaManager manager;
448  return manager.isUseableAttachPoint(path, mtab);
449 }
450 
451 
453 //
454 //
455 // METHOD NAME : MediaHandler::setMediaSource
456 // METHOD TYPE : void
457 //
458 // DESCRIPTION :
459 //
460 void
462 {
464  if( ref && !ref->type.empty() && !ref->name.empty())
465  _mediaSource = ref;
466 }
467 
469 //
470 //
471 // METHOD NAME : MediaHandler::attachedMedia
472 // METHOD TYPE : AttachedMedia
473 //
474 // DESCRIPTION :
475 //
478 {
479  if ( _mediaSource && _attachPoint)
481  else
482  return AttachedMedia();
483 }
484 
486 //
487 //
488 // METHOD NAME : MediaHandler::isSharedMedia
489 // METHOD TYPE : bool
490 //
491 // DESCRIPTION :
492 //
493 bool
495 {
496  return !_mediaSource.unique();
497 }
498 
500 //
501 //
502 // METHOD NAME : MediaHandler::checkAttached
503 // METHOD TYPE : bool
504 //
505 // DESCRIPTION :
506 //
507 bool
508 MediaHandler::checkAttached(bool matchMountFs) const
509 {
510  bool _isAttached = false;
511 
512  AttachedMedia ref( attachedMedia() );
513  if( ref.mediaSource )
514  {
515  time_t old_mtime = _attach_mtime;
517  if( !(old_mtime <= 0 || _attach_mtime != old_mtime) )
518  {
519  // OK, skip the check (we've seen it at least once)
520  _isAttached = true;
521  }
522  else
523  {
524  if( old_mtime > 0)
525  DBG << "Mount table changed - rereading it" << std::endl;
526  else
527  DBG << "Forced check of the mount table" << std::endl;
528 
529  MountEntries entries( MediaManager::getMountEntries());
530  for_( e, entries.begin(), entries.end() )
531  {
532  if ( ref.attachPoint->path != Pathname(e->dir) )
533  continue; // at least the mount points must match
534 
535  bool is_device = false;
536  PathInfo dev_info;
537  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
538  dev_info(e->src) && dev_info.isBlk() )
539  {
540  is_device = true;
541  }
542 
543  if( is_device && (ref.mediaSource->maj_nr &&
544  ref.mediaSource->bdir.empty()))
545  {
546  std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
547  MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
548 
549  if( ref.mediaSource->equals( media ) )
550  {
551  DBG << "Found media device "
552  << ref.mediaSource->asString()
553  << " in the mount table as " << e->src << std::endl;
554  _isAttached = true;
555  break;
556  }
557  // differs
558  }
559  else
560  if(!is_device && (!ref.mediaSource->maj_nr ||
561  !ref.mediaSource->bdir.empty()))
562  {
563  if( ref.mediaSource->bdir.empty())
564  {
565  // bnc#710269: Type nfs may appear as nfs4 in in the mount table
566  // and maybe vice versa. Similar cifs/smb. Need to unify these types:
567  if ( matchMountFs && e->type != ref.mediaSource->type )
568  {
569  if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) )
570  matchMountFs = false;
571  else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) )
572  matchMountFs = false;
573  else
574  continue; // different types cannot match
575  }
576  // Here: Types are ok or not to check.
577  // Check the name except for nfs (bnc#804544; symlink resolution in mount path)
578  //
579  // [fibonacci]$ ls -l /Local/ma/c12.1
580  // lrwxrwxrwx /Local/ma/c12.1 -> zypp-SuSE-Code-12_1-Branch/
581  //
582  // [localhost]$ mount -t nfs4 fibonacci:/Local/ma/c12.1 /mnt
583  // [localhost]$ mount
584  // fibonacci:/Local/ma/zypp-SuSE-Code-12_1-Branch on /mnt
585 
586  // std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
587  // MediaSource media(mtype, e->src);
588 
589  if( ref.mediaSource->name == e->src || str::hasPrefix( ref.mediaSource->type, "nfs" ) )
590  {
591  DBG << "Found media name "
592  << ref.mediaSource->asString()
593  << " in the mount table as " << e->src << std::endl;
594  _isAttached = true;
595  break;
596  }
597  }
598  else
599  {
600  if ( ref.mediaSource->bdir == e->src )
601  {
602  DBG << "Found bound media "
603  << ref.mediaSource->asString()
604  << " in the mount table as " << e->src << std::endl;
605  _isAttached = true;
606  break;
607  }
608  }
609  // differs
610  }
611  else // mixed cases:
612  {
613  // Type ISO: Since 11.1 mtab might contain the name of
614  // the loop device instead of the iso file:
615  if ( ref.mediaSource->type == "iso"
616  && str::hasPrefix( Pathname(e->src).asString(), "/dev/loop" )
617  && ref.attachPoint->path == Pathname(e->dir) )
618  {
619  DBG << "Found bound media "
620  << ref.mediaSource->asString()
621  << " in the mount table as " << e->src << std::endl;
622  _isAttached = true;
623  break;
624  }
625  }
626  }
627 
628  if( !_isAttached)
629  {
630  MIL << "Looking for " << ref << endl;
631  if( entries.empty() )
632  {
633  ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
634  }
635  else
636  {
637  dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
638  }
639  if( old_mtime > 0 )
640  {
641  ERR << "Attached media not in mount table any more - forcing reset!"
642  << std::endl;
643 
645  }
646  else
647  {
648  WAR << "Attached media not in mount table ..." << std::endl;
649  }
650 
651  // reset the mtime and force a new check to make sure,
652  // that we've found the media at least once in the mtab.
653  _attach_mtime = 0;
654  }
655  }
656  }
657  return _isAttached;
658 }
659 
661 //
662 //
663 // METHOD NAME : MediaHandler::attach
664 // METHOD TYPE : PMError
665 //
666 // DESCRIPTION :
667 //
668 void MediaHandler::attach( bool next )
669 {
670  if ( isAttached() )
671  return;
672 
673  // reset it in case of overloaded isAttached()
674  // that checks the media against /etc/mtab ...
676 
678  setAttachPoint(ap.path, ap.temp);
679 
680  try
681  {
682  attachTo( next ); // pass to concrete handler
683  }
684  catch(const MediaException &e)
685  {
687  ZYPP_RETHROW(e);
688  }
689  MIL << "Attached: " << *this << endl;
690 }
691 
692 
694 //
695 //
696 // METHOD NAME : MediaHandler::localPath
697 // METHOD TYPE : Pathname
698 //
699 Pathname MediaHandler::localPath( const Pathname & pathname ) const
700 {
701  Pathname _localRoot( localRoot());
702  if ( _localRoot.empty() )
703  return _localRoot;
704 
705  // we must check maximum file name length
706  // this is important for fetching the suseservers, the
707  // url with all parameters can get too long (bug #42021)
708 
709  return _localRoot + pathname.absolutename();
710 }
711 
712 
713 
714 
715 
717 //
718 //
719 // METHOD NAME : MediaHandler::disconnect
720 // METHOD TYPE : PMError
721 //
723 {
724  if ( !isAttached() )
725  return;
726 
727  disconnectFrom(); // pass to concrete handler
728  MIL << "Disconnected: " << *this << endl;
729 }
730 
732 //
733 //
734 // METHOD NAME : MediaHandler::release
735 // METHOD TYPE : PMError
736 //
737 // DESCRIPTION :
738 //
739 void MediaHandler::release( const std::string & ejectDev )
740 {
741  if ( !isAttached() ) {
742  DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
743  << std::endl;
744  if ( !ejectDev.empty() )
745  forceEject(ejectDev);
746  return;
747  }
748 
749  DBG << "Request to release attached media "
750  << _mediaSource->asString()
751  << ", use count=" << _mediaSource.use_count()
752  << std::endl;
753 
754  if( _mediaSource.unique())
755  {
756  DBG << "Releasing media " << _mediaSource->asString() << std::endl;
757  try {
758  releaseFrom( ejectDev ); // pass to concrete handler
759  }
760  catch(const MediaNotEjectedException &e)
761  {
762  // not ejected because the media
763  // is mounted by somebody else
764  // (if our attach point is busy,
765  // we get an umount exception)
766  _mediaSource.reset(NULL);
768  // OK, retrow now
769  ZYPP_RETHROW(e);
770  }
771  _mediaSource.reset(NULL);
773  }
774  else if( !ejectDev.empty() ) {
775  //
776  // Can't eject a shared media
777  //
778  //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
779 
781  _mediaSource.reset(NULL);
782 
783  MediaManager manager;
784  manager.forceReleaseShared(media);
785 
786  setMediaSource(media);
787  DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
788  try {
789  releaseFrom( ejectDev ); // pass to concrete handler
790  }
791  catch(const MediaNotEjectedException &e)
792  {
793  // not ejected because the media
794  // is mounted by somebody else
795  // (if our attach point is busy,
796  // we get an umount exception)
797  _mediaSource.reset(NULL);
799  // OK, retrow now
800  ZYPP_RETHROW(e);
801  }
802  _mediaSource.reset(NULL);
804  }
805  else {
806  DBG << "Releasing shared media reference only" << std::endl;
807  _mediaSource.reset(NULL);
808  setAttachPoint("", true);
809  }
810  MIL << "Released: " << *this << endl;
811 }
812 
813 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
814 {
815  forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
816 }
817 
819  bool matchMountFs)
820 {
821  if( !ref)
822  return;
823 
824  MountEntries entries( MediaManager::getMountEntries());
825  MountEntries::const_iterator e;
826  for( e = entries.begin(); e != entries.end(); ++e)
827  {
828  bool is_device = false;
829  PathInfo dev_info;
830 
831  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
832  dev_info(e->src) && dev_info.isBlk())
833  {
834  is_device = true;
835  }
836 
837  if( is_device && ref->maj_nr)
838  {
839  std::string mtype(matchMountFs ? e->type : ref->type);
840  MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
841 
842  if( ref->equals( media) && e->type != "subfs")
843  {
844  DBG << "Forcing release of media device "
845  << ref->asString()
846  << " in the mount table as "
847  << e->src << std::endl;
848  try {
849  Mount mount;
850  mount.umount(e->dir);
851  }
852  catch (const Exception &e)
853  {
854  ZYPP_CAUGHT(e);
855  }
856  }
857  }
858  else
859  if(!is_device && !ref->maj_nr)
860  {
861  std::string mtype(matchMountFs ? e->type : ref->type);
862  MediaSource media(mtype, e->src);
863  if( ref->equals( media))
864  {
865  DBG << "Forcing release of media name "
866  << ref->asString()
867  << " in the mount table as "
868  << e->src << std::endl;
869  try {
870  Mount mount;
871  mount.umount(e->dir);
872  }
873  catch (const Exception &e)
874  {
875  ZYPP_CAUGHT(e);
876  }
877  }
878  }
879  }
880 }
881 
882 bool
883 MediaHandler::checkAttachPoint(const Pathname &apoint) const
884 {
885  return MediaHandler::checkAttachPoint( apoint, true, false);
886 }
887 
888 // STATIC
889 bool
890 MediaHandler::checkAttachPoint(const Pathname &apoint,
891  bool emptydir,
892  bool writeable)
893 {
894  if( apoint.empty() || !apoint.absolute())
895  {
896  ERR << "Attach point '" << apoint << "' is not absolute"
897  << std::endl;
898  return false;
899  }
900  if( apoint == "/")
901  {
902  ERR << "Attach point '" << apoint << "' is not allowed"
903  << std::endl;
904  return false;
905  }
906 
907  PathInfo ainfo(apoint);
908  if( !ainfo.isDir())
909  {
910  ERR << "Attach point '" << apoint << "' is not a directory"
911  << std::endl;
912  return false;
913  }
914 
915  if( emptydir)
916  {
917  if( 0 != zypp::filesystem::is_empty_dir(apoint))
918  {
919  ERR << "Attach point '" << apoint << "' is not a empty directory"
920  << std::endl;
921  return false;
922  }
923  }
924 
925  if( writeable)
926  {
927  Pathname apath(apoint + "XXXXXX");
928  char *atemp = ::strdup( apath.asString().c_str());
929  char *atest = NULL;
930  if( !ainfo.userMayRWX() || atemp == NULL ||
931  (atest=::mkdtemp(atemp)) == NULL)
932  {
933  if( atemp != NULL)
934  ::free(atemp);
935 
936  ERR << "Attach point '" << ainfo.path()
937  << "' is not a writeable directory" << std::endl;
938  return false;
939  }
940  else if( atest != NULL)
941  ::rmdir(atest);
942 
943  if( atemp != NULL)
944  ::free(atemp);
945  }
946  return true;
947 }
948 
950 //
951 // METHOD NAME : MediaHandler::dependsOnParent
952 // METHOD TYPE : bool
953 //
954 // DESCRIPTION :
955 //
956 bool
958 {
959  return _parentId != 0;
960 }
961 
962 bool
963 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
964 {
965  if( _parentId != 0)
966  {
967  if(parentId == _parentId)
968  return true;
969 
970  if( !exactIdMatch)
971  {
972  MediaManager mm;
974  AttachedMedia am2 = mm.getAttachedMedia(parentId);
975  if( am1.mediaSource && am2.mediaSource)
976  {
977  return am1.mediaSource->equals( *(am2.mediaSource));
978  }
979  }
980  }
981  return false;
982 }
983 
985 //
986 //
987 // METHOD NAME : MediaHandler::provideFile
988 // METHOD TYPE : PMError
989 //
990 // DESCRIPTION :
991 //
992 void MediaHandler::provideFileCopy(Pathname srcFilename,
993  Pathname targetFilename , const ByteCount &expectedFileSize_r) const
994 {
995  if ( !isAttached() ) {
996  INT << "Media not_attached on provideFileCopy(" << srcFilename
997  << "," << targetFilename << ")" << endl;
999  }
1000 
1001  getFileCopy( srcFilename, targetFilename, expectedFileSize_r ); // pass to concrete handler
1002  DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl;
1003 }
1004 
1005 void MediaHandler::provideFile(Pathname filename , const ByteCount &expectedFileSize_r) const
1006 {
1007  if ( !isAttached() ) {
1008  INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
1010  }
1011 
1012  getFile( filename, expectedFileSize_r ); // pass to concrete handler
1013  DBG << "provideFile(" << filename << ")" << 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 //
1044 void MediaHandler::provideDirTree( Pathname dirname ) const
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  Pathname dirFile = dirname + "directory.yast";
1177  getFile( dirFile, 0 );
1178  DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1179 
1180  // using directory.yast
1181  ifstream dir( localPath( dirFile ).asString().c_str() );
1182  if ( dir.fail() ) {
1183  ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl;
1185  "Unable to load '" + localPath( dirFile ).asString() + "'"));
1186  }
1187 
1188  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 ostream & operator<<( ostream & str, const MediaHandler & obj )
1218 {
1219  str << obj.url() << ( obj.isAttached() ? "" : " not" )
1220  << " attached; localRoot \"" << obj.localRoot() << "\"";
1221  return str;
1222 }
1223 
1225 //
1226 //
1227 // METHOD NAME : MediaHandler::getFile
1228 // METHOD TYPE : PMError
1229 //
1230 // DESCRIPTION : Asserted that media is attached.
1231 // Default implementation of pure virtual.
1232 //
1233 void MediaHandler::getFile(const Pathname & filename , const ByteCount &) const
1234 {
1235  PathInfo info( localPath( filename ) );
1236  if( info.isFile() ) {
1237  return;
1238  }
1239 
1240  if (info.isExist())
1242  else
1244 }
1245 
1246 
1247 void MediaHandler::getFileCopy (const Pathname & srcFilename, const Pathname & targetFilename , const ByteCount &expectedFileSize_r) const
1248 {
1249  getFile(srcFilename, expectedFileSize_r);
1250 
1251  if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
1252  ZYPP_THROW(MediaWriteException(targetFilename));
1253  }
1254 }
1255 
1256 
1257 
1259 //
1260 //
1261 // METHOD NAME : MediaHandler::getDir
1262 // METHOD TYPE : PMError
1263 //
1264 // DESCRIPTION : Asserted that media is attached.
1265 // Default implementation of pure virtual.
1266 //
1267 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1268 {
1269  PathInfo info( localPath( dirname ) );
1270  if( info.isDir() ) {
1271  return;
1272  }
1273 
1274  if (info.isExist())
1276  else
1278 }
1279 
1281 //
1282 //
1283 // METHOD NAME : MediaHandler::getDirInfo
1284 // METHOD TYPE : PMError
1285 //
1286 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1287 // Default implementation of pure virtual.
1288 //
1289 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1290  const Pathname & dirname, bool dots ) const
1291 {
1292  PathInfo info( localPath( dirname ) );
1293  if( ! info.isDir() ) {
1295  }
1296 
1297 #if NONREMOTE_DIRECTORY_YAST
1298  // use directory.yast if available
1299  try {
1300  getDirectoryYast( retlist, dirname, dots );
1301  }
1302  catch (const MediaException & excpt_r)
1303  {
1304 #endif
1305 
1306  // readdir
1307  int res = readdir( retlist, info.path(), dots );
1308  if ( res )
1309  {
1310  MediaSystemException nexcpt(url(), "readdir failed");
1311 #if NONREMOTE_DIRECTORY_YAST
1312  nexcpt.remember(excpt_r);
1313 #endif
1314  ZYPP_THROW(nexcpt);
1315  }
1316 
1317 #if NONREMOTE_DIRECTORY_YAST
1318  }
1319 #endif
1320 
1321  return;
1322 }
1323 
1325 //
1326 //
1327 // METHOD NAME : MediaHandler::getDirInfo
1328 // METHOD TYPE : PMError
1329 //
1330 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1331 // Default implementation of pure virtual.
1332 //
1334  const Pathname & dirname, bool dots ) const
1335 {
1336  PathInfo info( localPath( dirname ) );
1337  if( ! info.isDir() ) {
1339  }
1340 
1341 #if NONREMOTE_DIRECTORY_YAST
1342  // use directory.yast if available
1343  try {
1344  getDirectoryYast( retlist, dirname, dots );
1345  }
1346  catch (const MediaException & excpt_r)
1347  {
1348 #endif
1349 
1350  // readdir
1351  int res = readdir( retlist, info.path(), dots );
1352  if ( res )
1353  {
1354  MediaSystemException nexcpt(url(), "readdir failed");
1355 #if NONREMOTE_DIRECTORY_YAST
1356  nexcpt.remember(excpt_r);
1357 #endif
1358  ZYPP_THROW(nexcpt);
1359  }
1360 #if NONREMOTE_DIRECTORY_YAST
1361  }
1362 #endif
1363 }
1364 
1366 //
1367 //
1368 // METHOD NAME : MediaHandler::getDoesFileExist
1369 // METHOD TYPE : PMError
1370 //
1371 // DESCRIPTION : Asserted that file is not a directory
1372 // Default implementation of pure virtual.
1373 //
1374 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1375 {
1376  PathInfo info( localPath( filename ) );
1377  if( info.isDir() ) {
1379  }
1380  return info.isExist();
1381 }
1382 
1384 {
1385  return false;
1386 }
1387 
1388 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
1389  unsigned int & index) const
1390 {
1391  // clear the vector by default
1392  if (!devices.empty())
1393  devices.clear();
1394  index = 0;
1395 
1396  DBG << "No devices for this medium" << endl;
1397 }
1398 
1399 void MediaHandler::setDeltafile( const Pathname & filename ) const
1400 {
1401  _deltafile = filename;
1402 }
1403 
1404 Pathname MediaHandler::deltafile() const {
1405  return _deltafile;
1406 }
1407 
1408  } // namespace media
1409 } // namespace zypp
1410 // vim: set ts=8 sts=2 sw=2 ai noet:
std::string asString(const Patch::Category &obj)
Definition: Patch.cc:117
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
bool unique() const
Definition: PtrTypes.h:343
Listentry returned by readdir.
Definition: PathInfo.h:532
Interface to the mount program.
Definition: Mount.h:69
#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.
Pathname path() const
Definition: TmpPath.cc:146
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
Store and operate with byte count.
Definition: ByteCount.h:30
Pathname _relativeRoot
The relative root directory of the data on the media.
Definition: MediaHandler.h:92
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.
const std::string & asString() const
String representation.
Definition: Pathname.h:90
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
virtual void getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const
Call concrete handler to provide file below attach point.
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 'rm -r DIR/ *'.
Definition: PathInfo.cc:443
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 'localRoot' (recursive!!).
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
#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.
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:650
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:89
Pathname deltafile() const
virtual void getFileCopy(const Pathname &srcFilename, const Pathname &targetFilename, const ByteCount &expectedFileSize_r) const
Call concrete handler to provide a file under a different place in the file system (usually not under...
#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 'physical' 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 'unlink'.
Definition: PathInfo.cc:662
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 provideFile(Pathname filename, const ByteCount &expectedFileSize_r) const
Use concrete handler to provide file denoted by path below 'localRoot'.
void disconnect()
Use concrete handler to isconnect media.
void attach(bool next)
Use concrete handler to attach the media.
const char * c_str() const
String representation.
Definition: Pathname.h:109
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
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.
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
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 'localPath(filename)'.
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
#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:598
int rmdir(const Pathname &path)
Like 'rmdir'.
Definition: PathInfo.cc:367
Manages access to the 'physical' 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...
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
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.
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:163
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:527
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 'localRoot' (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:1036
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.
void provideFileCopy(Pathname srcFilename, Pathname targetFilename, const ByteCount &expectedFileSize_r) const
Call concrete handler to provide a copy of a file under a different place in the file system (usually...
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.