KDE3Support
k3tempfile.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "k3tempfile.h"
00021
00022 #include <config.h>
00023
00024 #include <sys/types.h>
00025
00026 #ifdef HAVE_SYS_STAT_H
00027 #include <sys/stat.h>
00028 #endif
00029
00030 #include <fcntl.h>
00031 #include <stdlib.h>
00032 #include <unistd.h>
00033 #include <errno.h>
00034
00035 #ifdef HAVE_TEST
00036 #include <test.h>
00037 #endif
00038 #ifdef HAVE_PATHS_H
00039 #include <paths.h>
00040 #endif
00041
00042 #ifndef _PATH_TMP
00043 #define _PATH_TMP "/tmp"
00044 #endif
00045
00046 #include <QtCore/QCharRef>
00047 #include <QtCore/QDate>
00048 #include <QtCore/QFile>
00049 #include <QtCore/QDataStream>
00050 #include <QtCore/QTextIStream>
00051
00052 #include "kglobal.h"
00053 #include "krandom.h"
00054 #include "kcomponentdata.h"
00055 #include "kstandarddirs.h"
00056 #include "kde_file.h"
00057 #include "kdebug.h"
00058
00059 class K3TempFile::Private
00060 {
00061 public:
00062 int _Error;
00063 #define mError d->_Error
00064 QString _TmpName;
00065 #define mTmpName d->_TmpName
00066 int _Fd;
00067 #define mFd d->_Fd
00068 FILE *_Stream;
00069 #define mStream d->_Stream
00070 QFile *_File;
00071 #define mFile d->_File
00072 QTextStream *_TextStream;
00073 #define mTextStream d->_TextStream
00074 QDataStream *_DataStream;
00075 #define mDataStream d->_DataStream
00076 bool _Open;
00077 #define bOpen d->_Open
00078 bool _AutoDelete;
00079 #define bAutoDelete d->_AutoDelete
00080 };
00081
00082 K3TempFile::K3TempFile(const QString& filePrefix,
00083 const QString& fileExtension, int mode)
00084 : d(new Private)
00085 {
00086 bAutoDelete = false;
00087 mFd = -1;
00088 mStream = 0;
00089 mFile = 0;
00090 mTextStream = 0;
00091 mDataStream = 0;
00092 mError = 0;
00093 bOpen = false;
00094 QString extension = fileExtension;
00095 QString prefix = filePrefix;
00096 if (extension.isEmpty())
00097 extension = QLatin1String(".tmp");
00098 if (prefix.isEmpty())
00099 {
00100 prefix = KStandardDirs::locateLocal("tmp", KGlobal::mainComponent().componentName());
00101 }
00102 (void) create(prefix, extension, mode);
00103 }
00104
00105 K3TempFile::K3TempFile(bool):d(new Private)
00106 {
00107 bAutoDelete = false;
00108 mFd = -1;
00109 mStream = 0;
00110 mFile = 0;
00111 mTextStream = 0;
00112 mDataStream = 0;
00113 mError = 0;
00114 bOpen = false;
00115 }
00116
00117 bool
00118 K3TempFile::create(const QString &filePrefix, const QString &fileExtension,
00119 int mode)
00120 {
00121
00122 (void) KRandom::random();
00123
00124 QByteArray ext = QFile::encodeName(fileExtension);
00125 QByteArray nme = QFile::encodeName(filePrefix) + "XXXXXX" + ext;
00126 if((mFd = mkstemps(nme.data(), ext.length())) < 0)
00127 {
00128
00129 nme = QFile::encodeName(filePrefix) + "XXXXXX" + ext;
00130 kWarning() << "K3TempFile: Error trying to create " << nme << ": " << strerror(errno);
00131 mError = errno;
00132 mTmpName.clear();
00133 return false;
00134 }
00135
00136
00137 mTmpName = QFile::decodeName(nme);
00138 mode_t tmp = 0;
00139 mode_t umsk = umask(tmp);
00140 umask(umsk);
00141 fchmod(mFd, mode&(~umsk));
00142
00143
00144 bOpen = true;
00145
00146
00147 fchown(mFd, getuid(), getgid());
00148
00149 #ifndef Q_WS_WIN
00150
00151 fcntl(mFd, F_SETFD, FD_CLOEXEC);
00152 #endif
00153 return true;
00154 }
00155
00156 K3TempFile::~K3TempFile()
00157 {
00158 close();
00159 if (bAutoDelete)
00160 unlink();
00161 delete d;
00162 }
00163
00164 int
00165 K3TempFile::status() const
00166 {
00167 return mError;
00168 }
00169
00170 QString
00171 K3TempFile::name() const
00172 {
00173 return mTmpName;
00174 }
00175
00176 int
00177 K3TempFile::handle() const
00178 {
00179 return mFd;
00180 }
00181
00182 FILE *
00183 K3TempFile::fstream()
00184 {
00185 if (mStream) return mStream;
00186 if (mFd < 0) return 0;
00187
00188
00189 mStream = KDE_fdopen(mFd, "r+");
00190 if (!mStream) {
00191 kWarning() << "K3TempFile: Error trying to open " << mTmpName << ": " << strerror(errno);
00192 mError = errno;
00193 }
00194 return mStream;
00195 }
00196
00197 QFile *
00198 K3TempFile::file()
00199 {
00200 if (mFile) return mFile;
00201 if ( !fstream() ) return 0;
00202
00203 mFile = new QFile();
00204 mFile->setFileName( name() );
00205 mFile->open(mStream, QIODevice::ReadWrite);
00206 return mFile;
00207 }
00208
00209 QTextStream *
00210 K3TempFile::textStream()
00211 {
00212 if (mTextStream) return mTextStream;
00213 if ( !file() ) return 0;
00214
00215 mTextStream = new QTextStream( mFile );
00216 return mTextStream;
00217 }
00218
00219 QDataStream *
00220 K3TempFile::dataStream()
00221 {
00222 if (mDataStream) return mDataStream;
00223 if ( !file() ) return 0;
00224
00225 mDataStream = new QDataStream( mFile );
00226 return mDataStream;
00227 }
00228
00229 void
00230 K3TempFile::unlink()
00231 {
00232 if (!mTmpName.isEmpty())
00233 QFile::remove( mTmpName );
00234 mTmpName.clear();
00235 }
00236
00237 #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
00238 #define FDATASYNC fdatasync
00239 #else
00240 #define FDATASYNC fsync
00241 #endif
00242
00243 bool
00244 K3TempFile::sync()
00245 {
00246 int result = 0;
00247
00248 if (mStream)
00249 {
00250 do {
00251 result = fflush(mStream);
00252 }
00253 while ((result == -1) && (errno == EINTR));
00254
00255 if (result)
00256 {
00257 kWarning() << "K3TempFile: Error trying to flush " << mTmpName << ": " << strerror(errno);
00258 mError = errno;
00259 }
00260 }
00261
00262 if (mFd >= 0)
00263 {
00264 if( qgetenv( "KDE_EXTRA_FSYNC" ) == "1" )
00265 {
00266 result = FDATASYNC(mFd);
00267 if (result)
00268 {
00269 kWarning() << "K3TempFile: Error trying to sync " << mTmpName << ": " << strerror(errno);
00270 mError = errno;
00271 }
00272 }
00273 }
00274
00275 return (mError == 0);
00276 }
00277
00278 #undef FDATASYNC
00279
00280 bool
00281 K3TempFile::close()
00282 {
00283 int result = 0;
00284 delete mTextStream; mTextStream = 0;
00285 delete mDataStream; mDataStream = 0;
00286 delete mFile; mFile = 0;
00287
00288 if (mStream)
00289 {
00290 result = ferror(mStream);
00291 if (result)
00292 mError = ENOSPC;
00293
00294 result = fclose(mStream);
00295 mStream = 0;
00296 mFd = -1;
00297 if (result != 0) {
00298 kWarning() << "K3TempFile: Error trying to close " << mTmpName << ": " << strerror(errno);
00299 mError = errno;
00300 }
00301 }
00302
00303
00304 if (mFd >= 0)
00305 {
00306 result = ::close(mFd);
00307 mFd = -1;
00308 if (result != 0) {
00309 kWarning() << "K3TempFile: Error trying to close " << mTmpName << ": " << strerror(errno);
00310 mError = errno;
00311 }
00312 }
00313
00314 bOpen = false;
00315 return (mError == 0);
00316 }
00317
00318 void
00319 K3TempFile::setAutoDelete(bool autoDelete)
00320 {
00321 bAutoDelete = autoDelete;
00322 }
00323
00324 void
00325 K3TempFile::setError(int error)
00326 {
00327 mError = error;
00328 }
00329
00330 bool
00331 K3TempFile::isOpen() const
00332 {
00333 return bOpen;
00334 }
00335
00336 #undef mError
00337 #undef mTmpName
00338 #undef mFd
00339 #undef mStream
00340 #undef mFile
00341 #undef mTextStream
00342 #undef mDataStream
00343 #undef bOpen
00344 #undef bAutoDelete