libzypp  13.10.6
TmpPath.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <cstdlib>
14 #include <cstring>
15 #include <cerrno>
16 
17 #include <iostream>
18 
20 #include "zypp/base/NonCopyable.h"
21 #include "zypp/base/Logger.h"
22 #include "zypp/PathInfo.h"
23 #include "zypp/TmpPath.h"
24 
25 using namespace std;
26 
27 namespace zypp {
28  namespace filesystem {
29 
31  //
32  // CLASS NAME : TmpPath::Impl
37  {
38  public:
39 
40  enum Flags
41  {
42  NoOp = 0,
43  Autodelete = 1L << 0,
44  KeepTopdir = 1L << 1,
45  //
46  CtorDefault = Autodelete
47  };
48 
49  public:
50 
51  Impl( const Pathname & path_r, Flags flags_r = CtorDefault )
52  : _path( path_r ), _flags( flags_r )
53  {}
54 
56  {
57  if ( ! (_flags & Autodelete) || _path.empty() )
58  return;
59 
60  PathInfo p( _path, PathInfo::LSTAT );
61  if ( ! p.isExist() )
62  return;
63 
64  int res = 0;
65  if ( p.isDir() )
66  {
67  if ( _flags & KeepTopdir )
68  res = clean_dir( _path );
69  else
70  res = recursive_rmdir( _path );
71  }
72  else
73  res = unlink( _path );
74 
75  if ( res )
76  INT << "TmpPath cleanup error (" << res << ") " << p << endl;
77  else
78  DBG << "TmpPath cleaned up " << p << endl;
79  }
80 
81  const Pathname &
82  path() const
83  { return _path; }
84 
85  bool autoCleanup() const
86  { return( _flags & Autodelete ); }
87 
88  void autoCleanup( bool yesno_r )
89  { _flags = yesno_r ? CtorDefault : NoOp; }
90 
91  private:
94  };
96 
98  //
99  // CLASS NAME : TmpPath
100  //
102 
104  //
105  // METHOD NAME : TmpPath::TmpPath
106  // METHOD TYPE : Constructor
107  //
108  TmpPath::TmpPath()
109  {}
110 
112  //
113  // METHOD NAME : TmpPath::TmpPath
114  // METHOD TYPE : Constructor
115  //
116  TmpPath::TmpPath( const Pathname & tmpPath_r )
117  :_impl( tmpPath_r.empty() ? nullptr : new Impl( tmpPath_r ) )
118  {}
119 
121  //
122  // METHOD NAME : TmpPath::~TmpPath
123  // METHOD TYPE : Destructor
124  //
126  {
127  // virtual not inlined dtor.
128  }
129 
131  //
132  // METHOD NAME : TmpPath::operator const void *
133  // METHOD TYPE :
134  //
135  TmpPath::operator bool() const
136  {
137  return _impl.get();
138  }
139 
141  //
142  // METHOD NAME : TmpPath::path
143  // METHOD TYPE : Pathname
144  //
145  Pathname
147  {
148  return _impl.get() ? _impl->path() : Pathname();
149  }
150 
152  //
153  // METHOD NAME : TmpPath::defaultLocation
154  // METHOD TYPE : const Pathname &
155  //
156  const Pathname &
158  {
159  static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
160  return p;
161  }
162 
163  bool TmpPath::autoCleanup() const
164  { return _impl.get() ? _impl->autoCleanup() : false; }
165 
166  void TmpPath::autoCleanup( bool yesno_r )
167  { if ( _impl.get() ) _impl->autoCleanup( yesno_r ); }
168 
170  //
171  // CLASS NAME : TmpFile
172  //
174 
175 
177  //
178  // METHOD NAME : TmpFile::TmpFile
179  // METHOD TYPE : Constructor
180  //
181  TmpFile::TmpFile( const Pathname & inParentDir_r,
182  const std::string & prefix_r )
183  {
184  // parent dir must exist
185  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
186  {
187  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
188  return;
189  }
190 
191  // create the temp file
192  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
193  char * buf = ::strdup( tmpPath.asString().c_str() );
194  if ( ! buf )
195  {
196  ERR << "Out of memory" << endl;
197  return;
198  }
199 
200  int tmpFd = ::mkostemp( buf, O_CLOEXEC );
201  if ( tmpFd != -1 )
202  {
203  // success; create _impl
204  ::close( tmpFd );
205  _impl = RW_pointer<Impl>( new Impl( buf ) );
206  }
207  else
208  ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
209 
210  ::free( buf );
211  }
212 
214  //
215  // METHOD NAME : TmpFile::makeSibling
216  // METHOD TYPE : TmpFile
217  //
218  TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
219  {
220  TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
221  // clone mode if sibling_r exists
222  PathInfo p( sibling_r );
223  if ( p.isFile() )
224  {
225  ::chmod( ret.path().c_str(), p.st_mode() );
226  }
227  return ret;
228  }
229 
231  //
232  // METHOD NAME : TmpFile::defaultPrefix
233  // METHOD TYPE : const std::string &
234  //
235  const std::string &
237  {
238  static string p( "TmpFile." );
239  return p;
240  }
241 
243  //
244  // CLASS NAME : TmpDir
245  //
247 
249  //
250  // METHOD NAME : TmpDir::TmpDir
251  // METHOD TYPE : Constructor
252  //
253  TmpDir::TmpDir( const Pathname & inParentDir_r,
254  const std::string & prefix_r )
255  {
256  // parent dir must exist
257  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
258  {
259  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
260  return;
261  }
262 
263  // create the temp dir
264  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
265  char * buf = ::strdup( tmpPath.asString().c_str() );
266  if ( ! buf )
267  {
268  ERR << "Out of memory" << endl;
269  return;
270  }
271 
272  char * tmp = ::mkdtemp( buf );
273  if ( tmp )
274  // success; create _impl
275  _impl = RW_pointer<Impl>( new Impl( tmp ) );
276  else
277  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
278 
279  ::free( buf );
280  }
281 
283  //
284  // METHOD NAME : TmpDir::makeSibling
285  // METHOD TYPE : TmpDir
286  //
287  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
288  {
289  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
290  // clone mode if sibling_r exists
291  PathInfo p( sibling_r );
292  if ( p.isDir() )
293  {
294  ::chmod( ret.path().c_str(), p.st_mode() );
295  }
296  return ret;
297  }
298 
300  //
301  // METHOD NAME : TmpDir::defaultPrefix
302  // METHOD TYPE : const std::string &
303  //
304  const std::string &
306  {
307  static string p( "TmpDir." );
308  return p;
309  }
310 
311  } // namespace filesystem
312 } // namespace zypp
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:324
Impl(const Pathname &path_r, Flags flags_r=CtorDefault)
Definition: TmpPath.cc:51
TmpFile(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:181
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:124
Pathname path() const
Definition: TmpPath.cc:146
static TmpDir makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:287
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
const std::string & asString() const
String representation.
Definition: Pathname.h:90
#define INT
Definition: Logger.h:51
int chmod(const Pathname &path, mode_t mode)
Like &#39;chmod&#39;.
Definition: PathInfo.cc:1021
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:120
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:438
static const Pathname & defaultLocation()
Definition: TmpPath.cc:157
TmpDir(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:253
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:126
const Pathname & path() const
Definition: TmpPath.cc:82
#define ERR
Definition: Logger.h:49
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
Clean or delete a directory on destruction.
Definition: TmpPath.cc:36
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h:170
static const std::string & defaultPrefix()
Definition: TmpPath.cc:236
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:660
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:417
#define nullptr
Definition: Easy.h:54
Base class for reference counted objects.
virtual ~TmpPath()
Dtor.
Definition: TmpPath.cc:125
Wrapper for const correct access via Smart pointer types.
Definition: PtrTypes.h:265
RW_pointer< Impl > _impl
Definition: TmpPath.h:96
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:218
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:163
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:51
void autoCleanup(bool yesno_r)
Definition: TmpPath.cc:88
#define DBG
Definition: Logger.h:46
static const std::string & defaultPrefix()
Definition: TmpPath.cc:305