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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • io
ktempdir.cpp
Go to the documentation of this file.
1 /* kate: tab-indents off; replace-tabs on; tab-width 4; remove-trailing-space on; encoding utf-8;*/
2 /*
3  * This file is part of the KDE libraries
4  * Copyright (c) 2003 Joseph Wenninger <jowenn@kde.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License version 2 as published by the Free Software Foundation.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB. If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  **/
20 
21 #include "ktempdir.h"
22 
23 #include <config.h>
24 
25 #include <sys/types.h>
26 
27 #ifdef HAVE_SYS_STAT_H
28 #include <sys/stat.h>
29 #endif
30 
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <dirent.h>
36 
37 #ifdef HAVE_TEST
38 #include <test.h>
39 #endif
40 #ifdef HAVE_PATHS_H
41 #include <paths.h>
42 #endif
43 
44 #include <QtCore/QDir>
45 
46 #include "kglobal.h"
47 #include "krandom.h"
48 #include "kcomponentdata.h"
49 #include "kstandarddirs.h"
50 #include <kdebug.h>
51 #include "kde_file.h"
52 
53 #ifdef Q_WS_WIN
54 #include <QtCore/QVarLengthArray>
55 #include <windows.h>
56 #include <shellapi.h>
57 extern QString mkdtemp_QString (const QString &_template);
58 #endif
59 
60 #ifdef _WIN32_WCE
61 #include <shellapi.h>
62 #endif
63 
64 class KTempDir::Private
65 {
66 public:
67  int error;
68  QString tmpName;
69  bool exists;
70  bool autoRemove;
71 
72  Private()
73  {
74  autoRemove = true;
75  exists = false;
76  error=0;
77  }
78 };
79 
80 KTempDir::KTempDir(const QString &directoryPrefix, int mode) : d(new Private)
81 {
82  (void) create( directoryPrefix.isEmpty() ? KStandardDirs::locateLocal("tmp", KGlobal::mainComponent().componentName()) : directoryPrefix , mode);
83 }
84 
85 bool KTempDir::create(const QString &directoryPrefix, int mode)
86 {
87  (void) KRandom::random();
88 
89 #ifdef Q_WS_WIN
90  const QString nme = directoryPrefix + QLatin1String("XXXXXX");
91  const QString realName = mkdtemp_QString(nme);
92  if(realName.isEmpty())
93  {
94  kWarning(180) << "KTempDir: Error trying to create " << nme
95  << ": " << ::strerror(errno) << endl;
96  d->error = errno;
97  d->tmpName.clear();
98  return false;
99  }
100 
101  // got a return value != 0
102  d->tmpName = realName + QLatin1Char('/');
103  kDebug(180) << "KTempDir: Temporary directory created :" << d->tmpName
104  << endl;
105  mode_t umsk = KGlobal::umask();
106  KDE::chmod(nme, mode&(~umsk));
107 
108  // Success!
109  d->exists = true;
110 #else
111  QByteArray nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
112  char *realName;
113  if((realName=mkdtemp(nme.data())) == 0)
114  {
115  // Recreate it for the warning, mkdtemps emptied it
116  nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
117  kWarning(180) << "KTempDir: Error trying to create " << nme.data()
118  << ": " << ::strerror(errno) << endl;
119  d->error = errno;
120  d->tmpName.clear();
121  return false;
122  }
123 
124  // got a return value != 0
125  QByteArray realNameStr(realName);
126  d->tmpName = QFile::decodeName(realNameStr)+QLatin1Char('/');
127  kDebug(180) << "KTempDir: Temporary directory created :" << d->tmpName
128  << endl;
129 
130  mode_t umsk = KGlobal::umask();
131  if(chmod(nme, mode&(~umsk)) < 0) {
132  kWarning(180) << "KTempDir: Unable to change permissions on" << d->tmpName
133  << ":" << ::strerror(errno);
134  d->error = errno;
135  d->tmpName.clear();
136  (void) ::rmdir(realName); // Cleanup created directory
137  return false;
138  }
139 
140  // Success!
141  d->exists = true;
142 
143  // Set uid/gid (necessary for SUID programs)
144  if(chown(nme, getuid(), getgid()) < 0) {
145  // Just warn, but don't failover yet
146  kWarning(180) << "KTempDir: Unable to change owner on" << d->tmpName
147  << ":" << ::strerror(errno);
148  }
149 
150 #endif
151  return true;
152 }
153 
154 KTempDir::~KTempDir()
155 {
156  if (d->autoRemove) {
157  unlink();
158  }
159 
160  delete d;
161 }
162 
163 int KTempDir::status() const
164 {
165  return d->error;
166 }
167 
168 QString KTempDir::name() const
169 {
170  return d->tmpName;
171 }
172 
173 bool KTempDir::exists() const
174 {
175  return d->exists;
176 }
177 
178 void KTempDir::setAutoRemove(bool autoRemove)
179 {
180  d->autoRemove = autoRemove;
181 }
182 
183 bool KTempDir::autoRemove() const
184 {
185  return d->autoRemove;
186 }
187 
188 void KTempDir::unlink()
189 {
190  if (!d->exists) return;
191  if (KTempDir::removeDir(d->tmpName))
192  d->error=0;
193  else
194  d->error=errno;
195  d->exists=false;
196 }
197 
198 #ifndef Q_WS_WIN
199 // Auxiliary recursive function for removeDirs
200 static bool rmtree(const QByteArray& name)
201 {
202  //kDebug(180) << "Checking directory for remove" << name;
203  KDE_struct_stat st;
204  if ( KDE_lstat( name.data(), &st ) == -1 ) // Do not dereference symlink!
205  return false;
206  if ( S_ISDIR( st.st_mode ) )
207  {
208  // This is a directory, so process it
209  //kDebug(180) << "File" << name << "is DIRECTORY!";
210  KDE_struct_dirent* ep;
211  DIR* dp = ::opendir( name.data() );
212  if ( !dp )
213  return false;
214  while ( ( ep = KDE_readdir( dp ) ) )
215  {
216  //kDebug(180) << "CHECKING" << name << "/" << ep->d_name;
217  if ( !qstrcmp( ep->d_name, "." ) || !qstrcmp( ep->d_name, ".." ) )
218  continue;
219  QByteArray newName( name );
220  newName += '/';
221  newName += ep->d_name;
222  /*
223  * Be defensive and close the directory.
224  *
225  * Potential problems:
226  * - opendir/readdir/closedir is not re-entrant
227  * - unlink and rmdir invalidates a opendir/readdir/closedir
228  * - limited number of file descriptors for opendir/readdir/closedir
229  */
230  if ( ::closedir( dp ) ) {
231  kDebug(180) << "Error closing" << name;
232  return false;
233  }
234  // Recurse!
235  //kDebug(180) << "RECURSE: " << newName;
236  if ( ! rmtree( newName ) )
237  return false;
238  // We have to re-open the directory before continuing
239  dp = ::opendir( name.data() );
240  if ( !dp )
241  return false;
242  }
243  if ( ::closedir( dp ) ) {
244  kDebug(180) << "Error closing" << name;
245  return false;
246  }
247  //kDebug(180) << "RMDIR dir " << name;
248  return ! ::rmdir( name );
249  }
250  else
251  {
252  // This is a non-directory file, so remove it
253  //kDebug(180) << "KTempDir: unlinking file" << name;
254  return ! ::unlink( name );
255  }
256 }
257 #endif
258 
259 bool KTempDir::removeDir( const QString& path )
260 {
261  //kDebug(180) << path;
262  if ( !QFile::exists( path ) )
263  return true; // The goal is that there is no directory
264 
265 #ifdef Q_WS_WIN
266  QVarLengthArray<WCHAR, MAX_PATH> name;
267  name.resize( path.length() + 2 ); // double null terminated!
268  memcpy( name.data(), path.utf16(), path.length() * sizeof(WCHAR) );
269  name[path.length() ] = 0;
270  name[path.length() + 1 ] = 0;
271  if(path.endsWith(QLatin1Char('/')) || path.endsWith(QLatin1Char('\\')))
272  name[path.length() - 1 ] = 0;
273  SHFILEOPSTRUCTW fileOp;
274  memset(&fileOp, 0, sizeof(SHFILEOPSTRUCTW) );
275  fileOp.wFunc = FO_DELETE;
276  fileOp.pFrom = (LPCWSTR)name.constData();
277  fileOp.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;
278 #ifdef _WIN32_WCE
279  // FOF_NOERRORUI is not defined in wince
280 #else
281  fileOp.fFlags |= FOF_NOERRORUI;
282 #endif
283  errno = SHFileOperationW( &fileOp );
284  return (errno == 0);
285 #else
286  const QByteArray cstr( QFile::encodeName( path ) );
287  return rmtree( cstr );
288 #endif
289 }
290 
krandom.h
mkdtemp_QString
QString mkdtemp_QString(const QString &_template)
Definition: kde_file_win.cpp:79
kdebug.h
KTempDir::removeDir
static bool removeDir(const QString &path)
Remove a directory and all its contents.
Definition: ktempdir.cpp:259
QByteArray
KTempDir::create
bool create(const QString &directoryPrefix, int mode)
Creates a "random" directory with specified mode.
Definition: ktempdir.cpp:85
QVarLengthArray::constData
const T * constData() const
KTempDir::unlink
void unlink()
Deletes the directory recursively.
Definition: ktempdir.cpp:188
QVarLengthArray
KDE::chmod
int chmod(const QString &path, mode_t mode)
Definition: kde_file_win.cpp:138
KTempDir::autoRemove
bool autoRemove() const
Definition: ktempdir.cpp:183
QFile::exists
bool exists() const
KRandom::random
int random()
Generates a uniform random number.
Definition: krandom.cpp:32
KTempDir::~KTempDir
~KTempDir()
The destructor deletes the directory and its contents if autoRemove is set to true.
Definition: ktempdir.cpp:154
kglobal.h
ktempdir.h
KTempDir::exists
bool exists() const
Returns true if a temporary directory has successfully been created and has not been unlinked yet...
Definition: ktempdir.cpp:173
KGlobal::umask
mode_t umask()
Returns the umask of the process.
Definition: kglobal.cpp:224
QString::isEmpty
bool isEmpty() const
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QString
QLatin1Char
KTempDir::status
int status() const
Returns the status of the directory creation based on errno.
Definition: ktempdir.cpp:163
kWarning
#define kWarning
Definition: kdebug.h:322
QString::utf16
const ushort * utf16() const
KTempDir::KTempDir
KTempDir(const QString &directoryPrefix=QString(), int mode=0700)
Creates a temporary directory with the name:
Definition: ktempdir.cpp:80
QLatin1String
KStandardDirs::locateLocal
static QString locateLocal(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
This function is much like locate.
Definition: kstandarddirs.cpp:2091
kstandarddirs.h
KGlobal::mainComponent
const KComponentData & mainComponent()
Returns the global component data.
Definition: kglobal.cpp:145
QString::length
int length() const
QVarLengthArray::data
T * data()
QByteArray::data
char * data()
kDebug
#define kDebug
Definition: kdebug.h:316
kcomponentdata.h
KTempDir::setAutoRemove
void setAutoRemove(bool autoRemove)
Turn automatic deletion of the directory on or off.
Definition: ktempdir.cpp:178
QVarLengthArray::resize
void resize(int size)
KTempDir::name
QString name() const
Returns the full path and name of the directory, including a trailing '/'.
Definition: ktempdir.cpp:168
QFile::encodeName
QByteArray encodeName(const QString &fileName)
QFile::decodeName
QString decodeName(const QByteArray &localFileName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal