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