libzypp  17.35.12
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 
54  Impl(const Impl &) = delete;
55  Impl(Impl &&) = delete;
56  Impl &operator=(const Impl &) = delete;
57  Impl &operator=(Impl &&) = delete;
58 
59  ~Impl() override
60  {
61  if ( ! (_flags & Autodelete) || _path.empty() )
62  return;
63 
65  if ( ! p.isExist() )
66  return;
67 
68  int res = 0;
69  if ( p.isDir() )
70  {
71  if ( _flags & KeepTopdir )
72  res = clean_dir( _path );
73  else
74  res = recursive_rmdir( _path );
75  }
76  else
77  res = unlink( _path );
78 
79  if ( res )
80  INT << "TmpPath cleanup error (" << res << ") " << p << endl;
81  else
82  DBG << "TmpPath cleaned up " << p << endl;
83  }
84 
85  const Pathname &
86  path() const
87  { return _path; }
88 
89  bool autoCleanup() const
90  { return( _flags & Autodelete ); }
91 
92  void autoCleanup( bool yesno_r )
93  { _flags = yesno_r ? CtorDefault : NoOp; }
94 
95  private:
98  };
100 
102  //
103  // CLASS NAME : TmpPath
104  //
106 
108  //
109  // METHOD NAME : TmpPath::TmpPath
110  // METHOD TYPE : Constructor
111  //
113  {}
114 
116  //
117  // METHOD NAME : TmpPath::TmpPath
118  // METHOD TYPE : Constructor
119  //
121  :_impl( tmpPath_r.empty() ? nullptr : new Impl( std::move(tmpPath_r) ) )
122  {}
123 
125  //
126  // METHOD NAME : TmpPath::~TmpPath
127  // METHOD TYPE : Destructor
128  //
130  {
131  // virtual not inlined dtor.
132  }
133 
135  //
136  // METHOD NAME : TmpPath::operator const void *
137  // METHOD TYPE :
138  //
139  TmpPath::operator bool() const
140  {
141  return _impl.get();
142  }
143 
145  //
146  // METHOD NAME : TmpPath::path
147  // METHOD TYPE : Pathname
148  //
149  Pathname
151  {
152  return _impl.get() ? _impl->path() : Pathname();
153  }
154 
156  //
157  // METHOD NAME : TmpPath::defaultLocation
158  // METHOD TYPE : const Pathname &
159  //
160  const Pathname &
162  {
163  static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
164  return p;
165  }
166 
167  bool TmpPath::autoCleanup() const
168  { return _impl.get() ? _impl->autoCleanup() : false; }
169 
170  void TmpPath::autoCleanup( bool yesno_r )
171  { if ( _impl.get() ) _impl->autoCleanup( yesno_r ); }
172 
174  //
175  // CLASS NAME : TmpFile
176  //
178 
179 
181  //
182  // METHOD NAME : TmpFile::TmpFile
183  // METHOD TYPE : Constructor
184  //
185  TmpFile::TmpFile( const Pathname & inParentDir_r,
186  const std::string & prefix_r )
187  {
188  // parent dir must exist
189  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
190  {
191  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
192  return;
193  }
194 
195  // create the temp file
196  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
197  AutoFREE<char> buf { ::strdup( tmpPath.asString().c_str() ) };
198  if ( ! buf )
199  {
200  ERR << "Out of memory" << endl;
201  return;
202  }
203 
204  int tmpFd = ::mkostemp( buf, O_CLOEXEC );
205  if ( tmpFd != -1 )
206  {
207  // success; create _impl
208  ::close( tmpFd );
209  _impl = RW_pointer<Impl>( new Impl( Pathname(buf) ) );
210  }
211  else
212  ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
213  }
214 
216  //
217  // METHOD NAME : TmpFile::makeSibling
218  // METHOD TYPE : TmpFile
219  //
220  TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
221  { return makeSibling( sibling_r, -1U ); }
222 
223  TmpFile TmpFile::makeSibling( const Pathname & sibling_r, unsigned mode )
224  {
225  TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
226  if ( ret ) {
227  // clone mode if sibling_r exists
228  PathInfo p( sibling_r );
229  if ( p.isFile() ) {
230  ::chmod( ret.path().c_str(), p.st_mode() );
231  } else if ( mode != -1U ) {
232  ::chmod( ret.path().c_str(), applyUmaskTo( mode ) );
233  }
234  }
235  return ret;
236  }
237 
239  {
240  filesystem::TmpFile tmpFile;
241  ManagedFile mFile ( tmpFile.path(), filesystem::unlink );
242  tmpFile.autoCleanup(false); //cleaned up by ManagedFile
243  return mFile;
244  }
245 
247  //
248  // METHOD NAME : TmpFile::defaultPrefix
249  // METHOD TYPE : const std::string &
250  //
251  const std::string &
253  {
254  static std::string p( "TmpFile." );
255  return p;
256  }
257 
259  //
260  // CLASS NAME : TmpDir
261  //
263 
265  //
266  // METHOD NAME : TmpDir::TmpDir
267  // METHOD TYPE : Constructor
268  //
269  TmpDir::TmpDir( const Pathname & inParentDir_r,
270  const std::string & prefix_r )
271  {
272  // parent dir must exist
273  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
274  {
275  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
276  return;
277  }
278 
279  // create the temp dir
280  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
281  AutoFREE<char> buf { ::strdup( tmpPath.asString().c_str() ) };
282  if ( ! buf )
283  {
284  ERR << "Out of memory" << endl;
285  return;
286  }
287 
288  char * tmp = ::mkdtemp( buf );
289  if ( tmp )
290  // success; create _impl
291  _impl = RW_pointer<Impl>( new Impl( tmp ) );
292  else
293  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
294  }
295 
297  //
298  // METHOD NAME : TmpDir::makeSibling
299  // METHOD TYPE : TmpDir
300  //
301  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
302  { return makeSibling( sibling_r, -1U ); }
303 
304  TmpDir TmpDir::makeSibling( const Pathname & sibling_r, unsigned mode )
305  {
306  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
307  if ( ret ) {
308  // clone mode if sibling_r exists
309  PathInfo p( sibling_r );
310  if ( p.isDir() ) {
311  ::chmod( ret.path().c_str(), p.st_mode() );
312  } else if ( mode != -1U ) {
313  ::chmod( ret.path().c_str(), applyUmaskTo( mode ) );
314  }
315  }
316  return ret;
317  }
318 
320  //
321  // METHOD NAME : TmpDir::defaultPrefix
322  // METHOD TYPE : const std::string &
323  //
324  const std::string &
326  {
327  static std::string p( "TmpDir." );
328  return p;
329  }
330 
331  } // namespace filesystem
332 } // namespace zypp
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:167
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:185
static TmpDir makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:301
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:447
TmpPath()
Default Ctor.
Definition: TmpPath.cc:112
#define INT
Definition: Logger.h:102
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:161
Pathname path() const
Definition: TmpPath.cc:150
TmpDir(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:269
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:100
const D * get() const
Definition: PtrTypes.h:340
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:54
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:181
static const std::string & defaultPrefix()
Definition: TmpPath.cc:252
const Pathname & path() const
Definition: TmpPath.cc:86
const std::string & asString() const
String representation.
Definition: Pathname.h:93
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:282
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:129
Impl & operator=(const Impl &)=delete
RW_pointer< Impl > _impl
Definition: TmpPath.h:97
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:220
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Definition: PathInfo.h:799
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
void autoCleanup(bool yesno_r)
Definition: TmpPath.cc:92
#define DBG
Definition: Logger.h:97
mode_t st_mode() const
Definition: PathInfo.h:327
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:238
static const std::string & defaultPrefix()
Definition: TmpPath.cc:325