• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

ktempdir.cpp

Go to the documentation of this file.
00001 /* kate: tab-indents off; replace-tabs on; tab-width 4; remove-trailing-space on; encoding utf-8;*/
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (c) 2003 Joseph Wenninger <jowenn@kde.org>
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License version 2 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Library General Public License
00016  *  along with this library; see the file COPYING.LIB.  If not, write to
00017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  *  Boston, MA 02110-1301, USA.
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 #ifdef _WIN32_WCE
00061 #include <shellapi.h>
00062 #endif
00063 
00064 class KTempDir::Private
00065 {
00066 public:
00067     int error;
00068     QString tmpName;
00069     bool exists;
00070     bool autoRemove;
00071 
00072     Private()
00073     {
00074         autoRemove = true;
00075         exists = false;
00076         error=0;
00077     }
00078 };
00079 
00080 KTempDir::KTempDir(const QString &directoryPrefix, int mode) : d(new Private)
00081 {
00082     (void) create( directoryPrefix.isEmpty() ? KStandardDirs::locateLocal("tmp", KGlobal::mainComponent().componentName()) : directoryPrefix , mode);
00083 }
00084 
00085 bool KTempDir::create(const QString &directoryPrefix, int mode)
00086 {
00087    (void) KRandom::random();
00088 
00089 #ifdef Q_WS_WIN
00090    const QString nme = directoryPrefix + QLatin1String("XXXXXX");
00091    const QString realName = mkdtemp_QString(nme);
00092    if(realName.isEmpty())
00093    {
00094        kWarning(180) << "KTempDir: Error trying to create " << nme
00095               << ": " << ::strerror(errno) << endl;
00096        d->error = errno;
00097        d->tmpName.clear();
00098        return false;
00099    }
00100 
00101    // got a return value != 0
00102    d->tmpName = realName + QLatin1Char('/');
00103    kDebug(180) << "KTempDir: Temporary directory created :" << d->tmpName
00104             << endl;
00105    mode_t umsk = KGlobal::umask();
00106    KDE::chmod(nme, mode&(~umsk));
00107 
00108    // Success!
00109    d->exists = true;
00110 #else
00111    QByteArray nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
00112    char *realName;
00113    if((realName=mkdtemp(nme.data())) == 0)
00114    {
00115        // Recreate it for the warning, mkdtemps emptied it
00116        nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
00117        kWarning(180) << "KTempDir: Error trying to create " << nme.data()
00118               << ": " << ::strerror(errno) << endl;
00119        d->error = errno;
00120        d->tmpName.clear();
00121        return false;
00122    }
00123 
00124    // got a return value != 0
00125    QByteArray realNameStr(realName);
00126    d->tmpName = QFile::decodeName(realNameStr)+QLatin1Char('/');
00127    kDebug(180) << "KTempDir: Temporary directory created :" << d->tmpName
00128             << endl;
00129 
00130    mode_t umsk = KGlobal::umask();
00131    if(chmod(nme, mode&(~umsk)) < 0) {
00132        kWarning(180) << "KTempDir: Unable to change permissions on" << d->tmpName
00133                      << ":" << ::strerror(errno);
00134        d->error = errno;
00135        d->tmpName.clear();
00136        (void) ::rmdir(realName); // Cleanup created directory
00137        return false;
00138    }
00139 
00140    // Success!
00141    d->exists = true;
00142 
00143    // Set uid/gid (necessary for SUID programs)
00144    if(chown(nme, getuid(), getgid()) < 0) {
00145        // Just warn, but don't failover yet
00146        kWarning(180) << "KTempDir: Unable to change owner on" << d->tmpName
00147                      << ":" << ::strerror(errno);
00148    }
00149 
00150 #endif
00151    return true;
00152 }
00153 
00154 KTempDir::~KTempDir()
00155 {
00156     if (d->autoRemove) {
00157         unlink();
00158     }
00159 
00160     delete d;
00161 }
00162 
00163 int KTempDir::status() const
00164 {
00165     return d->error;
00166 }
00167 
00168 QString KTempDir::name() const
00169 {
00170     return d->tmpName;
00171 }
00172 
00173 bool KTempDir::exists() const
00174 {
00175     return d->exists;
00176 }
00177 
00178 void KTempDir::setAutoRemove(bool autoRemove)
00179 {
00180     d->autoRemove = autoRemove;
00181 }
00182 
00183 bool KTempDir::autoRemove() const
00184 {
00185     return d->autoRemove;
00186 }
00187 
00188 void KTempDir::unlink()
00189 {
00190     if (!d->exists) return;
00191     if (KTempDir::removeDir(d->tmpName))
00192         d->error=0;
00193     else
00194         d->error=errno;
00195     d->exists=false;
00196 }
00197 
00198 #ifndef Q_WS_WIN
00199 // Auxiliary recursive function for removeDirs
00200 static bool rmtree(const QByteArray& name)
00201 {
00202     //kDebug(180) << "Checking directory for remove" << name;
00203     KDE_struct_stat st;
00204     if ( KDE_lstat( name.data(), &st ) == -1 ) // Do not dereference symlink!
00205         return false;
00206     if ( S_ISDIR( st.st_mode ) )
00207     {
00208         // This is a directory, so process it
00209         //kDebug(180) << "File" << name << "is DIRECTORY!";
00210         KDE_struct_dirent* ep;
00211         DIR* dp = ::opendir( name.data() );
00212         if ( !dp )
00213             return false;
00214         while ( ( ep = KDE_readdir( dp ) ) )
00215         {
00216             //kDebug(180) << "CHECKING" << name << "/" << ep->d_name;
00217             if ( !qstrcmp( ep->d_name, "." ) || !qstrcmp( ep->d_name, ".." ) )
00218                 continue;
00219             QByteArray newName( name );
00220             newName += '/';
00221             newName += ep->d_name;
00222             /*
00223              * Be defensive and close the directory.
00224              *
00225              * Potential problems:
00226              * - opendir/readdir/closedir is not re-entrant
00227              * - unlink and rmdir invalidates a opendir/readdir/closedir
00228              * - limited number of file descriptors for opendir/readdir/closedir
00229              */
00230             if ( ::closedir( dp ) ) {
00231                 kDebug(180) << "Error closing" << name;
00232                 return false;
00233             }
00234             // Recurse!
00235             //kDebug(180) << "RECURSE: " << newName;
00236             if ( ! rmtree( newName ) )
00237                 return false;
00238             // We have to re-open the directory before continuing
00239             dp = ::opendir( name.data() );
00240             if ( !dp )
00241                 return false;
00242         }
00243         if ( ::closedir( dp ) ) {
00244             kDebug(180) << "Error closing" << name;
00245             return false;
00246         }
00247         //kDebug(180) << "RMDIR dir " << name;
00248         return ! ::rmdir( name );
00249     }
00250     else
00251     {
00252         // This is a non-directory file, so remove it
00253         //kDebug(180) << "KTempDir: unlinking file" << name;
00254         return ! ::unlink( name );
00255     }
00256 }
00257 #endif
00258 
00259 bool KTempDir::removeDir( const QString& path )
00260 {
00261     //kDebug(180) << path;
00262     if ( !QFile::exists( path ) )
00263         return true; // The goal is that there is no directory
00264 
00265 #ifdef Q_WS_WIN
00266     QVarLengthArray<WCHAR, MAX_PATH> name;
00267     name.resize( path.length() + 2 ); // double null terminated!
00268     memcpy( name.data(), path.utf16(), path.length() * sizeof(WCHAR) );
00269     name[path.length()     ] = 0;
00270     name[path.length() + 1 ] = 0;
00271     if(path.endsWith(QLatin1Char('/')) || path.endsWith(QLatin1Char('\\')))
00272       name[path.length() - 1 ] = 0;
00273     SHFILEOPSTRUCTW fileOp;
00274     memset(&fileOp, 0, sizeof(SHFILEOPSTRUCTW) );
00275     fileOp.wFunc = FO_DELETE;
00276     fileOp.pFrom = (LPCWSTR)name.constData();
00277     fileOp.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;
00278 #ifdef _WIN32_WCE
00279     // FOF_NOERRORUI is not defined in wince
00280 #else
00281     fileOp.fFlags |= FOF_NOERRORUI;
00282 #endif
00283     errno = SHFileOperationW( &fileOp );
00284     return (errno == 0);
00285 #else
00286     const QByteArray cstr( QFile::encodeName( path ) );
00287     return rmtree( cstr );
00288 #endif
00289 }
00290 

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal