/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "lockbyte.hxx" #include "sal/types.h" #include "osl/diagnose.h" #include "osl/file.h" #include "osl/process.h" #include "rtl/alloc.h" #include "rtl/ustring.hxx" #include "object.hxx" #include "storbase.hxx" #ifndef INCLUDED_STRING_H #include #define INCLUDED_STRING_H #endif using namespace store; /*======================================================================== * * ILockBytes (non-virtual interface) implementation. * *======================================================================*/ storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) { OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize"); return initialize_Impl (rxAllocator, nPageSize); } storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset) { OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset"); if (nOffset == STORE_PAGE_NULL) return store_E_CantSeek; return readPageAt_Impl (rPage, nOffset); } storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset) { // [SECURITY:ValInput] PageData const * pagedata = rPage.get(); OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page"); if (pagedata == 0) return store_E_InvalidParameter; sal_uInt32 const offset = pagedata->location(); OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset"); if (nOffset != offset) return store_E_InvalidParameter; OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset"); if (nOffset == STORE_PAGE_NULL) return store_E_CantSeek; return writePageAt_Impl (rPage, nOffset); } storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) { // [SECURITY:ValInput] sal_uInt8 * dst_lo = static_cast(pBuffer); if (!(dst_lo != 0)) return store_E_InvalidParameter; sal_uInt8 * dst_hi = dst_lo + nBytes; if (!(dst_lo < dst_hi)) return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None; OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset"); if (nOffset == STORE_PAGE_NULL) return store_E_CantSeek; sal_uInt64 const src_size = nOffset + nBytes; if (src_size > SAL_MAX_UINT32) return store_E_CantSeek; return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo)); } storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) { // [SECURITY:ValInput] sal_uInt8 const * src_lo = static_cast(pBuffer); if (!(src_lo != 0)) return store_E_InvalidParameter; sal_uInt8 const * src_hi = src_lo + nBytes; if (!(src_lo < src_hi)) return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None; OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset"); if (nOffset == STORE_PAGE_NULL) return store_E_CantSeek; sal_uInt64 const dst_size = nOffset + nBytes; if (dst_size > SAL_MAX_UINT32) return store_E_CantSeek; return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo)); } storeError ILockBytes::getSize (sal_uInt32 & rnSize) { rnSize = 0; return getSize_Impl (rnSize); } storeError ILockBytes::setSize (sal_uInt32 nSize) { return setSize_Impl (nSize); } storeError ILockBytes::flush() { return flush_Impl(); } /*======================================================================== * * FileLockBytes implementation. * *======================================================================*/ namespace store { struct FileHandle { oslFileHandle m_handle; FileHandle() : m_handle(0) {} bool operator != (FileHandle const & rhs) { return (m_handle != rhs.m_handle); } static storeError errorFromNative (oslFileError eErrno) { switch (eErrno) { case osl_File_E_None: return store_E_None; case osl_File_E_NOENT: return store_E_NotExists; case osl_File_E_ACCES: case osl_File_E_PERM: return store_E_AccessViolation; case osl_File_E_AGAIN: case osl_File_E_DEADLK: return store_E_LockingViolation; case osl_File_E_BADF: return store_E_InvalidHandle; case osl_File_E_INVAL: return store_E_InvalidParameter; case osl_File_E_NOMEM: return store_E_OutOfMemory; case osl_File_E_NOSPC: return store_E_OutOfSpace; case osl_File_E_OVERFLOW: return store_E_CantSeek; default: return store_E_Unknown; } } static sal_uInt32 modeToNative (storeAccessMode eAccessMode) { sal_uInt32 nFlags = 0; switch (eAccessMode) { case store_AccessCreate: case store_AccessReadCreate: nFlags |= osl_File_OpenFlag_Create; // fall through case store_AccessReadWrite: nFlags |= osl_File_OpenFlag_Write; // fall through case store_AccessReadOnly: nFlags |= osl_File_OpenFlag_Read; break; default: OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode"); } return nFlags; } storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode) { // Verify arguments. sal_uInt32 nFlags = modeToNative (eAccessMode); if (!pFilename || !nFlags) return store_E_InvalidParameter; // Convert into FileUrl. rtl::OUString aFileUrl; if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None) { // Not system path. Assume file url. rtl_uString_assign (&(aFileUrl.pData), pFilename); } if (aFileUrl.compareToAscii("file://", 7) != 0) { // Not file url. Assume relative path. rtl::OUString aCwdUrl; (void) osl_getProcessWorkingDir (&(aCwdUrl.pData)); // Absolute file url. (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData)); } // Acquire handle. oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags); if (result == osl_File_E_EXIST) { // Already existing (O_CREAT | O_EXCL). result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write); if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate)) { // Truncate existing file. result = osl_setFileSize (m_handle, 0); } } if (result != osl_File_E_None) return errorFromNative(result); return store_E_None; } /** @see FileLockBytes destructor */ static void closeFile (oslFileHandle hFile) { (void) osl_closeFile (hFile); } /** @see ResourceHolder::destructor_type */ struct CloseFile { void operator()(FileHandle & rFile) const { // Release handle. closeFile (rFile.m_handle); rFile.m_handle = 0; } }; typedef CloseFile destructor_type; }; class FileLockBytes : public store::OStoreObject, public store::ILockBytes { /** Representation. */ oslFileHandle m_hFile; sal_uInt32 m_nSize; rtl::Reference< PageData::Allocator > m_xAllocator; storeError initSize_Impl (sal_uInt32 & rnSize); /** ILockBytes implementation. */ virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize); virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset); virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset); virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes); virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes); virtual storeError getSize_Impl (sal_uInt32 & rnSize); virtual storeError setSize_Impl (sal_uInt32 nSize); virtual storeError flush_Impl(); /** Not implemented. */ FileLockBytes (FileLockBytes const &); FileLockBytes & operator= (FileLockBytes const &); public: /** Construction. */ explicit FileLockBytes (FileHandle & rFile); /** Delegate multiple inherited IReference. */ virtual oslInterlockedCount SAL_CALL acquire(); virtual oslInterlockedCount SAL_CALL release(); protected: /** Destruction. */ virtual ~FileLockBytes(); }; } // namespace store FileLockBytes::FileLockBytes (FileHandle & rFile) : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator() { } FileLockBytes::~FileLockBytes() { FileHandle::closeFile (m_hFile); } oslInterlockedCount SAL_CALL FileLockBytes::acquire() { return OStoreObject::acquire(); } oslInterlockedCount SAL_CALL FileLockBytes::release() { return OStoreObject::release(); } storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize) { /* osl_getFileSize() uses slow 'fstat(h, &size)', * instead of fast 'size = lseek(h, 0, SEEK_END)'. * so, init size here, and track changes. */ sal_uInt64 uSize = 0; oslFileError result = osl_getFileSize (m_hFile, &uSize); if (result != osl_File_E_None) return FileHandle::errorFromNative(result); if (uSize > SAL_MAX_UINT32) return store_E_CantSeek; rnSize = sal::static_int_cast(uSize); return store_E_None; } storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) { storeError result = initSize_Impl (m_nSize); if (result != store_E_None) return (result); result = PageData::Allocator::createInstance (rxAllocator, nPageSize); if (result != store_E_None) return (result); // @see readPageAt_Impl(). m_xAllocator = rxAllocator; return store_E_None; } storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) { if (m_xAllocator.is()) { PageHolder page (m_xAllocator->construct(), m_xAllocator); page.swap (rPage); } if (!m_xAllocator.is()) return store_E_InvalidAccess; if (!rPage.get()) return store_E_OutOfMemory; PageData * pagedata = rPage.get(); return readAt_Impl (nOffset, pagedata, pagedata->size()); } storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) { PageData const * pagedata = rPage.get(); OSL_PRECOND(pagedata != 0, "contract violation"); return writeAt_Impl (nOffset, pagedata, pagedata->size()); } storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) { sal_uInt64 nDone = 0; oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone); if (result != osl_File_E_None) return FileHandle::errorFromNative(result); if (nDone != nBytes) return (nDone != 0) ? store_E_CantRead : store_E_NotExists; return store_E_None; } storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) { sal_uInt64 nDone = 0; oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone); if (result != osl_File_E_None) return FileHandle::errorFromNative(result); if (nDone != nBytes) return store_E_CantWrite; sal_uInt64 const uSize = nOffset + nBytes; OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation"); if (uSize > m_nSize) m_nSize = sal::static_int_cast(uSize); return store_E_None; } storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize) { rnSize = m_nSize; return store_E_None; } storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize) { oslFileError result = osl_setFileSize (m_hFile, nSize); if (result != osl_File_E_None) return FileHandle::errorFromNative(result); m_nSize = nSize; return store_E_None; } storeError FileLockBytes::flush_Impl() { oslFileError result = osl_syncFile (m_hFile); if (result != osl_File_E_None) return FileHandle::errorFromNative(result); return store_E_None; } /*======================================================================== * * MappedLockBytes implementation. * *======================================================================*/ namespace store { struct FileMapping { sal_uInt8 * m_pAddr; sal_uInt32 m_nSize; oslFileHandle m_hFile; FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {} bool operator != (FileMapping const & rhs) const { return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize)); } oslFileError initialize (oslFileHandle hFile) { // Determine mapping size. sal_uInt64 uSize = 0; oslFileError result = osl_getFileSize (hFile, &uSize); if (result != osl_File_E_None) return result; // [SECURITY:IntOver] if (uSize > SAL_MAX_UINT32) return osl_File_E_OVERFLOW; m_nSize = sal::static_int_cast(uSize); m_hFile = hFile; // Acquire mapping. return osl_mapFile (hFile, reinterpret_cast(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess); } /** @see MappedLockBytes::destructor. */ static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize) { (void) osl_unmapMappedFile (hFile, pAddr, nSize); (void) osl_closeFile (hFile); } /** @see ResourceHolder::destructor_type */ struct UnmapFile { void operator ()(FileMapping & rMapping) const { // Release mapping. unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize); rMapping.m_pAddr = 0, rMapping.m_nSize = 0; } }; typedef UnmapFile destructor_type; }; class MappedLockBytes : public store::OStoreObject, public store::PageData::Allocator, public store::ILockBytes { /** Representation. */ sal_uInt8 * m_pData; sal_uInt32 m_nSize; sal_uInt16 m_nPageSize; oslFileHandle m_hFile; /** PageData::Allocator implementation. */ virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize); virtual void deallocate_Impl (void * pPage); /** ILockBytes implementation. */ virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize); virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset); virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset); virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes); virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes); virtual storeError getSize_Impl (sal_uInt32 & rnSize); virtual storeError setSize_Impl (sal_uInt32 nSize); virtual storeError flush_Impl(); /** Not implemented. */ MappedLockBytes (MappedLockBytes const &); MappedLockBytes & operator= (MappedLockBytes const &); public: /** Construction. */ explicit MappedLockBytes (FileMapping & rMapping); /** Delegate multiple inherited IReference. */ virtual oslInterlockedCount SAL_CALL acquire(); virtual oslInterlockedCount SAL_CALL release(); protected: /* Destruction. */ virtual ~MappedLockBytes(); }; } // namespace store MappedLockBytes::MappedLockBytes (FileMapping & rMapping) : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile) { } MappedLockBytes::~MappedLockBytes() { FileMapping::unmapFile (m_hFile, m_pData, m_nSize); } oslInterlockedCount SAL_CALL MappedLockBytes::acquire() { return OStoreObject::acquire(); } oslInterlockedCount SAL_CALL MappedLockBytes::release() { return OStoreObject::release(); } void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) { OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation"); if ((ppPage != 0) && (pnSize != 0)) *ppPage = 0, *pnSize = m_nPageSize; } void MappedLockBytes::deallocate_Impl (void * pPage) { OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation"); (void)pPage; // UNUSED } storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) { rxAllocator = this; m_nPageSize = nPageSize; return store_E_None; } storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) { sal_uInt8 * src_lo = m_pData + nOffset; if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) return store_E_NotExists; sal_uInt8 * src_hi = src_lo + m_nPageSize; if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) return store_E_CantRead; PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this)); page.swap (rPage); return store_E_None; } storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/) { return store_E_AccessViolation; } storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) { sal_uInt8 const * src_lo = m_pData + nOffset; if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) return store_E_NotExists; sal_uInt8 const * src_hi = src_lo + nBytes; if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) return store_E_CantRead; memcpy (pBuffer, src_lo, (src_hi - src_lo)); return store_E_None; } storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/) { return store_E_AccessViolation; } storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize) { rnSize = m_nSize; return store_E_None; } storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/) { return store_E_AccessViolation; } storeError MappedLockBytes::flush_Impl() { return store_E_None; } /*======================================================================== * * MemoryLockBytes implementation. * *======================================================================*/ namespace store { class MemoryLockBytes : public store::OStoreObject, public store::ILockBytes { /** Representation. */ sal_uInt8 * m_pData; sal_uInt32 m_nSize; rtl::Reference< PageData::Allocator > m_xAllocator; /** ILockBytes implementation. */ virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize); virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset); virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset); virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes); virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes); virtual storeError getSize_Impl (sal_uInt32 & rnSize); virtual storeError setSize_Impl (sal_uInt32 nSize); virtual storeError flush_Impl(); /** Not implemented. */ MemoryLockBytes (MemoryLockBytes const &); MemoryLockBytes& operator= (MemoryLockBytes const &); public: /** Construction. */ MemoryLockBytes(); /** Delegate multiple inherited IReference. */ virtual oslInterlockedCount SAL_CALL acquire(); virtual oslInterlockedCount SAL_CALL release(); protected: /** Destruction. */ virtual ~MemoryLockBytes(); }; } // namespace store MemoryLockBytes::MemoryLockBytes() : m_pData (0), m_nSize (0), m_xAllocator() {} MemoryLockBytes::~MemoryLockBytes() { rtl_freeMemory (m_pData); } oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void) { return OStoreObject::acquire(); } oslInterlockedCount SAL_CALL MemoryLockBytes::release (void) { return OStoreObject::release(); } storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) { storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize); if (result == store_E_None) { // @see readPageAt_Impl(). m_xAllocator = rxAllocator; } return result; } storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) { if (m_xAllocator.is()) { PageHolder page (m_xAllocator->construct(), m_xAllocator); page.swap (rPage); } if (!m_xAllocator.is()) return store_E_InvalidAccess; if (!rPage.get()) return store_E_OutOfMemory; PageData * pagedata = rPage.get(); return readAt_Impl (nOffset, pagedata, pagedata->size()); } storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) { PageData const * pagedata = rPage.get(); OSL_PRECOND(!(pagedata == 0), "contract violation"); return writeAt_Impl (nOffset, pagedata, pagedata->size()); } storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) { sal_uInt8 const * src_lo = m_pData + nOffset; if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) return store_E_NotExists; sal_uInt8 const * src_hi = src_lo + nBytes; if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) return store_E_CantRead; memcpy (pBuffer, src_lo, (src_hi - src_lo)); return store_E_None; } storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) { sal_uInt64 const dst_size = nOffset + nBytes; OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation"); if (dst_size > m_nSize) { storeError eErrCode = setSize_Impl (sal::static_int_cast(dst_size)); if (eErrCode != store_E_None) return eErrCode; } OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation"); sal_uInt8 * dst_lo = m_pData + nOffset; if (dst_lo >= m_pData + m_nSize) return store_E_CantSeek; sal_uInt8 * dst_hi = dst_lo + nBytes; if (dst_hi > m_pData + m_nSize) return store_E_CantWrite; memcpy (dst_lo, pBuffer, (dst_hi - dst_lo)); return store_E_None; } storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize) { rnSize = m_nSize; return store_E_None; } storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize) { if (nSize != m_nSize) { sal_uInt8 * pData = reinterpret_cast(rtl_reallocateMemory (m_pData, nSize)); if (pData != 0) { if (nSize > m_nSize) memset (pData + m_nSize, 0, sal::static_int_cast(nSize - m_nSize)); } else { if (nSize != 0) return store_E_OutOfMemory; } m_pData = pData, m_nSize = nSize; } return store_E_None; } storeError MemoryLockBytes::flush_Impl() { return store_E_None; } /*======================================================================== * * ILockBytes factory implementations. * *======================================================================*/ namespace store { template< class T > struct ResourceHolder { typedef typename T::destructor_type destructor_type; T m_value; explicit ResourceHolder (T const & value = T()) : m_value (value) {} ~ResourceHolder() { reset(); } T & get() { return m_value; } T const & get() const { return m_value; } void set (T const & value) { m_value = value; } void reset (T const & value = T()) { T tmp (m_value); if (tmp != value) destructor_type()(tmp); set (value); } T release() { T tmp (m_value); set (T()); return tmp; } ResourceHolder (ResourceHolder & rhs) { set (rhs.release()); } ResourceHolder & operator= (ResourceHolder & rhs) { reset (rhs.release()); return *this; } }; storeError FileLockBytes_createInstance ( rtl::Reference< ILockBytes > & rxLockBytes, rtl_uString * pFilename, storeAccessMode eAccessMode ) { // Acquire file handle. ResourceHolder xFile; storeError result = xFile.get().initialize (pFilename, eAccessMode); if (result != store_E_None) return (result); if (eAccessMode == store_AccessReadOnly) { ResourceHolder xMapping; if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None) { rxLockBytes = new MappedLockBytes (xMapping.get()); if (!rxLockBytes.is()) return store_E_OutOfMemory; (void) xFile.release(); (void) xMapping.release(); } } if (!rxLockBytes.is()) { rxLockBytes = new FileLockBytes (xFile.get()); if (!rxLockBytes.is()) return store_E_OutOfMemory; (void) xFile.release(); } return store_E_None; } storeError MemoryLockBytes_createInstance ( rtl::Reference< ILockBytes > & rxLockBytes ) { rxLockBytes = new MemoryLockBytes(); if (!rxLockBytes.is()) return store_E_OutOfMemory; return store_E_None; } } // namespace store /* vim:set shiftwidth=4 softtabstop=4 expandtab: */