libzypp  17.16.0
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  filesystem::TmpFile tmpFile;
233  ManagedFile mFile ( tmpFile.path(), filesystem::unlink );
234  tmpFile.autoCleanup(false); //cleaned up by ManagedFile
235  return mFile;
236  }
237 
239  //
240  // METHOD NAME : TmpFile::defaultPrefix
241  // METHOD TYPE : const std::string &
242  //
243  const std::string &
245  {
246  static string p( "TmpFile." );
247  return p;
248  }
249 
251  //
252  // CLASS NAME : TmpDir
253  //
255 
257  //
258  // METHOD NAME : TmpDir::TmpDir
259  // METHOD TYPE : Constructor
260  //
261  TmpDir::TmpDir( const Pathname & inParentDir_r,
262  const std::string & prefix_r )
263  {
264  // parent dir must exist
265  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
266  {
267  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
268  return;
269  }
270 
271  // create the temp dir
272  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
273  char * buf = ::strdup( tmpPath.asString().c_str() );
274  if ( ! buf )
275  {
276  ERR << "Out of memory" << endl;
277  return;
278  }
279 
280  char * tmp = ::mkdtemp( buf );
281  if ( tmp )
282  // success; create _impl
283  _impl = RW_pointer<Impl>( new Impl( tmp ) );
284  else
285  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
286 
287  ::free( buf );
288  }
289 
291  //
292  // METHOD NAME : TmpDir::makeSibling
293  // METHOD TYPE : TmpDir
294  //
295  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
296  {
297  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
298  // clone mode if sibling_r exists
299  PathInfo p( sibling_r );
300  if ( p.isDir() )
301  {
302  ::chmod( ret.path().c_str(), p.st_mode() );
303  }
304  return ret;
305  }
306 
308  //
309  // METHOD NAME : TmpDir::defaultPrefix
310  // METHOD TYPE : const std::string &
311  //
312  const std::string &
314  {
315  static string p( "TmpDir." );
316  return p;
317  }
318 
319  } // namespace filesystem
320 } // namespace zypp
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:163
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
static TmpDir makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:295
#define INT
Definition: Logger.h:83
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
Definition: PathInfo.cc:1045
int clean_dir(const Pathname &path)
Like 'rm -r DIR/ *'.
Definition: PathInfo.cc:434
Definition: Arch.h:347
static const Pathname & defaultLocation()
Definition: TmpPath.cc:157
Pathname path() const
Definition: TmpPath.cc:146
TmpDir(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:261
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:127
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:127
#define ERR
Definition: Logger.h:81
const D * get() const
Definition: PtrTypes.h:330
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:177
static const std::string & defaultPrefix()
Definition: TmpPath.cc:244
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:653
const Pathname & path() const
Definition: TmpPath.cc:82
const std::string & asString() const
String representation.
Definition: Pathname.h:90
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:123
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition: PathInfo.cc:413
#define nullptr
Definition: Easy.h:55
Base class for reference counted objects.
virtual ~TmpPath()
Dtor.
Definition: TmpPath.cc:125
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:92
RW_pointer< Impl > _impl
Definition: TmpPath.h:97
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
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:53
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
void autoCleanup(bool yesno_r)
Definition: TmpPath.cc:88
#define DBG
Definition: Logger.h:78
static ManagedFile asManagedFile()
Create a temporary file and convert it to a automatically cleaned up ManagedFile.
Definition: TmpPath.cc:230
static const std::string & defaultPrefix()
Definition: TmpPath.cc:313