libzypp  17.37.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 #include <utility>
19 
22 #include <zypp-core/base/Logger.h>
23 #include <zypp-core/fs/PathInfo.h>
24 #include <zypp-core/fs/TmpPath.h>
25 
26 using std::endl;
27 
28 namespace zypp {
29  namespace filesystem {
30 
32  //
33  // CLASS NAME : TmpPath::Impl
38  {
39  public:
40 
41  enum Flags
42  {
43  NoOp = 0,
44  Autodelete = 1L << 0,
45  KeepTopdir = 1L << 1,
46  //
48  };
49 
50  public:
51  Impl(Pathname &&path_r, Flags flags_r = CtorDefault)
52  : _path(std::move(path_r)), _flags(flags_r) {
53  MIL << _path << endl;
54  }
55 
56  Impl(const Impl &) = delete;
57  Impl(Impl &&) = delete;
58  Impl &operator=(const Impl &) = delete;
59  Impl &operator=(Impl &&) = delete;
60 
61  ~Impl() override
62  {
63  if ( ! (_flags & Autodelete) || _path.empty() )
64  return;
65 
67  if ( ! p.isExist() )
68  return;
69 
70  int res = 0;
71  if ( p.isDir() )
72  {
73  if ( _flags & KeepTopdir )
74  res = clean_dir( _path );
75  else
76  res = recursive_rmdir( _path );
77  }
78  else
79  res = unlink( _path );
80 
81  if ( res )
82  INT << "TmpPath cleanup error (" << res << ") " << p << endl;
83  else
84  DBG << "TmpPath cleaned up " << p << endl;
85  }
86 
87  const Pathname &
88  path() const
89  { return _path; }
90 
91  bool autoCleanup() const
92  { return( _flags & Autodelete ); }
93 
94  void autoCleanup( bool yesno_r )
95  { _flags = yesno_r ? CtorDefault : NoOp; }
96 
97  private:
100  };
102 
104  //
105  // CLASS NAME : TmpPath
106  //
108 
110  //
111  // METHOD NAME : TmpPath::TmpPath
112  // METHOD TYPE : Constructor
113  //
115  {}
116 
118  //
119  // METHOD NAME : TmpPath::TmpPath
120  // METHOD TYPE : Constructor
121  //
123  :_impl( tmpPath_r.empty() ? nullptr : new Impl( std::move(tmpPath_r) ) )
124  {}
125 
127  //
128  // METHOD NAME : TmpPath::~TmpPath
129  // METHOD TYPE : Destructor
130  //
132  {
133  // virtual not inlined dtor.
134  }
135 
137  //
138  // METHOD NAME : TmpPath::operator const void *
139  // METHOD TYPE :
140  //
141  TmpPath::operator bool() const
142  {
143  return _impl.get();
144  }
145 
147  //
148  // METHOD NAME : TmpPath::path
149  // METHOD TYPE : Pathname
150  //
151  Pathname
153  {
154  return _impl.get() ? _impl->path() : Pathname();
155  }
156 
158  //
159  // METHOD NAME : TmpPath::defaultLocation
160  // METHOD TYPE : const Pathname &
161  //
162  const Pathname &
164  {
165  static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
166  return p;
167  }
168 
169  bool TmpPath::autoCleanup() const
170  { return _impl.get() ? _impl->autoCleanup() : false; }
171 
172  void TmpPath::autoCleanup( bool yesno_r )
173  { if ( _impl.get() ) _impl->autoCleanup( yesno_r ); }
174 
176  //
177  // CLASS NAME : TmpFile
178  //
180 
181 
183  //
184  // METHOD NAME : TmpFile::TmpFile
185  // METHOD TYPE : Constructor
186  //
187  TmpFile::TmpFile( const Pathname & inParentDir_r,
188  const std::string & prefix_r )
189  {
190  // parent dir must exist
191  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
192  {
193  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
194  return;
195  }
196 
197  // create the temp file
198  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
199  AutoFREE<char> buf { ::strdup( tmpPath.asString().c_str() ) };
200  if ( ! buf )
201  {
202  ERR << "Out of memory" << endl;
203  return;
204  }
205 
206  int tmpFd = ::mkostemp( buf, O_CLOEXEC );
207  if ( tmpFd != -1 )
208  {
209  // success; create _impl
210  ::close( tmpFd );
211  _impl = RW_pointer<Impl>( new Impl( Pathname(buf) ) );
212  }
213  else
214  ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
215  }
216 
218  //
219  // METHOD NAME : TmpFile::makeSibling
220  // METHOD TYPE : TmpFile
221  //
222  TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
223  { return makeSibling( sibling_r, -1U ); }
224 
225  TmpFile TmpFile::makeSibling( const Pathname & sibling_r, unsigned mode )
226  {
227  TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
228  if ( ret ) {
229  // clone mode if sibling_r exists
230  PathInfo p( sibling_r );
231  if ( p.isFile() ) {
232  ::chmod( ret.path().c_str(), p.st_mode() );
233  } else if ( mode != -1U ) {
234  ::chmod( ret.path().c_str(), applyUmaskTo( mode ) );
235  }
236  }
237  return ret;
238  }
239 
241  {
243  }
244 
245  ManagedFile TmpFile::asManagedFile(const Pathname &inParentDir_r, const std::string &prefix_r)
246  {
247  filesystem::TmpFile tmpFile( inParentDir_r, prefix_r );
248  ManagedFile mFile ( tmpFile.path(), filesystem::unlink );
249  tmpFile.autoCleanup(false); //cleaned up by ManagedFile
250  return mFile;
251  }
252 
254  //
255  // METHOD NAME : TmpFile::defaultPrefix
256  // METHOD TYPE : const std::string &
257  //
258  const std::string &
260  {
261  static std::string p( "TmpFile." );
262  return p;
263  }
264 
266  //
267  // CLASS NAME : TmpDir
268  //
270 
272  //
273  // METHOD NAME : TmpDir::TmpDir
274  // METHOD TYPE : Constructor
275  //
276  TmpDir::TmpDir( const Pathname & inParentDir_r,
277  const std::string & prefix_r )
278  {
279  // parent dir must exist
280  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
281  {
282  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
283  return;
284  }
285 
286  // create the temp dir
287  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
288  AutoFREE<char> buf { ::strdup( tmpPath.asString().c_str() ) };
289  if ( ! buf )
290  {
291  ERR << "Out of memory" << endl;
292  return;
293  }
294 
295  char * tmp = ::mkdtemp( buf );
296  if ( tmp )
297  // success; create _impl
298  _impl = RW_pointer<Impl>( new Impl( tmp ) );
299  else
300  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
301  }
302 
304  //
305  // METHOD NAME : TmpDir::makeSibling
306  // METHOD TYPE : TmpDir
307  //
308  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
309  { return makeSibling( sibling_r, -1U ); }
310 
311  TmpDir TmpDir::makeSibling( const Pathname & sibling_r, unsigned mode )
312  {
313  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
314  if ( ret ) {
315  // clone mode if sibling_r exists
316  PathInfo p( sibling_r );
317  if ( p.isDir() ) {
318  ::chmod( ret.path().c_str(), p.st_mode() );
319  } else if ( mode != -1U ) {
320  ::chmod( ret.path().c_str(), applyUmaskTo( mode ) );
321  }
322  }
323  return ret;
324  }
325 
327  //
328  // METHOD NAME : TmpDir::defaultPrefix
329  // METHOD TYPE : const std::string &
330  //
331  const std::string &
333  {
334  static std::string p( "TmpDir." );
335  return p;
336  }
337 
338  } // namespace filesystem
339 
341  {
342  static filesystem::TmpDir _tmpdir( filesystem::TmpPath::defaultLocation(), "zypp." );
343  return _tmpdir.path();
344  }
345 
346 } // namespace zypp
#define MIL
Definition: Logger.h:100
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:169
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:324
TmpFile(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:187
static TmpDir makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:308
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:447
TmpPath()
Default Ctor.
Definition: TmpPath.cc:114
#define INT
Definition: Logger.h:104
int chmod(const Pathname &path, mode_t mode)
Like &#39;chmod&#39;.
Definition: PathInfo.cc:1097
Impl(Pathname &&path_r, Flags flags_r=CtorDefault)
Definition: TmpPath.cc:51
Definition: Arch.h:363
static const Pathname & defaultLocation()
Definition: TmpPath.cc:163
Pathname path() const
Definition: TmpPath.cc:152
TmpDir(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:276
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:130
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:127
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:417
#define ERR
Definition: Logger.h:102
const D * get() const
Definition: PtrTypes.h:340
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:56
bool empty() const
Test for an empty path.
Definition: Pathname.h:116
Clean or delete a directory on destruction.
Definition: TmpPath.cc:37
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h:187
static const std::string & defaultPrefix()
Definition: TmpPath.cc:259
const Pathname & path() const
Definition: TmpPath.cc:88
const std::string & asString() const
String representation.
Definition: Pathname.h:93
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:286
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:126
Base class for reference counted objects.
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:705
virtual ~TmpPath()
Dtor.
Definition: TmpPath.cc:131
Impl & operator=(const Impl &)=delete
RW_pointer< Impl > _impl
Definition: TmpPath.h:97
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:225
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:222
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Definition: PathInfo.h:806
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
void autoCleanup(bool yesno_r)
Definition: TmpPath.cc:94
Pathname myTmpDir()
Global access to the zypp.TMPDIR (created on demand, deleted when libzypp is unloaded) ...
Definition: TmpPath.cc:340
#define DBG
Definition: Logger.h:99
mode_t st_mode() const
Definition: PathInfo.h:332
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
static ManagedFile asManagedFile()
Create a temporary file and convert it to a automatically cleaned up ManagedFile. ...
Definition: TmpPath.cc:240
static const std::string & defaultPrefix()
Definition: TmpPath.cc:332