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

Generated on Tue Nov 28 16:49:29 2006 for zypp by  doxygen 1.5.0