2010-10-14 08:30:07 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2009-03-13 15:52:34 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
2009-03-13 15:52:34 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
2009-03-13 15:52:34 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2009-03-13 15:52:34 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* This file is part of OpenOffice.org.
|
2009-03-13 15:52:34 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* 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.
|
2009-03-13 15:52:34 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* 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).
|
2009-03-13 15:52:34 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
|
|
* <http://www.openoffice.org/license.html>
|
|
|
|
* for a copy of the LGPLv3 License.
|
2009-03-13 15:52:34 +00:00
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
#include "lockbyte.hxx"
|
|
|
|
|
|
|
|
#include "sal/types.h"
|
|
|
|
#include "osl/diagnose.h"
|
|
|
|
#include "osl/file.h"
|
2009-03-20 15:07:51 +00:00
|
|
|
#include "osl/process.h"
|
2009-03-13 15:52:34 +00:00
|
|
|
#include "rtl/alloc.h"
|
|
|
|
#include "rtl/ustring.hxx"
|
|
|
|
|
|
|
|
#include "object.hxx"
|
|
|
|
#include "storbase.hxx"
|
|
|
|
|
|
|
|
#ifndef INCLUDED_STRING_H
|
|
|
|
#include <string.h>
|
|
|
|
#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<sal_uInt8*>(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<sal_uInt8 const*>(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)
|
|
|
|
{
|
2009-03-20 15:07:51 +00:00
|
|
|
// Not system path. Assume file url.
|
2009-03-13 15:52:34 +00:00
|
|
|
rtl_uString_assign (&(aFileUrl.pData), pFilename);
|
|
|
|
}
|
2009-03-20 15:07:51 +00:00
|
|
|
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));
|
|
|
|
}
|
2009-03-13 15:52:34 +00:00
|
|
|
|
|
|
|
// Acquire handle.
|
|
|
|
oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
|
|
|
|
if (result == osl_File_E_EXIST)
|
|
|
|
{
|
|
|
|
// Already existing (O_CREAT | O_EXCL).
|
2009-09-09 09:38:41 +00:00
|
|
|
result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
|
2009-03-13 15:52:34 +00:00
|
|
|
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<T>::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<sal_uInt32>(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<PageData>(), 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<sal_uInt32>(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;
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
oslFileHandle m_hFile;
|
2009-03-13 15:52:34 +00:00
|
|
|
|
2012-03-14 23:35:49 +01:00
|
|
|
FileMapping() : m_pAddr(0), m_nSize(0), m_hFile() {}
|
2009-03-13 15:52:34 +00:00
|
|
|
|
|
|
|
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<sal_uInt32>(uSize);
|
|
|
|
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
m_hFile = hFile;
|
|
|
|
|
2009-03-13 15:52:34 +00:00
|
|
|
// Acquire mapping.
|
|
|
|
return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @see MappedLockBytes::destructor.
|
|
|
|
*/
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
|
2009-03-13 15:52:34 +00:00
|
|
|
{
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
(void) osl_unmapMappedFile (hFile, pAddr, nSize);
|
2012-01-10 12:36:03 +00:00
|
|
|
(void) osl_closeFile (hFile);
|
2009-03-13 15:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @see ResourceHolder<T>::destructor_type
|
|
|
|
*/
|
|
|
|
struct UnmapFile
|
|
|
|
{
|
|
|
|
void operator ()(FileMapping & rMapping) const
|
|
|
|
{
|
|
|
|
// Release mapping.
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize);
|
2009-03-13 15:52:34 +00:00
|
|
|
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;
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
oslFileHandle m_hFile;
|
2009-03-13 15:52:34 +00:00
|
|
|
|
|
|
|
/** 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)
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
: m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
|
2009-03-13 15:52:34 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MappedLockBytes::~MappedLockBytes()
|
|
|
|
{
|
osl_unmapFile can't work for files bundled inside the .apk on Android
On Android, when an app is installed, arbitrary files bundled in the
app won't be unpacked into actual separate files in the file
system. They will exist only as archive entries in the .apk file
(which is a zip archive).
The SDK tooling puts such files under the /assets folder in the
.apk. The LibreOffice bootstrapping code for Android maps the .apk
file into memory.
osl_openFile() knows about the /assets special case, and uses a
separate abstraction for such memory-mapped files.
Obviously, when producing an .apk, one needs to make sure these
bundled files are not compressed, if one wants to be able to use them
directly from the memory-mapped .apk file. We do that in our test and
sample Android projects.
When mapping such files under /assets , just return a pointer to the
file's location inside the mapped .apk archive.
We can't use the old osl_unmapFile() on such mapped files, as that
would unexpectedly unmap fairly arbitrary pages of the .apk mapping,
wreaking havoc on later use of the same pages.
So, introduce a new osl_unmapMappedFile() function that takes also the
oslFileHandle originally passed to osl_mapFile(). Use this instead in
the few places where the code actually called osl_unmapFile(). Make
sure osl_mapFile() is nonexistent on Android.
2011-12-21 13:51:50 +02:00
|
|
|
FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
|
2009-03-13 15:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
2010-11-25 14:18:45 +01:00
|
|
|
if ((ppPage != 0) && (pnSize != 0))
|
|
|
|
*ppPage = 0, *pnSize = m_nPageSize;
|
2009-03-13 15:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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<PageData>(), 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<sal_uInt32>(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<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
|
|
|
|
if (pData != 0)
|
|
|
|
{
|
|
|
|
if (nSize > m_nSize)
|
|
|
|
memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(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<FileHandle> xFile;
|
|
|
|
storeError result = xFile.get().initialize (pFilename, eAccessMode);
|
|
|
|
if (result != store_E_None)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
if (eAccessMode == store_AccessReadOnly)
|
|
|
|
{
|
|
|
|
ResourceHolder<FileMapping> 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;
|
2012-01-10 12:36:03 +00:00
|
|
|
(void) xFile.release();
|
2009-03-13 15:52:34 +00:00
|
|
|
(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
|
2010-10-14 08:30:07 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|