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