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       private:
00086         Pathname _path;
00087         Flags    _flags;
00088     };
00090 
00092     //
00093     //  CLASS NAME : TmpPath
00094     //
00096 
00098     //
00099     //  METHOD NAME : TmpPath::TmpPath
00100     //  METHOD TYPE : Constructor
00101     //
00102     TmpPath::TmpPath()
00103     :_impl( 0 ) // empty Pathname
00104     {
00105     }
00106 
00108     //
00109     //  METHOD NAME : TmpPath::TmpPath
00110     //  METHOD TYPE : Constructor
00111     //
00112     TmpPath::TmpPath( const Pathname & tmpPath_r )
00113     :_impl( tmpPath_r.empty() ? 0 : new Impl( tmpPath_r ) )
00114     {
00115     }
00116 
00118     //
00119     //  METHOD NAME : TmpPath::~TmpPath
00120     //  METHOD TYPE : Destructor
00121     //
00122     TmpPath::~TmpPath()
00123     {
00124       // virtual not inlined dtor.
00125     }
00126 
00128     //
00129     //      METHOD NAME : TmpPath::operator const void *
00130     //      METHOD TYPE :
00131     //
00132     TmpPath::operator const void * () const
00133     {
00134       return _impl.get();
00135     }
00136 
00138     //
00139     //  METHOD NAME : TmpPath::path
00140     //  METHOD TYPE : Pathname
00141     //
00142     Pathname
00143     TmpPath::path() const
00144     {
00145       return _impl.get() ? _impl->path() : Pathname();
00146     }
00147 
00149     //
00150     //  METHOD NAME : TmpPath::defaultLocation
00151     //  METHOD TYPE : const Pathname &
00152     //
00153     const Pathname &
00154     TmpPath::defaultLocation()
00155     {
00156       static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
00157       return p;
00158     }
00160     //
00161     //  CLASS NAME : TmpFile
00162     //
00164 
00165 
00167     //
00168     //  METHOD NAME : TmpFile::TmpFile
00169     //  METHOD TYPE : Constructor
00170     //
00171     TmpFile::TmpFile( const Pathname & inParentDir_r,
00172                       const std::string & prefix_r )
00173     {
00174       // parent dir must exist
00175       if ( filesystem::assert_dir( inParentDir_r ) != 0 )
00176       {
00177         ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
00178         return;
00179       }
00180 
00181       // create the temp file
00182       Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
00183       char * buf = ::strdup( tmpPath.asString().c_str() );
00184       if ( ! buf )
00185         {
00186           ERR << "Out of memory" << endl;
00187           return;
00188         }
00189 
00190       int tmpFd = ::mkstemp( buf );
00191       if ( tmpFd != -1 )
00192         {
00193           // success; create _impl
00194           ::close( tmpFd );
00195           _impl = RW_pointer<Impl>( new Impl( buf ) );
00196         }
00197       else
00198         ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
00199 
00200       ::free( buf );
00201     }
00202 
00204     //
00205     //  METHOD NAME : TmpFile::makeSibling
00206     //  METHOD TYPE : TmpFile
00207     //
00208     TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
00209     {
00210       TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
00211       // clone mode if sibling_r exists
00212       PathInfo p( sibling_r );
00213       if ( p.isFile() )
00214       {
00215         ::chmod( ret.path().c_str(), p.st_mode() );
00216       }
00217       return ret;
00218     }
00219 
00221     //
00222     //  METHOD NAME : TmpFile::defaultPrefix
00223     //  METHOD TYPE : const std::string &
00224     //
00225     const std::string &
00226     TmpFile::defaultPrefix()
00227     {
00228       static string p( "TmpFile." );
00229       return p;
00230     }
00231 
00233     //
00234     //  CLASS NAME : TmpDir
00235     //
00237 
00239     //
00240     //  METHOD NAME : TmpDir::TmpDir
00241     //  METHOD TYPE : Constructor
00242     //
00243     TmpDir::TmpDir( const Pathname & inParentDir_r,
00244                     const std::string & prefix_r )
00245     {
00246       // parent dir must exist
00247       if ( filesystem::assert_dir( inParentDir_r ) != 0  )
00248       {
00249         ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
00250         return;
00251       }
00252 
00253       // create the temp dir
00254       Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
00255       char * buf = ::strdup( tmpPath.asString().c_str() );
00256       if ( ! buf )
00257         {
00258           ERR << "Out of memory" << endl;
00259           return;
00260         }
00261 
00262       char * tmp = ::mkdtemp( buf );
00263       if ( tmp )
00264         // success; create _impl
00265         _impl = RW_pointer<Impl>( new Impl( tmp ) );
00266       else
00267         ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
00268 
00269       ::free( buf );
00270     }
00271 
00273     //
00274     //  METHOD NAME : TmpDir::makeSibling
00275     //  METHOD TYPE : TmpDir
00276     //
00277     TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
00278     {
00279       TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
00280       // clone mode if sibling_r exists
00281       PathInfo p( sibling_r );
00282       if ( p.isDir() )
00283       {
00284         ::chmod( ret.path().c_str(), p.st_mode() );
00285       }
00286       return ret;
00287     }
00288 
00290     //
00291     //  METHOD NAME : TmpDir::defaultPrefix
00292     //  METHOD TYPE : const std::string &
00293     //
00294     const std::string &
00295     TmpDir::defaultPrefix()
00296     {
00297       static string p( "TmpDir." );
00298       return p;
00299     }
00300 
00301   } // namespace filesystem
00302 } // namespace zypp

doxygen