libzypp  13.10.6
MediaHandler.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 #include <fstream>
15 #include <sstream>
16 
17 #include "zypp/TmpPath.h"
18 #include "zypp/Date.h"
19 #include "zypp/base/LogTools.h"
20 #include "zypp/base/String.h"
23 #include "zypp/media/Mount.h"
24 #include <limits.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 
28 
29 using namespace std;
30 
31 // use directory.yast on every media (not just via ftp/http)
32 #define NONREMOTE_DIRECTORY_YAST 1
33 
34 namespace zypp {
35  namespace media {
36 
37  Pathname MediaHandler::_attachPrefix("");
38 
40 //
41 // CLASS NAME : MediaHandler
42 //
44 
46 //
47 //
48 // METHOD NAME : MediaHandler::MediaHandler
49 // METHOD TYPE : Constructor
50 //
51 // DESCRIPTION :
52 //
53 MediaHandler::MediaHandler ( const Url & url_r,
54  const Pathname & attach_point_r,
55  const Pathname & urlpath_below_attachpoint_r,
56  const bool does_download_r )
57  : _mediaSource()
58  , _attachPoint( new AttachPoint())
59  , _AttachPointHint()
60  , _relativeRoot( urlpath_below_attachpoint_r)
61  , _does_download( does_download_r )
62  , _attach_mtime(0)
63  , _url( url_r )
64  , _parentId(0)
65 {
66  Pathname real_attach_point( getRealPath(attach_point_r.asString()));
67 
68  if ( !real_attach_point.empty() ) {
70  // check if provided attachpoint is usable.
72 
73  PathInfo adir( real_attach_point );
74  //
75  // The verify if attach_point_r isn't a mountpoint of another
76  // device is done in the particular media handler (if needed).
77  //
78  // We just verify, if attach_point_r is a directory and for
79  // schemes other than "file" and "dir", if it is absolute.
80  //
81  if ( !adir.isDir()
82  || (_url.getScheme() != "file"
83  && _url.getScheme() != "dir"
84  && !real_attach_point.absolute()) )
85  {
86  ERR << "Provided attach point is not a absolute directory: "
87  << adir << endl;
88  }
89  else {
90  attachPointHint( real_attach_point, false);
91  setAttachPoint( real_attach_point, false);
92  }
93  }
94 }
95 
97 //
98 //
99 // METHOD NAME : MediaHandler::~MediaHandler
100 // METHOD TYPE : Destructor
101 //
102 // DESCRIPTION :
103 //
105 {
106  try
107  {
109  }
110  catch(...) {}
111 }
112 
113 void
115 {
116  _parentId = 0;
117 }
118 
119 std::string
120 MediaHandler::getRealPath(const std::string &path)
121 {
122  std::string real;
123  if( !path.empty())
124  {
125 #if __GNUC__ > 2
126 
127  char *ptr = ::realpath(path.c_str(), NULL);
128  if( ptr != NULL)
129  {
130  real = ptr;
131  free( ptr);
132  }
133  else
135  if( EINVAL == errno)
136  {
137  char buff[PATH_MAX + 2];
138  memset(buff, '\0', sizeof(buff));
139  if( ::realpath(path.c_str(), buff) != NULL)
140  {
141  real = buff;
142  }
143  }
144 #else
145  char buff[PATH_MAX + 2];
146  memset(buff, '\0', sizeof(buff));
147  if( ::realpath(path.c_str(), buff) != NULL)
148  {
149  real = buff;
150  }
151 #endif
152  }
153  return real;
154 }
155 
156 zypp::Pathname
157 MediaHandler::getRealPath(const Pathname &path)
158 {
159  return zypp::Pathname(getRealPath(path.asString()));
160 }
161 
162 
164 //
165 //
166 // METHOD NAME : MediaHandler::removeAttachPoint
167 // METHOD TYPE : void
168 //
169 // DESCRIPTION :
170 //
171 void
173 {
174  if ( _mediaSource ) {
175  INT << "MediaHandler deleted with media attached." << endl;
176  return; // no cleanup if media still mounted!
177  }
178 
179  DBG << "MediaHandler - checking if to remove attach point" << endl;
180  if ( _attachPoint.unique() &&
181  _attachPoint->temp &&
182  !_attachPoint->path.empty() &&
183  PathInfo(_attachPoint->path).isDir())
184  {
185  Pathname path(_attachPoint->path);
186 
187  setAttachPoint("", true);
188 
189  int res = recursive_rmdir( path );
190  if ( res == 0 ) {
191  MIL << "Deleted default attach point " << path << endl;
192  } else {
193  ERR << "Failed to Delete default attach point " << path
194  << " errno(" << res << ")" << endl;
195  }
196  }
197  else
198  {
199  if( !_attachPoint->path.empty() && !_attachPoint->temp)
200  DBG << "MediaHandler - attachpoint is not temporary" << endl;
201  }
202 }
203 
204 
206 //
207 //
208 // METHOD NAME : MediaHandler::attachPoint
209 // METHOD TYPE : Pathname
210 //
211 // DESCRIPTION :
212 //
213 Pathname
215 {
216  return _attachPoint->path;
217 }
218 
219 
221 //
222 //
223 // METHOD NAME : MediaHandler::attachPoint
224 // METHOD TYPE :
225 //
226 // DESCRIPTION :
227 //
228 void
229 MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
230 {
231  _attachPoint.reset( new AttachPoint(path, temporary));
232 }
233 
234 Pathname
236 {
237  if( _attachPoint->path.empty())
238  return Pathname();
239  else
240  return _attachPoint->path + _relativeRoot;
241 }
242 
244 //
245 //
246 // METHOD NAME : MediaHandler::attachPoint
247 // METHOD TYPE :
248 //
249 // DESCRIPTION :
250 //
251 void
253 {
254  if( ref)
256  else
258 }
259 
261 //
262 //
263 // METHOD NAME : MediaHandler::attachPointHint
264 // METHOD TYPE : void
265 //
266 // DESCRIPTION :
267 //
268 void
269 MediaHandler::attachPointHint(const Pathname &path, bool temporary)
270 {
271  _AttachPointHint.path = path;
272  _AttachPointHint.temp = temporary;
273 }
274 
276 //
277 //
278 // METHOD NAME : MediaHandler::attachPointHint
279 // METHOD TYPE : AttachPoint
280 //
281 // DESCRIPTION :
282 //
285 {
286  return _AttachPointHint;
287 }
288 
290 //
291 //
292 // METHOD NAME : MediaHandler::findAttachedMedia
293 // METHOD TYPE : AttachedMedia
294 //
295 // DESCRIPTION :
296 //
299 {
300  return MediaManager().findAttachedMedia(media);
301 }
302 
304 //
305 //
306 // METHOD NAME : MediaHandler::setAttachPrefix
307 // METHOD TYPE : void
308 //
309 // DESCRIPTION :
310 //
311 bool
312 MediaHandler::setAttachPrefix(const Pathname &attach_prefix)
313 {
314  if( attach_prefix.empty())
315  {
316  MIL << "Reseting to built-in attach point prefixes."
317  << std::endl;
318  MediaHandler::_attachPrefix = attach_prefix;
319  return true;
320  }
321  else
322  if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
323  {
324  MIL << "Setting user defined attach point prefix: "
325  << attach_prefix << std::endl;
326  MediaHandler::_attachPrefix = attach_prefix;
327  return true;
328  }
329  return false;
330 }
331 
333 //
334 //
335 // METHOD NAME : MediaHandler::attach
336 // METHOD TYPE : Pathname
337 //
338 // DESCRIPTION :
339 //
340 Pathname
342 {
344  // provide a default (temporary) attachpoint
346  const char * defmounts[] = {
347  "/var/adm/mount", filesystem::TmpPath::defaultLocation().c_str(), NULL
348  };
349 
350  Pathname apoint;
351  Pathname aroot( MediaHandler::_attachPrefix);
352 
353  if( !aroot.empty())
354  {
355  apoint = createAttachPoint(aroot);
356  }
357  for ( const char ** def = defmounts; *def && apoint.empty(); ++def ) {
358  aroot = *def;
359  if( aroot.empty())
360  continue;
361 
362  apoint = createAttachPoint(aroot);
363  }
364 
365  if ( aroot.empty() ) {
366  ERR << "Create attach point: Can't find a writable directory to create an attach point" << std::endl;
367  return aroot;
368  }
369 
370  if ( !apoint.empty() ) {
371  MIL << "Created default attach point " << apoint << std::endl;
372  }
373  return apoint;
374 }
375 
376 Pathname
377 MediaHandler::createAttachPoint(const Pathname &attach_root) const
378 {
379  Pathname apoint;
380 
381  if( attach_root.empty() || !attach_root.absolute()) {
382  ERR << "Create attach point: invalid attach root: '"
383  << attach_root << "'" << std::endl;
384  return apoint;
385  }
386 
387  PathInfo adir( attach_root );
388  if( !adir.isDir() || (geteuid() != 0 && !adir.userMayRWX())) {
389  DBG << "Create attach point: attach root is not a writable directory: '"
390  << attach_root << "'" << std::endl;
391  return apoint;
392  }
393 
394  static bool cleanup_once( true );
395  if ( cleanup_once )
396  {
397  cleanup_once = false;
398  DBG << "Look for orphaned attach points in " << adir << std::endl;
399  std::list<std::string> entries;
400  filesystem::readdir( entries, attach_root, false );
401  for ( const std::string & entry : entries )
402  {
403  if ( ! str::hasPrefix( entry, "AP_0x" ) )
404  continue;
405  PathInfo sdir( attach_root + entry );
406  if ( sdir.isDir()
407  && sdir.dev() == adir.dev()
408  && ( Date::now()-sdir.mtime() > Date::month ) )
409  {
410  DBG << "Remove orphaned attach point " << sdir << std::endl;
411  filesystem::recursive_rmdir( sdir.path() );
412  }
413  }
414  }
415 
416  filesystem::TmpDir tmpdir( attach_root, "AP_0x" );
417  if ( tmpdir )
418  {
419  apoint = getRealPath( tmpdir.path().asString() );
420  if ( ! apoint.empty() )
421  {
422  tmpdir.autoCleanup( false ); // Take responsibility for cleanup.
423  }
424  else
425  {
426  ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl;
427  }
428  }
429  else
430  {
431  ERR << "Unable to create attach point below " << attach_root << std::endl;
432  }
433  return apoint;
434 }
435 
437 //
438 //
439 // METHOD NAME : MediaHandler::isUseableAttachPoint
440 // METHOD TYPE : bool
441 //
442 // DESCRIPTION :
443 //
444 bool
445 MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const
446 {
447  MediaManager manager;
448  return manager.isUseableAttachPoint(path, mtab);
449 }
450 
451 
453 //
454 //
455 // METHOD NAME : MediaHandler::setMediaSource
456 // METHOD TYPE : void
457 //
458 // DESCRIPTION :
459 //
460 void
462 {
464  if( ref && !ref->type.empty() && !ref->name.empty())
465  _mediaSource = ref;
466 }
467 
469 //
470 //
471 // METHOD NAME : MediaHandler::attachedMedia
472 // METHOD TYPE : AttachedMedia
473 //
474 // DESCRIPTION :
475 //
478 {
479  if ( _mediaSource && _attachPoint)
481  else
482  return AttachedMedia();
483 }
484 
486 //
487 //
488 // METHOD NAME : MediaHandler::isSharedMedia
489 // METHOD TYPE : bool
490 //
491 // DESCRIPTION :
492 //
493 bool
495 {
496  return !_mediaSource.unique();
497 }
498 
500 //
501 //
502 // METHOD NAME : MediaHandler::checkAttached
503 // METHOD TYPE : bool
504 //
505 // DESCRIPTION :
506 //
507 bool
508 MediaHandler::checkAttached(bool matchMountFs) const
509 {
510  bool _isAttached = false;
511 
512  AttachedMedia ref( attachedMedia() );
513  if( ref.mediaSource )
514  {
515  time_t old_mtime = _attach_mtime;
517  if( !(old_mtime <= 0 || _attach_mtime != old_mtime) )
518  {
519  // OK, skip the check (we've seen it at least once)
520  _isAttached = true;
521  }
522  else
523  {
524  if( old_mtime > 0)
525  DBG << "Mount table changed - rereading it" << std::endl;
526  else
527  DBG << "Forced check of the mount table" << std::endl;
528 
529  MountEntries entries( MediaManager::getMountEntries());
530  for_( e, entries.begin(), entries.end() )
531  {
532  if ( ref.attachPoint->path != Pathname(e->dir) )
533  continue; // at least the mount points must match
534 
535  bool is_device = false;
536  PathInfo dev_info;
537  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
538  dev_info(e->src) && dev_info.isBlk() )
539  {
540  is_device = true;
541  }
542 
543  if( is_device && (ref.mediaSource->maj_nr &&
544  ref.mediaSource->bdir.empty()))
545  {
546  std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
547  MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
548 
549  if( ref.mediaSource->equals( media ) )
550  {
551  DBG << "Found media device "
552  << ref.mediaSource->asString()
553  << " in the mount table as " << e->src << std::endl;
554  _isAttached = true;
555  break;
556  }
557  // differs
558  }
559  else
560  if(!is_device && (!ref.mediaSource->maj_nr ||
561  !ref.mediaSource->bdir.empty()))
562  {
563  if( ref.mediaSource->bdir.empty())
564  {
565  // bnc#710269: Type nfs may appear as nfs4 in in the mount table
566  // and maybe vice versa. Similar cifs/smb. Need to unify these types:
567  if ( matchMountFs && e->type != ref.mediaSource->type )
568  {
569  if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) )
570  matchMountFs = false;
571  else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) )
572  matchMountFs = false;
573  else
574  continue; // different types cannot match
575  }
576  // Here: Types are ok or not to check.
577  // Check the name except for nfs (bnc#804544; symlink resolution in mount path)
578  //
579  // [fibonacci]$ ls -l /Local/ma/c12.1
580  // lrwxrwxrwx /Local/ma/c12.1 -> zypp-SuSE-Code-12_1-Branch/
581  //
582  // [localhost]$ mount -t nfs4 fibonacci:/Local/ma/c12.1 /mnt
583  // [localhost]$ mount
584  // fibonacci:/Local/ma/zypp-SuSE-Code-12_1-Branch on /mnt
585 
586  // std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
587  // MediaSource media(mtype, e->src);
588 
589  if( ref.mediaSource->name == e->src || str::hasPrefix( ref.mediaSource->type, "nfs" ) )
590  {
591  DBG << "Found media name "
592  << ref.mediaSource->asString()
593  << " in the mount table as " << e->src << std::endl;
594  _isAttached = true;
595  break;
596  }
597  }
598  else
599  {
600  if ( ref.mediaSource->bdir == e->src )
601  {
602  DBG << "Found bound media "
603  << ref.mediaSource->asString()
604  << " in the mount table as " << e->src << std::endl;
605  _isAttached = true;
606  break;
607  }
608  }
609  // differs
610  }
611  }
612 
613  if( !_isAttached)
614  {
615  MIL << "Looking for " << ref << endl;
616  if( entries.empty() )
617  {
618  ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
619  }
620  else
621  {
622  dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
623  }
624  if( old_mtime > 0 )
625  {
626  ERR << "Attached media not in mount table any more - forcing reset!"
627  << std::endl;
628 
630  }
631  else
632  {
633  WAR << "Attached media not in mount table ..." << std::endl;
634  }
635 
636  // reset the mtime and force a new check to make sure,
637  // that we've found the media at least once in the mtab.
638  _attach_mtime = 0;
639  }
640  }
641  }
642  return _isAttached;
643 }
644 
646 //
647 //
648 // METHOD NAME : MediaHandler::attach
649 // METHOD TYPE : PMError
650 //
651 // DESCRIPTION :
652 //
653 void MediaHandler::attach( bool next )
654 {
655  if ( isAttached() )
656  return;
657 
658  // reset it in case of overloaded isAttached()
659  // that checks the media against /etc/mtab ...
661 
663  setAttachPoint(ap.path, ap.temp);
664 
665  try
666  {
667  attachTo( next ); // pass to concrete handler
668  }
669  catch(const MediaException &e)
670  {
672  ZYPP_RETHROW(e);
673  }
674  MIL << "Attached: " << *this << endl;
675 }
676 
677 
679 //
680 //
681 // METHOD NAME : MediaHandler::localPath
682 // METHOD TYPE : Pathname
683 //
684 Pathname MediaHandler::localPath( const Pathname & pathname ) const
685 {
686  Pathname _localRoot( localRoot());
687  if ( _localRoot.empty() )
688  return _localRoot;
689 
690  // we must check maximum file name length
691  // this is important for fetching the suseservers, the
692  // url with all parameters can get too long (bug #42021)
693 
694  return _localRoot + pathname.absolutename();
695 }
696 
697 
698 
699 
700 
702 //
703 //
704 // METHOD NAME : MediaHandler::disconnect
705 // METHOD TYPE : PMError
706 //
708 {
709  if ( !isAttached() )
710  return;
711 
712  disconnectFrom(); // pass to concrete handler
713  MIL << "Disconnected: " << *this << endl;
714 }
715 
717 //
718 //
719 // METHOD NAME : MediaHandler::release
720 // METHOD TYPE : PMError
721 //
722 // DESCRIPTION :
723 //
724 void MediaHandler::release( const std::string & ejectDev )
725 {
726  if ( !isAttached() ) {
727  DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
728  << std::endl;
729  if ( !ejectDev.empty() )
730  forceEject(ejectDev);
731  return;
732  }
733 
734  DBG << "Request to release attached media "
735  << _mediaSource->asString()
736  << ", use count=" << _mediaSource.use_count()
737  << std::endl;
738 
739  if( _mediaSource.unique())
740  {
741  DBG << "Releasing media " << _mediaSource->asString() << std::endl;
742  try {
743  releaseFrom( ejectDev ); // pass to concrete handler
744  }
745  catch(const MediaNotEjectedException &e)
746  {
747  // not ejected because the media
748  // is mounted by somebody else
749  // (if our attach point is busy,
750  // we get an umount exception)
751  _mediaSource.reset(NULL);
753  // OK, retrow now
754  ZYPP_RETHROW(e);
755  }
756  _mediaSource.reset(NULL);
758  }
759  else if( !ejectDev.empty() ) {
760  //
761  // Can't eject a shared media
762  //
763  //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
764 
766  _mediaSource.reset(NULL);
767 
768  MediaManager manager;
769  manager.forceReleaseShared(media);
770 
771  setMediaSource(media);
772  DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
773  try {
774  releaseFrom( ejectDev ); // pass to concrete handler
775  }
776  catch(const MediaNotEjectedException &e)
777  {
778  // not ejected because the media
779  // is mounted by somebody else
780  // (if our attach point is busy,
781  // we get an umount exception)
782  _mediaSource.reset(NULL);
784  // OK, retrow now
785  ZYPP_RETHROW(e);
786  }
787  _mediaSource.reset(NULL);
789  }
790  else {
791  DBG << "Releasing shared media reference only" << std::endl;
792  _mediaSource.reset(NULL);
793  setAttachPoint("", true);
794  }
795  MIL << "Released: " << *this << endl;
796 }
797 
798 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
799 {
800  forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
801 }
802 
804  bool matchMountFs)
805 {
806  if( !ref)
807  return;
808 
809  MountEntries entries( MediaManager::getMountEntries());
810  MountEntries::const_iterator e;
811  for( e = entries.begin(); e != entries.end(); ++e)
812  {
813  bool is_device = false;
814  PathInfo dev_info;
815 
816  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
817  dev_info(e->src) && dev_info.isBlk())
818  {
819  is_device = true;
820  }
821 
822  if( is_device && ref->maj_nr)
823  {
824  std::string mtype(matchMountFs ? e->type : ref->type);
825  MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
826 
827  if( ref->equals( media) && e->type != "subfs")
828  {
829  DBG << "Forcing release of media device "
830  << ref->asString()
831  << " in the mount table as "
832  << e->src << std::endl;
833  try {
834  Mount mount;
835  mount.umount(e->dir);
836  }
837  catch (const Exception &e)
838  {
839  ZYPP_CAUGHT(e);
840  }
841  }
842  }
843  else
844  if(!is_device && !ref->maj_nr)
845  {
846  std::string mtype(matchMountFs ? e->type : ref->type);
847  MediaSource media(mtype, e->src);
848  if( ref->equals( media))
849  {
850  DBG << "Forcing release of media name "
851  << ref->asString()
852  << " in the mount table as "
853  << e->src << std::endl;
854  try {
855  Mount mount;
856  mount.umount(e->dir);
857  }
858  catch (const Exception &e)
859  {
860  ZYPP_CAUGHT(e);
861  }
862  }
863  }
864  }
865 }
866 
867 bool
868 MediaHandler::checkAttachPoint(const Pathname &apoint) const
869 {
870  return MediaHandler::checkAttachPoint( apoint, true, false);
871 }
872 
873 // STATIC
874 bool
875 MediaHandler::checkAttachPoint(const Pathname &apoint,
876  bool emptydir,
877  bool writeable)
878 {
879  if( apoint.empty() || !apoint.absolute())
880  {
881  ERR << "Attach point '" << apoint << "' is not absolute"
882  << std::endl;
883  return false;
884  }
885  if( apoint == "/")
886  {
887  ERR << "Attach point '" << apoint << "' is not allowed"
888  << std::endl;
889  return false;
890  }
891 
892  PathInfo ainfo(apoint);
893  if( !ainfo.isDir())
894  {
895  ERR << "Attach point '" << apoint << "' is not a directory"
896  << std::endl;
897  return false;
898  }
899 
900  if( emptydir)
901  {
902  if( 0 != zypp::filesystem::is_empty_dir(apoint))
903  {
904  ERR << "Attach point '" << apoint << "' is not a empty directory"
905  << std::endl;
906  return false;
907  }
908  }
909 
910  if( writeable)
911  {
912  Pathname apath(apoint + "XXXXXX");
913  char *atemp = ::strdup( apath.asString().c_str());
914  char *atest = NULL;
915  if( !ainfo.userMayRWX() || atemp == NULL ||
916  (atest=::mkdtemp(atemp)) == NULL)
917  {
918  if( atemp != NULL)
919  ::free(atemp);
920 
921  ERR << "Attach point '" << ainfo.path()
922  << "' is not a writeable directory" << std::endl;
923  return false;
924  }
925  else if( atest != NULL)
926  ::rmdir(atest);
927 
928  if( atemp != NULL)
929  ::free(atemp);
930  }
931  return true;
932 }
933 
935 //
936 // METHOD NAME : MediaHandler::dependsOnParent
937 // METHOD TYPE : bool
938 //
939 // DESCRIPTION :
940 //
941 bool
943 {
944  return _parentId != 0;
945 }
946 
947 bool
948 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
949 {
950  if( _parentId != 0)
951  {
952  if(parentId == _parentId)
953  return true;
954 
955  if( !exactIdMatch)
956  {
957  MediaManager mm;
959  AttachedMedia am2 = mm.getAttachedMedia(parentId);
960  if( am1.mediaSource && am2.mediaSource)
961  {
962  return am1.mediaSource->equals( *(am2.mediaSource));
963  }
964  }
965  }
966  return false;
967 }
968 
970 //
971 //
972 // METHOD NAME : MediaHandler::provideFile
973 // METHOD TYPE : PMError
974 //
975 // DESCRIPTION :
976 //
977 void MediaHandler::provideFileCopy( Pathname srcFilename,
978  Pathname targetFilename ) const
979 {
980  if ( !isAttached() ) {
981  INT << "Media not_attached on provideFileCopy(" << srcFilename
982  << "," << targetFilename << ")" << endl;
984  }
985 
986  getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
987  DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl;
988 }
989 
990 void MediaHandler::provideFile( Pathname filename ) const
991 {
992  if ( !isAttached() ) {
993  INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
995  }
996 
997  getFile( filename ); // pass to concrete handler
998  DBG << "provideFile(" << filename << ")" << endl;
999 }
1000 
1001 
1003 //
1004 //
1005 // METHOD NAME : MediaHandler::provideDir
1006 // METHOD TYPE : PMError
1007 //
1008 // DESCRIPTION :
1009 //
1010 void MediaHandler::provideDir( Pathname dirname ) const
1011 {
1012  if ( !isAttached() ) {
1013  INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
1015  }
1016 
1017  getDir( dirname, /*recursive*/false ); // pass to concrete handler
1018  MIL << "provideDir(" << dirname << ")" << endl;
1019 }
1020 
1022 //
1023 //
1024 // METHOD NAME : MediaHandler::provideDirTree
1025 // METHOD TYPE : PMError
1026 //
1027 // DESCRIPTION :
1028 //
1029 void MediaHandler::provideDirTree( Pathname dirname ) const
1030 {
1031  if ( !isAttached() ) {
1032  INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
1034  }
1035 
1036  getDir( dirname, /*recursive*/true ); // pass to concrete handler
1037  MIL << "provideDirTree(" << dirname << ")" << endl;
1038 }
1039 
1041 //
1042 //
1043 // METHOD NAME : MediaHandler::releasePath
1044 // METHOD TYPE : PMError
1045 //
1046 // DESCRIPTION :
1047 //
1048 void MediaHandler::releasePath( Pathname pathname ) const
1049 {
1050  if ( ! _does_download || _attachPoint->empty() )
1051  return;
1052 
1053  PathInfo info( localPath( pathname ) );
1054 
1055  if ( info.isFile() ) {
1056  unlink( info.path() );
1057  } else if ( info.isDir() ) {
1058  if ( info.path() != localRoot() ) {
1059  recursive_rmdir( info.path() );
1060  } else {
1061  clean_dir( info.path() );
1062  }
1063  }
1064 }
1065 
1067 //
1068 //
1069 // METHOD NAME : MediaHandler::dirInfo
1070 // METHOD TYPE : PMError
1071 //
1072 // DESCRIPTION :
1073 //
1074 void MediaHandler::dirInfo( std::list<std::string> & retlist,
1075  const Pathname & dirname, bool dots ) const
1076 {
1077  retlist.clear();
1078 
1079  if ( !isAttached() ) {
1080  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1082  }
1083 
1084  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1085  MIL << "dirInfo(" << dirname << ")" << endl;
1086 }
1087 
1089 //
1090 //
1091 // METHOD NAME : MediaHandler::dirInfo
1092 // METHOD TYPE : PMError
1093 //
1094 // DESCRIPTION :
1095 //
1097  const Pathname & dirname, bool dots ) const
1098 {
1099  retlist.clear();
1100 
1101  if ( !isAttached() ) {
1102  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1104  }
1105 
1106  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1107  MIL << "dirInfo(" << dirname << ")" << endl;
1108 }
1109 
1111 //
1112 //
1113 // METHOD NAME : MediaHandler::doesFileExist
1114 // METHOD TYPE : PMError
1115 //
1116 // DESCRIPTION :
1117 //
1118 bool MediaHandler::doesFileExist( const Pathname & filename ) const
1119 {
1120  // TODO do some logging
1121  if ( !isAttached() ) {
1122  INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
1124  }
1125  return getDoesFileExist( filename );
1126  MIL << "doesFileExist(" << filename << ")" << endl;
1127 }
1128 
1130 //
1131 //
1132 // METHOD NAME : MediaHandler::getDirectoryYast
1133 // METHOD TYPE : PMError
1134 //
1135 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
1136  const Pathname & dirname, bool dots ) const
1137 {
1138  retlist.clear();
1139 
1140  filesystem::DirContent content;
1141  getDirectoryYast( content, dirname, dots );
1142 
1143  // convert to std::list<std::string>
1144  for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1145  retlist.push_back( it->name );
1146  }
1147 }
1148 
1150 //
1151 //
1152 // METHOD NAME : MediaHandler::getDirectoryYast
1153 // METHOD TYPE : PMError
1154 //
1156  const Pathname & dirname, bool dots ) const
1157 {
1158  retlist.clear();
1159 
1160  // look for directory.yast
1161  Pathname dirFile = dirname + "directory.yast";
1162  getFile( dirFile );
1163  DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1164 
1165  // using directory.yast
1166  ifstream dir( localPath( dirFile ).asString().c_str() );
1167  if ( dir.fail() ) {
1168  ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl;
1170  "Unable to load '" + localPath( dirFile ).asString() + "'"));
1171  }
1172 
1173  string line;
1174  while( getline( dir, line ) ) {
1175  if ( line.empty() ) continue;
1176  if ( line == "directory.yast" ) continue;
1177 
1178  // Newer directory.yast append '/' to directory names
1179  // Remaining entries are unspecified, although most probabely files.
1181  if ( *line.rbegin() == '/' ) {
1182  line.erase( line.end()-1 );
1183  type = filesystem::FT_DIR;
1184  }
1185 
1186  if ( dots ) {
1187  if ( line == "." || line == ".." ) continue;
1188  } else {
1189  if ( *line.begin() == '.' ) continue;
1190  }
1191 
1192  retlist.push_back( filesystem::DirEntry( line, type ) );
1193  }
1194 }
1195 
1196 /******************************************************************
1197 **
1198 **
1199 ** FUNCTION NAME : operator<<
1200 ** FUNCTION TYPE : ostream &
1201 */
1202 ostream & operator<<( ostream & str, const MediaHandler & obj )
1203 {
1204  str << obj.url() << ( obj.isAttached() ? "" : " not" )
1205  << " attached; localRoot \"" << obj.localRoot() << "\"";
1206  return str;
1207 }
1208 
1210 //
1211 //
1212 // METHOD NAME : MediaHandler::getFile
1213 // METHOD TYPE : PMError
1214 //
1215 // DESCRIPTION : Asserted that media is attached.
1216 // Default implementation of pure virtual.
1217 //
1218 void MediaHandler::getFile( const Pathname & filename ) const
1219 {
1220  PathInfo info( localPath( filename ) );
1221  if( info.isFile() ) {
1222  return;
1223  }
1224 
1225  if (info.isExist())
1227  else
1229 }
1230 
1231 
1232 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
1233 {
1234  getFile(srcFilename);
1235 
1236  if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
1237  ZYPP_THROW(MediaWriteException(targetFilename));
1238  }
1239 }
1240 
1241 
1242 
1244 //
1245 //
1246 // METHOD NAME : MediaHandler::getDir
1247 // METHOD TYPE : PMError
1248 //
1249 // DESCRIPTION : Asserted that media is attached.
1250 // Default implementation of pure virtual.
1251 //
1252 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1253 {
1254  PathInfo info( localPath( dirname ) );
1255  if( info.isDir() ) {
1256  return;
1257  }
1258 
1259  if (info.isExist())
1261  else
1263 }
1264 
1266 //
1267 //
1268 // METHOD NAME : MediaHandler::getDirInfo
1269 // METHOD TYPE : PMError
1270 //
1271 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1272 // Default implementation of pure virtual.
1273 //
1274 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1275  const Pathname & dirname, bool dots ) const
1276 {
1277  PathInfo info( localPath( dirname ) );
1278  if( ! info.isDir() ) {
1280  }
1281 
1282 #if NONREMOTE_DIRECTORY_YAST
1283  // use directory.yast if available
1284  try {
1285  getDirectoryYast( retlist, dirname, dots );
1286  }
1287  catch (const MediaException & excpt_r)
1288  {
1289 #endif
1290 
1291  // readdir
1292  int res = readdir( retlist, info.path(), dots );
1293  if ( res )
1294  {
1295  MediaSystemException nexcpt(url(), "readdir failed");
1296 #if NONREMOTE_DIRECTORY_YAST
1297  nexcpt.remember(excpt_r);
1298 #endif
1299  ZYPP_THROW(nexcpt);
1300  }
1301 
1302 #if NONREMOTE_DIRECTORY_YAST
1303  }
1304 #endif
1305 
1306  return;
1307 }
1308 
1310 //
1311 //
1312 // METHOD NAME : MediaHandler::getDirInfo
1313 // METHOD TYPE : PMError
1314 //
1315 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1316 // Default implementation of pure virtual.
1317 //
1319  const Pathname & dirname, bool dots ) const
1320 {
1321  PathInfo info( localPath( dirname ) );
1322  if( ! info.isDir() ) {
1324  }
1325 
1326 #if NONREMOTE_DIRECTORY_YAST
1327  // use directory.yast if available
1328  try {
1329  getDirectoryYast( retlist, dirname, dots );
1330  }
1331  catch (const MediaException & excpt_r)
1332  {
1333 #endif
1334 
1335  // readdir
1336  int res = readdir( retlist, info.path(), dots );
1337  if ( res )
1338  {
1339  MediaSystemException nexcpt(url(), "readdir failed");
1340 #if NONREMOTE_DIRECTORY_YAST
1341  nexcpt.remember(excpt_r);
1342 #endif
1343  ZYPP_THROW(nexcpt);
1344  }
1345 #if NONREMOTE_DIRECTORY_YAST
1346  }
1347 #endif
1348 }
1349 
1351 //
1352 //
1353 // METHOD NAME : MediaHandler::getDoesFileExist
1354 // METHOD TYPE : PMError
1355 //
1356 // DESCRIPTION : Asserted that file is not a directory
1357 // Default implementation of pure virtual.
1358 //
1359 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1360 {
1361  PathInfo info( localPath( filename ) );
1362  if( info.isDir() ) {
1364  }
1365  return info.isExist();
1366 }
1367 
1369 {
1370  return false;
1371 }
1372 
1373 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
1374  unsigned int & index) const
1375 {
1376  // clear the vector by default
1377  if (!devices.empty())
1378  devices.clear();
1379  index = 0;
1380 
1381  DBG << "No devices for this medium" << endl;
1382 }
1383 
1384 void MediaHandler::setDeltafile( const Pathname & filename ) const
1385 {
1386  _deltafile = filename;
1387 }
1388 
1389 Pathname MediaHandler::deltafile() const {
1390  return _deltafile;
1391 }
1392 
1393  } // namespace media
1394 } // namespace zypp
1395 // vim: set ts=8 sts=2 sw=2 ai noet:
Attach point of a media source.
Definition: MediaSource.h:105
void resetParentId()
Called in case, where the media manager takes over the destruction of the parent id (e...
#define MIL
Definition: Logger.h:47
void provideFile(Pathname filename) const
Use concrete handler to provide file denoted by path below &#39;localRoot&#39;.
Listentry returned by readdir.
Definition: PathInfo.h:532
Interface to the mount program.
Definition: Mount.h:69
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:320
bool isSharedMedia() const
Returns a hint if the media is shared or not.
Pathname path() const
Definition: TmpPath.cc:146
virtual void getDir(const Pathname &dirname, bool recurse_r) const =0
Call concrete handler to provide directory content (not recursive!) below attach point.
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)
long use_count() const
Definition: PtrTypes.h:326
bool doesFileExist(const Pathname &filename) const
check if a file exists
#define INT
Definition: Logger.h:51
void setAttachPoint(const Pathname &path, bool temp)
Set a new attach point.
virtual void disconnectFrom()
Call concrete handler to disconnect media.
Definition: MediaHandler.h:325
Pathname createAttachPoint() const
Try to create a default / temporary attach point.
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:438
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:49
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:47
int is_empty_dir(const Pathname &path_r)
Check if the specified directory is empty.
Definition: PathInfo.cc:648
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:328
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, _Iterator begin, _Iterator 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:660
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.
const char * c_str() const
String representation.
Definition: Pathname.h:109
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:417
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:48
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:544
virtual bool hasMoreDevices()
Check if the media has one more device available for attach(true).
Pathname localPath(const Pathname &pathname) const
Files provided will be available at &#39;localPath(filename)&#39;.
bool isUseableAttachPoint(const Pathname &path, bool mtab=true) const
Ask media manager, if the specified path is already used as attach point or if there are another atta...
virtual bool isAttached() const
True if media is attached.
Definition: MediaHandler.h:523
AttachedMedia findAttachedMedia(const MediaSourceRef &media) const
void getDirectoryYast(std::list< std::string > &retlist, const Pathname &dirname, bool dots=true) const
Retrieve and if available scan dirname/directory.yast.
void removeAttachPoint()
Remove unused attach point.
void forceReleaseShared(const MediaSourceRef &media)
std::string asString(const Patch::SeverityFlag &obj)
Definition: Patch.cc:149
Media source internally used by MediaManager and MediaHandler.
Definition: MediaSource.h:36
AttachPoint _AttachPointHint
The user provided attach preferred point.
Definition: MediaHandler.h:85
bool unique() const
Definition: PtrTypes.h:323
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:324
virtual void forceEject(const std::string &device)
Call concrete handler to physically eject the media (i.e.
Definition: MediaHandler.h:347
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:599
int rmdir(const Pathname &path)
Like &#39;rmdir&#39;.
Definition: PathInfo.cc:371
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...
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
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:76
MediaAccessId _parentId
Access Id of media handler we depend on.
Definition: MediaHandler.h:115
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 (&quot;mounted&quot;).
Definition: MediaHandler.h:73
time_t _attach_mtime
timestamp of the the last attach verification
Definition: MediaHandler.h:101
void swap(RW_pointer &rhs)
Definition: PtrTypes.h:295
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 &#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:828
virtual void getDetectedDevices(std::vector< std::string > &devices, unsigned int &index) const
Fill in a vector of detected ejectable devices and the index of the currently attached device within ...
Url url() const
Url used.
Definition: MediaHandler.h:506
bool _does_download
True if concrete handler downloads files to the local filesystem.
Definition: MediaHandler.h:98
static time_t getMountTableMTime()
Get the modification time of the /etc/mtab file.
Url manipulation class.
Definition: Url.h:87
void umount(const std::string &path)
umount device
Definition: Mount.cc:162
#define DBG
Definition: Logger.h:46
static std::vector< MountEntry > getMountEntries()
Get current mount entries from /etc/mtab file.