KDECore
ktempdir.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ktempdir.h"
00022
00023 #include <config.h>
00024
00025 #include <sys/types.h>
00026
00027 #ifdef HAVE_SYS_STAT_H
00028 #include <sys/stat.h>
00029 #endif
00030
00031 #include <fcntl.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 #include <errno.h>
00035 #include <dirent.h>
00036
00037 #ifdef HAVE_TEST
00038 #include <test.h>
00039 #endif
00040 #ifdef HAVE_PATHS_H
00041 #include <paths.h>
00042 #endif
00043
00044 #include <QtCore/QDir>
00045
00046 #include "kglobal.h"
00047 #include "krandom.h"
00048 #include "kcomponentdata.h"
00049 #include "kstandarddirs.h"
00050 #include <kdebug.h>
00051 #include "kde_file.h"
00052
00053 #ifdef Q_WS_WIN
00054 #include <QtCore/QVarLengthArray>
00055 #include <windows.h>
00056 #include <shellapi.h>
00057 extern QString mkdtemp_QString (const QString &_template);
00058 #endif
00059
00060 class KTempDir::Private
00061 {
00062 public:
00063 int error;
00064 QString tmpName;
00065 bool exists;
00066 bool autoRemove;
00067
00068 Private()
00069 {
00070 autoRemove = true;
00071 exists = false;
00072 error=0;
00073 }
00074 };
00075
00076 KTempDir::KTempDir(const QString &directoryPrefix, int mode) : d(new Private)
00077 {
00078 (void) create( directoryPrefix.isEmpty() ? KStandardDirs::locateLocal("tmp", KGlobal::mainComponent().componentName()) : directoryPrefix , mode);
00079 }
00080
00081 bool KTempDir::create(const QString &directoryPrefix, int mode)
00082 {
00083 (void) KRandom::random();
00084
00085 #ifdef Q_WS_WIN
00086 const QString nme = directoryPrefix + "XXXXXX";
00087 const QString realName = mkdtemp_QString(nme);
00088 if(realName.isEmpty())
00089 {
00090 kWarning(180) << "KTempDir: Error trying to create " << nme
00091 << ": " << ::strerror(errno) << endl;
00092 d->error = errno;
00093 d->tmpName.clear();
00094 return false;
00095 }
00096
00097
00098 d->tmpName = realName + '/';
00099 kDebug(180) << "KTempDir: Temporary directory created :" << d->tmpName
00100 << endl;
00101 mode_t umsk = KGlobal::umask();
00102 KDE::chmod(nme, mode&(~umsk));
00103
00104
00105 d->exists = true;
00106 #else
00107 QByteArray nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
00108 char *realName;
00109 if((realName=mkdtemp(nme.data())) == 0)
00110 {
00111
00112 nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
00113 kWarning(180) << "KTempDir: Error trying to create " << nme.data()
00114 << ": " << ::strerror(errno) << endl;
00115 d->error = errno;
00116 d->tmpName.clear();
00117 return false;
00118 }
00119
00120
00121 QByteArray realNameStr(realName);
00122 d->tmpName = QFile::decodeName(realNameStr)+'/';
00123 kDebug(180) << "KTempDir: Temporary directory created :" << d->tmpName
00124 << endl;
00125 mode_t umsk = KGlobal::umask();
00126 chmod(nme, mode&(~umsk));
00127
00128
00129 d->exists = true;
00130
00131
00132 chown(nme, getuid(), getgid());
00133 #endif
00134 return true;
00135 }
00136
00137 KTempDir::~KTempDir()
00138 {
00139 if (d->autoRemove) {
00140 unlink();
00141 }
00142
00143 delete d;
00144 }
00145
00146 int KTempDir::status() const
00147 {
00148 return d->error;
00149 }
00150
00151 QString KTempDir::name() const
00152 {
00153 return d->tmpName;
00154 }
00155
00156 bool KTempDir::exists() const
00157 {
00158 return d->exists;
00159 }
00160
00161 void KTempDir::setAutoRemove(bool autoRemove)
00162 {
00163 d->autoRemove = autoRemove;
00164 }
00165
00166 bool KTempDir::autoRemove() const
00167 {
00168 return d->autoRemove;
00169 }
00170
00171 void KTempDir::unlink()
00172 {
00173 if (!d->exists) return;
00174 if (KTempDir::removeDir(d->tmpName))
00175 d->error=0;
00176 else
00177 d->error=errno;
00178 d->exists=false;
00179 }
00180
00181 #ifndef Q_WS_WIN
00182
00183 static bool rmtree(const QByteArray& name)
00184 {
00185
00186 KDE_struct_stat st;
00187 if ( KDE_lstat( name.data(), &st ) == -1 )
00188 return false;
00189 if ( S_ISDIR( st.st_mode ) )
00190 {
00191
00192
00193 KDE_struct_dirent* ep;
00194 DIR* dp = ::opendir( name.data() );
00195 if ( !dp )
00196 return false;
00197 while ( ( ep = KDE_readdir( dp ) ) )
00198 {
00199
00200 if ( !qstrcmp( ep->d_name, "." ) || !qstrcmp( ep->d_name, ".." ) )
00201 continue;
00202 QByteArray newName( name );
00203 newName += '/';
00204 newName += ep->d_name;
00205
00206
00207
00208
00209
00210
00211
00212
00213 if ( ::closedir( dp ) )
00214 return false;
00215
00216
00217 if ( ! rmtree( newName ) )
00218 return false;
00219
00220 dp = ::opendir( name.data() );
00221 if ( !dp )
00222 return false;
00223 }
00224 if ( ::closedir( dp ) )
00225 return false;
00226
00227 return ! ::rmdir( name );
00228 }
00229 else
00230 {
00231
00232 kDebug(180) << "KTempDir: unlinking file " << name;
00233 return ! ::unlink( name );
00234 }
00235 }
00236 #endif
00237
00238 bool KTempDir::removeDir( const QString& path )
00239 {
00240 kDebug(180) << " " << path;
00241 if ( !QFile::exists( path ) )
00242 return true;
00243
00244 #ifdef Q_WS_WIN
00245 QVarLengthArray<WCHAR, MAX_PATH> name;
00246 name.resize( path.length() + 2 );
00247 memcpy( name.data(), path.utf16(), path.length() * sizeof(WCHAR) );
00248 name[path.length() ] = 0;
00249 name[path.length() + 1 ] = 0;
00250 if(path.endsWith('/') || path.endsWith('\\'))
00251 name[path.length() - 1 ] = 0;
00252 SHFILEOPSTRUCTW fileOp;
00253 memset(&fileOp, 0, sizeof(SHFILEOPSTRUCTW) );
00254 fileOp.wFunc = FO_DELETE;
00255 fileOp.pFrom = (LPCWSTR)name.constData();
00256 fileOp.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
00257 errno = SHFileOperationW( &fileOp );
00258 return (errno == 0);
00259 #else
00260 const QByteArray cstr( QFile::encodeName( path ) );
00261 return rmtree( cstr );
00262 #endif
00263 }
00264