libzypp  11.13.5
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 
55  ~Impl()
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  :_impl( 0 ) // empty Pathname
110  {
111  }
112 
114  //
115  // METHOD NAME : TmpPath::TmpPath
116  // METHOD TYPE : Constructor
117  //
118  TmpPath::TmpPath( const Pathname & tmpPath_r )
119  :_impl( tmpPath_r.empty() ? 0 : new Impl( tmpPath_r ) )
120  {
121  }
122 
124  //
125  // METHOD NAME : TmpPath::~TmpPath
126  // METHOD TYPE : Destructor
127  //
129  {
130  // virtual not inlined dtor.
131  }
132 
134  //
135  // METHOD NAME : TmpPath::operator const void *
136  // METHOD TYPE :
137  //
138  TmpPath::operator const void * () const
139  {
140  return _impl.get();
141  }
142 
144  //
145  // METHOD NAME : TmpPath::path
146  // METHOD TYPE : Pathname
147  //
148  Pathname
150  {
151  return _impl.get() ? _impl->path() : Pathname();
152  }
153 
155  //
156  // METHOD NAME : TmpPath::defaultLocation
157  // METHOD TYPE : const Pathname &
158  //
159  const Pathname &
161  {
162  static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
163  return p;
164  }
165 
166  bool TmpPath::autoCleanup() const
167  { return _impl.get() ? _impl->autoCleanup() : false; }
168 
169  void TmpPath::autoCleanup( bool yesno_r )
170  { if ( _impl.get() ) _impl->autoCleanup( yesno_r ); }
171 
173  //
174  // CLASS NAME : TmpFile
175  //
177 
178 
180  //
181  // METHOD NAME : TmpFile::TmpFile
182  // METHOD TYPE : Constructor
183  //
184  TmpFile::TmpFile( const Pathname & inParentDir_r,
185  const std::string & prefix_r )
186  {
187  // parent dir must exist
188  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
189  {
190  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
191  return;
192  }
193 
194  // create the temp file
195  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
196  char * buf = ::strdup( tmpPath.asString().c_str() );
197  if ( ! buf )
198  {
199  ERR << "Out of memory" << endl;
200  return;
201  }
202 
203  int tmpFd = ::mkostemp( buf, O_CLOEXEC );
204  if ( tmpFd != -1 )
205  {
206  // success; create _impl
207  ::close( tmpFd );
208  _impl = RW_pointer<Impl>( new Impl( buf ) );
209  }
210  else
211  ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
212 
213  ::free( buf );
214  }
215 
217  //
218  // METHOD NAME : TmpFile::makeSibling
219  // METHOD TYPE : TmpFile
220  //
221  TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
222  {
223  TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
224  // clone mode if sibling_r exists
225  PathInfo p( sibling_r );
226  if ( p.isFile() )
227  {
228  ::chmod( ret.path().c_str(), p.st_mode() );
229  }
230  return ret;
231  }
232 
234  //
235  // METHOD NAME : TmpFile::defaultPrefix
236  // METHOD TYPE : const std::string &
237  //
238  const std::string &
240  {
241  static string p( "TmpFile." );
242  return p;
243  }
244 
246  //
247  // CLASS NAME : TmpDir
248  //
250 
252  //
253  // METHOD NAME : TmpDir::TmpDir
254  // METHOD TYPE : Constructor
255  //
256  TmpDir::TmpDir( const Pathname & inParentDir_r,
257  const std::string & prefix_r )
258  {
259  // parent dir must exist
260  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
261  {
262  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
263  return;
264  }
265 
266  // create the temp dir
267  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
268  char * buf = ::strdup( tmpPath.asString().c_str() );
269  if ( ! buf )
270  {
271  ERR << "Out of memory" << endl;
272  return;
273  }
274 
275  char * tmp = ::mkdtemp( buf );
276  if ( tmp )
277  // success; create _impl
278  _impl = RW_pointer<Impl>( new Impl( tmp ) );
279  else
280  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
281 
282  ::free( buf );
283  }
284 
286  //
287  // METHOD NAME : TmpDir::makeSibling
288  // METHOD TYPE : TmpDir
289  //
290  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
291  {
292  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
293  // clone mode if sibling_r exists
294  PathInfo p( sibling_r );
295  if ( p.isDir() )
296  {
297  ::chmod( ret.path().c_str(), p.st_mode() );
298  }
299  return ret;
300  }
301 
303  //
304  // METHOD NAME : TmpDir::defaultPrefix
305  // METHOD TYPE : const std::string &
306  //
307  const std::string &
309  {
310  static string p( "TmpDir." );
311  return p;
312  }
313 
314  } // namespace filesystem
315 } // namespace zypp