tdetempfile.cpp
00001 /* 00002 * 00003 * This file is part of the KDE libraries 00004 * Copyright (c) 1999 Waldo Bastian <bastian@kde.org> 00005 * 00006 * $Id$ 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Library General Public 00010 * License version 2 as published by the Free Software Foundation. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Library General Public License 00018 * along with this library; see the file COPYING.LIB. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 * Boston, MA 02110-1301, USA. 00021 **/ 00022 00023 #include <config.h> 00024 00025 #include <sys/types.h> 00026 00027 #ifdef HAVE_SYS_STAT_H 00028 #include <sys/stat.h> 00029 #endif 00030 00031 #include <fcntl.h> 00032 #include <stdlib.h> 00033 #include <unistd.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 <tqdatetime.h> 00047 #include <tqfile.h> 00048 #include <tqdatastream.h> 00049 #include <tqtextstream.h> 00050 00051 #include "tdeglobal.h" 00052 #include "tdeapplication.h" 00053 #include "kinstance.h" 00054 #include "tdetempfile.h" 00055 #include "kstandarddirs.h" 00056 #include "kde_file.h" 00057 #include "kdebug.h" 00058 00059 /* antlarr: KDE 4: make the parameters const TQString & */ 00060 KTempFile::KTempFile(TQString filePrefix, TQString fileExtension, int mode) 00061 { 00062 bAutoDelete = false; 00063 mFd = -1; 00064 mStream = 0; 00065 mFile = 0; 00066 mTextStream = 0; 00067 mDataStream = 0; 00068 mError = 0; 00069 bOpen = false; 00070 if (fileExtension.isEmpty()) 00071 fileExtension = ".tmp"; 00072 if (filePrefix.isEmpty()) 00073 { 00074 filePrefix = locateLocal("tmp", TDEGlobal::instance()->instanceName()); 00075 } 00076 (void) create(filePrefix, fileExtension, mode); 00077 } 00078 00079 KTempFile::KTempFile(bool) 00080 { 00081 bAutoDelete = false; 00082 mFd = -1; 00083 mStream = 0; 00084 mFile = 0; 00085 mTextStream = 0; 00086 mDataStream = 0; 00087 mError = 0; 00088 bOpen = false; 00089 } 00090 00091 bool 00092 KTempFile::create(const TQString &filePrefix, const TQString &fileExtension, 00093 int mode) 00094 { 00095 // make sure the random seed is randomized 00096 (void) TDEApplication::random(); 00097 00098 TQCString ext = TQFile::encodeName(fileExtension); 00099 TQCString nme = TQFile::encodeName(filePrefix) + "XXXXXX" + ext; 00100 if((mFd = mkstemps(nme.data(), ext.length())) < 0) 00101 { 00102 // Recreate it for the warning, mkstemps emptied it 00103 TQCString nme = TQFile::encodeName(filePrefix) + "XXXXXX" + ext; 00104 kdWarning() << "KTempFile: Error trying to create " << nme << ": " << strerror(errno) << endl; 00105 mError = errno; 00106 mTmpName = TQString::null; 00107 return false; 00108 } 00109 00110 // got a file descriptor. nme contains the name 00111 mTmpName = TQFile::decodeName(nme); 00112 mode_t tmp = 0; 00113 mode_t umsk = umask(tmp); 00114 umask(umsk); 00115 fchmod(mFd, mode&(~umsk)); 00116 00117 // Success! 00118 bOpen = true; 00119 00120 uid_t uid = getuid(); 00121 uid_t euid = geteuid(); 00122 if (uid != euid) { 00123 // Set uid/gid (necessary for SUID programs) 00124 fchown(mFd, getuid(), getgid()); 00125 } 00126 00127 // Set close on exec 00128 fcntl(mFd, F_SETFD, FD_CLOEXEC); 00129 00130 return true; 00131 } 00132 00133 KTempFile::~KTempFile() 00134 { 00135 close(); 00136 if (bAutoDelete) 00137 unlink(); 00138 } 00139 00140 int 00141 KTempFile::status() const 00142 { 00143 return mError; 00144 } 00145 00146 TQString 00147 KTempFile::name() const 00148 { 00149 return mTmpName; 00150 } 00151 00152 int 00153 KTempFile::handle() const 00154 { 00155 return mFd; 00156 } 00157 00158 FILE * 00159 KTempFile::fstream() 00160 { 00161 if (mStream) return mStream; 00162 if (mFd < 0) return 0; 00163 00164 // Create a stream 00165 mStream = KDE_fdopen(mFd, "r+"); 00166 if (!mStream) { 00167 kdWarning() << "KTempFile: Error trying to open " << mTmpName << ": " << strerror(errno) << endl; 00168 mError = errno; 00169 } 00170 return mStream; 00171 } 00172 00173 TQFile * 00174 KTempFile::file() 00175 { 00176 if (mFile) return mFile; 00177 if ( !fstream() ) return 0; 00178 00179 mFile = new TQFile(); 00180 mFile->setName( name() ); 00181 mFile->open(IO_ReadWrite, mStream); 00182 return mFile; 00183 } 00184 00185 TQTextStream * 00186 KTempFile::textStream() 00187 { 00188 if (mTextStream) return mTextStream; 00189 if ( !file() ) return 0; // Initialize mFile 00190 00191 mTextStream = new TQTextStream( mFile ); 00192 return mTextStream; 00193 } 00194 00195 TQDataStream * 00196 KTempFile::dataStream() 00197 { 00198 if (mDataStream) return mDataStream; 00199 if ( !file() ) return 0; // Initialize mFile 00200 00201 mDataStream = new TQDataStream( mFile ); 00202 return mDataStream; 00203 } 00204 00205 void 00206 KTempFile::unlink() 00207 { 00208 if (!mTmpName.isEmpty()) 00209 TQFile::remove( mTmpName ); 00210 mTmpName = TQString::null; 00211 } 00212 00213 #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 00214 #define FDATASYNC fdatasync 00215 #else 00216 #define FDATASYNC fsync 00217 #endif 00218 00219 bool 00220 KTempFile::sync() 00221 { 00222 int result = 0; 00223 00224 if (mStream) 00225 { 00226 do { 00227 result = fflush(mStream); // We need to flush first otherwise fsync may not have our data 00228 } 00229 while ((result == -1) && (errno == EINTR)); 00230 00231 if (result) 00232 { 00233 kdWarning() << "KTempFile: Error trying to flush " << mTmpName << ": " << strerror(errno) << endl; 00234 mError = errno; 00235 } 00236 } 00237 00238 if (mFd >= 0) 00239 { 00240 if( qstrcmp( getenv( "TDE_EXTRA_FSYNC" ), "1" ) == 0 ) 00241 { 00242 result = FDATASYNC(mFd); 00243 if (result) 00244 { 00245 kdWarning() << "KTempFile: Error trying to sync " << mTmpName << ": " << strerror(errno) << endl; 00246 mError = errno; 00247 } 00248 } 00249 } 00250 00251 return (mError == 0); 00252 } 00253 00254 #undef FDATASYNC 00255 00256 bool 00257 KTempFile::close() 00258 { 00259 int result = 0; 00260 delete mTextStream; mTextStream = 0; 00261 delete mDataStream; mDataStream = 0; 00262 delete mFile; mFile = 0; 00263 00264 if (mStream) 00265 { 00266 result = ferror(mStream); 00267 if (result) 00268 mError = ENOSPC; // Assume disk full. 00269 00270 result = fclose(mStream); 00271 mStream = 0; 00272 mFd = -1; 00273 if (result != 0) { 00274 kdWarning() << "KTempFile: Error trying to close " << mTmpName << ": " << strerror(errno) << endl; 00275 mError = errno; 00276 } 00277 } 00278 00279 00280 if (mFd >= 0) 00281 { 00282 result = ::close(mFd); 00283 mFd = -1; 00284 if (result != 0) { 00285 kdWarning() << "KTempFile: Error trying to close " << mTmpName << ": " << strerror(errno) << endl; 00286 mError = errno; 00287 } 00288 } 00289 00290 bOpen = false; 00291 return (mError == 0); 00292 } 00293