TmpFile.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *    this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 }  // end of unnamed namespace
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       // work like close, but don't delete the file, it will be given to the
00314       // caller
00315       delete [] m_filename;
00316       m_filename = NULL;
00317       m_hdl = BLOCXX_INVALID_FILEHANDLE;
00318    }
00319    return rval;
00320 }
00321 
00322 } // end namespace BLOCXX_NAMESPACE
00323 

Generated on Fri Jun 16 15:39:09 2006 for blocxx by  doxygen 1.4.6