libzypp  17.36.3
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  {
242  filesystem::TmpFile tmpFile;
243  ManagedFile mFile ( tmpFile.path(), filesystem::unlink );
244  tmpFile.autoCleanup(false); //cleaned up by ManagedFile
245  return mFile;
246  }
247 
249  //
250  // METHOD NAME : TmpFile::defaultPrefix
251  // METHOD TYPE : const std::string &
252  //
253  const std::string &
255  {
256  static std::string p( "TmpFile." );
257  return p;
258  }
259 
261  //
262  // CLASS NAME : TmpDir
263  //
265 
267  //
268  // METHOD NAME : TmpDir::TmpDir
269  // METHOD TYPE : Constructor
270  //
271  TmpDir::TmpDir( const Pathname & inParentDir_r,
272  const std::string & prefix_r )
273  {
274  // parent dir must exist
275  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
276  {
277  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
278  return;
279  }
280 
281  // create the temp dir
282  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
283  AutoFREE<char> buf { ::strdup( tmpPath.asString().c_str() ) };
284  if ( ! buf )
285  {
286  ERR << "Out of memory" << endl;
287  return;
288  }
289 
290  char * tmp = ::mkdtemp( buf );
291  if ( tmp )
292  // success; create _impl
293  _impl = RW_pointer<Impl>( new Impl( tmp ) );
294  else
295  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
296  }
297 
299  //
300  // METHOD NAME : TmpDir::makeSibling
301  // METHOD TYPE : TmpDir
302  //
303  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
304  { return makeSibling( sibling_r, -1U ); }
305 
306  TmpDir TmpDir::makeSibling( const Pathname & sibling_r, unsigned mode )
307  {
308  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
309  if ( ret ) {
310  // clone mode if sibling_r exists
311  PathInfo p( sibling_r );
312  if ( p.isDir() ) {
313  ::chmod( ret.path().c_str(), p.st_mode() );
314  } else if ( mode != -1U ) {
315  ::chmod( ret.path().c_str(), applyUmaskTo( mode ) );
316  }
317  }
318  return ret;
319  }
320 
322  //
323  // METHOD NAME : TmpDir::defaultPrefix
324  // METHOD TYPE : const std::string &
325  //
326  const std::string &
328  {
329  static std::string p( "TmpDir." );
330  return p;
331  }
332 
333  } // namespace filesystem
334 
336  {
337  static filesystem::TmpDir _tmpdir( filesystem::TmpPath::defaultLocation(), "zypp." );
338  return _tmpdir.path();
339  }
340 
341 } // 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:303
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:271
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: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:254
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:335
#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:327