KTempDir ?
Joseph Wenninger
jowenn at kde.org
Wed Feb 5 01:52:29 GMT 2003
Hi
I would need something like KTempFile for an appliaction, I'm working at
(kexi), but for directories. I think that could be usefull for others
too, so I decided to create a KTempDir class.
I enclose a patchfile for the kdelibs build system and the fakes.c file.
The fakes.c part of the patch should provide a platform independent
mkdtemp (most of the code taken from the already existing mkstemps.
Additionaly I enclose the two cpp and h file which does the real work ;)
What do you think. Would it be usefull to include something like that
into kdecore ? Any major design flaws ?
Kind regards
Joseph Wenninger
-------------- next part --------------
Index: configure.in.in
===================================================================
RCS file: /home/kde/kdelibs/configure.in.in,v
retrieving revision 1.104
diff -u -3 -p -r1.104 configure.in.in
--- configure.in.in 10 Jan 2003 15:07:10 -0000 1.104
+++ configure.in.in 4 Feb 2003 21:16:28 -0000
@@ -102,6 +102,7 @@ AC_CHECK_SETENV
AC_CHECK_UNSETENV
AC_CHECK_RANDOM
AC_CHECK_MKSTEMPS
+AC_CHECK_MKDTEMP
AC_CHECK_FUNCS(strtoll socket seteuid setegid strfmon stpcpy gettimeofday)
AH_BOTTOM([
Index: admin/acinclude.m4.in
===================================================================
RCS file: /home/kde/kde-common/admin/acinclude.m4.in,v
retrieving revision 2.333
diff -u -3 -p -r2.333 acinclude.m4.in
--- admin/acinclude.m4.in 22 Jan 2003 12:48:06 -0000 2.333
+++ admin/acinclude.m4.in 4 Feb 2003 21:16:33 -0000
@@ -2167,6 +2167,20 @@ mkstemps("/tmp/aaaXXXXXX", 6);
[MKSTEMPS])
])
+AC_DEFUN(AC_CHECK_MKDTEMP,
+[
+ KDE_CHECK_FUNC_EXT(mkdtemp, [
+#include <stdlib.h>
+#include <unistd.h>
+],
+ [
+mkdtemp("/tmp/aaaXXXXXX");
+],
+ [char *mkdtemp(char *)],
+ [MKDTEMP])
+])
+
+
AC_DEFUN(AC_CHECK_RES_INIT,
[
AC_MSG_CHECKING([if res_init needs -lresolv])
Index: kdecore/Makefile.am
===================================================================
RCS file: /home/kde/kdelibs/kdecore/Makefile.am,v
retrieving revision 1.321
diff -u -3 -p -r1.321 Makefile.am
--- kdecore/Makefile.am 30 Jan 2003 23:15:24 -0000 1.321
+++ kdecore/Makefile.am 4 Feb 2003 21:16:53 -0000
@@ -54,7 +54,7 @@ include_HEADERS = kconfig.h kconfigdata.
klargefile.h kmultipledrag.h kgenericfactory.h kgenericfactory.tcc ktypelist.h \
ksortablevaluelist.h kdebugclasses.h kclipboard.h kcalendarsystem.h \
kcalendarsystemfactory.h kmacroexpander.h kmanagerselection.h \
- kidna.h
+ kidna.h ktempdir.h
libkdefakes_la_SOURCES = fakes.c vsnprintf.c
libkdefakes_la_LDFLAGS = -version-info 6:0:2
@@ -104,7 +104,8 @@ libkdecore_la_SOURCES = libintl.cpp kapp
kdeversion.cpp kdebugdcopiface.cpp kdebugdcopiface.skel \
kcalendarsystem.cpp kcalendarsystemgregorian.cpp \
kcalendarsystemhijri.cpp kcalendarsystemhebrew.cpp \
- kcalendarsystemfactory.cpp kmacroexpander.cpp kidna.cpp
+ kcalendarsystemfactory.cpp kmacroexpander.cpp kidna.cpp \
+ ktempdir.cpp
libkdecore_la_LDFLAGS = $(QT_LDFLAGS) $(KDE_RPATH) $(KDE_MT_LDFLAGS) $(X_LDFLAGS) $(USER_LDFLAGS) -version-info 6:0:2 -no-undefined
libkdecore_la_LIBADD = malloc/libklmalloc.la $(SVGICON_LIB) ../dcop/libDCOP.la ../libltdl/libltdlc.la $(LIB_XEXT) $(LIBRESOLV) $(LIBUTIL) $(LIBART_LIBS) ../kdefx/libkdefx.la
Index: kdecore/fakes.c
===================================================================
RCS file: /home/kde/kdelibs/kdecore/fakes.c,v
retrieving revision 1.15
diff -u -3 -p -r1.15 fakes.c
--- kdecore/fakes.c 28 Dec 2002 15:21:42 -0000 1.15
+++ kdecore/fakes.c 4 Feb 2003 21:16:53 -0000
@@ -231,6 +231,71 @@ int mkstemp (char* _template)
}
#endif
+#ifndef HAVE_MKDTEMP
+
+#ifndef HAVE_MKSTEMPS
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#endif
+
+/* Generate a unique temporary directory name from TEMPLATE.
+
+ TEMPLATE has the form:
+
+ <path>/ccXXXXXX
+
+
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the filename unique.
+
+ Returns a file descriptor open on the file for reading and writing. */
+
+char* mkdtemp (char* _template)
+{
+ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ char *XXXXXX;
+ int len;
+ int count;
+ int value;
+
+ len = strlen (_template);
+
+ if ((int) len < 6 || strncmp (&_template[len - 6], "XXXXXX", 6))
+ return 0;
+
+ XXXXXX = &_template[len - 6];
+
+ value = rand();
+ for (count = 0; count < 256; ++count)
+ {
+ int v = value;
+
+ /* Fill in the random bits. */
+ XXXXXX[0] = letters[v % 62];
+ v /= 62;
+ XXXXXX[1] = letters[v % 62];
+ v /= 62;
+ XXXXXX[2] = letters[v % 62];
+ v /= 62;
+ XXXXXX[3] = letters[v % 62];
+ v /= 62;
+ XXXXXX[4] = letters[v % 62];
+ v /= 62;
+ XXXXXX[5] = letters[v % 62];
+
+ /* This is a random value. It is only necessary that the next
+ TMP_MAX values generated by adding 7777 to VALUE are different
+ with (module 2^32). */
+ value += 7777;
+
+ if (!mkdir(_template,0700))
+ return _template;
+ }
+ return 0;
+}
+#endif
#ifndef HAVE_REVOKE
#include <errno.h>
-------------- next part --------------
/*
This file is part of the KDE libraries
Copyright (c) 2003 Joseph Wenninger <jowenn at kde.org>
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _KTEMPDIR_H_
#define _KTEMPDIR_H_
#include <qstring.h>
#include <stdio.h>
#include <errno.h>
class QDir;
class KTempDirPrivate;
/**
* The KTempDir class creates a unique directory for temporary use.
*
* This is especially useful if you need to create a directory in a world
* writable directory like /tmp without being vulnerable to so called
* symlink attacks.
*
* KDE applications, however, shouldn't create files or directories in /tmp in the first
* place but use the "tmp" resource instead. The standard KTempDir
* constructor will do that by default.
*
* To create a temporary directory that starts with a certain name
* in the "tmp" resource, one should use:
* KTempDir(locateLocal("tmp", prefix));
*
* KTempFile does not create any missing directories, but locateLocal() does.
*
* See also @ref KStandardDirs
*
* @author Joseph Wenninger <jowenn at kde.org>
*/
class KTempDir
{
public:
/**
* Creates a temporary directory with the name:
* <directoryPrefix><six letters>
*
* The default @p directoryPrefix is "$KDEHOME/tmp-$HOST/appname"
* @param directoryPrefix the prefix of the file name, or QString::null
* for the default value
**/
KTempDir(QString directoryPrefix=QString::null,
int mode = 0700 );
/**
* The destructor deletes the directory and it's contents if autoDelete is enabled
**/
~KTempDir();
/**
* Turn automatic deletion on or off.
* Automatic deletion is off by default.
* @param autoDelete true to turn automatic deletion on
**/
void setAutoDelete(bool autoDelete) { bAutoDelete = autoDelete; }
/**
* Returns the status of the directory creation based on errno. (see errno.h)
* 0 means OK.
*
* You should check the status after object creation to check
* whether a directory could be created in the first place.
*
* @return the errno status, 0 means ok
**/
int status() const;
/**
* Returns the full path and name of the directory.
* @return The name of the file, or QString::null if creating the
* directory has failed or the directory has been unlinked
**/
QString name() const;
/**
* Returns the @ref QDir* of the temporary directory.
* @return QDir directory information of the directory or 0 if their is no managed directory
* The caller has to free the pointer open for writing to the
**/
QDir *qDir();
/**
* Deletes the directory recursively
**/
void unlink();
/**
* @return true if a temporary directory has successfully been created and not been unlinked yet
*/
bool existing() const;
protected:
bool create(const QString &directoryPrefix, int mode);
void setError(int error) { mError = error; }
private:
int mError;
QString mTmpName;
bool bExisting;
bool bAutoDelete;
KTempDirPrivate *d;
};
#endif
-------------- next part --------------
/*
*
* This file is part of the KDE libraries
* Copyright (c) 2003 Joseph Wenninger <jowenn at 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, 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>
#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"
KTempDir::KTempDir(QString directoryPrefix, int mode)
{
bAutoDelete = false;
bExisting = false;
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";
if(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
mTmpName = QFile::decodeName(nme);
mode_t tmp = 0;
mode_t umsk = umask(tmp);
umask(umsk);
chmod(nme, mode&(~umsk));
// Success!
bExisting = true;
// Set uid/gid (neccesary for SUID programs)
chown(nme, getuid(), getgid());
return true;
}
KTempDir::~KTempDir()
{
if (bAutoDelete)
unlink();
}
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;
QString rmstr("rm -rf ");
rmstr += KProcess::quote(mTmpName);
::system( QFile::encodeName(rmstr) );
bExisting=false;
mError=0;
}
More information about the kde-core-devel
mailing list