--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/TmpPath.cc
+ *
+*/
+
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+#include <iostream>
+
+#include "zypp/base/ReferenceCounted.h"
+#include "zypp/base/NonCopyable.h"
+#include "zypp/base/Logger.h"
+#include "zypp/PathInfo.h"
+#include "zypp/TmpPath.h"
+
+using namespace std;
+
+namespace zypp {
+ namespace filesystem {
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : TmpPath::Impl
+ /**
+ * Clean or delete a directory on destruction.
+ **/
+ class TmpPath::Impl : public base::ReferenceCounted, private base::NonCopyable
+ {
+ public:
+
+ enum Flags
+ {
+ NoOp = 0,
+ Autodelete = 1L << 0,
+ KeepTopdir = 1L << 1,
+ //
+ CtorDefault = Autodelete
+ };
+
+ public:
+
+ Impl( const Pathname & path_r, Flags flags_r = CtorDefault )
+ : _path( path_r ), _flags( flags_r )
+ {}
+
+ ~Impl()
+ {
+ if ( ! (_flags & Autodelete) || _path.empty() )
+ return;
+
+ PathInfo p( _path, PathInfo::LSTAT );
+ if ( ! p.isExist() )
+ return;
+
+ int res = 0;
+ if ( p.isDir() )
+ {
+ if ( _flags & KeepTopdir )
+ res = clean_dir( _path );
+ else
+ res = recursive_rmdir( _path );
+ }
+ else
+ res = unlink( _path );
+
+ if ( res )
+ INT << "TmpPath cleanup error (" << res << ") " << p << endl;
+ else
+ DBG << "TmpPath cleaned up " << p << endl;
+ }
+
+ const Pathname &
+ path() const
+ { return _path; }
+
+ private:
+ Pathname _path;
+ Flags _flags;
+ };
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : TmpPath
+ //
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpPath::TmpPath
+ // METHOD TYPE : Constructor
+ //
+ TmpPath::TmpPath()
+ :_impl( 0 ) // empty Pathname
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpPath::TmpPath
+ // METHOD TYPE : Constructor
+ //
+ TmpPath::TmpPath( const Pathname & tmpPath_r )
+ :_impl( tmpPath_r.empty() ? 0 : new Impl( tmpPath_r ) )
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpPath::~TmpPath
+ // METHOD TYPE : Destructor
+ //
+ TmpPath::~TmpPath()
+ {
+ // virtual not inlined dtor.
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpPath::operator const void *const
+ // METHOD TYPE :
+ //
+ TmpPath::operator const void *const() const
+ {
+ return _impl.get();
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpPath::path
+ // METHOD TYPE : Pathname
+ //
+ Pathname
+ TmpPath::path() const
+ {
+ return _impl.get() ? _impl->path() : Pathname();
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpPath::defaultLocation
+ // METHOD TYPE : const Pathname &
+ //
+ const Pathname &
+ TmpPath::defaultLocation()
+ {
+ static Pathname p( "/var/tmp" );
+ return p;
+ }
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : TmpFile
+ //
+ ///////////////////////////////////////////////////////////////////
+
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpFile::TmpFile
+ // METHOD TYPE : Constructor
+ //
+ TmpFile::TmpFile( const Pathname & inParentDir_r,
+ const std::string & prefix_r )
+ {
+ // parent dir must exist
+ PathInfo p( inParentDir_r );
+ if ( ! p.isDir() )
+ {
+ ERR << "Parent directory does not exist: " << p << endl;
+ return;
+ }
+
+ // create the temp file
+ Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
+ char * buf = ::strdup( tmpPath.asString().c_str() );
+ if ( ! buf )
+ {
+ ERR << "Out of memory" << endl;
+ return;
+ }
+
+ int tmpFd = ::mkstemp( buf );
+ if ( tmpFd != -1 )
+ {
+ // success; create _impl
+ ::close( tmpFd );
+ _impl = RW_pointer<Impl>( new Impl( buf ) );
+ }
+ else
+ ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
+
+ ::free( buf );
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpFile::defaultPrefix
+ // METHOD TYPE : const std::string &
+ //
+ const std::string &
+ TmpFile::defaultPrefix()
+ {
+ static string p( "TmpFile." );
+ return p;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : TmpDir
+ //
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpDir::TmpDir
+ // METHOD TYPE : Constructor
+ //
+ TmpDir::TmpDir( const Pathname & inParentDir_r,
+ const std::string & prefix_r )
+ {
+ // parent dir must exist
+ PathInfo p( inParentDir_r );
+ if ( ! p.isDir() )
+ {
+ ERR << "Parent directory does not exist: " << p << endl;
+ return;
+ }
+
+ // create the temp dir
+ Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
+ char * buf = ::strdup( tmpPath.asString().c_str() );
+ if ( ! buf )
+ {
+ ERR << "Out of memory" << endl;
+ return;
+ }
+
+ char * tmp = ::mkdtemp( buf );
+ if ( tmp )
+ // success; create _impl
+ _impl = RW_pointer<Impl>( new Impl( tmp ) );
+ else
+ ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
+
+ ::free( buf );
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // METHOD NAME : TmpDir::defaultPrefix
+ // METHOD TYPE : const std::string &
+ //
+ const std::string &
+ TmpDir::defaultPrefix()
+ {
+ static string p( "TmpDir." );
+ return p;
+ }
+
+ } // namespace filesystem
+} // namespace zypp
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/TmpPath.h
+ *
+*/
+#ifndef ZYPP_TMPPATH_H
+#define ZYPP_TMPPATH_H
+
+#include <iosfwd>
+
+#include "zypp/Pathname.h"
+#include "zypp/base/PtrTypes.h"
+
+namespace zypp {
+ namespace filesystem {
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : TmpPath
+ /**
+ * @short Automaticaly deletes files or directories when no longer needed.
+ *
+ * TmpPath is constructed from a Pathname. Multiple TmpPath instances
+ * created by copy and assign, share the same reference counted internal
+ * repesentation.
+ *
+ * When the last reference drops any file or directory located at the path
+ * passed to the ctor is deleted (recursivly in case of directories).
+ *
+ * Principally serves as base class, but standalone usable.
+ **/
+ class TmpPath
+ {
+ public:
+ /**
+ * Default Ctor. An empty Pathname.
+ **/
+ TmpPath();
+
+ /**
+ * Ctor. Takes a Pathname.
+ **/
+ explicit
+ TmpPath( const Pathname & tmpPath_r );
+
+ /**
+ * Dtor.
+ **/
+ virtual
+ ~TmpPath();
+
+ /**
+ * Test whether the Pathname is valid (i.e. not empty. NOT whether
+ * it realy denotes an existing file or directory).
+ **/
+ operator const void *const() const;
+
+ /**
+ * @return The Pathname.
+ **/
+ Pathname
+ path() const;
+
+ /**
+ * Type conversion to Pathname.
+ **/
+ operator Pathname() const
+ { return path(); }
+
+ public:
+ /**
+ * @return The default directory where temporary
+ * files should be are created (/var/tmp).
+ **/
+ static const Pathname &
+ defaultLocation();
+
+ protected:
+ class Impl;
+ RW_pointer<Impl> _impl;
+
+ };
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Stream output as pathname.
+ **/
+ inline std::ostream &
+ operator<<( std::ostream & str, const TmpPath & obj )
+ { return str << static_cast<Pathname>(obj); }
+
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : TmpFile
+ /**
+ * @short Provide a new empty temporary file and delete it when no
+ * longer needed.
+ *
+ * The temporary file is per default created in '/var/tmp' and named
+ ' TmpFile.XXXXXX', with XXXXXX replaced by a string which makes the
+ * name unique. Different location and file prefix may be passed to
+ * the ctor. TmpFile is created with mode 0600.
+ *
+ * The directory where the temporary file is to be created must exist.
+ * TmpFile provides the Pathname of the temporary file, or an empty
+ * path in case of any error.
+ **/
+ class TmpFile : public TmpPath
+ {
+ public:
+ /**
+ * Ctor. Takes a Pathname.
+ **/
+ explicit
+ TmpFile( const Pathname & inParentDir_r = defaultLocation(),
+ const std::string & prefix_r = defaultPrefix() );
+
+ public:
+ /**
+ * @return The default prefix for temporary files (TmpFile.)
+ **/
+ static const std::string &
+ defaultPrefix();
+
+ };
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : TmpDir
+ /**
+ * @short Provide a new empty temporary directory and recursively
+ * delete it when no longer needed.
+ *
+ * The temporary directory is per default created in '/var/tmp' and
+ ' named TmpDir.XXXXXX', with XXXXXX replaced by a string which makes
+ * the name unique. Different location and file prefix may be passed
+ * to the ctor. TmpDir is created with mode 0700.
+ *
+ * The directory where the temporary directory is to be created must exist.
+ * TmpDir provides the Pathname of the temporary directory , or an empty
+ * path in case of any error.
+ **/
+ class TmpDir : public TmpPath
+ {
+ public:
+ /**
+ * Ctor. Takes a Pathname.
+ **/
+ explicit
+ TmpDir( const Pathname & inParentDir_r = defaultLocation(),
+ const std::string & prefix_r = defaultPrefix() );
+
+ public:
+ /**
+ * @return The default prefix for temporary directories (TmpDir.)
+ **/
+ static const std::string &
+ defaultPrefix();
+ };
+ ///////////////////////////////////////////////////////////////////
+
+ } // namespace filesystem
+} // namespace zypp
+
+#endif // ZYPP_TMPPATH_H