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