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

Generated on Thu Jul 6 00:07:21 2006 for zypp by  doxygen 1.4.6