KDE3Support
k3tempfile.cpp
Go to the documentation of this file.
00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (c) 1999 Waldo Bastian <bastian@kde.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License version 2 as published by the Free Software Foundation. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public License 00015 * along with this library; see the file COPYING.LIB. If not, write to 00016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 * Boston, MA 02110-1301, USA. 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 // make sure the random seed is randomized 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 // Recreate it for the warning, mkstemps emptied it 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 // got a file descriptor. nme contains the name 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 // Success! 00141 bOpen = true; 00142 00143 // Set uid/gid (necessary for SUID programs) 00144 fchown(mFd, getuid(), getgid()); 00145 00146 #ifndef Q_WS_WIN 00147 // Set close on exec 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 // Create a stream 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; // Initialize mFile 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; // Initialize mFile 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); // We need to flush first otherwise fsync may not have our data 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; // Assume disk full. 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
KDE 4.6 API Reference