/* * * 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 "tdeglobal.h" #include "tdeapplication.h" #include "kinstance.h" #include "tdetempfile.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", TDEGlobal::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) TDEApplication::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; uid_t uid = getuid(); uid_t euid = geteuid(); if (uid != euid) { // 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( "TDE_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); }