00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/Types.hpp"
00040 #include "blocxx/TmpFile.hpp"
00041 #include "blocxx/IOException.hpp"
00042 #include "blocxx/MutexLock.hpp"
00043 #include "blocxx/String.hpp"
00044 #include "blocxx/Format.hpp"
00045 #include "blocxx/System.hpp"
00046 #include <cstring>
00047 #include <cstdlib>
00048 #include <cerrno>
00049 #include <cstdio>
00050 extern "C"
00051 {
00052 #include <sys/types.h>
00053 #include <sys/stat.h>
00054 #include <fcntl.h>
00055
00056 #if defined(BLOCXX_WIN32)
00057 #include <io.h>
00058 #endif
00059 }
00060
00061 namespace BLOCXX_NAMESPACE
00062 {
00063
00064 namespace {
00065
00066 #ifndef BLOCXX_WIN32
00067 inline int
00068 closeFile(int fd)
00069 {
00070 return ::close(fd);
00071 }
00072
00073 #else
00074 inline int
00075 closeFile(HANDLE fh)
00076 {
00077 return CloseHandle(fh) ? 0 : -1;
00078 }
00079 #endif
00080
00081 }
00082
00084 TmpFileImpl::TmpFileImpl()
00085 : m_filename(NULL)
00086 , m_hdl(BLOCXX_INVALID_FILEHANDLE)
00087 {
00088 open();
00089 }
00091 TmpFileImpl::TmpFileImpl(String const& filename)
00092 : m_filename(NULL)
00093 , m_hdl(BLOCXX_INVALID_FILEHANDLE)
00094 {
00095 size_t len = filename.length();
00096 m_filename = new char[len + 1];
00097 ::strncpy(m_filename, filename.c_str(), len);
00098 m_filename[len] = '\0';
00099 #if defined(BLOCXX_WIN32)
00100 m_hdl = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
00101 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
00102 FILE_ATTRIBUTE_NORMAL, NULL);
00103 #else
00104 m_hdl = ::open(m_filename, O_RDWR);
00105 #endif
00106 if (m_hdl == BLOCXX_INVALID_FILEHANDLE)
00107 {
00108 delete[] m_filename;
00109 m_filename = NULL;
00110 BLOCXX_THROW(IOException, Format("Error opening file %1: %2", filename,
00111 System::lastErrorMsg()).c_str());
00112 }
00113 }
00115 TmpFileImpl::~TmpFileImpl()
00116 {
00117 close();
00118 }
00119
00120 #ifdef BLOCXX_WIN32
00121
00122 int
00123 TmpFileImpl::seek(long offset, int whence)
00124 {
00125 DWORD moveMethod;
00126 switch(whence)
00127 {
00128 case SEEK_END: moveMethod = FILE_END; break;
00129 case SEEK_CUR: moveMethod = FILE_CURRENT; break;
00130 default: moveMethod = FILE_BEGIN; break;
00131 }
00132 return (int) SetFilePointer(m_hdl, (LONG)offset, NULL, moveMethod);
00133 }
00134
00136 long
00137 TmpFileImpl::tell()
00138 {
00139 return (long) SetFilePointer(m_hdl, 0L, NULL, FILE_CURRENT);
00140 }
00141
00143 void
00144 TmpFileImpl::rewind()
00145 {
00146 SetFilePointer(m_hdl, 0L, NULL, FILE_BEGIN);
00147 }
00148
00150 int
00151 TmpFileImpl::flush()
00152 {
00153 if(m_hdl != BLOCXX_INVALID_FILEHANDLE)
00154 {
00155 FlushFileBuffers(m_hdl);
00156 }
00157 return 0;
00158 }
00159 #endif
00160
00162 long
00163 TmpFileImpl::getSize()
00164 {
00165 #ifdef BLOCXX_WIN32
00166 return (long) GetFileSize(m_hdl, NULL);
00167 #else
00168 long cv = tell();
00169 seek(0L, SEEK_END);
00170 long rv = tell();
00171 seek(cv, SEEK_SET);
00172 return rv;
00173 #endif
00174 }
00176 #if defined(BLOCXX_WIN32)
00177 void
00178 TmpFileImpl::open()
00179 {
00180 close();
00181
00182 char bfr[MAX_PATH];
00183 if(!GetTempFileName(".", "owtempfile", 0, bfr))
00184 {
00185 BLOCXX_THROW(IOException,
00186 Format("Error generating temp file name: %1",
00187 System::lastErrorMsg()).c_str());
00188 }
00189
00190 size_t len = ::strlen(bfr);
00191 m_filename = new char[len + 1];
00192 ::strncpy(m_filename, bfr, len);
00193 m_filename[len] = '\0';
00194
00195 static Mutex tmpfileMutex;
00196 MutexLock tmpfileML(tmpfileMutex);
00197 m_hdl = CreateFile(m_filename, GENERIC_READ | GENERIC_WRITE,
00198 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
00199 FILE_ATTRIBUTE_NORMAL, NULL);
00200 if (m_hdl == INVALID_HANDLE_VALUE)
00201 {
00202 delete[] m_filename;
00203 m_filename = NULL;
00204 BLOCXX_THROW(IOException, Format("Error opening temp file %1: %2",
00205 bfr, System::lastErrorMsg()).c_str());
00206 }
00207 }
00208 #else
00209 void
00210 TmpFileImpl::open()
00211 {
00212 close();
00213 String sfname("/tmp/owtmpfileXXXXXX");
00214 size_t len = sfname.length();
00215 m_filename = new char[len + 1];
00216 strncpy(m_filename, sfname.c_str(), len);
00217 m_filename[len] = '\0';
00218 static Mutex tmpfileMutex;
00219 MutexLock tmpfileML(tmpfileMutex);
00220 m_hdl = mkstemp(m_filename);
00221 if (m_hdl == -1)
00222 {
00223 delete[] m_filename;
00224 m_filename = NULL;
00225 BLOCXX_THROW_ERRNO_MSG(IOException, "mkstemp failed");
00226 }
00227 }
00228 #endif
00229
00231 int
00232 TmpFileImpl::close()
00233 {
00234 int rv = -1;
00235 if (m_hdl != BLOCXX_INVALID_FILEHANDLE)
00236 {
00237 rv = closeFile(m_hdl);
00238 #if defined(BLOCXX_WIN32)
00239 DeleteFile(m_filename);
00240 #else
00241 remove(m_filename);
00242 #endif
00243 delete [] m_filename;
00244 m_filename = NULL;
00245 m_hdl = BLOCXX_INVALID_FILEHANDLE;
00246 }
00247 return rv;
00248 }
00250 size_t
00251 TmpFileImpl::read(void* bfr, size_t numberOfBytes, long offset)
00252 {
00253 if (offset == -1L)
00254 {
00255 seek(0L, SEEK_CUR);
00256 }
00257 else
00258 {
00259 seek(offset, SEEK_SET);
00260 }
00261 #if defined(BLOCXX_WIN32)
00262 DWORD bytesRead;
00263 size_t cc = (size_t)-1;
00264 if(ReadFile(m_hdl, bfr, (DWORD)numberOfBytes, &bytesRead, NULL))
00265 {
00266 cc = (size_t)bytesRead;
00267 }
00268 return cc;
00269 #else
00270 return ::read(m_hdl, bfr, numberOfBytes);
00271 #endif
00272 }
00274 size_t
00275 TmpFileImpl::write(const void* bfr, size_t numberOfBytes, long offset)
00276 {
00277 if (offset == -1L)
00278 {
00279 seek(0L, SEEK_CUR);
00280 }
00281 else
00282 {
00283 seek(offset, SEEK_SET);
00284 }
00285 #if defined(BLOCXX_WIN32)
00286 DWORD bytesWritten;
00287 int rv = -1;
00288 if(WriteFile(m_hdl, bfr, (DWORD)numberOfBytes, &bytesWritten, NULL))
00289 {
00290 rv = (int)bytesWritten;
00291 }
00292 return rv;
00293 #else
00294 int rv = ::write(m_hdl, bfr, numberOfBytes);
00295 if (rv == -1)
00296 {
00297 perror("TmpFile::write()");
00298 }
00299 return rv;
00300 #endif
00301 }
00303 String
00304 TmpFileImpl::releaseFile()
00305 {
00306 String rval(m_filename);
00307 if (m_hdl != BLOCXX_INVALID_FILEHANDLE)
00308 {
00309 if (closeFile(m_hdl) == -1)
00310 {
00311 BLOCXX_THROW_ERRNO_MSG(IOException, "Unable to close file");
00312 }
00313
00314
00315 delete [] m_filename;
00316 m_filename = NULL;
00317 m_hdl = BLOCXX_INVALID_FILEHANDLE;
00318 }
00319 return rval;
00320 }
00321
00322 }
00323