build require libproxy
[platform/upstream/libzypp.git] / zypp / TmpPath.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/TmpPath.cc
10  *
11 */
12
13 #include <cstdlib>
14 #include <cstring>
15 #include <cerrno>
16
17 #include <iostream>
18
19 #include "zypp/base/ReferenceCounted.h"
20 #include "zypp/base/NonCopyable.h"
21 #include "zypp/base/Logger.h"
22 #include "zypp/PathInfo.h"
23 #include "zypp/TmpPath.h"
24
25 using namespace std;
26
27 namespace zypp {
28   namespace filesystem {
29
30     ///////////////////////////////////////////////////////////////////
31     //
32     //  CLASS NAME : TmpPath::Impl
33     /**
34      * Clean or delete a directory on destruction.
35      **/
36     class TmpPath::Impl : public base::ReferenceCounted, private base::NonCopyable
37     {
38       public:
39
40         enum Flags
41           {
42             NoOp         = 0,
43             Autodelete   = 1L << 0,
44             KeepTopdir   = 1L << 1,
45             //
46             CtorDefault  = Autodelete
47           };
48
49       public:
50
51         Impl( const Pathname & path_r, Flags flags_r = CtorDefault )
52         : _path( path_r ), _flags( flags_r )
53         {}
54
55         ~Impl()
56         {
57           if ( ! (_flags & Autodelete) || _path.empty() )
58             return;
59
60           PathInfo p( _path, PathInfo::LSTAT );
61           if ( ! p.isExist() )
62             return;
63
64           int res = 0;
65           if ( p.isDir() )
66             {
67               if ( _flags & KeepTopdir )
68                 res = clean_dir( _path );
69               else
70                 res = recursive_rmdir( _path );
71             }
72           else
73             res = unlink( _path );
74
75           if ( res )
76             INT << "TmpPath cleanup error (" << res << ") " << p << endl;
77           else
78             DBG << "TmpPath cleaned up " << p << endl;
79         }
80
81         const Pathname &
82         path() const
83         { return _path; }
84
85       private:
86         Pathname _path;
87         Flags    _flags;
88     };
89     ///////////////////////////////////////////////////////////////////
90
91     ///////////////////////////////////////////////////////////////////
92     //
93     //  CLASS NAME : TmpPath
94     //
95     ///////////////////////////////////////////////////////////////////
96
97     ///////////////////////////////////////////////////////////////////
98     //
99     //  METHOD NAME : TmpPath::TmpPath
100     //  METHOD TYPE : Constructor
101     //
102     TmpPath::TmpPath()
103     :_impl( 0 ) // empty Pathname
104     {
105     }
106
107     ///////////////////////////////////////////////////////////////////
108     //
109     //  METHOD NAME : TmpPath::TmpPath
110     //  METHOD TYPE : Constructor
111     //
112     TmpPath::TmpPath( const Pathname & tmpPath_r )
113     :_impl( tmpPath_r.empty() ? 0 : new Impl( tmpPath_r ) )
114     {
115     }
116
117     ///////////////////////////////////////////////////////////////////
118     //
119     //  METHOD NAME : TmpPath::~TmpPath
120     //  METHOD TYPE : Destructor
121     //
122     TmpPath::~TmpPath()
123     {
124       // virtual not inlined dtor.
125     }
126
127     ///////////////////////////////////////////////////////////////////
128     //
129     //      METHOD NAME : TmpPath::operator const void *
130     //      METHOD TYPE :
131     //
132     TmpPath::operator const void * () const
133     {
134       return _impl.get();
135     }
136
137     ///////////////////////////////////////////////////////////////////
138     //
139     //  METHOD NAME : TmpPath::path
140     //  METHOD TYPE : Pathname
141     //
142     Pathname
143     TmpPath::path() const
144     {
145       return _impl.get() ? _impl->path() : Pathname();
146     }
147
148     ///////////////////////////////////////////////////////////////////
149     //
150     //  METHOD NAME : TmpPath::defaultLocation
151     //  METHOD TYPE : const Pathname &
152     //
153     const Pathname &
154     TmpPath::defaultLocation()
155     {
156       static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" );
157       return p;
158     }
159     ///////////////////////////////////////////////////////////////////
160     //
161     //  CLASS NAME : TmpFile
162     //
163     ///////////////////////////////////////////////////////////////////
164
165
166     ///////////////////////////////////////////////////////////////////
167     //
168     //  METHOD NAME : TmpFile::TmpFile
169     //  METHOD TYPE : Constructor
170     //
171     TmpFile::TmpFile( const Pathname & inParentDir_r,
172                       const std::string & prefix_r )
173     {
174       // parent dir must exist
175       if ( filesystem::assert_dir( inParentDir_r ) != 0 )
176       {
177         ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
178         return;
179       }
180
181       // create the temp file
182       Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
183       char * buf = ::strdup( tmpPath.asString().c_str() );
184       if ( ! buf )
185         {
186           ERR << "Out of memory" << endl;
187           return;
188         }
189
190       int tmpFd = ::mkstemp( buf );
191       if ( tmpFd != -1 )
192         {
193           // success; create _impl
194           ::close( tmpFd );
195           _impl = RW_pointer<Impl>( new Impl( buf ) );
196         }
197       else
198         ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl;
199
200       ::free( buf );
201     }
202
203     ///////////////////////////////////////////////////////////////////
204     //
205     //  METHOD NAME : TmpFile::makeSibling
206     //  METHOD TYPE : TmpFile
207     //
208     TmpFile TmpFile::makeSibling( const Pathname & sibling_r )
209     {
210       TmpFile ret( sibling_r.dirname(), sibling_r.basename() );
211       // clone mode if sibling_r exists
212       PathInfo p( sibling_r );
213       if ( p.isFile() )
214       {
215         ::chmod( ret.path().c_str(), p.st_mode() );
216       }
217       return ret;
218     }
219
220     ///////////////////////////////////////////////////////////////////
221     //
222     //  METHOD NAME : TmpFile::defaultPrefix
223     //  METHOD TYPE : const std::string &
224     //
225     const std::string &
226     TmpFile::defaultPrefix()
227     {
228       static string p( "TmpFile." );
229       return p;
230     }
231
232     ///////////////////////////////////////////////////////////////////
233     //
234     //  CLASS NAME : TmpDir
235     //
236     ///////////////////////////////////////////////////////////////////
237
238     ///////////////////////////////////////////////////////////////////
239     //
240     //  METHOD NAME : TmpDir::TmpDir
241     //  METHOD TYPE : Constructor
242     //
243     TmpDir::TmpDir( const Pathname & inParentDir_r,
244                     const std::string & prefix_r )
245     {
246       // parent dir must exist
247       if ( filesystem::assert_dir( inParentDir_r ) != 0  )
248       {
249         ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl;
250         return;
251       }
252
253       // create the temp dir
254       Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX");
255       char * buf = ::strdup( tmpPath.asString().c_str() );
256       if ( ! buf )
257         {
258           ERR << "Out of memory" << endl;
259           return;
260         }
261
262       char * tmp = ::mkdtemp( buf );
263       if ( tmp )
264         // success; create _impl
265         _impl = RW_pointer<Impl>( new Impl( tmp ) );
266       else
267         ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl;
268
269       ::free( buf );
270     }
271
272     ///////////////////////////////////////////////////////////////////
273     //
274     //  METHOD NAME : TmpDir::makeSibling
275     //  METHOD TYPE : TmpDir
276     //
277     TmpDir TmpDir::makeSibling( const Pathname & sibling_r )
278     {
279       TmpDir ret( sibling_r.dirname(), sibling_r.basename() );
280       // clone mode if sibling_r exists
281       PathInfo p( sibling_r );
282       if ( p.isDir() )
283       {
284         ::chmod( ret.path().c_str(), p.st_mode() );
285       }
286       return ret;
287     }
288
289     ///////////////////////////////////////////////////////////////////
290     //
291     //  METHOD NAME : TmpDir::defaultPrefix
292     //  METHOD TYPE : const std::string &
293     //
294     const std::string &
295     TmpDir::defaultPrefix()
296     {
297       static string p( "TmpDir." );
298       return p;
299     }
300
301   } // namespace filesystem
302 } // namespace zypp