libzypp  10.5.0
TmpPath.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00013 #include <cstdlib>
00014 #include <cstring>
00015 #include <cerrno>
00016 
00017 #include <iostream>
00018 
00019 #include "zypp/base/ReferenceCounted.h"
00020 #include "zypp/base/NonCopyable.h"
00021 #include "zypp/base/Logger.h"
00022 #include "zypp/PathInfo.h"
00023 #include "zypp/TmpPath.h"
00024 
00025 using namespace std;
00026 
00027 namespace zypp {
00028   namespace filesystem {
00029 
00031     //
00032     //  CLASS NAME : TmpPath::Impl
00036     class TmpPath::Impl : public base::ReferenceCounted, private base::NonCopyable
00037     {
00038       public:
00039 
00040         enum Flags
00041           {
00042             NoOp         = 0,
00043             Autodelete   = 1L << 0,
00044             KeepTopdir   = 1L << 1,
00045             //
00046             CtorDefault  = Autodelete
00047           };
00048 
00049       public:
00050 
00051         Impl( const Pathname & path_r, Flags flags_r = CtorDefault )
00052         : _path( path_r ), _flags( flags_r )
00053         {}
00054 
00055         ~Impl()
00056         {
00057           if ( ! (_flags & Autodelete) || _path.empty() )
00058             return;
00059 
00060           PathInfo p( _path, PathInfo::LSTAT );
00061           if ( ! p.isExist() )
00062             return;
00063 
00064           int res = 0;
00065           if ( p.isDir() )
00066             {
00067               if ( _flags & KeepTopdir )
00068                 res = clean_dir( _path );
00069               else
00070                 res = recursive_rmdir( _path );
00071             }
00072           else
00073             res = unlink( _path );
00074 
00075           if ( res )
00076             INT << "TmpPath cleanup error (" << res << ") " << p << endl;
00077           else
00078             DBG << "TmpPath cleaned up " << p << endl;
00079         }
00080 
00081         const Pathname &
00082         path() const
00083         { return _path; }
00084 
00085         bool autoCleanup() const
00086         { return( _flags & Autodelete ); }
00087 
00088         void autoCleanup( bool yesno_r )
00089         { _flags = yesno_r ? CtorDefault : NoOp; }
00090 
00091       private:
00092         Pathname _path;
00093         Flags    _flags;
00094     };
00096 
00098     //
00099     //  CLASS NAME : TmpPath
00100     //
00102 
00104     //
00105     //  METHOD NAME : TmpPath::TmpPath
00106     //  METHOD TYPE : Constructor
00107     //
00108     TmpPath::TmpPath()
00109     :_impl( 0 ) // empty Pathname
00110     {
00111     }
00112 
00114     //
00115     //  METHOD NAME : TmpPath::TmpPath
00116     //  METHOD TYPE : Constructor
00117     //
00118     TmpPath::TmpPath( const Pathname & tmpPath_r )
00119     :_impl( tmpPath_r.empty() ? 0 : new Impl( tmpPath_r ) )
00120     {
00121     }
00122 
00124     //
00125     //  METHOD NAME : TmpPath::~TmpPath
00126     //  METHOD TYPE : Destructor
00127     //
00128     TmpPath::~TmpPath()
00129     {
00130       // virtual not inlined dtor.
00131     }
00132 
00134     //
00135     //      METHOD NAME : TmpPath::operator const void *
00136     //      METHOD TYPE :
00137     //
00138     TmpPath::operator const void * () const
00139     {
00140       return _impl.get();
00141     }
00142 
00144     //
00145     //  METHOD NAME : TmpPath::path
00146     //  METHOD TYPE : Pathname
00147     //
00148     Pathname
00149     TmpPath::path() const
00150     {
00151       return _impl.get() ? _impl->path() : Pathname();
00152     }
00153 
00155     //
00156     //  METHOD NAME : TmpPath::defaultLocation
00157     //  METHOD TYPE : const Pathname &
00158     //
00159     const Pathname &
00160     TmpPath::defaultLocation()
00161     {
00162       static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
00163       return p;
00164     }
00165 
00166     bool TmpPath::autoCleanup() const
00167     { return _impl.get() ? _impl->autoCleanup() : false; }
00168 
00169     void TmpPath::autoCleanup( bool yesno_r )
00170     { if ( _impl.get() ) _impl->autoCleanup( yesno_r ); }
00171 
00173     //
00174     //  CLASS NAME : TmpFile
00175     //
00177 
00178 
00180     //
00181     //  METHOD NAME : TmpFile::TmpFile
00182     //  METHOD TYPE : Constructor
00183     //
00184     TmpFile::TmpFile( const Pathname & inParentDir_r,
00185                       const std::string & prefix_r )
00186     {
00187       // parent dir must exist
00188       if ( filesystem::assert_dir( inParentDir_r ) != 0 )
00189       {
00190         ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
00191         return;
00192       }
00193 
00194       // create the temp file
00195       Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
00196       char * buf = ::strdup( tmpPath.asString().c_str() );
00197       if ( ! buf )
00198         {
00199           ERR << "Out of memory" << endl;
00200           return;
00201         }
00202 
00203       int tmpFd = ::mkostemp( buf, O_CLOEXEC );
00204       if ( tmpFd != -1 )
00205         {
00206           // success; create _impl
00207           ::close( tmpFd );
00208           _impl = RW_pointer<Impl>( new Impl( buf ) );
00209         }
00210       else
00211         ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
00212 
00213       ::free( buf );
00214     }
00215 
00217     //
00218     //  METHOD NAME : TmpFile::makeSibling
00219     //  METHOD TYPE : TmpFile
00220     //
00221     TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
00222     {
00223       TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
00224       // clone mode if sibling_r exists
00225       PathInfo p( sibling_r );
00226       if ( p.isFile() )
00227       {
00228         ::chmod( ret.path().c_str(), p.st_mode() );
00229       }
00230       return ret;
00231     }
00232 
00234     //
00235     //  METHOD NAME : TmpFile::defaultPrefix
00236     //  METHOD TYPE : const std::string &
00237     //
00238     const std::string &
00239     TmpFile::defaultPrefix()
00240     {
00241       static string p( "TmpFile." );
00242       return p;
00243     }
00244 
00246     //
00247     //  CLASS NAME : TmpDir
00248     //
00250 
00252     //
00253     //  METHOD NAME : TmpDir::TmpDir
00254     //  METHOD TYPE : Constructor
00255     //
00256     TmpDir::TmpDir( const Pathname & inParentDir_r,
00257                     const std::string & prefix_r )
00258     {
00259       // parent dir must exist
00260       if ( filesystem::assert_dir( inParentDir_r ) != 0  )
00261       {
00262         ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
00263         return;
00264       }
00265 
00266       // create the temp dir
00267       Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
00268       char * buf = ::strdup( tmpPath.asString().c_str() );
00269       if ( ! buf )
00270         {
00271           ERR << "Out of memory" << endl;
00272           return;
00273         }
00274 
00275       char * tmp = ::mkdtemp( buf );
00276       if ( tmp )
00277         // success; create _impl
00278         _impl = RW_pointer<Impl>( new Impl( tmp ) );
00279       else
00280         ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
00281 
00282       ::free( buf );
00283     }
00284 
00286     //
00287     //  METHOD NAME : TmpDir::makeSibling
00288     //  METHOD TYPE : TmpDir
00289     //
00290     TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
00291     {
00292       TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
00293       // clone mode if sibling_r exists
00294       PathInfo p( sibling_r );
00295       if ( p.isDir() )
00296       {
00297         ::chmod( ret.path().c_str(), p.st_mode() );
00298       }
00299       return ret;
00300     }
00301 
00303     //
00304     //  METHOD NAME : TmpDir::defaultPrefix
00305     //  METHOD TYPE : const std::string &
00306     //
00307     const std::string &
00308     TmpDir::defaultPrefix()
00309     {
00310       static string p( "TmpDir." );
00311       return p;
00312     }
00313 
00314   } // namespace filesystem
00315 } // namespace zypp