libzypp  16.6.1
MediaHandler.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 #include <fstream>
15 #include <sstream>
16 
17 #include "zypp/ZConfig.h"
18 #include "zypp/TmpPath.h"
19 #include "zypp/Date.h"
20 #include "zypp/base/LogTools.h"
21 #include "zypp/base/Gettext.h"
22 #include "zypp/base/String.h"
25 #include "zypp/media/Mount.h"
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 
30 
31 using namespace std;
32 
33 // use directory.yast on every media (not just via ftp/http)
34 #define NONREMOTE_DIRECTORY_YAST 1
35 
36 namespace zypp {
37  namespace media {
38 
39  Pathname MediaHandler::_attachPrefix("");
40 
42 //
43 // CLASS NAME : MediaHandler
44 //
46 
48 //
49 //
50 // METHOD NAME : MediaHandler::MediaHandler
51 // METHOD TYPE : Constructor
52 //
53 // DESCRIPTION :
54 //
55 MediaHandler::MediaHandler ( const Url & url_r,
56  const Pathname & attach_point_r,
57  const Pathname & urlpath_below_attachpoint_r,
58  const bool does_download_r )
59  : _mediaSource()
60  , _attachPoint( new AttachPoint())
61  , _attachPointHint()
62  , _relativeRoot( urlpath_below_attachpoint_r)
63  , _does_download( does_download_r )
64  , _attach_mtime(0)
65  , _url( url_r )
66  , _parentId(0)
67 {
68  Pathname real_attach_point( getRealPath(attach_point_r.asString()));
69 
70  if ( !real_attach_point.empty() ) {
72  // check if provided attachpoint is usable.
74 
75  PathInfo adir( real_attach_point );
76  //
77  // The verify if attach_point_r isn't a mountpoint of another
78  // device is done in the particular media handler (if needed).
79  //
80  // We just verify, if attach_point_r is a directory and for
81  // schemes other than "file" and "dir", if it is absolute.
82  //
83  if ( !adir.isDir()
84  || (_url.getScheme() != "file"
85  && _url.getScheme() != "dir"
86  && !real_attach_point.absolute()) )
87  {
88  ERR << "Provided attach point is not a absolute directory: "
89  << adir << endl;
90  }
91  else {
92  attachPointHint( real_attach_point, false);
93  setAttachPoint( real_attach_point, false);
94  }
95  }
96 }
97 
99 //
100 //
101 // METHOD NAME : MediaHandler::~MediaHandler
102 // METHOD TYPE : Destructor
103 //
104 // DESCRIPTION :
105 //
107 {
108  try
109  {
111  }
112  catch(...) {}
113 }
114 
115 void
117 {
118  _parentId = 0;
119 }
120 
121 std::string
122 MediaHandler::getRealPath(const std::string &path)
123 {
124  std::string real;
125  if( !path.empty())
126  {
127 #if __GNUC__ > 2
128 
129  char *ptr = ::realpath(path.c_str(), NULL);
130  if( ptr != NULL)
131  {
132  real = ptr;
133  free( ptr);
134  }
135  else
137  if( EINVAL == errno)
138  {
139  char buff[PATH_MAX + 2];
140  memset(buff, '\0', sizeof(buff));
141  if( ::realpath(path.c_str(), buff) != NULL)
142  {
143  real = buff;
144  }
145  }
146 #else
147  char buff[PATH_MAX + 2];
148  memset(buff, '\0', sizeof(buff));
149  if( ::realpath(path.c_str(), buff) != NULL)
150  {
151  real = buff;
152  }
153 #endif
154  }
155  return real;
156 }
157 
160 {
161  return zypp::Pathname(getRealPath(path.asString()));
162 }
163 
164 
166 //
167 //
168 // METHOD NAME : MediaHandler::removeAttachPoint
169 // METHOD TYPE : void
170 //
171 // DESCRIPTION :
172 //
173 void
175 {
176  if ( _mediaSource ) {
177  INT << "MediaHandler deleted with media attached." << endl;
178  return; // no cleanup if media still mounted!
179  }
180 
181  DBG << "MediaHandler - checking if to remove attach point" << endl;
182  if ( _attachPoint.unique() &&
183  _attachPoint->temp &&
184  !_attachPoint->path.empty() &&
185  PathInfo(_attachPoint->path).isDir())
186  {
187  Pathname path(_attachPoint->path);
188 
189  setAttachPoint("", true);
190 
191  int res = recursive_rmdir( path );
192  if ( res == 0 ) {
193  MIL << "Deleted default attach point " << path << endl;
194  } else {
195  ERR << "Failed to Delete default attach point " << path
196  << " errno(" << res << ")" << endl;
197  }
198  }
199  else
200  {
201  if( !_attachPoint->path.empty() && !_attachPoint->temp)
202  DBG << "MediaHandler - attachpoint is not temporary" << endl;
203  }
204 }
205 
206 
208 //
209 //
210 // METHOD NAME : MediaHandler::attachPoint
211 // METHOD TYPE : Pathname
212 //
213 // DESCRIPTION :
214 //
215 Pathname
217 {
218  return _attachPoint->path;
219 }
220 
221 
223 //
224 //
225 // METHOD NAME : MediaHandler::attachPoint
226 // METHOD TYPE :
227 //
228 // DESCRIPTION :
229 //
230 void
231 MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
232 {
233  _attachPoint.reset( new AttachPoint(path, temporary));
234 }
235 
236 Pathname
238 {
239  if( _attachPoint->path.empty())
240  return Pathname();
241  else
242  return _attachPoint->path + _relativeRoot;
243 }
244 
246 //
247 //
248 // METHOD NAME : MediaHandler::attachPoint
249 // METHOD TYPE :
250 //
251 // DESCRIPTION :
252 //
253 void
255 {
256  if( ref)
258  else
260 }
261 
263 //
264 //
265 // METHOD NAME : MediaHandler::attachPointHint
266 // METHOD TYPE : void
267 //
268 // DESCRIPTION :
269 //
270 void
271 MediaHandler::attachPointHint(const Pathname &path, bool temporary)
272 {
273  _attachPointHint.path = path;
274  _attachPointHint.temp = temporary;
275 }
276 
278 //
279 //
280 // METHOD NAME : MediaHandler::attachPointHint
281 // METHOD TYPE : AttachPoint
282 //
283 // DESCRIPTION :
284 //
287 {
288  return _attachPointHint;
289 }
290 
292 //
293 //
294 // METHOD NAME : MediaHandler::findAttachedMedia
295 // METHOD TYPE : AttachedMedia
296 //
297 // DESCRIPTION :
298 //
301 {
302  return MediaManager().findAttachedMedia(media);
303 }
304 
306 //
307 //
308 // METHOD NAME : MediaHandler::setAttachPrefix
309 // METHOD TYPE : void
310 //
311 // DESCRIPTION :
312 //
313 bool
315 {
316  if( attach_prefix.empty())
317  {
318  MIL << "Reseting to built-in attach point prefixes."
319  << std::endl;
320  MediaHandler::_attachPrefix = attach_prefix;
321  return true;
322  }
323  else
324  if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
325  {
326  MIL << "Setting user defined attach point prefix: "
327  << attach_prefix << std::endl;
328  MediaHandler::_attachPrefix = attach_prefix;
329  return true;
330  }
331  return false;
332 }
333 
335 //
336 //
337 // METHOD NAME : MediaHandler::attach
338 // METHOD TYPE : Pathname
339 //
340 // DESCRIPTION :
341 //
342 Pathname
344 {
345  Pathname aroot;
346  Pathname apoint;
347  {
348  aroot = MediaHandler::_attachPrefix; // explicit request
349  if ( ! aroot.empty() )
350  apoint = createAttachPoint( aroot );
351  }
352 
353  if ( apoint.empty() ) // fallback to config value
354  {
356  if ( ! aroot.empty() )
357  apoint = createAttachPoint( aroot );
358  }
359 
360  if ( apoint.empty() ) // fall back to temp space
361  {
363  if ( ! aroot.empty() )
364  apoint = createAttachPoint( aroot );
365  }
366 
367  if ( apoint.empty() )
368  {
369  auto except = MediaBadAttachPointException( url() );
370  except.addHistory( _("Create attach point: Can't find a writable directory to create an attach point") );
371  ZYPP_THROW( std::move(except) );
372  }
373 
374  MIL << "Created default attach point " << apoint << std::endl;
375  return apoint;
376 }
377 
378 Pathname
379 MediaHandler::createAttachPoint(const Pathname &attach_root) const
380 {
381  Pathname apoint;
382 
383  if( attach_root.empty() || !attach_root.absolute()) {
384  ERR << "Create attach point: invalid attach root: '"
385  << attach_root << "'" << std::endl;
386  return apoint;
387  }
388 
389  PathInfo adir( attach_root );
390  if( !adir.isDir() || (geteuid() != 0 && !adir.userMayRWX())) {
391  DBG << "Create attach point: attach root is not a writable directory: '"
392  << attach_root << "'" << std::endl;
393  return apoint;
394  }
395 
396  static bool cleanup_once( true );
397  if ( cleanup_once )
398  {
399  cleanup_once = false;
400  DBG << "Look for orphaned attach points in " << adir << std::endl;
401  std::list<std::string> entries;
402  filesystem::readdir( entries, attach_root, false );
403  for ( const std::string & entry : entries )
404  {
405  if ( ! str::hasPrefix( entry, "AP_0x" ) )
406  continue;
407  PathInfo sdir( attach_root + entry );
408  if ( sdir.isDir()
409  && sdir.dev() == adir.dev()
410  && ( Date::now()-sdir.mtime() > Date::month ) )
411  {
412  DBG << "Remove orphaned attach point " << sdir << std::endl;
414  }
415  }
416  }
417 
418  filesystem::TmpDir tmpdir( attach_root, "AP_0x" );
419  if ( tmpdir )
420  {
421  apoint = getRealPath( tmpdir.path().asString() );
422  if ( ! apoint.empty() )
423  {
424  tmpdir.autoCleanup( false ); // Take responsibility for cleanup.
425  }
426  else
427  {
428  ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl;
429  }
430  }
431  else
432  {
433  ERR << "Unable to create attach point below " << attach_root << std::endl;
434  }
435  return apoint;
436 }
437 
439 //
440 //
441 // METHOD NAME : MediaHandler::isUseableAttachPoint
442 // METHOD TYPE : bool
443 //
444 // DESCRIPTION :
445 //
446 bool
447 MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const
448 {
449  MediaManager manager;
450  return manager.isUseableAttachPoint(path, mtab);
451 }
452 
453 
455 //
456 //
457 // METHOD NAME : MediaHandler::setMediaSource
458 // METHOD TYPE : void
459 //
460 // DESCRIPTION :
461 //
462 void
464 {
466  if( ref && !ref->type.empty() && !ref->name.empty())
467  _mediaSource = ref;
468 }
469 
471 //
472 //
473 // METHOD NAME : MediaHandler::attachedMedia
474 // METHOD TYPE : AttachedMedia
475 //
476 // DESCRIPTION :
477 //
480 {
481  if ( _mediaSource && _attachPoint)
483  else
484  return AttachedMedia();
485 }
486 
488 //
489 //
490 // METHOD NAME : MediaHandler::isSharedMedia
491 // METHOD TYPE : bool
492 //
493 // DESCRIPTION :
494 //
495 bool
497 {
498  return !_mediaSource.unique();
499 }
500 
502 //
503 //
504 // METHOD NAME : MediaHandler::checkAttached
505 // METHOD TYPE : bool
506 //
507 // DESCRIPTION :
508 //
509 bool
510 MediaHandler::checkAttached(bool matchMountFs) const
511 {
512  bool _isAttached = false;
513 
514  AttachedMedia ref( attachedMedia() );
515  if( ref.mediaSource )
516  {
517  time_t old_mtime = _attach_mtime;
519  if( !(old_mtime <= 0 || _attach_mtime != old_mtime) )
520  {
521  // OK, skip the check (we've seen it at least once)
522  _isAttached = true;
523  }
524  else
525  {
526  if( old_mtime > 0)
527  DBG << "Mount table changed - rereading it" << std::endl;
528  else
529  DBG << "Forced check of the mount table" << std::endl;
530 
531  MountEntries entries( MediaManager::getMountEntries());
532  for_( e, entries.begin(), entries.end() )
533  {
534  if ( ref.attachPoint->path != Pathname(e->dir) )
535  continue; // at least the mount points must match
536 
537  bool is_device = false;
538  PathInfo dev_info;
539  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
540  dev_info(e->src) && dev_info.isBlk() )
541  {
542  is_device = true;
543  }
544 
545  if( is_device && (ref.mediaSource->maj_nr &&
546  ref.mediaSource->bdir.empty()))
547  {
548  std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
549  MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor());
550 
551  if( ref.mediaSource->equals( media ) )
552  {
553  DBG << "Found media device "
554  << ref.mediaSource->asString()
555  << " in the mount table as " << e->src << std::endl;
556  _isAttached = true;
557  break;
558  }
559  // differs
560  }
561  else
562  if(!is_device && (!ref.mediaSource->maj_nr ||
563  !ref.mediaSource->bdir.empty()))
564  {
565  if( ref.mediaSource->bdir.empty())
566  {
567  // bnc#710269: Type nfs may appear as nfs4 in in the mount table
568  // and maybe vice versa. Similar cifs/smb. Need to unify these types:
569  if ( matchMountFs && e->type != ref.mediaSource->type )
570  {
571  if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) )
572  matchMountFs = false;
573  else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) )
574  matchMountFs = false;
575  else
576  continue; // different types cannot match
577  }
578  // Here: Types are ok or not to check.
579  // Check the name except for nfs (bnc#804544; symlink resolution in mount path)
580  //
581  // [fibonacci]$ ls -l /Local/ma/c12.1
582  // lrwxrwxrwx /Local/ma/c12.1 -> zypp-SuSE-Code-12_1-Branch/
583  //
584  // [localhost]$ mount -t nfs4 fibonacci:/Local/ma/c12.1 /mnt
585  // [localhost]$ mount
586  // fibonacci:/Local/ma/zypp-SuSE-Code-12_1-Branch on /mnt
587 
588  // std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
589  // MediaSource media(mtype, e->src);
590 
591  if( ref.mediaSource->name == e->src || str::hasPrefix( ref.mediaSource->type, "nfs" ) )
592  {
593  DBG << "Found media name "
594  << ref.mediaSource->asString()
595  << " in the mount table as " << e->src << std::endl;
596  _isAttached = true;
597  break;
598  }
599  }
600  else
601  {
602  if ( ref.mediaSource->bdir == e->src )
603  {
604  DBG << "Found bound media "
605  << ref.mediaSource->asString()
606  << " in the mount table as " << e->src << std::endl;
607  _isAttached = true;
608  break;
609  }
610  }
611  // differs
612  }
613  }
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
871 {
872  return MediaHandler::checkAttachPoint( apoint, true, false);
873 }
874 
875 // STATIC
876 bool
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 //
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 //
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 
1392  return _deltafile;
1393 }
1394 
1395  } // namespace media
1396 } // namespace zypp
1397 // vim: set ts=8 sts=2 sw=2 ai noet:
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:527
Attach point of a media source.
Definition: MediaSource.h:105
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
Interface to gettext.
void resetParentId()
Called in case, where the media manager takes over the destruction of the parent id (e...
#define MIL
Definition: Logger.h:64
Listentry returned by readdir.
Definition: PathInfo.h:532
Interface to the mount program.
Definition: Mount.h:69
const Pathname & path() const
Return current Pathname.
Definition: PathInfo.h:246
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:321
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:121
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
AttachPoint _attachPointHint
The user provided attach preferred point.
Definition: MediaHandler.h:85
virtual bool checkAttachPoint(const Pathname &apoint) const
Verify if the specified directory as attach point (root) as requires by the particular media handler ...
AttachedMedia attachedMedia() const
Returns the attached media.
Pathname _relativeRoot
The relative root directory of the data on the media.
Definition: MediaHandler.h:92
Pathname deltafile() const
Pathname path
The path name (mount point).
Definition: MediaSource.h:116
zypp::RW_pointer< MediaSource > MediaSourceRef
Definition: MediaSource.h:124
void provideFileCopy(Pathname srcFilename, Pathname targetFilename) const
Call concrete handler to provide a copy of a file under a different place in the file system (usually...
static std::string getRealPath(const std::string &path)
#define INT
Definition: Logger.h:68
static Pathname _attachPrefix
User defined default attach point prefix.
Definition: MediaHandler.h:61
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\ ", const std::string &sep="\ ", const std::string &sfx="\, const std::string &extro="}")
Print range defined by iterators (multiline style).
Definition: LogTools.h:91
void dirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Return content of directory on media via retlist.
virtual void disconnectFrom()
Call concrete handler to disconnect media.
Definition: MediaHandler.h:326
time_t mtime() const
Definition: PathInfo.h:376
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:434
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Ask media manager, if the specified path is already used as attach point or if there are another atta...
String related utilities and Regular expression matching.
Definition: Arch.h: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 provideDir(Pathname dirname) const
Use concrete handler to provide directory denoted by path below &#39;localRoot&#39; (not recursive!).
void releasePath(Pathname pathname) const
Remove pathname below localRoot IFF handler downloads files to the local filesystem.
long use_count() const
Definition: PtrTypes.h:346
void setDeltafile(const Pathname &filename=Pathname()) const
unsigned int devMinor() const
Definition: PathInfo.cc:252
bool doesFileExist(const Pathname &filename) const
check if a file exists
void provideFile(Pathname filename) const
Use concrete handler to provide file denoted by path below &#39;localRoot&#39;.
bool checkAttached(bool matchMountFs) const
Check actual mediaSource attachment against the current mount table of the system.
#define ERR
Definition: Logger.h:66
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
virtual void attachTo(bool next=false)=0
Call concrete handler to attach the media.
Pathname localPath(const Pathname &pathname) const
Files provided will be available at &#39;localPath(filename)&#39;.
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 download_mediaMountdir() const
Path where media are preferably mounted or downloaded.
Definition: ZConfig.cc:996
bool empty() const
Test for an empty path.
Definition: Pathname.h:113
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h: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
void provideDirTree(Pathname dirname) const
Use concrete handler to provide directory tree denoted by path below &#39;localRoot&#39; (recursive!!).
MediaSourceRef mediaSource
Definition: MediaSource.h:144
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h: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.
const std::string & asString() const
String representation.
Definition: Pathname.h:90
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
Just inherits Exception to separate media exceptions.
void disconnect()
Use concrete handler to isconnect media.
void attach(bool next)
Use concrete handler to attach the media.
bool isSharedMedia() const
Returns a hint if the media is shared or not.
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:413
virtual ~MediaHandler()
Contolling MediaAccess takes care, that attached media is released prior to deleting this...
static bool setAttachPrefix(const Pathname &attach_prefix)
#define WAR
Definition: Logger.h:65
std::list< DirEntry > DirContent
Returned by readdir.
Definition: PathInfo.h:547
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
AttachPoint attachPointHint() const
Get the actual attach point hint.
bool absolute() const
Test for an absolute path.
Definition: Pathname.h:115
#define _(MSG)
Definition: Gettext.h:29
virtual bool hasMoreDevices()
Check if the media has one more device available for attach(true).
AttachedMedia getAttachedMedia(MediaAccessId &accessId) const
void removeAttachPoint()
Remove unused attach point.
void forceReleaseShared(const MediaSourceRef &media)
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:36
Pathname localRoot() const
Return the local directory that corresponds to medias url, no matter if media isAttached or not...
std::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
Definition: IOStream.h:50
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h: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
void forceRelaseAllMedia(bool matchMountFs)
Call to this function will try to release all media matching the currenlty attached media source...
virtual void getDirInfo(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const =0
Call concrete handler to provide a content list of directory on media via retlist.
virtual bool getDoesFileExist(const Pathname &filename) const =0
check if a file exists
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
Ask the media manager if specified media source is already attached.
void swap(RW_pointer &rhs)
Definition: PtrTypes.h:315
Pathname absolutename() const
Return this path, adding a leading &#39;/&#39; if relative.
Definition: Pathname.h:135
Base class for Exception.
Definition: Exception.h:143
Pathname attachPoint() const
Return the currently used attach point.
FileType
File type information.
Definition: PathInfo.h:55
Url url() const
Url used.
Definition: MediaHandler.h:507
virtual void getDetectedDevices(std::vector< std::string > &devices, unsigned int &index) const
Fill in a vector of detected ejectable devices and the index of the currently attached device within ...
static Date now()
Return the current time.
Definition: Date.h:78
MediaAccessId _parentId
Access Id of media handler we depend on.
Definition: MediaHandler.h:115
bool unique() const
Definition: PtrTypes.h:343
virtual void getFile(const Pathname &filename) const =0
Call concrete handler to provide file below attach point.
AttachPointRef _attachPoint
This is where the media will be actually attached ("mounted").
Definition: MediaHandler.h:73
time_t _attach_mtime
timestamp of the the last attach verification
Definition: MediaHandler.h:101
unsigned int devMajor() const
Definition: PathInfo.cc:242
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
virtual void getFileCopy(const Pathname &srcFilename, const Pathname &targetFilename) const
Call concrete handler to provide a file under a different place in the file system (usually not under...
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
virtual bool isAttached() const
True if media is attached.
Definition: MediaHandler.h:524
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
void release(const std::string &ejectDev="")
Use concrete handler to release the media.
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1028
friend std::ostream & operator<<(std::ostream &str, const MediaHandler &obj)
bool _does_download
True if concrete handler downloads files to the local filesystem.
Definition: MediaHandler.h:98
static time_t getMountTableMTime()
Get the modification time of the /etc/mtab file.
bool userMayRWX() const
Definition: PathInfo.h:353
Url manipulation class.
Definition: Url.h:87
void umount(const std::string &path)
umount device
Definition: Mount.cc:162
#define DBG
Definition: Logger.h:63
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Check if the specified path is useable as attach point.