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

Generated on Thu Apr 24 02:24:49 2008 for zypp by  doxygen 1.4.6