MediaHandler.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00013 #include <iostream>
00014 #include <fstream>
00015 #include <sstream>
00016 
00017 #include "zypp/TmpPath.h"
00018 #include "zypp/base/LogTools.h"
00019 #include "zypp/base/String.h"
00020 #include "zypp/media/MediaHandler.h"
00021 #include "zypp/media/MediaManager.h"
00022 #include "zypp/media/Mount.h"
00023 #include <limits.h>
00024 #include <stdlib.h>
00025 #include <errno.h>
00026 
00027 
00028 using namespace std;
00029 
00030 // use directory.yast on every media (not just via ftp/http)
00031 #define NONREMOTE_DIRECTORY_YAST 1
00032 
00033 namespace zypp {
00034   namespace media {
00035 
00036   Pathname MediaHandler::_attachPrefix("");
00037 
00039 //
00040 //      CLASS NAME : MediaHandler
00041 //
00043 
00045 //
00046 //
00047 //      METHOD NAME : MediaHandler::MediaHandler
00048 //      METHOD TYPE : Constructor
00049 //
00050 //      DESCRIPTION :
00051 //
00052 MediaHandler::MediaHandler ( const Url &      url_r,
00053                              const Pathname & attach_point_r,
00054                              const Pathname & urlpath_below_attachpoint_r,
00055                              const bool       does_download_r )
00056     : _mediaSource()
00057     , _attachPoint( new AttachPoint())
00058     , _AttachPointHint()
00059     , _relativeRoot( urlpath_below_attachpoint_r)
00060     , _does_download( does_download_r )
00061     , _attach_mtime(0)
00062     , _url( url_r )
00063     , _parentId(0)
00064 {
00065   Pathname real_attach_point( getRealPath(attach_point_r.asString()));
00066 
00067   if ( !real_attach_point.empty() ) {
00069     // check if provided attachpoint is usable.
00071 
00072     PathInfo adir( real_attach_point );
00073     //
00074     // The verify if attach_point_r isn't a mountpoint of another
00075     // device is done in the particular media handler (if needed).
00076     //
00077     // We just verify, if attach_point_r is a directory and for
00078     // schemes other than "file" and "dir", if it is absolute.
00079     //
00080     if ( !adir.isDir()
00081          || (_url.getScheme() != "file"
00082              && _url.getScheme() != "dir"
00083              && !real_attach_point.absolute()) )
00084     {
00085       ERR << "Provided attach point is not a absolute directory: "
00086           << adir << endl;
00087     }
00088     else {
00089       attachPointHint( real_attach_point, false);
00090       setAttachPoint( real_attach_point, false);
00091     }
00092   }
00093 }
00094 
00096 //
00097 //
00098 //      METHOD NAME : MediaHandler::~MediaHandler
00099 //      METHOD TYPE : Destructor
00100 //
00101 //      DESCRIPTION :
00102 //
00103 MediaHandler::~MediaHandler()
00104 {
00105   try
00106     {
00107       removeAttachPoint();
00108     }
00109   catch(...) {}
00110 }
00111 
00112 void
00113 MediaHandler::resetParentId()
00114 {
00115   _parentId = 0;
00116 }
00117 
00118 std::string
00119 MediaHandler::getRealPath(const std::string &path)
00120 {
00121   std::string real;
00122   if( !path.empty())
00123   {
00124 #if __GNUC__ > 2
00125 
00126     char *ptr = ::realpath(path.c_str(), NULL);
00127     if( ptr != NULL)
00128     {
00129       real = ptr;
00130       free( ptr);
00131     }
00132     else
00134     if( EINVAL == errno)
00135     {
00136       char buff[PATH_MAX + 2];
00137       memset(buff, '\0', sizeof(buff));
00138       if( ::realpath(path.c_str(), buff) != NULL)
00139       {
00140         real = buff;
00141       }
00142     }
00143 #else
00144     char buff[PATH_MAX + 2];
00145     memset(buff, '\0', sizeof(buff));
00146     if( ::realpath(path.c_str(), buff) != NULL)
00147     {
00148       real = buff;
00149     }
00150 #endif
00151   }
00152   return real;
00153 }
00154 
00155 zypp::Pathname
00156 MediaHandler::getRealPath(const Pathname &path)
00157 {
00158   return zypp::Pathname(getRealPath(path.asString()));
00159 }
00160 
00161 
00163 //
00164 //
00165 //      METHOD NAME : MediaHandler::removeAttachPoint
00166 //      METHOD TYPE : void
00167 //
00168 //      DESCRIPTION :
00169 //
00170 void
00171 MediaHandler::removeAttachPoint()
00172 {
00173   if ( _mediaSource ) {
00174     INT << "MediaHandler deleted with media attached." << endl;
00175     return; // no cleanup if media still mounted!
00176   }
00177 
00178   DBG << "MediaHandler - checking if to remove attach point" << endl;
00179   if ( _attachPoint.unique() &&
00180        _attachPoint->temp    &&
00181        !_attachPoint->path.empty() &&
00182        PathInfo(_attachPoint->path).isDir())
00183   {
00184     Pathname path(_attachPoint->path);
00185 
00186     setAttachPoint("", true);
00187 
00188     int res = recursive_rmdir( path );
00189     if ( res == 0 ) {
00190       MIL << "Deleted default attach point " << path << endl;
00191     } else {
00192       ERR << "Failed to Delete default attach point " << path
00193         << " errno(" << res << ")" << endl;
00194     }
00195   }
00196   else
00197   {
00198     if( !_attachPoint->path.empty() && !_attachPoint->temp)
00199       DBG << "MediaHandler - attachpoint is not temporary" << endl;
00200   }
00201 }
00202 
00203 
00205 //
00206 //
00207 //      METHOD NAME : MediaHandler::attachPoint
00208 //      METHOD TYPE : Pathname
00209 //
00210 //      DESCRIPTION :
00211 //
00212 Pathname
00213 MediaHandler::attachPoint() const
00214 {
00215   return _attachPoint->path;
00216 }
00217 
00218 
00220 //
00221 //
00222 //      METHOD NAME : MediaHandler::attachPoint
00223 //      METHOD TYPE :
00224 //
00225 //      DESCRIPTION :
00226 //
00227 void
00228 MediaHandler::setAttachPoint(const Pathname &path, bool temporary)
00229 {
00230   _attachPoint.reset( new AttachPoint(path, temporary));
00231 }
00232 
00233 Pathname
00234 MediaHandler::localRoot() const
00235 {
00236   if( _attachPoint->path.empty())
00237     return Pathname();
00238   else
00239     return _attachPoint->path + _relativeRoot;
00240 }
00241 
00243 //
00244 //
00245 //      METHOD NAME : MediaHandler::attachPoint
00246 //      METHOD TYPE :
00247 //
00248 //      DESCRIPTION :
00249 //
00250 void
00251 MediaHandler::setAttachPoint(const AttachPointRef &ref)
00252 {
00253   if( ref)
00254     AttachPointRef(ref).swap(_attachPoint);
00255   else
00256     _attachPoint.reset( new AttachPoint());
00257 }
00258 
00260 //
00261 //
00262 //      METHOD NAME : MediaHandler::attachPointHint
00263 //      METHOD TYPE : void
00264 //
00265 //      DESCRIPTION :
00266 //
00267 void
00268 MediaHandler::attachPointHint(const Pathname &path, bool temporary)
00269 {
00270   _AttachPointHint.path = path;
00271   _AttachPointHint.temp = temporary;
00272 }
00273 
00275 //
00276 //
00277 //      METHOD NAME : MediaHandler::attachPointHint
00278 //      METHOD TYPE : AttachPoint
00279 //
00280 //      DESCRIPTION :
00281 //
00282 AttachPoint
00283 MediaHandler::attachPointHint() const
00284 {
00285   return _AttachPointHint;
00286 }
00287 
00289 //
00290 //
00291 //      METHOD NAME : MediaHandler::findAttachedMedia
00292 //      METHOD TYPE : AttachedMedia
00293 //
00294 //      DESCRIPTION :
00295 //
00296 AttachedMedia
00297 MediaHandler::findAttachedMedia(const MediaSourceRef &media) const
00298 {
00299         return MediaManager().findAttachedMedia(media);
00300 }
00301 
00303 //
00304 //
00305 //      METHOD NAME : MediaHandler::setAttachPrefix
00306 //      METHOD TYPE : void
00307 //
00308 //      DESCRIPTION :
00309 //
00310 bool
00311 MediaHandler::setAttachPrefix(const Pathname &attach_prefix)
00312 {
00313   if( attach_prefix.empty())
00314   {
00315     MIL << "Reseting to built-in attach point prefixes."
00316         << std::endl;
00317     MediaHandler::_attachPrefix = attach_prefix;
00318     return true;
00319   }
00320   else
00321   if( MediaHandler::checkAttachPoint(attach_prefix, false, true))
00322   {
00323     MIL << "Setting user defined attach point prefix: "
00324         << attach_prefix << std::endl;
00325     MediaHandler::_attachPrefix = attach_prefix;
00326     return true;
00327   }
00328   return false;
00329 }
00330 
00332 //
00333 //
00334 //      METHOD NAME : MediaHandler::attach
00335 //      METHOD TYPE : Pathname
00336 //
00337 //      DESCRIPTION :
00338 //
00339 Pathname
00340 MediaHandler::createAttachPoint() const
00341 {
00343   // provide a default (temporary) attachpoint
00345   const char * defmounts[] = {
00346       "/var/adm/mount", filesystem::TmpPath::defaultLocation().c_str(), NULL
00347   };
00348 
00349   Pathname apoint;
00350   Pathname aroot( MediaHandler::_attachPrefix);
00351 
00352   if( !aroot.empty())
00353   {
00354     apoint = createAttachPoint(aroot);
00355   }
00356   for ( const char ** def = defmounts; *def && apoint.empty(); ++def ) {
00357     aroot = *def;
00358     if( aroot.empty())
00359       continue;
00360 
00361     apoint = createAttachPoint(aroot);
00362   }
00363 
00364   if ( aroot.empty() ) {
00365     ERR << "Create attach point: Can't find a writable directory to create an attach point" << std::endl;
00366     return aroot;
00367   }
00368 
00369   if ( !apoint.empty() ) {
00370     MIL << "Created default attach point " << apoint << std::endl;
00371   }
00372   return apoint;
00373 }
00374 
00375 Pathname
00376 MediaHandler::createAttachPoint(const Pathname &attach_root) const
00377 {
00378   Pathname apoint;
00379 
00380   if( attach_root.empty() || !attach_root.absolute()) {
00381     ERR << "Create attach point: invalid attach root: '"
00382         << attach_root << "'" << std::endl;
00383     return apoint;
00384   }
00385 
00386   PathInfo adir( attach_root);
00387   if( !adir.isDir() || (getuid() != 0 && !adir.userMayRWX())) {
00388     DBG << "Create attach point: attach root is not a writable directory: '"
00389         << attach_root << "'" << std::endl;
00390     return apoint;
00391   }
00392 
00393   DBG << "Trying to create attach point in " << attach_root << std::endl;
00394 
00395   //
00396   // FIXME: use mkdtemp?
00397   //
00398 #warning Use class TmpDir from TmpPath.h
00399   Pathname abase( attach_root + "AP_" );
00400   //        ma and sh need more than 42 for debugging :-)
00401   //        since the readonly fs are handled now, ...
00402   for ( unsigned i = 1; i < 1000; ++i ) {
00403     adir( Pathname::extend( abase, str::hexstring( i ) ) );
00404     if ( ! adir.isExist() ) {
00405       int err = mkdir( adir.path() );
00406       if (err == 0 ) {
00407         apoint = getRealPath(adir.asString());
00408         if( apoint.empty())
00409         {
00410           ERR << "Unable to resolve a real path for "
00411               << adir.path() << std::endl;
00412           rmdir(adir.path());
00413         }
00414         break;
00415       }
00416       else
00417       if (err != EEXIST)        // readonly fs or other, dont try further
00418         break;
00419     }
00420   }
00421 
00422   if ( apoint.empty()) {
00423     ERR << "Unable to create an attach point below of "
00424         << attach_root << std::endl;
00425   }
00426   return apoint;
00427 }
00428 
00430 //
00431 //
00432 //      METHOD NAME : MediaHandler::isUseableAttachPoint
00433 //      METHOD TYPE : bool
00434 //
00435 //      DESCRIPTION :
00436 //
00437 bool
00438 MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const
00439 {
00440   MediaManager  manager;
00441   return manager.isUseableAttachPoint(path, mtab);
00442 }
00443 
00444 
00446 //
00447 //
00448 //      METHOD NAME : MediaHandler::setMediaSource
00449 //      METHOD TYPE : void
00450 //
00451 //      DESCRIPTION :
00452 //
00453 void
00454 MediaHandler::setMediaSource(const MediaSourceRef &ref)
00455 {
00456   _mediaSource.reset();
00457   if( ref && !ref->type.empty() && !ref->name.empty())
00458     _mediaSource = ref;
00459 }
00460 
00462 //
00463 //
00464 //      METHOD NAME : MediaHandler::attachedMedia
00465 //      METHOD TYPE : AttachedMedia
00466 //
00467 //      DESCRIPTION :
00468 //
00469 AttachedMedia
00470 MediaHandler::attachedMedia() const
00471 {
00472   if ( _mediaSource && _attachPoint)
00473     return AttachedMedia(_mediaSource, _attachPoint);
00474   else
00475     return AttachedMedia();
00476 }
00477 
00479 //
00480 //
00481 //      METHOD NAME : MediaHandler::isSharedMedia
00482 //      METHOD TYPE : bool
00483 //
00484 //      DESCRIPTION :
00485 //
00486 bool
00487 MediaHandler::isSharedMedia() const
00488 {
00489   return !_mediaSource.unique();
00490 }
00491 
00493 //
00494 //
00495 //      METHOD NAME : MediaHandler::checkAttached
00496 //      METHOD TYPE : bool
00497 //
00498 //      DESCRIPTION :
00499 //
00500 bool
00501 MediaHandler::checkAttached(bool matchMountFs) const
00502 {
00503   bool _isAttached = false;
00504 
00505   AttachedMedia ref( attachedMedia());
00506   if( ref.mediaSource )
00507   {
00508     time_t old_mtime = _attach_mtime;
00509     _attach_mtime = MediaManager::getMountTableMTime();
00510     if( !(old_mtime <= 0 || _attach_mtime != old_mtime) )
00511     {
00512       // OK, skip the check (we've seen it at least once)
00513       _isAttached = true;
00514     }
00515     else
00516     {
00517       if( old_mtime > 0)
00518         DBG << "Mount table changed - rereading it" << std::endl;
00519       else
00520         DBG << "Forced check of the mount table" << std::endl;
00521 
00522       MountEntries entries( MediaManager::getMountEntries());
00523       for_( e, entries.begin(), entries.end() )
00524       {
00525         bool        is_device = false;
00526         PathInfo    dev_info;
00527 
00528         if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
00529             dev_info(e->src) && dev_info.isBlk())
00530         {
00531           is_device = true;
00532         }
00533 
00534         if( is_device &&  (ref.mediaSource->maj_nr &&
00535                            ref.mediaSource->bdir.empty()))
00536         {
00537           std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
00538           MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
00539 
00540           if( ref.mediaSource->equals( media) &&
00541               ref.attachPoint->path == Pathname(e->dir))
00542           {
00543             DBG << "Found media device "
00544                 << ref.mediaSource->asString()
00545                 << " in the mount table as " << e->src << std::endl;
00546             _isAttached = true;
00547             break;
00548           }
00549           // differs
00550         }
00551         else
00552         if(!is_device && (!ref.mediaSource->maj_nr ||
00553                           !ref.mediaSource->bdir.empty()))
00554         {
00555           if( ref.mediaSource->bdir.empty())
00556           {
00557             // bnc#710269: Type nfs may appear as nfs4 in in the mount table
00558             // and maybe vice versa. Similar cifs/smb. Need to unify these types:
00559             if ( matchMountFs && e->type != ref.mediaSource->type )
00560             {
00561               if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) )
00562                 matchMountFs = false;
00563               else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) )
00564                 matchMountFs = false;
00565             }
00566             std::string mtype(matchMountFs ? e->type : ref.mediaSource->type);
00567             MediaSource media(mtype, e->src);
00568 
00569             if( ref.mediaSource->equals( media) &&
00570                 ref.attachPoint->path == Pathname(e->dir))
00571             {
00572               DBG << "Found media name "
00573                   << ref.mediaSource->asString()
00574                   << " in the mount table as " << e->src << std::endl;
00575               _isAttached = true;
00576               break;
00577             }
00578           }
00579           else
00580           {
00581             if(ref.mediaSource->bdir == e->src &&
00582                ref.attachPoint->path == Pathname(e->dir))
00583             {
00584               DBG << "Found bound media "
00585                   << ref.mediaSource->asString()
00586                   << " in the mount table as " << e->src << std::endl;
00587               _isAttached = true;
00588               break;
00589             }
00590           }
00591           // differs
00592         }
00593       }
00594 
00595       if( !_isAttached)
00596       {
00597         MIL << "Looking for " << ref << endl;
00598         if( entries.empty() )
00599         {
00600           ERR << "Unable to find any entry in the /etc/mtab file" << std::endl;
00601         }
00602         else
00603         {
00604           dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl;
00605         }
00606         if( old_mtime > 0 )
00607         {
00608           ERR << "Attached media not in mount table any more - forcing reset!"
00609               << std::endl;
00610 
00611           _mediaSource.reset();
00612         }
00613         else
00614         {
00615           WAR << "Attached media not in mount table ..." << std::endl;
00616         }
00617 
00618         // reset the mtime and force a new check to make sure,
00619         // that we've found the media at least once in the mtab.
00620         _attach_mtime = 0;
00621       }
00622     }
00623   }
00624   return _isAttached;
00625 }
00626 
00628 //
00629 //
00630 //      METHOD NAME : MediaHandler::attach
00631 //      METHOD TYPE : PMError
00632 //
00633 //      DESCRIPTION :
00634 //
00635 void MediaHandler::attach( bool next )
00636 {
00637   if ( isAttached() )
00638     return;
00639 
00640   // reset it in case of overloaded isAttached()
00641   // that checks the media against /etc/mtab ...
00642   setMediaSource(MediaSourceRef());
00643 
00644   AttachPoint ap( attachPointHint());
00645   setAttachPoint(ap.path, ap.temp);
00646 
00647   try
00648   {
00649     attachTo( next ); // pass to concrete handler
00650   }
00651   catch(const MediaException &e)
00652   {
00653     removeAttachPoint();
00654     ZYPP_RETHROW(e);
00655   }
00656   MIL << "Attached: " << *this << endl;
00657 }
00658 
00659 
00661 //
00662 //
00663 //      METHOD NAME : MediaHandler::localPath
00664 //      METHOD TYPE : Pathname
00665 //
00666 Pathname MediaHandler::localPath( const Pathname & pathname ) const
00667 {
00668     Pathname _localRoot( localRoot());
00669     if ( _localRoot.empty() )
00670         return _localRoot;
00671 
00672     // we must check maximum file name length
00673     // this is important for fetching the suseservers, the
00674     // url with all parameters can get too long (bug #42021)
00675 
00676     return _localRoot + pathname.absolutename();
00677 }
00678 
00679 
00680 
00681 
00682 
00684 //
00685 //
00686 //      METHOD NAME : MediaHandler::disconnect
00687 //      METHOD TYPE : PMError
00688 //
00689 void MediaHandler::disconnect()
00690 {
00691   if ( !isAttached() )
00692     return;
00693 
00694   disconnectFrom(); // pass to concrete handler
00695   MIL << "Disconnected: " << *this << endl;
00696 }
00697 
00699 //
00700 //
00701 //      METHOD NAME : MediaHandler::release
00702 //      METHOD TYPE : PMError
00703 //
00704 //      DESCRIPTION :
00705 //
00706 void MediaHandler::release( const std::string & ejectDev )
00707 {
00708   if ( !isAttached() ) {
00709     DBG << "Request to release media - not attached; eject '" << ejectDev << "'"
00710         << std::endl;
00711     if ( !ejectDev.empty() )
00712       forceEject(ejectDev);
00713     return;
00714   }
00715 
00716   DBG << "Request to release attached media "
00717       << _mediaSource->asString()
00718       << ", use count=" << _mediaSource.use_count()
00719       << std::endl;
00720 
00721   if( _mediaSource.unique())
00722   {
00723     DBG << "Releasing media " << _mediaSource->asString() << std::endl;
00724     try {
00725       releaseFrom( ejectDev ); // pass to concrete handler
00726     }
00727     catch(const MediaNotEjectedException &e)
00728     {
00729       // not ejected because the media
00730       // is mounted by somebody else
00731       // (if our attach point is busy,
00732       //  we get an umount exception)
00733       _mediaSource.reset(NULL);
00734       removeAttachPoint();
00735       // OK, retrow now
00736       ZYPP_RETHROW(e);
00737     }
00738     _mediaSource.reset(NULL);
00739     removeAttachPoint();
00740   }
00741   else if( !ejectDev.empty() ) {
00742     //
00743     // Can't eject a shared media
00744     //
00745     //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString()));
00746 
00747     MediaSourceRef media( new MediaSource(*_mediaSource));
00748     _mediaSource.reset(NULL);
00749 
00750     MediaManager manager;
00751     manager.forceReleaseShared(media);
00752 
00753     setMediaSource(media);
00754     DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl;
00755     try {
00756       releaseFrom( ejectDev ); // pass to concrete handler
00757     }
00758     catch(const MediaNotEjectedException &e)
00759     {
00760       // not ejected because the media
00761       // is mounted by somebody else
00762       // (if our attach point is busy,
00763       //  we get an umount exception)
00764       _mediaSource.reset(NULL);
00765       removeAttachPoint();
00766       // OK, retrow now
00767       ZYPP_RETHROW(e);
00768     }
00769     _mediaSource.reset(NULL);
00770     removeAttachPoint();
00771   }
00772   else {
00773     DBG << "Releasing shared media reference only" << std::endl;
00774     _mediaSource.reset(NULL);
00775     setAttachPoint("", true);
00776   }
00777   MIL << "Released: " << *this << endl;
00778 }
00779 
00780 bool MediaHandler::isAutoMountedMedia(const AttachedMedia &media)
00781 {
00782   (void)media;
00783   return false;
00784 }
00785 
00786 void MediaHandler::forceRelaseAllMedia(bool matchMountFs, bool autoMountedOny)
00787 {
00788   forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs, autoMountedOny);
00789 }
00790 
00791 void MediaHandler::forceRelaseAllMedia(const MediaSourceRef &ref,
00792                                        bool                  matchMountFs,
00793                                        bool                  autoMountedOny)
00794 {
00795   if( !ref)
00796     return;
00797 
00798   MountEntries  entries( MediaManager::getMountEntries());
00799   MountEntries::const_iterator e;
00800   for( e = entries.begin(); e != entries.end(); ++e)
00801   {
00802     bool        is_device = false;
00803     PathInfo    dev_info;
00804 
00805     if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) &&
00806         dev_info(e->src) && dev_info.isBlk())
00807     {
00808       is_device = true;
00809     }
00810 
00811     if( is_device &&  ref->maj_nr)
00812     {
00813       std::string mtype(matchMountFs ? e->type : ref->type);
00814       MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor());
00815 
00816       if( ref->equals( media) && e->type != "subfs")
00817       {
00818         if(autoMountedOny)
00819         {
00820           try {
00821             AttachedMedia am(MediaSourceRef(new MediaSource(media)),
00822                              AttachPointRef(new AttachPoint(e->dir)));
00823             if( !isAutoMountedMedia(am))
00824               continue;
00825           }
00826           catch(...)
00827           {
00828               continue;
00829           }
00830         }
00831         DBG << "Forcing release of media device "
00832             << ref->asString()
00833             << " in the mount table as "
00834             << e->src << std::endl;
00835         try {
00836           Mount mount;
00837           mount.umount(e->dir);
00838         }
00839         catch (const Exception &e)
00840         {
00841           ZYPP_CAUGHT(e);
00842         }
00843       }
00844     }
00845     else
00846     if(!is_device && !ref->maj_nr)
00847     {
00848       std::string mtype(matchMountFs ? e->type : ref->type);
00849       MediaSource media(mtype, e->src);
00850       if( ref->equals( media))
00851       {
00852         if(autoMountedOny)
00853         {
00854           try {
00855             AttachedMedia am(MediaSourceRef(new MediaSource(media)),
00856                              AttachPointRef(new AttachPoint(e->dir)));
00857             if( !isAutoMountedMedia(am))
00858               continue;
00859           }
00860           catch(...)
00861           {
00862               continue;
00863           }
00864         }
00865         DBG << "Forcing release of media name "
00866             << ref->asString()
00867             << " in the mount table as "
00868             << e->src << std::endl;
00869         try {
00870           Mount mount;
00871           mount.umount(e->dir);
00872         }
00873         catch (const Exception &e)
00874         {
00875           ZYPP_CAUGHT(e);
00876         }
00877       }
00878     }
00879   }
00880 }
00881 
00882 bool
00883 MediaHandler::checkAttachPoint(const Pathname &apoint) const
00884 {
00885   return MediaHandler::checkAttachPoint( apoint, true, false);
00886 }
00887 
00888 // STATIC
00889 bool
00890 MediaHandler::checkAttachPoint(const Pathname &apoint,
00891                                bool            emptydir,
00892                                bool            writeable)
00893 {
00894   if( apoint.empty() || !apoint.absolute())
00895   {
00896     ERR << "Attach point '" << apoint << "' is not absolute"
00897         << std::endl;
00898     return false;
00899   }
00900   if( apoint == "/")
00901   {
00902     ERR << "Attach point '" << apoint << "' is not allowed"
00903         << std::endl;
00904     return false;
00905   }
00906 
00907   PathInfo ainfo(apoint);
00908   if( !ainfo.isDir())
00909   {
00910     ERR << "Attach point '" << apoint << "' is not a directory"
00911         << std::endl;
00912     return false;
00913   }
00914 
00915   if( emptydir)
00916   {
00917     if( 0 != zypp::filesystem::is_empty_dir(apoint))
00918     {
00919       ERR << "Attach point '" << apoint << "' is not a empty directory"
00920           << std::endl;
00921       return false;
00922     }
00923   }
00924 
00925   if( writeable)
00926   {
00927     Pathname apath(apoint + "XXXXXX");
00928     char    *atemp = ::strdup( apath.asString().c_str());
00929     char    *atest = NULL;
00930     if( !ainfo.userMayRWX() || atemp == NULL ||
00931         (atest=::mkdtemp(atemp)) == NULL)
00932     {
00933       if( atemp != NULL)
00934         ::free(atemp);
00935 
00936       ERR << "Attach point '" << ainfo.path()
00937           << "' is not a writeable directory" << std::endl;
00938       return false;
00939     }
00940     else if( atest != NULL)
00941       ::rmdir(atest);
00942 
00943     if( atemp != NULL)
00944       ::free(atemp);
00945   }
00946   return true;
00947 }
00948 
00950 //
00951 //      METHOD NAME : MediaHandler::dependsOnParent
00952 //      METHOD TYPE : bool
00953 //
00954 //      DESCRIPTION :
00955 //
00956 bool
00957 MediaHandler::dependsOnParent()
00958 {
00959   return _parentId != 0;
00960 }
00961 
00962 bool
00963 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
00964 {
00965   if( _parentId != 0)
00966   {
00967     if(parentId == _parentId)
00968       return true;
00969 
00970     if( !exactIdMatch)
00971     {
00972       MediaManager mm;
00973       AttachedMedia am1 = mm.getAttachedMedia(_parentId);
00974       AttachedMedia am2 = mm.getAttachedMedia(parentId);
00975       if( am1.mediaSource && am2.mediaSource)
00976       {
00977         return am1.mediaSource->equals( *(am2.mediaSource));
00978       }
00979     }
00980   }
00981   return false;
00982 }
00983 
00985 //
00986 //
00987 //      METHOD NAME : MediaHandler::provideFile
00988 //      METHOD TYPE : PMError
00989 //
00990 //      DESCRIPTION :
00991 //
00992 void MediaHandler::provideFileCopy( Pathname srcFilename,
00993                                        Pathname targetFilename ) const
00994 {
00995   if ( !isAttached() ) {
00996     INT << "Media not_attached on provideFileCopy(" << srcFilename
00997         << "," << targetFilename << ")" << endl;
00998     ZYPP_THROW(MediaNotAttachedException(url()));
00999   }
01000 
01001   getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
01002   DBG << "provideFileCopy(" << srcFilename << "," << targetFilename  << ")" << endl;
01003 }
01004 
01005 void MediaHandler::provideFile( Pathname filename ) const
01006 {
01007   if ( !isAttached() ) {
01008     INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
01009     ZYPP_THROW(MediaNotAttachedException(url()));
01010   }
01011 
01012   getFile( filename ); // pass to concrete handler
01013   DBG << "provideFile(" << filename << ")" << endl;
01014 }
01015 
01016 
01018 //
01019 //
01020 //      METHOD NAME : MediaHandler::provideDir
01021 //      METHOD TYPE : PMError
01022 //
01023 //      DESCRIPTION :
01024 //
01025 void MediaHandler::provideDir( Pathname dirname ) const
01026 {
01027   if ( !isAttached() ) {
01028     INT << "Error: Not attached on provideDir(" << dirname << ")" << endl;
01029     ZYPP_THROW(MediaNotAttachedException(url()));
01030   }
01031 
01032   getDir( dirname, /*recursive*/false ); // pass to concrete handler
01033   MIL << "provideDir(" << dirname << ")" << endl;
01034 }
01035 
01037 //
01038 //
01039 //      METHOD NAME : MediaHandler::provideDirTree
01040 //      METHOD TYPE : PMError
01041 //
01042 //      DESCRIPTION :
01043 //
01044 void MediaHandler::provideDirTree( Pathname dirname ) const
01045 {
01046   if ( !isAttached() ) {
01047     INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl;
01048     ZYPP_THROW(MediaNotAttachedException(url()));
01049   }
01050 
01051   getDir( dirname, /*recursive*/true ); // pass to concrete handler
01052   MIL << "provideDirTree(" << dirname << ")" << endl;
01053 }
01054 
01056 //
01057 //
01058 //      METHOD NAME : MediaHandler::releasePath
01059 //      METHOD TYPE : PMError
01060 //
01061 //      DESCRIPTION :
01062 //
01063 void MediaHandler::releasePath( Pathname pathname ) const
01064 {
01065   if ( ! _does_download || _attachPoint->empty() )
01066     return;
01067 
01068   PathInfo info( localPath( pathname ) );
01069 
01070   if ( info.isFile() ) {
01071     unlink( info.path() );
01072   } else if ( info.isDir() ) {
01073     if ( info.path() != localRoot() ) {
01074       recursive_rmdir( info.path() );
01075     } else {
01076       clean_dir( info.path() );
01077     }
01078   }
01079 }
01080 
01082 //
01083 //
01084 //      METHOD NAME : MediaHandler::dirInfo
01085 //      METHOD TYPE : PMError
01086 //
01087 //      DESCRIPTION :
01088 //
01089 void MediaHandler::dirInfo( std::list<std::string> & retlist,
01090                             const Pathname & dirname, bool dots ) const
01091 {
01092   retlist.clear();
01093 
01094   if ( !isAttached() ) {
01095     INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
01096     ZYPP_THROW(MediaNotAttachedException(url()));
01097   }
01098 
01099   getDirInfo( retlist, dirname, dots ); // pass to concrete handler
01100   MIL << "dirInfo(" << dirname << ")" << endl;
01101 }
01102 
01104 //
01105 //
01106 //      METHOD NAME : MediaHandler::dirInfo
01107 //      METHOD TYPE : PMError
01108 //
01109 //      DESCRIPTION :
01110 //
01111 void MediaHandler::dirInfo( filesystem::DirContent & retlist,
01112                             const Pathname & dirname, bool dots ) const
01113 {
01114   retlist.clear();
01115 
01116   if ( !isAttached() ) {
01117     INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl;
01118     ZYPP_THROW(MediaNotAttachedException(url()));
01119   }
01120 
01121   getDirInfo( retlist, dirname, dots ); // pass to concrete handler
01122   MIL << "dirInfo(" << dirname << ")" << endl;
01123 }
01124 
01126 //
01127 //
01128 //      METHOD NAME : MediaHandler::doesFileExist
01129 //      METHOD TYPE : PMError
01130 //
01131 //      DESCRIPTION :
01132 //
01133 bool MediaHandler::doesFileExist( const Pathname & filename ) const
01134 {
01135   // TODO do some logging
01136   if ( !isAttached() ) {
01137     INT << "Error Not attached on doesFileExist(" << filename << ")" << endl;
01138     ZYPP_THROW(MediaNotAttachedException(url()));
01139   }
01140   return getDoesFileExist( filename );
01141   MIL << "doesFileExist(" << filename << ")" << endl;
01142 }
01143 
01145 //
01146 //
01147 //      METHOD NAME : MediaHandler::getDirectoryYast
01148 //      METHOD TYPE : PMError
01149 //
01150 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist,
01151                                         const Pathname & dirname, bool dots ) const
01152 {
01153   retlist.clear();
01154 
01155   filesystem::DirContent content;
01156   getDirectoryYast( content, dirname, dots );
01157 
01158   // convert to std::list<std::string>
01159   for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) {
01160     retlist.push_back( it->name );
01161   }
01162 }
01163 
01165 //
01166 //
01167 //      METHOD NAME : MediaHandler::getDirectoryYast
01168 //      METHOD TYPE : PMError
01169 //
01170 void MediaHandler::getDirectoryYast( filesystem::DirContent & retlist,
01171                                      const Pathname & dirname, bool dots ) const
01172 {
01173   retlist.clear();
01174 
01175   // look for directory.yast
01176   Pathname dirFile = dirname + "directory.yast";
01177   getFile( dirFile );
01178   DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
01179 
01180   // using directory.yast
01181   ifstream dir( localPath( dirFile ).asString().c_str() );
01182   if ( dir.fail() ) {
01183     ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl;
01184     ZYPP_THROW(MediaSystemException(url(),
01185       "Unable to load '" + localPath( dirFile ).asString() + "'"));
01186   }
01187 
01188   string line;
01189   while( getline( dir, line ) ) {
01190     if ( line.empty() ) continue;
01191     if ( line == "directory.yast" ) continue;
01192 
01193     // Newer directory.yast append '/' to directory names
01194     // Remaining entries are unspecified, although most probabely files.
01195     filesystem::FileType type = filesystem::FT_NOT_AVAIL;
01196     if ( *line.rbegin() == '/' ) {
01197       line.erase( line.end()-1 );
01198       type = filesystem::FT_DIR;
01199     }
01200 
01201     if ( dots ) {
01202       if ( line == "." || line == ".." ) continue;
01203     } else {
01204       if ( *line.begin() == '.' ) continue;
01205     }
01206 
01207     retlist.push_back( filesystem::DirEntry( line, type ) );
01208   }
01209 }
01210 
01211 /******************************************************************
01212 **
01213 **
01214 **      FUNCTION NAME : operator<<
01215 **      FUNCTION TYPE : ostream &
01216 */
01217 ostream & operator<<( ostream & str, const MediaHandler & obj )
01218 {
01219   str << obj.url() << ( obj.isAttached() ? "" : " not" )
01220     << " attached; localRoot \"" << obj.localRoot() << "\"";
01221   return str;
01222 }
01223 
01225 //
01226 //
01227 //      METHOD NAME : MediaHandler::getFile
01228 //      METHOD TYPE : PMError
01229 //
01230 //      DESCRIPTION : Asserted that media is attached.
01231 //                    Default implementation of pure virtual.
01232 //
01233 void MediaHandler::getFile( const Pathname & filename ) const
01234 {
01235     PathInfo info( localPath( filename ) );
01236     if( info.isFile() ) {
01237         return;
01238     }
01239 
01240     if (info.isExist())
01241       ZYPP_THROW(MediaNotAFileException(url(), localPath(filename)));
01242     else
01243       ZYPP_THROW(MediaFileNotFoundException(url(), filename));
01244 }
01245 
01246 
01247 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
01248 {
01249   getFile(srcFilename);
01250 
01251   if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
01252     ZYPP_THROW(MediaWriteException(targetFilename));
01253   }
01254 }
01255 
01256 
01257 
01259 //
01260 //
01261 //      METHOD NAME : MediaHandler::getDir
01262 //      METHOD TYPE : PMError
01263 //
01264 //      DESCRIPTION : Asserted that media is attached.
01265 //                    Default implementation of pure virtual.
01266 //
01267 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const
01268 {
01269   PathInfo info( localPath( dirname ) );
01270   if( info.isDir() ) {
01271     return;
01272   }
01273 
01274   if (info.isExist())
01275     ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
01276   else
01277     ZYPP_THROW(MediaFileNotFoundException(url(), dirname));
01278 }
01279 
01281 //
01282 //
01283 //      METHOD NAME : MediaHandler::getDirInfo
01284 //      METHOD TYPE : PMError
01285 //
01286 //      DESCRIPTION : Asserted that media is attached and retlist is empty.
01287 //                    Default implementation of pure virtual.
01288 //
01289 void MediaHandler::getDirInfo( std::list<std::string> & retlist,
01290                                const Pathname & dirname, bool dots ) const
01291 {
01292   PathInfo info( localPath( dirname ) );
01293   if( ! info.isDir() ) {
01294     ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
01295   }
01296 
01297 #if NONREMOTE_DIRECTORY_YAST
01298   // use directory.yast if available
01299   try {
01300     getDirectoryYast( retlist, dirname, dots );
01301   }
01302   catch (const MediaException & excpt_r)
01303   {
01304 #endif
01305 
01306     // readdir
01307     int res = readdir( retlist, info.path(), dots );
01308     if ( res )
01309     {
01310       MediaSystemException nexcpt(url(), "readdir failed");
01311 #if NONREMOTE_DIRECTORY_YAST
01312       nexcpt.remember(excpt_r);
01313 #endif
01314       ZYPP_THROW(nexcpt);
01315     }
01316 
01317 #if NONREMOTE_DIRECTORY_YAST
01318   }
01319 #endif
01320 
01321   return;
01322 }
01323 
01325 //
01326 //
01327 //      METHOD NAME : MediaHandler::getDirInfo
01328 //      METHOD TYPE : PMError
01329 //
01330 //      DESCRIPTION : Asserted that media is attached and retlist is empty.
01331 //                    Default implementation of pure virtual.
01332 //
01333 void MediaHandler::getDirInfo( filesystem::DirContent & retlist,
01334                                const Pathname & dirname, bool dots ) const
01335 {
01336   PathInfo info( localPath( dirname ) );
01337   if( ! info.isDir() ) {
01338     ZYPP_THROW(MediaNotADirException(url(), localPath(dirname)));
01339   }
01340 
01341 #if NONREMOTE_DIRECTORY_YAST
01342   // use directory.yast if available
01343   try {
01344     getDirectoryYast( retlist, dirname, dots );
01345   }
01346   catch (const MediaException & excpt_r)
01347   {
01348 #endif
01349 
01350     // readdir
01351     int res = readdir( retlist, info.path(), dots );
01352     if ( res )
01353     {
01354         MediaSystemException nexcpt(url(), "readdir failed");
01355 #if NONREMOTE_DIRECTORY_YAST
01356         nexcpt.remember(excpt_r);
01357 #endif
01358         ZYPP_THROW(nexcpt);
01359     }
01360 #if NONREMOTE_DIRECTORY_YAST
01361   }
01362 #endif
01363 }
01364 
01366 //
01367 //
01368 //      METHOD NAME : MediaHandler::getDoesFileExist
01369 //      METHOD TYPE : PMError
01370 //
01371 //      DESCRIPTION : Asserted that file is not a directory
01372 //                    Default implementation of pure virtual.
01373 //
01374 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const
01375 {
01376   PathInfo info( localPath( filename ) );
01377   if( info.isDir() ) {
01378     ZYPP_THROW(MediaNotAFileException(url(), localPath(filename)));
01379   }
01380   return info.isExist();
01381 }
01382 
01383 bool MediaHandler::hasMoreDevices()
01384 {
01385   return false;
01386 }
01387 
01388 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices,
01389                                       unsigned int & index) const
01390 {
01391   // clear the vector by default
01392   if (!devices.empty())
01393     devices.clear();
01394   index = 0;
01395 
01396   DBG << "No devices for this medium" << endl;
01397 }
01398 
01399 
01400   } // namespace media
01401 } // namespace zypp
01402 // vim: set ts=8 sts=2 sw=2 ai noet:

doxygen