diff options
Diffstat (limited to 'tdecore/ktempfile.cpp')
-rw-r--r-- | tdecore/ktempfile.cpp | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/tdecore/ktempfile.cpp b/tdecore/ktempfile.cpp new file mode 100644 index 000000000..f439b55ef --- /dev/null +++ b/tdecore/ktempfile.cpp @@ -0,0 +1,289 @@ +/* + * + * This file is part of the KDE libraries + * Copyright (c) 1999 Waldo Bastian <bastian@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> + +#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 <tqfile.h> +#include <tqdatastream.h> +#include <tqtextstream.h> + +#include "kglobal.h" +#include "kapplication.h" +#include "kinstance.h" +#include "ktempfile.h" +#include "kstandarddirs.h" +#include "kde_file.h" +#include "kdebug.h" + +/* antlarr: KDE 4: make the parameters const TQString & */ +KTempFile::KTempFile(TQString filePrefix, TQString fileExtension, int mode) +{ + bAutoDelete = false; + mFd = -1; + mStream = 0; + mFile = 0; + mTextStream = 0; + mDataStream = 0; + mError = 0; + bOpen = false; + if (fileExtension.isEmpty()) + fileExtension = ".tmp"; + if (filePrefix.isEmpty()) + { + filePrefix = locateLocal("tmp", KGlobal::instance()->instanceName()); + } + (void) create(filePrefix, fileExtension, mode); +} + +KTempFile::KTempFile(bool) +{ + bAutoDelete = false; + mFd = -1; + mStream = 0; + mFile = 0; + mTextStream = 0; + mDataStream = 0; + mError = 0; + bOpen = false; +} + +bool +KTempFile::create(const TQString &filePrefix, const TQString &fileExtension, + int mode) +{ + // make sure the random seed is randomized + (void) KApplication::random(); + + TQCString ext = TQFile::encodeName(fileExtension); + TQCString nme = TQFile::encodeName(filePrefix) + "XXXXXX" + ext; + if((mFd = mkstemps(nme.data(), ext.length())) < 0) + { + // Recreate it for the warning, mkstemps emptied it + TQCString nme = TQFile::encodeName(filePrefix) + "XXXXXX" + ext; + kdWarning() << "KTempFile: Error trying to create " << nme << ": " << strerror(errno) << endl; + mError = errno; + mTmpName = TQString::null; + return false; + } + + // got a file descriptor. nme contains the name + mTmpName = TQFile::decodeName(nme); + mode_t tmp = 0; + mode_t umsk = umask(tmp); + umask(umsk); + fchmod(mFd, mode&(~umsk)); + + // Success! + bOpen = true; + + // Set uid/gid (necessary for SUID programs) + fchown(mFd, getuid(), getgid()); + + // Set close on exec + fcntl(mFd, F_SETFD, FD_CLOEXEC); + + return true; +} + +KTempFile::~KTempFile() +{ + close(); + if (bAutoDelete) + unlink(); +} + +int +KTempFile::status() const +{ + return mError; +} + +TQString +KTempFile::name() const +{ + return mTmpName; +} + +int +KTempFile::handle() const +{ + return mFd; +} + +FILE * +KTempFile::fstream() +{ + if (mStream) return mStream; + if (mFd < 0) return 0; + + // Create a stream + mStream = KDE_fdopen(mFd, "r+"); + if (!mStream) { + kdWarning() << "KTempFile: Error trying to open " << mTmpName << ": " << strerror(errno) << endl; + mError = errno; + } + return mStream; +} + +TQFile * +KTempFile::file() +{ + if (mFile) return mFile; + if ( !fstream() ) return 0; + + mFile = new TQFile(); + mFile->setName( name() ); + mFile->open(IO_ReadWrite, mStream); + return mFile; +} + +TQTextStream * +KTempFile::textStream() +{ + if (mTextStream) return mTextStream; + if ( !file() ) return 0; // Initialize mFile + + mTextStream = new TQTextStream( mFile ); + return mTextStream; +} + +TQDataStream * +KTempFile::dataStream() +{ + if (mDataStream) return mDataStream; + if ( !file() ) return 0; // Initialize mFile + + mDataStream = new TQDataStream( mFile ); + return mDataStream; +} + +void +KTempFile::unlink() +{ + if (!mTmpName.isEmpty()) + TQFile::remove( mTmpName ); + mTmpName = TQString::null; +} + +#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 +#define FDATASYNC fdatasync +#else +#define FDATASYNC fsync +#endif + +bool +KTempFile::sync() +{ + int result = 0; + + if (mStream) + { + do { + result = fflush(mStream); // We need to flush first otherwise fsync may not have our data + } + while ((result == -1) && (errno == EINTR)); + + if (result) + { + kdWarning() << "KTempFile: Error trying to flush " << mTmpName << ": " << strerror(errno) << endl; + mError = errno; + } + } + + if (mFd >= 0) + { + if( qstrcmp( getenv( "KDE_EXTRA_FSYNC" ), "1" ) == 0 ) + { + result = FDATASYNC(mFd); + if (result) + { + kdWarning() << "KTempFile: Error trying to sync " << mTmpName << ": " << strerror(errno) << endl; + mError = errno; + } + } + } + + return (mError == 0); +} + +#undef FDATASYNC + +bool +KTempFile::close() +{ + int result = 0; + delete mTextStream; mTextStream = 0; + delete mDataStream; mDataStream = 0; + delete mFile; mFile = 0; + + if (mStream) + { + result = ferror(mStream); + if (result) + mError = ENOSPC; // Assume disk full. + + result = fclose(mStream); + mStream = 0; + mFd = -1; + if (result != 0) { + kdWarning() << "KTempFile: Error trying to close " << mTmpName << ": " << strerror(errno) << endl; + mError = errno; + } + } + + + if (mFd >= 0) + { + result = ::close(mFd); + mFd = -1; + if (result != 0) { + kdWarning() << "KTempFile: Error trying to close " << mTmpName << ": " << strerror(errno) << endl; + mError = errno; + } + } + + bOpen = false; + return (mError == 0); +} + |