libzypp  11.13.5
MediaHandler.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 #include <fstream>
15 #include <sstream>
16 
17 #include "zypp/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() || (getuid() != 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 
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  bool is_device = false;
533  PathInfo dev_info;
534 
535  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
536  dev_info(e->src) && dev_info.isBlk())
537  {
538  is_device = true;
539  }
540 
541  if( is_device && (ref.mediaSource->maj_nr &&
542  ref.mediaSource->bdir.empty()))
543  {
544  std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
545  MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
546 
547  if( ref.mediaSource->equals( media) &&
548  ref.attachPoint->path == Pathname(e->dir))
549  {
550  DBG << "Found media device "
551  << ref.mediaSource->asString()
552  << " in the mount table as " << e->src << std::endl;
553  _isAttached = true;
554  break;
555  }
556  // differs
557  }
558  else
559  if(!is_device && (!ref.mediaSource->maj_nr ||
560  !ref.mediaSource->bdir.empty()))
561  {
562  if( ref.mediaSource->bdir.empty())
563  {
564  // bnc#710269: Type nfs may appear as nfs4 in in the mount table
565  // and maybe vice versa. Similar cifs/smb. Need to unify these types:
566  if ( matchMountFs && e->type != ref.mediaSource->type )
567  {
568  if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) )
569  matchMountFs = false;
570  else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) )
571  matchMountFs = false;
572  }
573  std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
574  MediaSource media(mtype, e->src);
575 
576  if( ref.mediaSource->equals( media) &&
577  ref.attachPoint->path == Pathname(e->dir))
578  {
579  DBG << "Found media name "
580  << ref.mediaSource->asString()
581  << " in the mount table as " << e->src << std::endl;
582  _isAttached = true;
583  break;
584  }
585  }
586  else
587  {
588  if(ref.mediaSource->bdir == e->src &&
589  ref.attachPoint->path == Pathname(e->dir))
590  {
591  DBG << "Found bound media "
592  << ref.mediaSource->asString()
593  << " in the mount table as " << e->src << std::endl;
594  _isAttached = true;
595  break;
596  }
597  }
598  // differs
599  }
600  }
601 
602  if( !_isAttached)
603  {
604  MIL << "Looking for " << ref << endl;
605  if( entries.empty() )
606  {
607  ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
608  }
609  else
610  {
611  dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
612  }
613  if( old_mtime > 0 )
614  {
615  ERR << "Attached media not in mount table any more - forcing reset!"
616  << std::endl;
617 
619  }
620  else
621  {
622  WAR << "Attached media not in mount table ..." << std::endl;
623  }
624 
625  // reset the mtime and force a new check to make sure,
626  // that we've found the media at least once in the mtab.
627  _attach_mtime = 0;
628  }
629  }
630  }
631  return _isAttached;
632 }
633 
635 //
636 //
637 // METHOD NAME : MediaHandler::attach
638 // METHOD TYPE : PMError
639 //
640 // DESCRIPTION :
641 //
642 void MediaHandler::attach( bool next )
643 {
644  if ( isAttached() )
645  return;
646 
647  // reset it in case of overloaded isAttached()
648  // that checks the media against /etc/mtab ...
650 
652  setAttachPoint(ap.path, ap.temp);
653 
654  try
655  {
656  attachTo( next ); // pass to concrete handler
657  }
658  catch(const MediaException &e)
659  {
661  ZYPP_RETHROW(e);
662  }
663  MIL << "Attached: " << *this << endl;
664 }
665 
666 
668 //
669 //
670 // METHOD NAME : MediaHandler::localPath
671 // METHOD TYPE : Pathname
672 //
673 Pathname MediaHandler::localPath( const Pathname & pathname ) const
674 {
675  Pathname _localRoot( localRoot());
676  if ( _localRoot.empty() )
677  return _localRoot;
678 
679  // we must check maximum file name length
680  // this is important for fetching the suseservers, the
681  // url with all parameters can get too long (bug #42021)
682 
683  return _localRoot + pathname.absolutename();
684 }
685 
686 
687 
688 
689 
691 //
692 //
693 // METHOD NAME : MediaHandler::disconnect
694 // METHOD TYPE : PMError
695 //
697 {
698  if ( !isAttached() )
699  return;
700 
701  disconnectFrom(); // pass to concrete handler
702  MIL << "Disconnected: " << *this << endl;
703 }
704 
706 //
707 //
708 // METHOD NAME : MediaHandler::release
709 // METHOD TYPE : PMError
710 //
711 // DESCRIPTION :
712 //
713 void MediaHandler::release( const std::string & ejectDev )
714 {
715  if ( !isAttached() ) {
716  DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
717  << std::endl;
718  if ( !ejectDev.empty() )
719  forceEject(ejectDev);
720  return;
721  }
722 
723  DBG << "Request to release attached media "
724  << _mediaSource->asString()
725  << ", use count=" << _mediaSource.use_count()
726  << std::endl;
727 
728  if( _mediaSource.unique())
729  {
730  DBG << "Releasing media " << _mediaSource->asString() << std::endl;
731  try {
732  releaseFrom( ejectDev ); // pass to concrete handler
733  }
734  catch(const MediaNotEjectedException &e)
735  {
736  // not ejected because the media
737  // is mounted by somebody else
738  // (if our attach point is busy,
739  // we get an umount exception)
740  _mediaSource.reset(NULL);
742  // OK, retrow now
743  ZYPP_RETHROW(e);
744  }
745  _mediaSource.reset(NULL);
747  }
748  else if( !ejectDev.empty() ) {
749  //
750  // Can't eject a shared media
751  //
752  //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
753 
755  _mediaSource.reset(NULL);
756 
757  MediaManager manager;
758  manager.forceReleaseShared(media);
759 
760  setMediaSource(media);
761  DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
762  try {
763  releaseFrom( ejectDev ); // pass to concrete handler
764  }
765  catch(const MediaNotEjectedException &e)
766  {
767  // not ejected because the media
768  // is mounted by somebody else
769  // (if our attach point is busy,
770  // we get an umount exception)
771  _mediaSource.reset(NULL);
773  // OK, retrow now
774  ZYPP_RETHROW(e);
775  }
776  _mediaSource.reset(NULL);
778  }
779  else {
780  DBG << "Releasing shared media reference only" << std::endl;
781  _mediaSource.reset(NULL);
782  setAttachPoint("", true);
783  }
784  MIL << "Released: " << *this << endl;
785 }
786 
787 void MediaHandler::forceRelaseAllMedia(bool matchMountFs)
788 {
789  forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs);
790 }
791 
793  bool matchMountFs)
794 {
795  if( !ref)
796  return;
797 
798  MountEntries entries( MediaManager::getMountEntries());
799  MountEntries::const_iterator e;
800  for( e = entries.begin(); e != entries.end(); ++e)
801  {
802  bool is_device = false;
803  PathInfo dev_info;
804 
805  if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
806  dev_info(e->src) && dev_info.isBlk())
807  {
808  is_device = true;
809  }
810 
811  if( is_device && ref->maj_nr)
812  {
813  std::string mtype(matchMountFs ? e->type : ref->type);
814  MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
815 
816  if( ref->equals( media) && e->type != "subfs")
817  {
818  DBG << "Forcing release of media device "
819  << ref->asString()
820  << " in the mount table as "
821  << e->src << std::endl;
822  try {
823  Mount mount;
824  mount.umount(e->dir);
825  }
826  catch (const Exception &e)
827  {
828  ZYPP_CAUGHT(e);
829  }
830  }
831  }
832  else
833  if(!is_device && !ref->maj_nr)
834  {
835  std::string mtype(matchMountFs ? e->type : ref->type);
836  MediaSource media(mtype, e->src);
837  if( ref->equals( media))
838  {
839  DBG << "Forcing release of media name "
840  << ref->asString()
841  << " in the mount table as "
842  << e->src << std::endl;
843  try {
844  Mount mount;
845  mount.umount(e->dir);
846  }
847  catch (const Exception &e)
848  {
849  ZYPP_CAUGHT(e);
850  }
851  }
852  }
853  }
854 }
855 
856 bool
857 MediaHandler::checkAttachPoint(const Pathname &apoint) const
858 {
859  return MediaHandler::checkAttachPoint( apoint, true, false);
860 }
861 
862 // STATIC
863 bool
864 MediaHandler::checkAttachPoint(const Pathname &apoint,
865  bool emptydir,
866  bool writeable)
867 {
868  if( apoint.empty() || !apoint.absolute())
869  {
870  ERR << "Attach point '" << apoint << "' is not absolute"
871  << std::endl;
872  return false;
873  }
874  if( apoint == "/")
875  {
876  ERR << "Attach point '" << apoint << "' is not allowed"
877  << std::endl;
878  return false;
879  }
880 
881  PathInfo ainfo(apoint);
882  if( !ainfo.isDir())
883  {
884  ERR << "Attach point '" << apoint << "' is not a directory"
885  << std::endl;
886  return false;
887  }
888 
889  if( emptydir)
890  {
891  if( 0 != zypp::filesystem::is_empty_dir(apoint))
892  {
893  ERR << "Attach point '" << apoint << "' is not a empty directory"
894  << std::endl;
895  return false;
896  }
897  }
898 
899  if( writeable)
900  {
901  Pathname apath(apoint + "XXXXXX");
902  char *atemp = ::strdup( apath.asString().c_str());
903  char *atest = NULL;
904  if( !ainfo.userMayRWX() || atemp == NULL ||
905  (atest=::mkdtemp(atemp)) == NULL)
906  {
907  if( atemp != NULL)
908  ::free(atemp);
909 
910  ERR << "Attach point '" << ainfo.path()
911  << "' is not a writeable directory" << std::endl;
912  return false;
913  }
914  else if( atest != NULL)
915  ::rmdir(atest);
916 
917  if( atemp != NULL)
918  ::free(atemp);
919  }
920  return true;
921 }
922 
924 //
925 // METHOD NAME : MediaHandler::dependsOnParent
926 // METHOD TYPE : bool
927 //
928 // DESCRIPTION :
929 //
930 bool
932 {
933  return _parentId != 0;
934 }
935 
936 bool
937 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
938 {
939  if( _parentId != 0)
940  {
941  if(parentId == _parentId)
942  return true;
943 
944  if( !exactIdMatch)
945  {
946  MediaManager mm;
948  AttachedMedia am2 = mm.getAttachedMedia(parentId);
949  if( am1.mediaSource && am2.mediaSource)
950  {
951  return am1.mediaSource->equals( *(am2.mediaSource));
952  }
953  }
954  }
955  return false;
956 }
957 
959 //
960 //
961 // METHOD NAME : MediaHandler::provideFile
962 // METHOD TYPE : PMError
963 //
964 // DESCRIPTION :
965 //
966 void MediaHandler::provideFileCopy( Pathname srcFilename,
967  Pathname targetFilename ) const
968 {
969  if ( !isAttached() ) {
970  INT << "Media not_attached on provideFileCopy(" << srcFilename
971  << "," << targetFilename << ")" << endl;
973  }
974 
975  getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
976  DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl;
977 }
978 
979 void MediaHandler::provideFile( Pathname filename ) const
980 {
981  if ( !isAttached() ) {
982  INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
984  }
985 
986  getFile( filename ); // pass to concrete handler
987  DBG << "provideFile(" << filename << ")" << endl;
988 }
989 
990 
992 //
993 //
994 // METHOD NAME : MediaHandler::provideDir
995 // METHOD TYPE : PMError
996 //
997 // DESCRIPTION :
998 //
999 void MediaHandler::provideDir( Pathname dirname ) const
1000 {
1001  if ( !isAttached() ) {
1002  INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
1004  }
1005 
1006  getDir( dirname, /*recursive*/false ); // pass to concrete handler
1007  MIL << "provideDir(" << dirname << ")" << endl;
1008 }
1009 
1011 //
1012 //
1013 // METHOD NAME : MediaHandler::provideDirTree
1014 // METHOD TYPE : PMError
1015 //
1016 // DESCRIPTION :
1017 //
1018 void MediaHandler::provideDirTree( Pathname dirname ) const
1019 {
1020  if ( !isAttached() ) {
1021  INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
1023  }
1024 
1025  getDir( dirname, /*recursive*/true ); // pass to concrete handler
1026  MIL << "provideDirTree(" << dirname << ")" << endl;
1027 }
1028 
1030 //
1031 //
1032 // METHOD NAME : MediaHandler::releasePath
1033 // METHOD TYPE : PMError
1034 //
1035 // DESCRIPTION :
1036 //
1037 void MediaHandler::releasePath( Pathname pathname ) const
1038 {
1039  if ( ! _does_download || _attachPoint->empty() )
1040  return;
1041 
1042  PathInfo info( localPath( pathname ) );
1043 
1044  if ( info.isFile() ) {
1045  unlink( info.path() );
1046  } else if ( info.isDir() ) {
1047  if ( info.path() != localRoot() ) {
1048  recursive_rmdir( info.path() );
1049  } else {
1050  clean_dir( info.path() );
1051  }
1052  }
1053 }
1054 
1056 //
1057 //
1058 // METHOD NAME : MediaHandler::dirInfo
1059 // METHOD TYPE : PMError
1060 //
1061 // DESCRIPTION :
1062 //
1063 void MediaHandler::dirInfo( std::list<std::string> & retlist,
1064  const Pathname & dirname, bool dots ) const
1065 {
1066  retlist.clear();
1067 
1068  if ( !isAttached() ) {
1069  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1071  }
1072 
1073  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1074  MIL << "dirInfo(" << dirname << ")" << endl;
1075 }
1076 
1078 //
1079 //
1080 // METHOD NAME : MediaHandler::dirInfo
1081 // METHOD TYPE : PMError
1082 //
1083 // DESCRIPTION :
1084 //
1086  const Pathname & dirname, bool dots ) const
1087 {
1088  retlist.clear();
1089 
1090  if ( !isAttached() ) {
1091  INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
1093  }
1094 
1095  getDirInfo( retlist, dirname, dots ); // pass to concrete handler
1096  MIL << "dirInfo(" << dirname << ")" << endl;
1097 }
1098 
1100 //
1101 //
1102 // METHOD NAME : MediaHandler::doesFileExist
1103 // METHOD TYPE : PMError
1104 //
1105 // DESCRIPTION :
1106 //
1107 bool MediaHandler::doesFileExist( const Pathname & filename ) const
1108 {
1109  // TODO do some logging
1110  if ( !isAttached() ) {
1111  INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
1113  }
1114  return getDoesFileExist( filename );
1115  MIL << "doesFileExist(" << filename << ")" << endl;
1116 }
1117 
1119 //
1120 //
1121 // METHOD NAME : MediaHandler::getDirectoryYast
1122 // METHOD TYPE : PMError
1123 //
1124 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
1125  const Pathname & dirname, bool dots ) const
1126 {
1127  retlist.clear();
1128 
1129  filesystem::DirContent content;
1130  getDirectoryYast( content, dirname, dots );
1131 
1132  // convert to std::list<std::string>
1133  for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
1134  retlist.push_back( it->name );
1135  }
1136 }
1137 
1139 //
1140 //
1141 // METHOD NAME : MediaHandler::getDirectoryYast
1142 // METHOD TYPE : PMError
1143 //
1145  const Pathname & dirname, bool dots ) const
1146 {
1147  retlist.clear();
1148 
1149  // look for directory.yast
1150  Pathname dirFile = dirname + "directory.yast";
1151  getFile( dirFile );
1152  DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
1153 
1154  // using directory.yast
1155  ifstream dir( localPath( dirFile ).asString().c_str() );
1156  if ( dir.fail() ) {
1157  ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl;
1159  "Unable to load '" + localPath( dirFile ).asString() + "'"));
1160  }
1161 
1162  string line;
1163  while( getline( dir, line ) ) {
1164  if ( line.empty() ) continue;
1165  if ( line == "directory.yast" ) continue;
1166 
1167  // Newer directory.yast append '/' to directory names
1168  // Remaining entries are unspecified, although most probabely files.
1170  if ( *line.rbegin() == '/' ) {
1171  line.erase( line.end()-1 );
1172  type = filesystem::FT_DIR;
1173  }
1174 
1175  if ( dots ) {
1176  if ( line == "." || line == ".." ) continue;
1177  } else {
1178  if ( *line.begin() == '.' ) continue;
1179  }
1180 
1181  retlist.push_back( filesystem::DirEntry( line, type ) );
1182  }
1183 }
1184 
1185 /******************************************************************
1186 **
1187 **
1188 ** FUNCTION NAME : operator<<
1189 ** FUNCTION TYPE : ostream &
1190 */
1191 ostream & operator<<( ostream & str, const MediaHandler & obj )
1192 {
1193  str << obj.url() << ( obj.isAttached() ? "" : " not" )
1194  << " attached; localRoot \"" << obj.localRoot() << "\"";
1195  return str;
1196 }
1197 
1199 //
1200 //
1201 // METHOD NAME : MediaHandler::getFile
1202 // METHOD TYPE : PMError
1203 //
1204 // DESCRIPTION : Asserted that media is attached.
1205 // Default implementation of pure virtual.
1206 //
1207 void MediaHandler::getFile( const Pathname & filename ) const
1208 {
1209  PathInfo info( localPath( filename ) );
1210  if( info.isFile() ) {
1211  return;
1212  }
1213 
1214  if (info.isExist())
1216  else
1218 }
1219 
1220 
1221 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
1222 {
1223  getFile(srcFilename);
1224 
1225  if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
1226  ZYPP_THROW(MediaWriteException(targetFilename));
1227  }
1228 }
1229 
1230 
1231 
1233 //
1234 //
1235 // METHOD NAME : MediaHandler::getDir
1236 // METHOD TYPE : PMError
1237 //
1238 // DESCRIPTION : Asserted that media is attached.
1239 // Default implementation of pure virtual.
1240 //
1241 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
1242 {
1243  PathInfo info( localPath( dirname ) );
1244  if( info.isDir() ) {
1245  return;
1246  }
1247 
1248  if (info.isExist())
1250  else
1252 }
1253 
1255 //
1256 //
1257 // METHOD NAME : MediaHandler::getDirInfo
1258 // METHOD TYPE : PMError
1259 //
1260 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1261 // Default implementation of pure virtual.
1262 //
1263 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
1264  const Pathname & dirname, bool dots ) const
1265 {
1266  PathInfo info( localPath( dirname ) );
1267  if( ! info.isDir() ) {
1269  }
1270 
1271 #if NONREMOTE_DIRECTORY_YAST
1272  // use directory.yast if available
1273  try {
1274  getDirectoryYast( retlist, dirname, dots );
1275  }
1276  catch (const MediaException & excpt_r)
1277  {
1278 #endif
1279 
1280  // readdir
1281  int res = readdir( retlist, info.path(), dots );
1282  if ( res )
1283  {
1284  MediaSystemException nexcpt(url(), "readdir failed");
1285 #if NONREMOTE_DIRECTORY_YAST
1286  nexcpt.remember(excpt_r);
1287 #endif
1288  ZYPP_THROW(nexcpt);
1289  }
1290 
1291 #if NONREMOTE_DIRECTORY_YAST
1292  }
1293 #endif
1294 
1295  return;
1296 }
1297 
1299 //
1300 //
1301 // METHOD NAME : MediaHandler::getDirInfo
1302 // METHOD TYPE : PMError
1303 //
1304 // DESCRIPTION : Asserted that media is attached and retlist is empty.
1305 // Default implementation of pure virtual.
1306 //
1308  const Pathname & dirname, bool dots ) const
1309 {
1310  PathInfo info( localPath( dirname ) );
1311  if( ! info.isDir() ) {
1313  }
1314 
1315 #if NONREMOTE_DIRECTORY_YAST
1316  // use directory.yast if available
1317  try {
1318  getDirectoryYast( retlist, dirname, dots );
1319  }
1320  catch (const MediaException & excpt_r)
1321  {
1322 #endif
1323 
1324  // readdir
1325  int res = readdir( retlist, info.path(), dots );
1326  if ( res )
1327  {
1328  MediaSystemException nexcpt(url(), "readdir failed");
1329 #if NONREMOTE_DIRECTORY_YAST
1330  nexcpt.remember(excpt_r);
1331 #endif
1332  ZYPP_THROW(nexcpt);
1333  }
1334 #if NONREMOTE_DIRECTORY_YAST
1335  }
1336 #endif
1337 }
1338 
1340 //
1341 //
1342 // METHOD NAME : MediaHandler::getDoesFileExist
1343 // METHOD TYPE : PMError
1344 //
1345 // DESCRIPTION : Asserted that file is not a directory
1346 // Default implementation of pure virtual.
1347 //
1348 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
1349 {
1350  PathInfo info( localPath( filename ) );
1351  if( info.isDir() ) {
1353  }
1354  return info.isExist();
1355 }
1356 
1358 {
1359  return false;
1360 }
1361 
1362 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
1363  unsigned int & index) const
1364 {
1365  // clear the vector by default
1366  if (!devices.empty())
1367  devices.clear();
1368  index = 0;
1369 
1370  DBG << "No devices for this medium" << endl;
1371 }
1372 
1373 void MediaHandler::setDeltafile( const Pathname & filename ) const
1374 {
1375  _deltafile = filename;
1376 }
1377 
1378 Pathname MediaHandler::deltafile() const {
1379  return _deltafile;
1380 }
1381 
1382  } // namespace media
1383 } // namespace zypp
1384 // vim: set ts=8 sts=2 sw=2 ai noet: