libzypp  17.38.7
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
34  //
39  {
40  public:
41 
42  enum Flags
43  {
44  NoOp = 0,
45  Autodelete = 1L << 0,
46  KeepTopdir = 1L << 1,
47  //
49  };
50 
51  public:
52  Impl(Pathname &&path_r, Flags flags_r = CtorDefault)
53  : _path(std::move(path_r)), _flags(flags_r) {
54  MIL << _path << endl;
55  }
56 
57  Impl(const Impl &) = delete;
58  Impl(Impl &&) = delete;
59  Impl &operator=(const Impl &) = delete;
60  Impl &operator=(Impl &&) = delete;
61 
62  ~Impl() override
63  {
64  if ( ! (_flags & Autodelete) || _path.empty() )
65  return;
66 
68  if ( ! p.isExist() )
69  return;
70 
71  int res = 0;
72  if ( p.isDir() )
73  {
74  if ( _flags & KeepTopdir )
75  res = clean_dir( _path );
76  else
77  res = recursive_rmdir( _path );
78  }
79  else
80  res = unlink( _path );
81 
82  if ( res )
83  INT << "TmpPath cleanup error (" << res << ") " << p << endl;
84  else
85  DBG << "TmpPath cleaned up " << p << endl;
86  }
87 
88  const Pathname & 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  // CLASS NAME : TmpPath
106 
108  {}
109 
111  :_impl( tmpPath_r.empty() ? nullptr : new Impl( std::move(tmpPath_r) ) )
112  {}
113 
115  {
116  // virtual not inlined dtor.
117  }
118 
119  TmpPath::operator bool() const
120  {
121  return _impl.get();
122  }
123 
125  {
126  return _impl.get() ? _impl->path() : Pathname();
127  }
128 
130  {
131  // bsc#1249435: We use 'zypp.tmp' as a fix directory
132  // component to ease setting up SELinux policies.
133  static Pathname p = []() {
134  Pathname ret = Pathname( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
135  if ( geteuid() == 0 )
136  ret /= "zypp.tmp";
137  return ret;
138  }();
139  return p;
140  }
141 
142  bool TmpPath::autoCleanup() const
143  { return _impl.get() ? _impl->autoCleanup() : false; }
144 
145  void TmpPath::autoCleanup( bool yesno_r )
146  { if ( _impl.get() ) _impl->autoCleanup( yesno_r ); }
147 
149  // CLASS NAME : TmpFile
151 
152  TmpFile::TmpFile( const Pathname & inParentDir_r,
153  const std::string & prefix_r )
154  {
155  // parent dir must exist
156  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
157  {
158  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
159  return;
160  }
161 
162  // create the temp file
163  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
164  AutoFREE<char> buf { ::strdup( tmpPath.asString().c_str() ) };
165  if ( ! buf )
166  {
167  ERR << "Out of memory" << endl;
168  return;
169  }
170 
171  int tmpFd = ::mkostemp( buf, O_CLOEXEC );
172  if ( tmpFd != -1 )
173  {
174  // success; create _impl
175  ::close( tmpFd );
176  _impl = RW_pointer<Impl>( new Impl( Pathname(buf) ) );
177  }
178  else
179  ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
180  }
181 
182  TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
183  { return makeSibling( sibling_r, -1U ); }
184 
185  TmpFile TmpFile::makeSibling( const Pathname & sibling_r, unsigned mode )
186  {
187  TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
188  if ( ret ) {
189  // clone mode if sibling_r exists
190  PathInfo p( sibling_r );
191  if ( p.isFile() ) {
192  ::chmod( ret.path().c_str(), p.st_mode() );
193  } else if ( mode != -1U ) {
194  ::chmod( ret.path().c_str(), applyUmaskTo( mode ) );
195  }
196  }
197  return ret;
198  }
199 
201  {
203  }
204 
205  ManagedFile TmpFile::asManagedFile(const Pathname &inParentDir_r, const std::string &prefix_r)
206  {
207  filesystem::TmpFile tmpFile( inParentDir_r, prefix_r );
208  ManagedFile mFile ( tmpFile.path(), filesystem::unlink );
209  tmpFile.autoCleanup(false); //cleaned up by ManagedFile
210  return mFile;
211  }
212 
213  const std::string & TmpFile::defaultPrefix()
214  {
215  static std::string p( "TmpFile." );
216  return p;
217  }
218 
220  // CLASS NAME : TmpDir
222 
223  TmpDir::TmpDir( const Pathname & inParentDir_r,
224  const std::string & prefix_r )
225  {
226  // parent dir must exist
227  if ( filesystem::assert_dir( inParentDir_r ) != 0 )
228  {
229  ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
230  return;
231  }
232 
233  // create the temp dir
234  Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
235  AutoFREE<char> buf { ::strdup( tmpPath.asString().c_str() ) };
236  if ( ! buf )
237  {
238  ERR << "Out of memory" << endl;
239  return;
240  }
241 
242  char * tmp = ::mkdtemp( buf );
243  if ( tmp )
244  // success; create _impl
245  _impl = RW_pointer<Impl>( new Impl( tmp ) );
246  else
247  ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
248  }
249 
250  TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
251  { return makeSibling( sibling_r, -1U ); }
252 
253  TmpDir TmpDir::makeSibling( const Pathname & sibling_r, unsigned mode )
254  {
255  TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
256  if ( ret ) {
257  // clone mode if sibling_r exists
258  PathInfo p( sibling_r );
259  if ( p.isDir() ) {
260  ::chmod( ret.path().c_str(), p.st_mode() );
261  } else if ( mode != -1U ) {
262  ::chmod( ret.path().c_str(), applyUmaskTo( mode ) );
263  }
264  }
265  return ret;
266  }
267 
268  const std::string & TmpDir::defaultPrefix()
269  {
270  static std::string p( "TmpDir." );
271  return p;
272  }
273 
274  } // namespace filesystem
275 
277  {
278  static filesystem::TmpDir _tmpdir( filesystem::TmpPath::defaultLocation(), "zypp." );
279  return _tmpdir.path();
280  }
281 
282 } // namespace zypp
#define MIL
Definition: Logger.h:103
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:142
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:338
TmpFile(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:152
static TmpDir makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:250
int clean_dir(const Pathname &path)
Like &#39;rm -r DIR/ *&#39;.
Definition: PathInfo.cc:461
TmpPath()
Default Ctor.
Definition: TmpPath.cc:107
#define INT
Definition: Logger.h:107
int chmod(const Pathname &path, mode_t mode)
Like &#39;chmod&#39;.
Definition: PathInfo.cc:1111
Impl(Pathname &&path_r, Flags flags_r=CtorDefault)
Definition: TmpPath.cc:52
Definition: ansi.h:854
static const Pathname & defaultLocation()
Definition: TmpPath.cc:129
Pathname path() const
Definition: TmpPath.cc:124
TmpDir(const Pathname &inParentDir_r=defaultLocation(), const std::string &prefix_r=defaultPrefix())
Ctor.
Definition: TmpPath.cc:223
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:137
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:117
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:431
#define ERR
Definition: Logger.h:105
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:117
Clean or delete a directory on destruction.
Definition: TmpPath.cc:38
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h:172
static const std::string & defaultPrefix()
Definition: TmpPath.cc:213
const Pathname & path() const
Definition: TmpPath.cc:88
const std::string & asString() const
String representation.
Definition: Pathname.h:94
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:133
Base class for reference counted objects.
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:719
virtual ~TmpPath()
Dtor.
Definition: TmpPath.cc:114
Impl & operator=(const Impl &)=delete
RW_pointer< Impl > _impl
Definition: TmpPath.h:92
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:182
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Definition: PathInfo.h:814
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
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:276
#define DBG
Definition: Logger.h:102
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:200
static const std::string & defaultPrefix()
Definition: TmpPath.cc:268