You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdelibs/kdecore/ktempdir.cpp

219 lines
5.4 KiB

/*
*
* 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 <tqdatetime.h>
#include <tqdir.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(TQString 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 TQString &directoryPrefix, int mode)
{
// make sure the random seed is randomized
(void) KApplication::random();
TQCString nme = TQFile::encodeName(directoryPrefix) + "XXXXXX";
char *realName;
if((realName=mkdtemp(nme.data())) == 0)
{
// Recreate it for the warning, mkdtemps emptied it
TQCString nme = TQFile::encodeName(directoryPrefix) + "XXXXXX";
qWarning("KTempDir: Error trying to create %s: %s", nme.data(), strerror(errno));
mError = errno;
mTmpName = TQString::null;
return false;
}
// got a return value != 0
TQCString realNameStr(realName);
mTmpName = TQFile::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;
}
TQString
KTempDir::name() const
{
return mTmpName;
}
bool
KTempDir::existing() const
{
return bExisting;
}
TQDir *
KTempDir::qDir()
{
if (bExisting) return new TQDir(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 TQCString& 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;
TQCString 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 tqinvalidates 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 TQString& path)
{
kdDebug() << k_funcinfo << " " << path << endl;
if ( !TQFile::exists( path ) )
return true; // The goal is that there is no directory
const TQCString cstr( TQFile::encodeName( path ) );
return rmtree( cstr );
}