libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00013 #include <cstdlib> 00014 #include <cstring> 00015 #include <cerrno> 00016 00017 #include <iostream> 00018 00019 #include "zypp/base/ReferenceCounted.h" 00020 #include "zypp/base/NonCopyable.h" 00021 #include "zypp/base/Logger.h" 00022 #include "zypp/PathInfo.h" 00023 #include "zypp/TmpPath.h" 00024 00025 using namespace std; 00026 00027 namespace zypp { 00028 namespace filesystem { 00029 00031 // 00032 // CLASS NAME : TmpPath::Impl 00036 class TmpPath::Impl : public base::ReferenceCounted, private base::NonCopyable 00037 { 00038 public: 00039 00040 enum Flags 00041 { 00042 NoOp = 0, 00043 Autodelete = 1L << 0, 00044 KeepTopdir = 1L << 1, 00045 // 00046 CtorDefault = Autodelete 00047 }; 00048 00049 public: 00050 00051 Impl( const Pathname & path_r, Flags flags_r = CtorDefault ) 00052 : _path( path_r ), _flags( flags_r ) 00053 {} 00054 00055 ~Impl() 00056 { 00057 if ( ! (_flags & Autodelete) || _path.empty() ) 00058 return; 00059 00060 PathInfo p( _path, PathInfo::LSTAT ); 00061 if ( ! p.isExist() ) 00062 return; 00063 00064 int res = 0; 00065 if ( p.isDir() ) 00066 { 00067 if ( _flags & KeepTopdir ) 00068 res = clean_dir( _path ); 00069 else 00070 res = recursive_rmdir( _path ); 00071 } 00072 else 00073 res = unlink( _path ); 00074 00075 if ( res ) 00076 INT << "TmpPath cleanup error (" << res << ") " << p << endl; 00077 else 00078 DBG << "TmpPath cleaned up " << p << endl; 00079 } 00080 00081 const Pathname & 00082 path() const 00083 { return _path; } 00084 00085 bool autoCleanup() const 00086 { return( _flags & Autodelete ); } 00087 00088 void autoCleanup( bool yesno_r ) 00089 { _flags = yesno_r ? CtorDefault : NoOp; } 00090 00091 private: 00092 Pathname _path; 00093 Flags _flags; 00094 }; 00096 00098 // 00099 // CLASS NAME : TmpPath 00100 // 00102 00104 // 00105 // METHOD NAME : TmpPath::TmpPath 00106 // METHOD TYPE : Constructor 00107 // 00108 TmpPath::TmpPath() 00109 :_impl( 0 ) // empty Pathname 00110 { 00111 } 00112 00114 // 00115 // METHOD NAME : TmpPath::TmpPath 00116 // METHOD TYPE : Constructor 00117 // 00118 TmpPath::TmpPath( const Pathname & tmpPath_r ) 00119 :_impl( tmpPath_r.empty() ? 0 : new Impl( tmpPath_r ) ) 00120 { 00121 } 00122 00124 // 00125 // METHOD NAME : TmpPath::~TmpPath 00126 // METHOD TYPE : Destructor 00127 // 00128 TmpPath::~TmpPath() 00129 { 00130 // virtual not inlined dtor. 00131 } 00132 00134 // 00135 // METHOD NAME : TmpPath::operator const void * 00136 // METHOD TYPE : 00137 // 00138 TmpPath::operator const void * () const 00139 { 00140 return _impl.get(); 00141 } 00142 00144 // 00145 // METHOD NAME : TmpPath::path 00146 // METHOD TYPE : Pathname 00147 // 00148 Pathname 00149 TmpPath::path() const 00150 { 00151 return _impl.get() ? _impl->path() : Pathname(); 00152 } 00153 00155 // 00156 // METHOD NAME : TmpPath::defaultLocation 00157 // METHOD TYPE : const Pathname & 00158 // 00159 const Pathname & 00160 TmpPath::defaultLocation() 00161 { 00162 static Pathname p( getenv("ZYPPTMPDIR") ? getenv("ZYPPTMPDIR") : "/var/tmp" ); 00163 return p; 00164 } 00165 00166 bool TmpPath::autoCleanup() const 00167 { return _impl.get() ? _impl->autoCleanup() : false; } 00168 00169 void TmpPath::autoCleanup( bool yesno_r ) 00170 { if ( _impl.get() ) _impl->autoCleanup( yesno_r ); } 00171 00173 // 00174 // CLASS NAME : TmpFile 00175 // 00177 00178 00180 // 00181 // METHOD NAME : TmpFile::TmpFile 00182 // METHOD TYPE : Constructor 00183 // 00184 TmpFile::TmpFile( const Pathname & inParentDir_r, 00185 const std::string & prefix_r ) 00186 { 00187 // parent dir must exist 00188 if ( filesystem::assert_dir( inParentDir_r ) != 0 ) 00189 { 00190 ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl; 00191 return; 00192 } 00193 00194 // create the temp file 00195 Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX"); 00196 char * buf = ::strdup( tmpPath.asString().c_str() ); 00197 if ( ! buf ) 00198 { 00199 ERR << "Out of memory" << endl; 00200 return; 00201 } 00202 00203 int tmpFd = ::mkostemp( buf, O_CLOEXEC ); 00204 if ( tmpFd != -1 ) 00205 { 00206 // success; create _impl 00207 ::close( tmpFd ); 00208 _impl = RW_pointer<Impl>( new Impl( buf ) ); 00209 } 00210 else 00211 ERR << "Cant create '" << buf << "' " << ::strerror( errno ) << endl; 00212 00213 ::free( buf ); 00214 } 00215 00217 // 00218 // METHOD NAME : TmpFile::makeSibling 00219 // METHOD TYPE : TmpFile 00220 // 00221 TmpFile TmpFile::makeSibling( const Pathname & sibling_r ) 00222 { 00223 TmpFile ret( sibling_r.dirname(), sibling_r.basename() ); 00224 // clone mode if sibling_r exists 00225 PathInfo p( sibling_r ); 00226 if ( p.isFile() ) 00227 { 00228 ::chmod( ret.path().c_str(), p.st_mode() ); 00229 } 00230 return ret; 00231 } 00232 00234 // 00235 // METHOD NAME : TmpFile::defaultPrefix 00236 // METHOD TYPE : const std::string & 00237 // 00238 const std::string & 00239 TmpFile::defaultPrefix() 00240 { 00241 static string p( "TmpFile." ); 00242 return p; 00243 } 00244 00246 // 00247 // CLASS NAME : TmpDir 00248 // 00250 00252 // 00253 // METHOD NAME : TmpDir::TmpDir 00254 // METHOD TYPE : Constructor 00255 // 00256 TmpDir::TmpDir( const Pathname & inParentDir_r, 00257 const std::string & prefix_r ) 00258 { 00259 // parent dir must exist 00260 if ( filesystem::assert_dir( inParentDir_r ) != 0 ) 00261 { 00262 ERR << "Parent directory '" << inParentDir_r << "' can't be created." << endl; 00263 return; 00264 } 00265 00266 // create the temp dir 00267 Pathname tmpPath = (inParentDir_r + prefix_r).extend( "XXXXXX"); 00268 char * buf = ::strdup( tmpPath.asString().c_str() ); 00269 if ( ! buf ) 00270 { 00271 ERR << "Out of memory" << endl; 00272 return; 00273 } 00274 00275 char * tmp = ::mkdtemp( buf ); 00276 if ( tmp ) 00277 // success; create _impl 00278 _impl = RW_pointer<Impl>( new Impl( tmp ) ); 00279 else 00280 ERR << "Cant create '" << tmpPath << "' " << ::strerror( errno ) << endl; 00281 00282 ::free( buf ); 00283 } 00284 00286 // 00287 // METHOD NAME : TmpDir::makeSibling 00288 // METHOD TYPE : TmpDir 00289 // 00290 TmpDir TmpDir::makeSibling( const Pathname & sibling_r ) 00291 { 00292 TmpDir ret( sibling_r.dirname(), sibling_r.basename() ); 00293 // clone mode if sibling_r exists 00294 PathInfo p( sibling_r ); 00295 if ( p.isDir() ) 00296 { 00297 ::chmod( ret.path().c_str(), p.st_mode() ); 00298 } 00299 return ret; 00300 } 00301 00303 // 00304 // METHOD NAME : TmpDir::defaultPrefix 00305 // METHOD TYPE : const std::string & 00306 // 00307 const std::string & 00308 TmpDir::defaultPrefix() 00309 { 00310 static string p( "TmpDir." ); 00311 return p; 00312 } 00313 00314 } // namespace filesystem 00315 } // namespace zypp