libzypp  16.22.5
MediaHandler.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 #include <fstream>
15 #include <sstream>
16 
17 #include "zypp/ZConfig.h"
18 #include "zypp/TmpPath.h"
19 #include "zypp/Date.h"
20 #include "zypp/base/LogTools.h"
21 #include "zypp/base/Gettext.h"
22 #include "zypp/base/String.h"
25 #include "zypp/media/Mount.h"
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 
30 
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 
158 zypp::Pathname
159 MediaHandler::getRealPath(const Pathname &path)
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
314 MediaHandler::setAttachPrefix(const Pathname &attach_prefix)
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;
413  filesystem::recursive_rmdir( sdir.path() );
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
885 MediaHandler::checkAttachPoint(const Pathname &apoint) const
886 {
887  return MediaHandler::checkAttachPoint( apoint, true, false);
888 }
889 
890 // STATIC
891 bool
892 MediaHandler::checkAttachPoint(const Pathname &apoint,
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 //
994 void MediaHandler::provideFileCopy(Pathname srcFilename,
995  Pathname targetFilename , const ByteCount &expectedFileSize_r) const
996 {
997  if ( !isAttached() ) {
998  INT << "Media not_attached on provideFileCopy(" << srcFilename
999  << "," << targetFilename << ")" << endl;
1001  }
1002 
1003  getFileCopy( srcFilename, targetFilename, expectedFileSize_r ); // pass to concrete handler
1004  DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl;
1005 }
1006 
1007 void MediaHandler::provideFile(Pathname filename , const ByteCount &expectedFileSize_r) const
1008 {
1009  if ( !isAttached() ) {
1010  INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
1012  }
1013 
1014  getFile( filename, expectedFileSize_r ); // 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 //
1046 void MediaHandler::provideDirTree( Pathname dirname ) const
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, 0 );
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 ByteCount &) 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 ByteCount &expectedFileSize_r) const
1250 {
1251  getFile(srcFilename, expectedFileSize_r);
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 
1406 Pathname MediaHandler::deltafile() const {
1407  return _deltafile;
1408 }
1409 
1410  } // namespace media
1411 } // namespace zypp
1412 // vim: set ts=8 sts=2 sw=2 ai noet:
Attach point of a media source.
Definition: MediaSource.h:105
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 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:350
bool isSharedMedia() const
Returns a hint if the media is shared or not.
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:122
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.
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:326
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:105
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:358
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.
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
Pathname download_mediaMountdir() const
Path where media are preferably mounted or downloaded.
Definition: ZConfig.cc:1013
#define _(MSG)
Definition: Gettext.h:29
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:524
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:354
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: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:1037
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:507
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.