libzypp  17.32.2
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 
20 #include <zypp-core/base/ReferenceCounted.h>
21 #include <zypp-core/base/NonCopyable.h>
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  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( buf ) );
210  }
211  else
212  ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
213 
214  ::free( buf );
215  }
216 
218  //
219  // METHOD NAME : TmpFile::makeSibling
220  // METHOD TYPE : TmpFile
221  //
222  TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
223  {
224  TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
225  if ( ret ) {
226  // clone mode if sibling_r exists
227  PathInfo p( sibling_r );
228  if ( p.isFile() ) {
229  ::chmod( ret.path().c_str(), p.st_mode() );
230  }
231  }
232  return ret;
233  }
234 
236  {
237  filesystem::TmpFile tmpFile;
238  ManagedFile mFile ( tmpFile.path(), filesystem::unlink );
239  tmpFile.autoCleanup(false); //cleaned up by ManagedFile
240  return mFile;
241  }
242 
244  //
245  // METHOD NAME : TmpFile::defaultPrefix
246  // METHOD TYPE : const std::string &
247  //
248  const std::string &
250  {
251  static std::string p( "TmpFile." );
252  return p;
253  }
254 
256  //
257  // CLASS NAME : TmpDir
258  //
260 
262  //
263  // METHOD NAME : TmpDir::TmpDir
264  // METHOD TYPE : Constructor
265  //
266  TmpDir::TmpDir( const Pathname & inParentDir_r,
267  const std::string & prefix_r )
268  {
269  // parent dir must exist
270  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
271  {
272  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
273  return;
274  }
275 
276  // create the temp dir
277  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
278  char * buf = ::strdup( tmpPath.asString().c_str() );
279  if ( ! buf )
280  {
281  ERR << "Out of memory" << endl;
282  return;
283  }
284 
285  char * tmp = ::mkdtemp( buf );
286  if ( tmp )
287  // success; create _impl
288  _impl = RW_pointer<Impl>( new Impl( tmp ) );
289  else
290  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
291 
292  ::free( buf );
293  }
294 
296  //
297  // METHOD NAME : TmpDir::makeSibling
298  // METHOD TYPE : TmpDir
299  //
300  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
301  {
302  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
303  if ( ret ) {
304  // clone mode if sibling_r exists
305  PathInfo p( sibling_r );
306  if ( p.isDir() ) {
307  ::chmod( ret.path().c_str(), p.st_mode() );
308  }
309  }
310  return ret;
311  }
312 
314  //
315  // METHOD NAME : TmpDir::defaultPrefix
316  // METHOD TYPE : const std::string &
317  //
318  const std::string &
320  {
321  static std::string p( "TmpDir." );
322  return p;
323  }
324 
325  } // namespace filesystem
326 } // namespace zypp
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:320
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:167
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:300
TmpPath()
Default Ctor.
Definition: TmpPath.cc:112
#define INT
Definition: Logger.h:100
int chmod(const Pathname &path, mode_t mode)
Like &#39;chmod&#39;.
Definition: PathInfo.cc:1093
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:443
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:266
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:127
#define ERR
Definition: Logger.h:98
const D * get() const
Definition: PtrTypes.h:339
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
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:177
static const std::string & defaultPrefix()
Definition: TmpPath.cc:249
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:701
const Pathname & path() const
Definition: TmpPath.cc:86
const std::string & asString() const
String representation.
Definition: Pathname.h:91
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:124
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:413
#define nullptr
Definition: Easy.h:55
Base class for reference counted objects.
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:222
std::string strerror(int errno_r)
Return string describing the error_r code.
Definition: String.cc:54
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
void autoCleanup(bool yesno_r)
Definition: TmpPath.cc:92
#define DBG
Definition: Logger.h:95
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:235
static const std::string & defaultPrefix()
Definition: TmpPath.cc:319