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

Generated on Mon Jun 5 19:10:33 2006 for zypp by  doxygen 1.4.6