libzypp  16.5.2
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  }
614 
615  if( !_isAttached)
616  {
617  MIL << "Looking for " << ref << endl;
618  if( entries.empty() )
619  {
620  ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
621  }
622  else
623  {
624  dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
625  }
626  if( old_mtime > 0 )
627  {
628  ERR << "Attached media not in mount table any more - forcing reset!"
629  << std::endl;
630 
632  }
633  else
634  {
635  WAR << "Attached media not in mount table ..." << std::endl;
636  }
637 
638  // reset the mtime and force a new check to make sure,
639  // that we've found the media at least once in the mtab.
640  _attach_mtime = 0;
641  }
642  }
643  }
644  return _isAttached;
645 }
646 
648 //
649 //
650 // METHOD NAME : MediaHandler::attach
651 // METHOD TYPE : PMError
652 //
653 // DESCRIPTION :
654 //
655 void MediaHandler::attach( bool next )
656 {
657  if ( isAttached() )
658  return;
659 
660  // reset it in case of overloaded isAttached()
661  // that checks the media against /etc/mtab ...
663 
665  setAttachPoint(ap.path, ap.temp);
666 
667  try
668  {
669  attachTo( next ); // pass to concrete handler
670  }
671  catch(const MediaException &e)
672  {
674  ZYPP_RETHROW(e);
675  }
676  MIL << "Attached: " << *this << endl;
677 }
678 
679 
681 //
682 //
683 // METHOD NAME : MediaHandler::localPath
684 // METHOD TYPE : Pathname
685 //
686 Pathname MediaHandler::localPath( const Pathname & pathname ) const
687 {
688  Pathname _localRoot( localRoot());
689  if ( _localRoot.empty() )
690  return _localRoot;
691 
692  // we must check maximum file name length
693  // this is important for fetching the suseservers, the
694  // url with all parameters can get too long (bug #42021)
695 
696  return _localRoot + pathname.absolutename();
697 }
698 
699 
700 
701 
702 
704 //
705 //
706 // METHOD NAME : MediaHandler::disconnect
707 // METHOD TYPE : PMError
708 //
710 {
711  if ( !isAttached() )
712  return;
713 
714  disconnectFrom(); // pass to concrete handler
715  MIL << "Disconnected: " << *this << endl;
716 }
717 
719 //
720 //
721 // METHOD NAME : MediaHandler::release
722 // METHOD TYPE : PMError
723 //
724 // DESCRIPTION :
725 //
726 void MediaHandler::release( const std::string & ejectDev )
727 {
728  if ( !isAttached() ) {
729  DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
730  << std::endl;
731  if ( !ejectDev.empty() )
732  forceEject(ejectDev);
733  return;
734  }
735 
736  DBG << "Request to release attached media "
737  << _mediaSource->asString()
738  << ", use count=" << _mediaSource.use_count()
739  << std::endl;
740 
741  if( _mediaSource.unique())
742  {
743  DBG << "Releasing media " << _mediaSource->asString() << std::endl;
744  try {
745  releaseFrom( ejectDev ); // pass to concrete handler
746  }
747  catch(const MediaNotEjectedException &e)
748  {
749  // not ejected because the media
750  // is mounted by somebody else
751  // (if our attach point is busy,
752  // we get an umount exception)
753  _mediaSource.reset(NULL);
755  // OK, retrow now
756  ZYPP_RETHROW(e);
757  }
758  _mediaSource.reset(NULL);
760  }
761  else if( !ejectDev.empty() ) {
762  //
763  // Can't eject a shared media
764  //
765  //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
766 
768  _mediaSource.reset(NULL);
769 
770  MediaManager manager;
771  manager.forceReleaseShared(media);
772 
773  setMediaSource(media);
774  DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
775  try {
776  releaseFrom( ejectDev ); // pass to concrete handler
777  }
778  catch(const MediaNotEjectedException &e)
779  {
780  // not ejected because the media
781  // is mounted by somebody else
782  // (if our attach point is busy,
783  // we get an umount exception)
784  _mediaSource.reset(NULL);
786  // OK, retrow now
787  ZYPP_RETHROW(e);
788  }
789  _mediaSource.reset(NULL);
791  }
792  else {
793  DBG << "Releasing shared media reference only" << std::endl;
794  _mediaSource.reset(NULL);
795  setAttachPoint("", true);
796  }
797  MIL << "Released: " << *this << endl;
798 }
799 
800 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
801 {
802  forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
803 }
804 
806  bool matchMountFs)
807 {
808  if( !ref)
809  return;
810 
811  MountEntries entries( MediaManager::getMountEntries());
812  MountEntries::const_iterator e;
813  for( e = entries.begin(); e != entries.end(); ++e)
814  {
815  bool is_device = false;
816  PathInfo dev_info;
817 
818  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
819  dev_info(e->src) && dev_info.isBlk())
820  {
821  is_device = true;
822  }
823 
824  if( is_device && ref->maj_nr)
825  {
826  std::string mtype(matchMountFs ? e->type : ref->type);
827  MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
828 
829  if( ref->equals( media) && e->type != "subfs")
830  {
831  DBG << "Forcing release of media device "
832  << ref->asString()
833  << " in the mount table as "
834  << e->src << std::endl;
835  try {
836  Mount mount;
837  mount.umount(e->dir);
838  }
839  catch (const Exception &e)
840  {
841  ZYPP_CAUGHT(e);
842  }
843  }
844  }
845  else
846  if(!is_device && !ref->maj_nr)
847  {
848  std::string mtype(matchMountFs ? e->type : ref->type);
849  MediaSource media(mtype, e->src);
850  if( ref->equals( media))
851  {
852  DBG << "Forcing release of media name "
853  << ref->asString()
854  << " in the mount table as "
855  << e->src << std::endl;
856  try {
857  Mount mount;
858  mount.umount(e->dir);
859  }
860  catch (const Exception &e)
861  {
862  ZYPP_CAUGHT(e);
863  }
864  }
865  }
866  }
867 }
868 
869 bool
870 MediaHandler::checkAttachPoint(const Pathname &apoint) const
871 {
872  return MediaHandler::checkAttachPoint( apoint, true, false);
873 }
874 
875 // STATIC
876 bool
877 MediaHandler::checkAttachPoint(const Pathname &apoint,
878  bool emptydir,
879  bool writeable)
880 {
881  if( apoint.empty() || !apoint.absolute())
882  {
883  ERR << "Attach point '" << apoint << "' is not absolute"
884  << std::endl;
885  return false;
886  }
887  if( apoint == "/")
888  {
889  ERR << "Attach point '" << apoint << "' is not allowed"
890  << std::endl;
891  return false;
892  }
893 
894  PathInfo ainfo(apoint);
895  if( !ainfo.isDir())
896  {
897  ERR << "Attach point '" << apoint << "' is not a directory"
898  << std::endl;
899  return false;
900  }
901 
902  if( emptydir)
903  {
904  if( 0 != zypp::filesystem::is_empty_dir(apoint))
905  {
906  ERR << "Attach point '" << apoint << "' is not a empty directory"
907  << std::endl;
908  return false;
909  }
910  }
911 
912  if( writeable)
913  {
914  Pathname apath(apoint + "XXXXXX");
915  char *atemp = ::strdup( apath.asString().c_str());
916  char *atest = NULL;
917  if( !ainfo.userMayRWX() || atemp == NULL ||
918  (atest=::mkdtemp(atemp)) == NULL)
919  {
920  if( atemp != NULL)
921  ::free(atemp);
922 
923  ERR << "Attach point '" << ainfo.path()
924  << "' is not a writeable directory" << std::endl;
925  return false;
926  }
927  else if( atest != NULL)
928  ::rmdir(atest);
929 
930  if( atemp != NULL)
931  ::free(atemp);
932  }
933  return true;
934 }
935 
937 //
938 // METHOD NAME : MediaHandler::dependsOnParent
939 // METHOD TYPE : bool
940 //
941 // DESCRIPTION :
942 //
943 bool
945 {
946  return _parentId != 0;
947 }
948 
949 bool
950 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
951 {
952  if( _parentId != 0)
953  {
954  if(parentId == _parentId)
955  return true;
956 
957  if( !exactIdMatch)
958  {
959  MediaManager mm;
961  AttachedMedia am2 = mm.getAttachedMedia(parentId);
962  if( am1.mediaSource && am2.mediaSource)
963  {
964  return am1.mediaSource->equals( *(am2.mediaSource));
965  }
966  }
967  }
968  return false;
969 }
970 
972 //
973 //
974 // METHOD NAME : MediaHandler::provideFile
975 // METHOD TYPE : PMError
976 //
977 // DESCRIPTION :
978 //
979 void MediaHandler::provideFileCopy( Pathname srcFilename,
980  Pathname targetFilename ) const
981 {
982  if ( !isAttached() ) {
983  INT << "Media not_attached on provideFileCopy(" << srcFilename
984  << "," << targetFilename << ")" << endl;
986  }
987 
988  getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
989  DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl;
990 }
991 
992 void MediaHandler::provideFile( Pathname filename ) const
993 {
994  if ( !isAttached() ) {
995  INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
997  }
998 
999  getFile( filename ); // pass to concrete handler
1000  DBG << "provideFile(" << filename << ")" << endl;
1001 }
1002 
1003 
1005 //
1006 //
1007 // METHOD NAME : MediaHandler::provideDir
1008 // METHOD TYPE : PMError
1009 //
1010 // DESCRIPTION :
1011 //
1012 void MediaHandler::provideDir( Pathname dirname ) const
1013 {
1014  if ( !isAttached() ) {
1015  INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
1017  }
1018 
1019  getDir( dirname, /*recursive*/false ); // pass to concrete handler
1020  MIL << "provideDir(" << dirname << ")" << endl;
1021 }
1022 
1024 //
1025 //
1026 // METHOD NAME : MediaHandler::provideDirTree
1027 // METHOD TYPE : PMError
1028 //
1029 // DESCRIPTION :
1030 //
1031 void MediaHandler::provideDirTree( Pathname dirname ) const
1032 {
1033  if ( !isAttached() ) {
1034  INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
1036  }
1037 
1038  getDir( dirname, /*recursive*/true ); // pass to concrete handler
1039  MIL << "provideDirTree(" << dirname << ")" << endl;
1040 }
1041 
1043 //
1044 //
1045 // METHOD NAME : MediaHandler::releasePath
1046 // METHOD TYPE : PMError
1047 //
1048 // DESCRIPTION :
1049 //
1050 void MediaHandler::releasePath( Pathname pathname ) const
1051 {
1052  if ( ! _does_download || _attachPoint->empty() )
1053  return;
1054 
1055  PathInfo info( localPath( pathname ) );
1056 
1057  if ( info.isFile() ) {
1058  unlink( info.path() );
1059  } else if ( info.isDir() ) {
1060  if ( info.path() != localRoot() ) {
1061  recursive_rmdir( info.path() );
1062  } else {
1063  clean_dir( info.path() );
1064  }
1065  }
1066 }
1067 
1069 //
1070 //
1071 // METHOD NAME : MediaHandler::dirInfo
1072 // METHOD TYPE : PMError
1073 //
1074 // DESCRIPTION :
1075 //
1076 void MediaHandler::dirInfo( std::list<std::string> & retlist,
1077  const Pathname & dirname, bool dots ) const
1078 {
1079  retlist.clear();
1080 
1081  if ( !isAttached() ) {
1082  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1084  }
1085 
1086  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1087  MIL << "dirInfo(" << dirname << ")" << endl;
1088 }
1089 
1091 //
1092 //
1093 // METHOD NAME : MediaHandler::dirInfo
1094 // METHOD TYPE : PMError
1095 //
1096 // DESCRIPTION :
1097 //
1099  const Pathname & dirname, bool dots ) const
1100 {
1101  retlist.clear();
1102 
1103  if ( !isAttached() ) {
1104  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1106  }
1107 
1108  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1109  MIL << "dirInfo(" << dirname << ")" << endl;
1110 }
1111 
1113 //
1114 //
1115 // METHOD NAME : MediaHandler::doesFileExist
1116 // METHOD TYPE : PMError
1117 //
1118 // DESCRIPTION :
1119 //
1120 bool MediaHandler::doesFileExist( const Pathname & filename ) const
1121 {
1122  // TODO do some logging
1123  if ( !isAttached() ) {
1124  INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
1126  }
1127  return getDoesFileExist( filename );
1128  MIL << "doesFileExist(" << filename << ")" << endl;
1129 }
1130 
1132 //
1133 //
1134 // METHOD NAME : MediaHandler::getDirectoryYast
1135 // METHOD TYPE : PMError
1136 //
1137 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
1138  const Pathname & dirname, bool dots ) const
1139 {
1140  retlist.clear();
1141 
1142  filesystem::DirContent content;
1143  getDirectoryYast( content, dirname, dots );
1144 
1145  // convert to std::list<std::string>
1146  for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1147  retlist.push_back( it->name );
1148  }
1149 }
1150 
1152 //
1153 //
1154 // METHOD NAME : MediaHandler::getDirectoryYast
1155 // METHOD TYPE : PMError
1156 //
1158  const Pathname & dirname, bool dots ) const
1159 {
1160  retlist.clear();
1161 
1162  // look for directory.yast
1163  Pathname dirFile = dirname + "directory.yast";
1164  getFile( dirFile );
1165  DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1166 
1167  // using directory.yast
1168  ifstream dir( localPath( dirFile ).asString().c_str() );
1169  if ( dir.fail() ) {
1170  ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl;
1172  "Unable to load '" + localPath( dirFile ).asString() + "'"));
1173  }
1174 
1175  string line;
1176  while( getline( dir, line ) ) {
1177  if ( line.empty() ) continue;
1178  if ( line == "directory.yast" ) continue;
1179 
1180  // Newer directory.yast append '/' to directory names
1181  // Remaining entries are unspecified, although most probabely files.
1183  if ( *line.rbegin() == '/' ) {
1184  line.erase( line.end()-1 );
1185  type = filesystem::FT_DIR;
1186  }
1187 
1188  if ( dots ) {
1189  if ( line == "." || line == ".." ) continue;
1190  } else {
1191  if ( *line.begin() == '.' ) continue;
1192  }
1193 
1194  retlist.push_back( filesystem::DirEntry( line, type ) );
1195  }
1196 }
1197 
1198 /******************************************************************
1199 **
1200 **
1201 ** FUNCTION NAME : operator<<
1202 ** FUNCTION TYPE : ostream &
1203 */
1204 ostream & operator<<( ostream & str, const MediaHandler & obj )
1205 {
1206  str << obj.url() << ( obj.isAttached() ? "" : " not" )
1207  << " attached; localRoot \"" << obj.localRoot() << "\"";
1208  return str;
1209 }
1210 
1212 //
1213 //
1214 // METHOD NAME : MediaHandler::getFile
1215 // METHOD TYPE : PMError
1216 //
1217 // DESCRIPTION : Asserted that media is attached.
1218 // Default implementation of pure virtual.
1219 //
1220 void MediaHandler::getFile( const Pathname & filename ) const
1221 {
1222  PathInfo info( localPath( filename ) );
1223  if( info.isFile() ) {
1224  return;
1225  }
1226 
1227  if (info.isExist())
1229  else
1231 }
1232 
1233 
1234 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
1235 {
1236  getFile(srcFilename);
1237 
1238  if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
1239  ZYPP_THROW(MediaWriteException(targetFilename));
1240  }
1241 }
1242 
1243 
1244 
1246 //
1247 //
1248 // METHOD NAME : MediaHandler::getDir
1249 // METHOD TYPE : PMError
1250 //
1251 // DESCRIPTION : Asserted that media is attached.
1252 // Default implementation of pure virtual.
1253 //
1254 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1255 {
1256  PathInfo info( localPath( dirname ) );
1257  if( info.isDir() ) {
1258  return;
1259  }
1260 
1261  if (info.isExist())
1263  else
1265 }
1266 
1268 //
1269 //
1270 // METHOD NAME : MediaHandler::getDirInfo
1271 // METHOD TYPE : PMError
1272 //
1273 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1274 // Default implementation of pure virtual.
1275 //
1276 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1277  const Pathname & dirname, bool dots ) const
1278 {
1279  PathInfo info( localPath( dirname ) );
1280  if( ! info.isDir() ) {
1282  }
1283 
1284 #if NONREMOTE_DIRECTORY_YAST
1285  // use directory.yast if available
1286  try {
1287  getDirectoryYast( retlist, dirname, dots );
1288  }
1289  catch (const MediaException & excpt_r)
1290  {
1291 #endif
1292 
1293  // readdir
1294  int res = readdir( retlist, info.path(), dots );
1295  if ( res )
1296  {
1297  MediaSystemException nexcpt(url(), "readdir failed");
1298 #if NONREMOTE_DIRECTORY_YAST
1299  nexcpt.remember(excpt_r);
1300 #endif
1301  ZYPP_THROW(nexcpt);
1302  }
1303 
1304 #if NONREMOTE_DIRECTORY_YAST
1305  }
1306 #endif
1307 
1308  return;
1309 }
1310 
1312 //
1313 //
1314 // METHOD NAME : MediaHandler::getDirInfo
1315 // METHOD TYPE : PMError
1316 //
1317 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1318 // Default implementation of pure virtual.
1319 //
1321  const Pathname & dirname, bool dots ) const
1322 {
1323  PathInfo info( localPath( dirname ) );
1324  if( ! info.isDir() ) {
1326  }
1327 
1328 #if NONREMOTE_DIRECTORY_YAST
1329  // use directory.yast if available
1330  try {
1331  getDirectoryYast( retlist, dirname, dots );
1332  }
1333  catch (const MediaException & excpt_r)
1334  {
1335 #endif
1336 
1337  // readdir
1338  int res = readdir( retlist, info.path(), dots );
1339  if ( res )
1340  {
1341  MediaSystemException nexcpt(url(), "readdir failed");
1342 #if NONREMOTE_DIRECTORY_YAST
1343  nexcpt.remember(excpt_r);
1344 #endif
1345  ZYPP_THROW(nexcpt);
1346  }
1347 #if NONREMOTE_DIRECTORY_YAST
1348  }
1349 #endif
1350 }
1351 
1353 //
1354 //
1355 // METHOD NAME : MediaHandler::getDoesFileExist
1356 // METHOD TYPE : PMError
1357 //
1358 // DESCRIPTION : Asserted that file is not a directory
1359 // Default implementation of pure virtual.
1360 //
1361 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1362 {
1363  PathInfo info( localPath( filename ) );
1364  if( info.isDir() ) {
1366  }
1367  return info.isExist();
1368 }
1369 
1371 {
1372  return false;
1373 }
1374 
1375 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
1376  unsigned int & index) const
1377 {
1378  // clear the vector by default
1379  if (!devices.empty())
1380  devices.clear();
1381  index = 0;
1382 
1383  DBG << "No devices for this medium" << endl;
1384 }
1385 
1386 void MediaHandler::setDeltafile( const Pathname & filename ) const
1387 {
1388  _deltafile = filename;
1389 }
1390 
1391 Pathname MediaHandler::deltafile() const {
1392  return _deltafile;
1393 }
1394 
1395  } // namespace media
1396 } // namespace zypp
1397 // 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
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:326
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
#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 &#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: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
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:348
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:589
int rmdir(const Pathname &path)
Like &#39;rmdir&#39;.
Definition: PathInfo.cc:367
Manages access to the &#39;physical&#39; media, e.g CDROM drives, Disk volumes, directory trees...
Definition: MediaManager.h:473
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: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.
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.