summaryrefslogtreecommitdiffstats
path: root/kdecore/ktempdir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/ktempdir.cpp')
-rw-r--r--kdecore/ktempdir.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/kdecore/ktempdir.cpp b/kdecore/ktempdir.cpp
new file mode 100644
index 000000000..141ee71a0
--- /dev/null
+++ b/kdecore/ktempdir.cpp
@@ -0,0 +1,218 @@
+/*
+ *
+ * This file is part of the KDE libraries
+ * Copyright (c) 2003 Joseph Wenninger <jowenn@kde.org>
+ *
+ * $Id$
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#ifdef HAVE_TEST
+#include <test.h>
+#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef _PATH_TMP
+#define _PATH_TMP "/tmp"
+#endif
+
+#include <qdatetime.h>
+#include <qdir.h>
+
+#include "kglobal.h"
+#include "kapplication.h"
+#include "kinstance.h"
+#include "ktempdir.h"
+#include "kstandarddirs.h"
+#include "kprocess.h"
+#include <kdebug.h>
+#include "kde_file.h"
+
+KTempDir::KTempDir(QString directoryPrefix, int mode)
+{
+ bAutoDelete = false;
+ bExisting = false;
+ mError=0;
+ if (directoryPrefix.isEmpty())
+ {
+ directoryPrefix = locateLocal("tmp", KGlobal::instance()->instanceName());
+ }
+ (void) create(directoryPrefix , mode);
+}
+
+bool
+KTempDir::create(const QString &directoryPrefix, int mode)
+{
+ // make sure the random seed is randomized
+ (void) KApplication::random();
+
+ QCString nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
+ char *realName;
+ if((realName=mkdtemp(nme.data())) == 0)
+ {
+ // Recreate it for the warning, mkdtemps emptied it
+ QCString nme = QFile::encodeName(directoryPrefix) + "XXXXXX";
+ qWarning("KTempDir: Error trying to create %s: %s", nme.data(), strerror(errno));
+ mError = errno;
+ mTmpName = QString::null;
+ return false;
+ }
+
+ // got a return value != 0
+ QCString realNameStr(realName);
+ mTmpName = QFile::decodeName(realNameStr)+"/";
+ kdDebug(180) << "KTempDir: Temporary directory created :" << mTmpName << endl;
+ mode_t tmp = 0;
+ mode_t umsk = umask(tmp);
+ umask(umsk);
+ chmod(nme, mode&(~umsk));
+
+ // Success!
+ bExisting = true;
+
+ // Set uid/gid (necessary for SUID programs)
+ chown(nme, getuid(), getgid());
+ return true;
+}
+
+KTempDir::~KTempDir()
+{
+ if (bAutoDelete)
+ unlink();
+
+// KTempDirPrivate doesn't exist, so it can't be deleted
+// delete d;
+}
+
+int
+KTempDir::status() const
+{
+ return mError;
+}
+
+QString
+KTempDir::name() const
+{
+ return mTmpName;
+}
+
+bool
+KTempDir::existing() const
+{
+ return bExisting;
+}
+
+QDir *
+KTempDir::qDir()
+{
+ if (bExisting) return new QDir(mTmpName);
+ return 0;
+}
+
+void
+KTempDir::unlink()
+{
+ if (!bExisting) return;
+ if (KTempDir::removeDir(mTmpName))
+ mError=0;
+ else
+ mError=errno;
+ bExisting=false;
+}
+
+// Auxiliary recursive function for removeDirs
+static bool
+rmtree(const QCString& name)
+{
+ kdDebug() << "Checking directory for remove " << name << endl;
+ KDE_struct_stat st;
+ if ( KDE_lstat( name.data(), &st ) == -1 ) // Do not dereference symlink!
+ return false;
+ if ( S_ISDIR( st.st_mode ) )
+ {
+ // This is a directory, so process it
+ kdDebug() << "File " << name << " is DIRECTORY!" << endl;
+ KDE_struct_dirent* ep;
+ DIR* dp = ::opendir( name.data() );
+ if ( !dp )
+ return false;
+ while ( ( ep = KDE_readdir( dp ) ) )
+ {
+ kdDebug() << "CHECKING " << name << "/" << ep->d_name << endl;
+ if ( !qstrcmp( ep->d_name, "." ) || !qstrcmp( ep->d_name, ".." ) )
+ continue;
+ QCString newName( name );
+ newName += "/"; // Careful: do not add '/' instead or you get problems with Qt3.
+ newName += ep->d_name;
+ /*
+ * Be defensive and close the directory.
+ *
+ * Potential problems:
+ * - opendir/readdir/closedir is not re-entrant
+ * - unlink and rmdir invalidates a opendir/readdir/closedir
+ * - limited number of file descriptors for opendir/readdir/closedir
+ */
+ if ( ::closedir( dp ) )
+ return false;
+ // Recurse!
+ kdDebug() << "RECURSE: " << newName << endl;
+ if ( ! rmtree( newName ) )
+ return false;
+ // We have to re-open the directory before continuing
+ dp = ::opendir( name.data() );
+ if ( !dp )
+ return false;
+ }
+ if ( ::closedir( dp ) )
+ return false;
+ kdDebug() << "RMDIR dir " << name << endl;
+ return ! ::rmdir( name );
+ }
+ else
+ {
+ // This is a non-directory file, so remove it
+ kdDebug() << "UNLINKING file " << name << endl;
+ return ! ::unlink( name );
+ }
+}
+
+bool
+KTempDir::removeDir(const QString& path)
+{
+ kdDebug() << k_funcinfo << " " << path << endl;
+ if ( !QFile::exists( path ) )
+ return true; // The goal is that there is no directory
+
+ const QCString cstr( QFile::encodeName( path ) );
+ return rmtree( cstr );
+}
+
+