1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "lockbyte.hxx"
22 #include <sal/types.h>
23 #include <osl/diagnose.h>
25 #include <osl/process.h>
26 #include <rtl/ustring.hxx>
27 #include <sal/log.hxx>
30 #include "storbase.hxx"
35 using namespace store
;
37 /*========================================================================
39 * ILockBytes (non-virtual interface) implementation.
41 *======================================================================*/
43 storeError
ILockBytes::initialize (rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
)
45 OSL_PRECOND((STORE_MINIMUM_PAGESIZE
<= nPageSize
) && (nPageSize
<= STORE_MAXIMUM_PAGESIZE
), "invalid PageSize");
46 return initialize_Impl (rxAllocator
, nPageSize
);
49 storeError
ILockBytes::readPageAt (std::shared_ptr
<PageData
> & rPage
, sal_uInt32 nOffset
)
51 OSL_PRECOND(!(nOffset
== STORE_PAGE_NULL
), "store::ILockBytes::readPageAt(): invalid Offset");
52 if (nOffset
== STORE_PAGE_NULL
)
53 return store_E_CantSeek
;
55 return readPageAt_Impl (rPage
, nOffset
);
58 storeError
ILockBytes::writePageAt (std::shared_ptr
<PageData
> const & rPage
, sal_uInt32 nOffset
)
60 // [SECURITY:ValInput]
61 PageData
const * pagedata
= rPage
.get();
62 OSL_PRECOND(!(pagedata
== nullptr), "store::ILockBytes::writePageAt(): invalid Page");
63 if (pagedata
== nullptr)
64 return store_E_InvalidParameter
;
66 sal_uInt32
const offset
= pagedata
->location();
67 OSL_PRECOND(!(nOffset
!= offset
), "store::ILockBytes::writePageAt(): inconsistent Offset");
68 if (nOffset
!= offset
)
69 return store_E_InvalidParameter
;
71 OSL_PRECOND(!(nOffset
== STORE_PAGE_NULL
), "store::ILockBytes::writePageAt(): invalid Offset");
72 if (nOffset
== STORE_PAGE_NULL
)
73 return store_E_CantSeek
;
75 return writePageAt_Impl (rPage
, nOffset
);
78 storeError
ILockBytes::readAt (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
)
80 // [SECURITY:ValInput]
81 sal_uInt8
* dst_lo
= static_cast<sal_uInt8
*>(pBuffer
);
82 if (dst_lo
== nullptr)
83 return store_E_InvalidParameter
;
85 sal_uInt8
* dst_hi
= dst_lo
+ nBytes
;
87 return (dst_lo
> dst_hi
) ? store_E_InvalidParameter
: store_E_None
;
89 OSL_PRECOND(!(nOffset
== STORE_PAGE_NULL
), "store::ILockBytes::readAt(): invalid Offset");
90 if (nOffset
== STORE_PAGE_NULL
)
91 return store_E_CantSeek
;
93 sal_uInt64
const src_size
= static_cast<sal_uInt64
>(nOffset
) + nBytes
;
94 if (src_size
> SAL_MAX_UINT32
)
95 return store_E_CantSeek
;
97 return readAt_Impl (nOffset
, dst_lo
, nBytes
);
100 storeError
ILockBytes::writeAt (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
)
102 // [SECURITY:ValInput]
103 sal_uInt8
const * src_lo
= static_cast<sal_uInt8
const*>(pBuffer
);
104 if (src_lo
== nullptr)
105 return store_E_InvalidParameter
;
107 sal_uInt8
const * src_hi
= src_lo
+ nBytes
;
108 if (src_lo
>= src_hi
)
109 return (src_lo
> src_hi
) ? store_E_InvalidParameter
: store_E_None
;
111 OSL_PRECOND(!(nOffset
== STORE_PAGE_NULL
), "store::ILockBytes::writeAt(): invalid Offset");
112 if (nOffset
== STORE_PAGE_NULL
)
113 return store_E_CantSeek
;
115 sal_uInt64
const dst_size
= static_cast<sal_uInt64
>(nOffset
) + nBytes
;
116 if (dst_size
> SAL_MAX_UINT32
)
117 return store_E_CantSeek
;
119 return writeAt_Impl (nOffset
, src_lo
, nBytes
);
122 storeError
ILockBytes::getSize (sal_uInt32
& rnSize
)
125 return getSize_Impl (rnSize
);
128 storeError
ILockBytes::setSize (sal_uInt32 nSize
)
130 return setSize_Impl (nSize
);
133 storeError
ILockBytes::flush()
138 /*========================================================================
140 * FileLockBytes implementation.
142 *======================================================================*/
150 oslFileHandle m_handle
;
152 FileHandle() : m_handle(nullptr) {}
154 bool operator != (FileHandle
const & rhs
)
156 return (m_handle
!= rhs
.m_handle
);
159 static storeError
errorFromNative (oslFileError eErrno
)
163 case osl_File_E_None
:
166 case osl_File_E_NOENT
:
167 return store_E_NotExists
;
169 case osl_File_E_ACCES
:
170 case osl_File_E_PERM
:
171 return store_E_AccessViolation
;
173 case osl_File_E_AGAIN
:
174 case osl_File_E_DEADLK
:
175 return store_E_LockingViolation
;
177 case osl_File_E_BADF
:
178 return store_E_InvalidHandle
;
180 case osl_File_E_INVAL
:
181 return store_E_InvalidParameter
;
183 case osl_File_E_NOMEM
:
184 return store_E_OutOfMemory
;
186 case osl_File_E_NOSPC
:
187 return store_E_OutOfSpace
;
189 case osl_File_E_OVERFLOW
:
190 return store_E_CantSeek
;
193 return store_E_Unknown
;
197 static sal_uInt32
modeToNative (storeAccessMode eAccessMode
)
199 sal_uInt32 nFlags
= 0;
202 case storeAccessMode::Create
:
203 nFlags
|= osl_File_OpenFlag_Create
;
205 case storeAccessMode::ReadWrite
:
206 nFlags
|= osl_File_OpenFlag_Write
;
208 case storeAccessMode::ReadOnly
:
209 nFlags
|= osl_File_OpenFlag_Read
;
212 OSL_PRECOND(false, "store::FileHandle: unknown storeAccessMode");
217 storeError
initialize (rtl_uString
* pFilename
, storeAccessMode eAccessMode
)
220 sal_uInt32 nFlags
= modeToNative (eAccessMode
);
221 if (!pFilename
|| !nFlags
)
222 return store_E_InvalidParameter
;
224 // Convert into FileUrl.
226 if (osl_getFileURLFromSystemPath (pFilename
, &(aFileUrl
.pData
)) != osl_File_E_None
)
228 // Not system path. Assume file url.
229 rtl_uString_assign (&(aFileUrl
.pData
), pFilename
);
231 if (!aFileUrl
.startsWith("file://"))
233 // Not file url. Assume relative path.
235 (void) osl_getProcessWorkingDir (&(aCwdUrl
.pData
));
237 // Absolute file url.
238 (void) osl_getAbsoluteFileURL (aCwdUrl
.pData
, aFileUrl
.pData
, &(aFileUrl
.pData
));
242 oslFileError result
= osl_openFile (aFileUrl
.pData
, &m_handle
, nFlags
);
243 if (result
== osl_File_E_EXIST
)
245 // Already existing (O_CREAT | O_EXCL).
246 result
= osl_openFile (aFileUrl
.pData
, &m_handle
, osl_File_OpenFlag_Read
| osl_File_OpenFlag_Write
);
247 if ((result
== osl_File_E_None
) && (eAccessMode
== storeAccessMode::Create
))
249 // Truncate existing file.
250 result
= osl_setFileSize (m_handle
, 0);
253 if (result
!= osl_File_E_None
)
254 return errorFromNative(result
);
258 /** @see FileLockBytes destructor
260 static void closeFile (oslFileHandle hFile
)
262 (void) osl_closeFile (hFile
);
265 /** @see ResourceHolder<T>::destructor_type
269 void operator()(FileHandle
& rFile
) const
272 closeFile (rFile
.m_handle
);
273 rFile
.m_handle
= nullptr;
276 typedef CloseFile destructor_type
;
279 class FileLockBytes
:
280 public store::OStoreObject
,
281 public store::ILockBytes
285 oslFileHandle
const m_hFile
;
287 rtl::Reference
< PageData::Allocator
> m_xAllocator
;
289 storeError
initSize_Impl (sal_uInt32
& rnSize
);
291 /** ILockBytes implementation.
293 virtual storeError
initialize_Impl (rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
) override
;
295 virtual storeError
readPageAt_Impl (std::shared_ptr
<PageData
> & rPage
, sal_uInt32 nOffset
) override
;
296 virtual storeError
writePageAt_Impl (std::shared_ptr
<PageData
> const & rPage
, sal_uInt32 nOffset
) override
;
298 virtual storeError
readAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
) override
;
299 virtual storeError
writeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
) override
;
301 virtual storeError
getSize_Impl (sal_uInt32
& rnSize
) override
;
302 virtual storeError
setSize_Impl (sal_uInt32 nSize
) override
;
304 virtual storeError
flush_Impl() override
;
309 explicit FileLockBytes (FileHandle
const & rFile
);
311 FileLockBytes(const FileLockBytes
&) = delete;
312 FileLockBytes
& operator=(const FileLockBytes
&) = delete;
317 virtual ~FileLockBytes() override
;
324 FileLockBytes::FileLockBytes (FileHandle
const & rFile
)
325 : m_hFile (rFile
.m_handle
), m_nSize (SAL_MAX_UINT32
), m_xAllocator()
329 FileLockBytes::~FileLockBytes()
331 FileHandle::closeFile (m_hFile
);
334 storeError
FileLockBytes::initSize_Impl (sal_uInt32
& rnSize
)
336 /* osl_getFileSize() uses slow 'fstat(h, &size)',
337 * instead of fast 'size = lseek(h, 0, SEEK_END)'.
338 * so, init size here, and track changes.
340 sal_uInt64 uSize
= 0;
341 oslFileError result
= osl_getFileSize (m_hFile
, &uSize
);
342 if (result
!= osl_File_E_None
)
343 return FileHandle::errorFromNative(result
);
344 if (uSize
> SAL_MAX_UINT32
)
345 return store_E_CantSeek
;
347 rnSize
= sal::static_int_cast
<sal_uInt32
>(uSize
);
351 storeError
FileLockBytes::initialize_Impl (rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
)
353 storeError result
= initSize_Impl (m_nSize
);
354 if (result
!= store_E_None
)
357 result
= PageData::Allocator::createInstance (rxAllocator
, nPageSize
);
358 if (result
!= store_E_None
)
361 // @see readPageAt_Impl().
362 m_xAllocator
= rxAllocator
;
366 storeError
FileLockBytes::readPageAt_Impl (std::shared_ptr
<PageData
> & rPage
, sal_uInt32 nOffset
)
368 if (m_xAllocator
.is())
370 std::shared_ptr
<PageData
> page (m_xAllocator
->construct
<PageData
>(), PageData::Deallocate(m_xAllocator
));
374 if (!m_xAllocator
.is())
375 return store_E_InvalidAccess
;
377 return store_E_OutOfMemory
;
379 PageData
* pagedata
= rPage
.get();
380 return readAt_Impl (nOffset
, pagedata
, pagedata
->size());
383 storeError
FileLockBytes::writePageAt_Impl (std::shared_ptr
<PageData
> const & rPage
, sal_uInt32 nOffset
)
385 PageData
const * pagedata
= rPage
.get();
386 OSL_PRECOND(pagedata
!= nullptr, "contract violation");
387 return writeAt_Impl (nOffset
, pagedata
, pagedata
->size());
390 storeError
FileLockBytes::readAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
)
392 sal_uInt64 nDone
= 0;
393 oslFileError result
= osl_readFileAt (m_hFile
, nOffset
, pBuffer
, nBytes
, &nDone
);
394 if (result
!= osl_File_E_None
)
395 return FileHandle::errorFromNative(result
);
397 return (nDone
!= 0) ? store_E_CantRead
: store_E_NotExists
;
401 storeError
FileLockBytes::writeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
)
403 sal_uInt64 nDone
= 0;
404 oslFileError result
= osl_writeFileAt (m_hFile
, nOffset
, pBuffer
, nBytes
, &nDone
);
405 if (result
!= osl_File_E_None
)
406 return FileHandle::errorFromNative(result
);
408 return store_E_CantWrite
;
410 sal_uInt64
const uSize
= nOffset
+ nBytes
;
411 OSL_PRECOND(uSize
< SAL_MAX_UINT32
, "store::ILockBytes::writeAt() contract violation");
413 m_nSize
= sal::static_int_cast
<sal_uInt32
>(uSize
);
417 storeError
FileLockBytes::getSize_Impl (sal_uInt32
& rnSize
)
423 storeError
FileLockBytes::setSize_Impl (sal_uInt32 nSize
)
425 oslFileError result
= osl_setFileSize (m_hFile
, nSize
);
426 if (result
!= osl_File_E_None
)
427 return FileHandle::errorFromNative(result
);
433 storeError
FileLockBytes::flush_Impl()
435 oslFileError result
= osl_syncFile (m_hFile
);
436 if (result
!= osl_File_E_None
)
437 return FileHandle::errorFromNative(result
);
441 /*========================================================================
443 * MappedLockBytes implementation.
445 *======================================================================*/
455 oslFileHandle m_hFile
;
457 FileMapping() : m_pAddr(nullptr), m_nSize(0), m_hFile(nullptr) {}
459 bool operator != (FileMapping
const & rhs
) const
461 return ((m_pAddr
!= rhs
.m_pAddr
) || (m_nSize
!= rhs
.m_nSize
));
464 oslFileError
initialize (oslFileHandle hFile
)
466 // Determine mapping size.
467 sal_uInt64 uSize
= 0;
468 oslFileError result
= osl_getFileSize (hFile
, &uSize
);
469 if (result
!= osl_File_E_None
)
472 // [SECURITY:IntOver]
473 if (uSize
> SAL_MAX_UINT32
)
474 return osl_File_E_OVERFLOW
;
475 m_nSize
= sal::static_int_cast
<sal_uInt32
>(uSize
);
480 return osl_mapFile (hFile
, reinterpret_cast<void**>(&m_pAddr
), m_nSize
, 0, osl_File_MapFlag_RandomAccess
);
483 /** @see MappedLockBytes::destructor.
485 static void unmapFile (oslFileHandle hFile
, sal_uInt8
* pAddr
, sal_uInt32 nSize
)
487 (void) osl_unmapMappedFile (hFile
, pAddr
, nSize
);
488 (void) osl_closeFile (hFile
);
491 /** @see ResourceHolder<T>::destructor_type
495 void operator ()(FileMapping
& rMapping
) const
498 unmapFile (rMapping
.m_hFile
, rMapping
.m_pAddr
, rMapping
.m_nSize
);
499 rMapping
.m_pAddr
= nullptr;
500 rMapping
.m_nSize
= 0;
503 typedef UnmapFile destructor_type
;
506 class MappedLockBytes
:
507 public store::OStoreObject
,
508 public store::PageData::Allocator
,
509 public store::ILockBytes
513 sal_uInt8
* const m_pData
;
514 sal_uInt32
const m_nSize
;
515 sal_uInt16 m_nPageSize
;
516 oslFileHandle
const m_hFile
;
518 /** PageData::Allocator implementation.
520 virtual void allocate_Impl (void ** ppPage
, sal_uInt16
* pnSize
) override
;
521 virtual void deallocate_Impl (void * pPage
) override
;
523 /** ILockBytes implementation.
525 virtual storeError
initialize_Impl (rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
) override
;
527 virtual storeError
readPageAt_Impl (std::shared_ptr
<PageData
> & rPage
, sal_uInt32 nOffset
) override
;
528 virtual storeError
writePageAt_Impl (std::shared_ptr
<PageData
> const & rPage
, sal_uInt32 nOffset
) override
;
530 virtual storeError
readAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
) override
;
531 virtual storeError
writeAt_Impl (sal_uInt32 nOffset
, const void * pBuffer
, sal_uInt32 nBytes
) override
;
533 virtual storeError
getSize_Impl (sal_uInt32
& rnSize
) override
;
534 virtual storeError
setSize_Impl (sal_uInt32 nSize
) override
;
536 virtual storeError
flush_Impl() override
;
541 explicit MappedLockBytes (FileMapping
const & rMapping
);
543 MappedLockBytes(const MappedLockBytes
&) = delete;
544 MappedLockBytes
& operator=(const MappedLockBytes
&) = delete;
549 virtual ~MappedLockBytes() override
;
556 MappedLockBytes::MappedLockBytes (FileMapping
const & rMapping
)
557 : m_pData (rMapping
.m_pAddr
), m_nSize (rMapping
.m_nSize
), m_nPageSize(0), m_hFile (rMapping
.m_hFile
)
561 MappedLockBytes::~MappedLockBytes()
563 FileMapping::unmapFile (m_hFile
, m_pData
, m_nSize
);
566 void MappedLockBytes::allocate_Impl (void ** ppPage
, sal_uInt16
* pnSize
)
568 OSL_PRECOND((ppPage
!= nullptr) && (pnSize
!= nullptr), "contract violation");
569 if ((ppPage
!= nullptr) && (pnSize
!= nullptr))
572 *pnSize
= m_nPageSize
;
576 void MappedLockBytes::deallocate_Impl (void * pPage
)
578 OSL_PRECOND((m_pData
<= pPage
) && (pPage
< m_pData
+ m_nSize
), "contract violation");
581 storeError
MappedLockBytes::initialize_Impl (rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
)
584 m_nPageSize
= nPageSize
;
588 storeError
MappedLockBytes::readPageAt_Impl (std::shared_ptr
<PageData
> & rPage
, sal_uInt32 nOffset
)
590 sal_uInt8
* src_lo
= m_pData
+ nOffset
;
591 if ((m_pData
> src_lo
) || (src_lo
>= m_pData
+ m_nSize
))
592 return store_E_NotExists
;
594 sal_uInt8
* src_hi
= src_lo
+ m_nPageSize
;
595 if ((m_pData
> src_hi
) || (src_hi
> m_pData
+ m_nSize
))
596 return store_E_CantRead
;
598 std::shared_ptr
<PageData
> page (reinterpret_cast< PageData
* >(src_lo
), PageData::Deallocate(static_cast< PageData::Allocator
* >(this)));
604 storeError
MappedLockBytes::writePageAt_Impl (std::shared_ptr
<PageData
> const & /*rPage*/, sal_uInt32
/*nOffset*/)
606 return store_E_AccessViolation
;
609 storeError
MappedLockBytes::readAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
)
611 sal_uInt8
const * src_lo
= m_pData
+ nOffset
;
612 if ((m_pData
> src_lo
) || (src_lo
>= m_pData
+ m_nSize
))
613 return store_E_NotExists
;
615 sal_uInt8
const * src_hi
= src_lo
+ nBytes
;
616 if ((m_pData
> src_hi
) || (src_hi
> m_pData
+ m_nSize
))
617 return store_E_CantRead
;
619 memcpy (pBuffer
, src_lo
, (src_hi
- src_lo
));
623 storeError
MappedLockBytes::writeAt_Impl (sal_uInt32
/*nOffset*/, void const * /*pBuffer*/, sal_uInt32
/*nBytes*/)
625 return store_E_AccessViolation
;
628 storeError
MappedLockBytes::getSize_Impl (sal_uInt32
& rnSize
)
634 storeError
MappedLockBytes::setSize_Impl (sal_uInt32
/*nSize*/)
636 return store_E_AccessViolation
;
639 storeError
MappedLockBytes::flush_Impl()
644 /*========================================================================
646 * MemoryLockBytes implementation.
648 *======================================================================*/
654 class MemoryLockBytes
:
655 public store::OStoreObject
,
656 public store::ILockBytes
662 rtl::Reference
< PageData::Allocator
> m_xAllocator
;
664 /** ILockBytes implementation.
666 virtual storeError
initialize_Impl (rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
) override
;
668 virtual storeError
readPageAt_Impl (std::shared_ptr
<PageData
> & rPage
, sal_uInt32 nOffset
) override
;
669 virtual storeError
writePageAt_Impl (std::shared_ptr
<PageData
> const & rPage
, sal_uInt32 nOffset
) override
;
671 virtual storeError
readAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
) override
;
672 virtual storeError
writeAt_Impl (sal_uInt32 nOffset
, const void * pBuffer
, sal_uInt32 nBytes
) override
;
674 virtual storeError
getSize_Impl (sal_uInt32
& rnSize
) override
;
675 virtual storeError
setSize_Impl (sal_uInt32 nSize
) override
;
677 virtual storeError
flush_Impl() override
;
684 MemoryLockBytes(const MemoryLockBytes
&) = delete;
685 MemoryLockBytes
& operator=(const MemoryLockBytes
&) = delete;
690 virtual ~MemoryLockBytes() override
;
697 MemoryLockBytes::MemoryLockBytes()
698 : m_pData (nullptr), m_nSize (0), m_xAllocator()
701 MemoryLockBytes::~MemoryLockBytes()
706 storeError
MemoryLockBytes::initialize_Impl (rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
)
708 storeError result
= PageData::Allocator::createInstance (rxAllocator
, nPageSize
);
709 if (result
== store_E_None
)
711 // @see readPageAt_Impl().
712 m_xAllocator
= rxAllocator
;
717 storeError
MemoryLockBytes::readPageAt_Impl (std::shared_ptr
<PageData
> & rPage
, sal_uInt32 nOffset
)
719 if (m_xAllocator
.is())
721 std::shared_ptr
<PageData
> page (m_xAllocator
->construct
<PageData
>(), PageData::Deallocate(m_xAllocator
));
725 if (!m_xAllocator
.is())
726 return store_E_InvalidAccess
;
728 return store_E_OutOfMemory
;
730 PageData
* pagedata
= rPage
.get();
731 return readAt_Impl (nOffset
, pagedata
, pagedata
->size());
734 storeError
MemoryLockBytes::writePageAt_Impl (std::shared_ptr
<PageData
> const & rPage
, sal_uInt32 nOffset
)
736 PageData
const * pagedata
= rPage
.get();
737 OSL_PRECOND(!(pagedata
== nullptr), "contract violation");
738 return writeAt_Impl (nOffset
, pagedata
, pagedata
->size());
741 storeError
MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset
, void * pBuffer
, sal_uInt32 nBytes
)
743 sal_uInt8
const * src_lo
= m_pData
+ nOffset
;
744 if ((m_pData
> src_lo
) || (src_lo
>= m_pData
+ m_nSize
))
745 return store_E_NotExists
;
747 sal_uInt8
const * src_hi
= src_lo
+ nBytes
;
748 if ((m_pData
> src_hi
) || (src_hi
> m_pData
+ m_nSize
))
749 return store_E_CantRead
;
751 memcpy (pBuffer
, src_lo
, (src_hi
- src_lo
));
755 storeError
MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset
, const void * pBuffer
, sal_uInt32 nBytes
)
757 sal_uInt64
const dst_size
= nOffset
+ nBytes
;
758 OSL_PRECOND(dst_size
< SAL_MAX_UINT32
, "store::ILockBytes::writeAt() contract violation");
759 if (dst_size
> m_nSize
)
761 storeError eErrCode
= setSize_Impl (sal::static_int_cast
<sal_uInt32
>(dst_size
));
762 if (eErrCode
!= store_E_None
)
765 SAL_WARN_IF(dst_size
> m_nSize
, "store", "store::MemoryLockBytes::setSize_Impl() contract violation");
767 sal_uInt8
* dst_lo
= m_pData
+ nOffset
;
768 if (dst_lo
>= m_pData
+ m_nSize
)
769 return store_E_CantSeek
;
771 sal_uInt8
* dst_hi
= dst_lo
+ nBytes
;
772 if (dst_hi
> m_pData
+ m_nSize
)
773 return store_E_CantWrite
;
775 memcpy (dst_lo
, pBuffer
, (dst_hi
- dst_lo
));
779 storeError
MemoryLockBytes::getSize_Impl (sal_uInt32
& rnSize
)
785 storeError
MemoryLockBytes::setSize_Impl (sal_uInt32 nSize
)
787 if (nSize
!= m_nSize
)
789 sal_uInt8
* pData
= static_cast<sal_uInt8
*>(std::realloc (m_pData
, nSize
));
790 if (pData
!= nullptr)
793 memset (pData
+ m_nSize
, 0, sal::static_int_cast
<size_t>(nSize
- m_nSize
));
798 return store_E_OutOfMemory
;
806 storeError
MemoryLockBytes::flush_Impl()
811 /*========================================================================
813 * ILockBytes factory implementations.
815 *======================================================================*/
821 template< class T
> struct ResourceHolder
823 typedef typename
T::destructor_type destructor_type
;
827 explicit ResourceHolder (T
const & value
= T()) : m_value (value
) {}
828 ~ResourceHolder() { reset(T()); }
830 T
& get() { return m_value
; }
831 T
const & get() const { return m_value
; }
833 void set (T
const & value
) { m_value
= value
; }
834 void reset (T
const & value
)
838 destructor_type()(tmp
);
848 ResourceHolder
& operator= (ResourceHolder
& rhs
)
850 reset (rhs
.release());
858 FileLockBytes_createInstance (
859 rtl::Reference
< ILockBytes
> & rxLockBytes
,
860 rtl_uString
* pFilename
,
861 storeAccessMode eAccessMode
864 // Acquire file handle.
865 ResourceHolder
<FileHandle
> xFile
;
866 storeError result
= xFile
.get().initialize (pFilename
, eAccessMode
);
867 if (result
!= store_E_None
)
870 if (eAccessMode
== storeAccessMode::ReadOnly
)
872 ResourceHolder
<FileMapping
> xMapping
;
873 if (xMapping
.get().initialize (xFile
.get().m_handle
) == osl_File_E_None
)
875 rxLockBytes
= new MappedLockBytes (xMapping
.get());
876 if (!rxLockBytes
.is())
877 return store_E_OutOfMemory
;
878 (void) xFile
.release();
879 (void) xMapping
.release();
882 if (!rxLockBytes
.is())
884 rxLockBytes
= new FileLockBytes (xFile
.get());
885 if (!rxLockBytes
.is())
886 return store_E_OutOfMemory
;
887 (void) xFile
.release();
894 MemoryLockBytes_createInstance (
895 rtl::Reference
< ILockBytes
> & rxLockBytes
898 rxLockBytes
= new MemoryLockBytes();
899 if (!rxLockBytes
.is())
900 return store_E_OutOfMemory
;
907 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */