Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : :
21 : : #include "lockbyte.hxx"
22 : :
23 : : #include "sal/types.h"
24 : : #include "osl/diagnose.h"
25 : : #include "osl/file.h"
26 : : #include "osl/process.h"
27 : : #include "rtl/alloc.h"
28 : : #include "rtl/ustring.hxx"
29 : :
30 : : #include "object.hxx"
31 : : #include "storbase.hxx"
32 : :
33 : : #include <string.h>
34 : :
35 : : using namespace store;
36 : :
37 : : /*========================================================================
38 : : *
39 : : * ILockBytes (non-virtual interface) implementation.
40 : : *
41 : : *======================================================================*/
42 : :
43 : 17391 : storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
44 : : {
45 : : OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize");
46 : 17391 : return initialize_Impl (rxAllocator, nPageSize);
47 : : }
48 : :
49 : 664066 : storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
50 : : {
51 : : OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
52 [ - + ]: 664066 : if (nOffset == STORE_PAGE_NULL)
53 : 0 : return store_E_CantSeek;
54 : :
55 : 664066 : return readPageAt_Impl (rPage, nOffset);
56 : : }
57 : :
58 : 376549 : storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
59 : : {
60 : : // [SECURITY:ValInput]
61 : 376549 : PageData const * pagedata = rPage.get();
62 : : OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
63 [ - + ]: 376549 : if (pagedata == 0)
64 : 0 : return store_E_InvalidParameter;
65 : :
66 : 376549 : sal_uInt32 const offset = pagedata->location();
67 : : OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
68 [ - + ]: 376549 : if (nOffset != offset)
69 : 0 : return store_E_InvalidParameter;
70 : :
71 : : OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
72 [ - + ]: 376549 : if (nOffset == STORE_PAGE_NULL)
73 : 0 : return store_E_CantSeek;
74 : :
75 : 376549 : return writePageAt_Impl (rPage, nOffset);
76 : : }
77 : :
78 : 35695 : storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
79 : : {
80 : : // [SECURITY:ValInput]
81 : 35695 : sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
82 [ - + ]: 35695 : if (!(dst_lo != 0))
83 : 0 : return store_E_InvalidParameter;
84 : :
85 : 35695 : sal_uInt8 * dst_hi = dst_lo + nBytes;
86 [ - + ]: 35695 : if (!(dst_lo < dst_hi))
87 [ # # ]: 0 : return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
88 : :
89 : : OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset");
90 [ - + ]: 35695 : if (nOffset == STORE_PAGE_NULL)
91 : 0 : return store_E_CantSeek;
92 : :
93 : 35695 : sal_uInt64 const src_size = nOffset + nBytes;
94 [ - + ]: 35695 : if (src_size > SAL_MAX_UINT32)
95 : 0 : return store_E_CantSeek;
96 : :
97 : 35695 : return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
98 : : }
99 : :
100 : 42490 : storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
101 : : {
102 : : // [SECURITY:ValInput]
103 : 42490 : sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
104 [ - + ]: 42490 : if (!(src_lo != 0))
105 : 0 : return store_E_InvalidParameter;
106 : :
107 : 42490 : sal_uInt8 const * src_hi = src_lo + nBytes;
108 [ - + ]: 42490 : if (!(src_lo < src_hi))
109 [ # # ]: 0 : return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
110 : :
111 : : OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset");
112 [ - + ]: 42490 : if (nOffset == STORE_PAGE_NULL)
113 : 0 : return store_E_CantSeek;
114 : :
115 : 42490 : sal_uInt64 const dst_size = nOffset + nBytes;
116 [ - + ]: 42490 : if (dst_size > SAL_MAX_UINT32)
117 : 0 : return store_E_CantSeek;
118 : :
119 : 42490 : return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
120 : : }
121 : :
122 : 124370 : storeError ILockBytes::getSize (sal_uInt32 & rnSize)
123 : : {
124 : 124370 : rnSize = 0;
125 : 124370 : return getSize_Impl (rnSize);
126 : : }
127 : :
128 : 6251 : storeError ILockBytes::setSize (sal_uInt32 nSize)
129 : : {
130 : 6251 : return setSize_Impl (nSize);
131 : : }
132 : :
133 : 66 : storeError ILockBytes::flush()
134 : : {
135 : 66 : return flush_Impl();
136 : : }
137 : :
138 : : /*========================================================================
139 : : *
140 : : * FileLockBytes implementation.
141 : : *
142 : : *======================================================================*/
143 : : namespace store
144 : : {
145 : :
146 : : struct FileHandle
147 : : {
148 : : oslFileHandle m_handle;
149 : :
150 : 53924 : FileHandle() : m_handle(0) {}
151 : :
152 : 18129 : bool operator != (FileHandle const & rhs)
153 : : {
154 : 18129 : return (m_handle != rhs.m_handle);
155 : : }
156 : :
157 : 463 : static storeError errorFromNative (oslFileError eErrno)
158 : : {
159 [ - + - - : 463 : switch (eErrno)
- - - - -
- ]
160 : : {
161 : : case osl_File_E_None:
162 : 0 : return store_E_None;
163 : :
164 : : case osl_File_E_NOENT:
165 : 463 : return store_E_NotExists;
166 : :
167 : : case osl_File_E_ACCES:
168 : : case osl_File_E_PERM:
169 : 0 : return store_E_AccessViolation;
170 : :
171 : : case osl_File_E_AGAIN:
172 : : case osl_File_E_DEADLK:
173 : 0 : return store_E_LockingViolation;
174 : :
175 : : case osl_File_E_BADF:
176 : 0 : return store_E_InvalidHandle;
177 : :
178 : : case osl_File_E_INVAL:
179 : 0 : return store_E_InvalidParameter;
180 : :
181 : : case osl_File_E_NOMEM:
182 : 0 : return store_E_OutOfMemory;
183 : :
184 : : case osl_File_E_NOSPC:
185 : 0 : return store_E_OutOfSpace;
186 : :
187 : : case osl_File_E_OVERFLOW:
188 : 0 : return store_E_CantSeek;
189 : :
190 : : default:
191 : 463 : return store_E_Unknown;
192 : : }
193 : : }
194 : :
195 : 18129 : static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
196 : : {
197 : 18129 : sal_uInt32 nFlags = 0;
198 [ + + + - ]: 18129 : switch (eAccessMode)
199 : : {
200 : : case store_AccessCreate:
201 : : case store_AccessReadCreate:
202 : 6123 : nFlags |= osl_File_OpenFlag_Create;
203 : : // fall through
204 : : case store_AccessReadWrite:
205 : 6395 : nFlags |= osl_File_OpenFlag_Write;
206 : : // fall through
207 : : case store_AccessReadOnly:
208 : 18129 : nFlags |= osl_File_OpenFlag_Read;
209 : 18129 : break;
210 : : default:
211 : : OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode");
212 : : }
213 : 18129 : return nFlags;
214 : : }
215 : :
216 : 18129 : storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
217 : : {
218 : : // Verify arguments.
219 : 18129 : sal_uInt32 nFlags = modeToNative (eAccessMode);
220 [ - + ][ + - ]: 18129 : if (!pFilename || !nFlags)
221 : 0 : return store_E_InvalidParameter;
222 : :
223 : : // Convert into FileUrl.
224 : 18129 : rtl::OUString aFileUrl;
225 [ + + ][ + - ]: 18129 : if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
226 : : {
227 : : // Not system path. Assume file url.
228 : 18127 : rtl_uString_assign (&(aFileUrl.pData), pFilename);
229 : : }
230 [ - + ]: 18129 : if (aFileUrl.compareToAscii("file://", 7) != 0)
231 : : {
232 : : // Not file url. Assume relative path.
233 : 0 : rtl::OUString aCwdUrl;
234 [ # # ]: 0 : (void) osl_getProcessWorkingDir (&(aCwdUrl.pData));
235 : :
236 : : // Absolute file url.
237 [ # # ]: 0 : (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData));
238 : : }
239 : :
240 : : // Acquire handle.
241 [ + - ]: 18129 : oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
242 [ + + ]: 18129 : if (result == osl_File_E_EXIST)
243 : : {
244 : : // Already existing (O_CREAT | O_EXCL).
245 [ + - ]: 1 : result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
246 [ + - ][ + - ]: 1 : if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
247 : : {
248 : : // Truncate existing file.
249 [ + - ]: 1 : result = osl_setFileSize (m_handle, 0);
250 : : }
251 : : }
252 [ + + ]: 18129 : if (result != osl_File_E_None)
253 : 463 : return errorFromNative(result);
254 : 18129 : return store_E_None;
255 : : }
256 : :
257 : : /** @see FileLockBytes destructor
258 : : */
259 : 6256 : static void closeFile (oslFileHandle hFile)
260 : : {
261 : 6256 : (void) osl_closeFile (hFile);
262 : 6256 : }
263 : :
264 : : /** @see ResourceHolder<T>::destructor_type
265 : : */
266 : : struct CloseFile
267 : : {
268 : 0 : void operator()(FileHandle & rFile) const
269 : : {
270 : : // Release handle.
271 : 0 : closeFile (rFile.m_handle);
272 : 0 : rFile.m_handle = 0;
273 : 0 : }
274 : : };
275 : : typedef CloseFile destructor_type;
276 : : };
277 : :
278 : : class FileLockBytes :
279 : : public store::OStoreObject,
280 : : public store::ILockBytes
281 : : {
282 : : /** Representation.
283 : : */
284 : : oslFileHandle m_hFile;
285 : : sal_uInt32 m_nSize;
286 : : rtl::Reference< PageData::Allocator > m_xAllocator;
287 : :
288 : : storeError initSize_Impl (sal_uInt32 & rnSize);
289 : :
290 : : /** ILockBytes implementation.
291 : : */
292 : : virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
293 : :
294 : : virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
295 : : virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
296 : :
297 : : virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
298 : : virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
299 : :
300 : : virtual storeError getSize_Impl (sal_uInt32 & rnSize);
301 : : virtual storeError setSize_Impl (sal_uInt32 nSize);
302 : :
303 : : virtual storeError flush_Impl();
304 : :
305 : : /** Not implemented.
306 : : */
307 : : FileLockBytes (FileLockBytes const &);
308 : : FileLockBytes & operator= (FileLockBytes const &);
309 : :
310 : : public:
311 : : /** Construction.
312 : : */
313 : : explicit FileLockBytes (FileHandle & rFile);
314 : :
315 : : /** Delegate multiple inherited IReference.
316 : : */
317 : : virtual oslInterlockedCount SAL_CALL acquire();
318 : : virtual oslInterlockedCount SAL_CALL release();
319 : :
320 : : protected:
321 : : /** Destruction.
322 : : */
323 : : virtual ~FileLockBytes();
324 : : };
325 : :
326 : : } // namespace store
327 : :
328 : 6256 : FileLockBytes::FileLockBytes (FileHandle & rFile)
329 : 6256 : : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
330 : : {
331 : 6256 : }
332 : :
333 [ + - ]: 6256 : FileLockBytes::~FileLockBytes()
334 : : {
335 [ + - ]: 6256 : FileHandle::closeFile (m_hFile);
336 [ - + ]: 12512 : }
337 : :
338 : 12512 : oslInterlockedCount SAL_CALL FileLockBytes::acquire()
339 : : {
340 : 12512 : return OStoreObject::acquire();
341 : : }
342 : :
343 : 12512 : oslInterlockedCount SAL_CALL FileLockBytes::release()
344 : : {
345 : 12512 : return OStoreObject::release();
346 : : }
347 : :
348 : 6252 : storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
349 : : {
350 : : /* osl_getFileSize() uses slow 'fstat(h, &size)',
351 : : * instead of fast 'size = lseek(h, 0, SEEK_END)'.
352 : : * so, init size here, and track changes.
353 : : */
354 : 6252 : sal_uInt64 uSize = 0;
355 [ + - ]: 6252 : oslFileError result = osl_getFileSize (m_hFile, &uSize);
356 [ - + ]: 6252 : if (result != osl_File_E_None)
357 : 0 : return FileHandle::errorFromNative(result);
358 [ - + ]: 6252 : if (uSize > SAL_MAX_UINT32)
359 : 0 : return store_E_CantSeek;
360 : :
361 : 6252 : rnSize = sal::static_int_cast<sal_uInt32>(uSize);
362 : 6252 : return store_E_None;
363 : : }
364 : :
365 : 6252 : storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
366 : : {
367 : 6252 : storeError result = initSize_Impl (m_nSize);
368 [ - + ]: 6252 : if (result != store_E_None)
369 : 0 : return (result);
370 : :
371 : 6252 : result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
372 [ - + ]: 6252 : if (result != store_E_None)
373 : 0 : return (result);
374 : :
375 : : // @see readPageAt_Impl().
376 : 6252 : m_xAllocator = rxAllocator;
377 : 6252 : return store_E_None;
378 : : }
379 : :
380 : 29749 : storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
381 : : {
382 [ + - ]: 29749 : if (m_xAllocator.is())
383 : : {
384 [ + - ][ + - ]: 29749 : PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
385 [ + - ][ + - ]: 29749 : page.swap (rPage);
386 : : }
387 : :
388 [ - + ]: 29749 : if (!m_xAllocator.is())
389 : 0 : return store_E_InvalidAccess;
390 [ - + ]: 29749 : if (!rPage.get())
391 : 0 : return store_E_OutOfMemory;
392 : :
393 : 29749 : PageData * pagedata = rPage.get();
394 : 29749 : return readAt_Impl (nOffset, pagedata, pagedata->size());
395 : : }
396 : :
397 : 372633 : storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
398 : : {
399 : 372633 : PageData const * pagedata = rPage.get();
400 : : OSL_PRECOND(pagedata != 0, "contract violation");
401 : 372633 : return writeAt_Impl (nOffset, pagedata, pagedata->size());
402 : : }
403 : :
404 : 54034 : storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
405 : : {
406 : 54034 : sal_uInt64 nDone = 0;
407 [ + - ]: 54034 : oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
408 [ - + ]: 54034 : if (result != osl_File_E_None)
409 : 0 : return FileHandle::errorFromNative(result);
410 [ + + ]: 54034 : if (nDone != nBytes)
411 [ - + ]: 6127 : return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
412 : 54034 : return store_E_None;
413 : : }
414 : :
415 : 414995 : storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
416 : : {
417 : 414995 : sal_uInt64 nDone = 0;
418 [ + - ]: 414995 : oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
419 [ - + ]: 414995 : if (result != osl_File_E_None)
420 : 0 : return FileHandle::errorFromNative(result);
421 [ - + ]: 414995 : if (nDone != nBytes)
422 : 0 : return store_E_CantWrite;
423 : :
424 : 414995 : sal_uInt64 const uSize = nOffset + nBytes;
425 : : OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
426 [ + + ]: 414995 : if (uSize > m_nSize)
427 : 128661 : m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
428 : 414995 : return store_E_None;
429 : : }
430 : :
431 : 122538 : storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
432 : : {
433 : 122538 : rnSize = m_nSize;
434 : 122538 : return store_E_None;
435 : : }
436 : :
437 : 6123 : storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
438 : : {
439 : 6123 : oslFileError result = osl_setFileSize (m_hFile, nSize);
440 [ - + ]: 6123 : if (result != osl_File_E_None)
441 : 0 : return FileHandle::errorFromNative(result);
442 : :
443 : 6123 : m_nSize = nSize;
444 : 6123 : return store_E_None;
445 : : }
446 : :
447 : 66 : storeError FileLockBytes::flush_Impl()
448 : : {
449 : 66 : oslFileError result = osl_syncFile (m_hFile);
450 [ - + ]: 66 : if (result != osl_File_E_None)
451 : 0 : return FileHandle::errorFromNative(result);
452 : 66 : return store_E_None;
453 : : }
454 : :
455 : : /*========================================================================
456 : : *
457 : : * MappedLockBytes implementation.
458 : : *
459 : : *======================================================================*/
460 : : namespace store
461 : : {
462 : :
463 : : struct FileMapping
464 : : {
465 : : sal_uInt8 * m_pAddr;
466 : : sal_uInt32 m_nSize;
467 : : oslFileHandle m_hFile;
468 : :
469 : 34238 : FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {}
470 : :
471 : 11414 : bool operator != (FileMapping const & rhs) const
472 : : {
473 [ + - ][ - + ]: 11414 : return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
474 : : }
475 : :
476 : 11414 : oslFileError initialize (oslFileHandle hFile)
477 : : {
478 : : // Determine mapping size.
479 : 11414 : sal_uInt64 uSize = 0;
480 [ + - ]: 11414 : oslFileError result = osl_getFileSize (hFile, &uSize);
481 [ - + ]: 11414 : if (result != osl_File_E_None)
482 : 0 : return result;
483 : :
484 : : // [SECURITY:IntOver]
485 [ - + ]: 11414 : if (uSize > SAL_MAX_UINT32)
486 : 0 : return osl_File_E_OVERFLOW;
487 : 11414 : m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
488 : :
489 : 11414 : m_hFile = hFile;
490 : :
491 : : // Acquire mapping.
492 [ + - ]: 11414 : return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
493 : : }
494 : :
495 : : /** @see MappedLockBytes::destructor.
496 : : */
497 : 10659 : static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
498 : : {
499 : 10659 : (void) osl_unmapMappedFile (hFile, pAddr, nSize);
500 : 10659 : (void) osl_closeFile (hFile);
501 : 10659 : }
502 : :
503 : : /** @see ResourceHolder<T>::destructor_type
504 : : */
505 : : struct UnmapFile
506 : : {
507 : 0 : void operator ()(FileMapping & rMapping) const
508 : : {
509 : : // Release mapping.
510 : 0 : unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize);
511 : 0 : rMapping.m_pAddr = 0, rMapping.m_nSize = 0;
512 : 0 : }
513 : : };
514 : : typedef UnmapFile destructor_type;
515 : : };
516 : :
517 : : class MappedLockBytes :
518 : : public store::OStoreObject,
519 : : public store::PageData::Allocator,
520 : : public store::ILockBytes
521 : : {
522 : : /** Representation.
523 : : */
524 : : sal_uInt8 * m_pData;
525 : : sal_uInt32 m_nSize;
526 : : sal_uInt16 m_nPageSize;
527 : : oslFileHandle m_hFile;
528 : :
529 : : /** PageData::Allocator implementation.
530 : : */
531 : : virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize);
532 : : virtual void deallocate_Impl (void * pPage);
533 : :
534 : : /** ILockBytes implementation.
535 : : */
536 : : virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
537 : :
538 : : virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
539 : : virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
540 : :
541 : : virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
542 : : virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
543 : :
544 : : virtual storeError getSize_Impl (sal_uInt32 & rnSize);
545 : : virtual storeError setSize_Impl (sal_uInt32 nSize);
546 : :
547 : : virtual storeError flush_Impl();
548 : :
549 : : /** Not implemented.
550 : : */
551 : : MappedLockBytes (MappedLockBytes const &);
552 : : MappedLockBytes & operator= (MappedLockBytes const &);
553 : :
554 : : public:
555 : : /** Construction.
556 : : */
557 : : explicit MappedLockBytes (FileMapping & rMapping);
558 : :
559 : : /** Delegate multiple inherited IReference.
560 : : */
561 : : virtual oslInterlockedCount SAL_CALL acquire();
562 : : virtual oslInterlockedCount SAL_CALL release();
563 : :
564 : : protected:
565 : : /* Destruction.
566 : : */
567 : : virtual ~MappedLockBytes();
568 : : };
569 : :
570 : : } // namespace store
571 : :
572 : 11410 : MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
573 : 11410 : : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
574 : : {
575 : 11410 : }
576 : :
577 : 10659 : MappedLockBytes::~MappedLockBytes()
578 : : {
579 [ + - ]: 10659 : FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
580 [ - + ]: 21318 : }
581 : :
582 : 50186882 : oslInterlockedCount SAL_CALL MappedLockBytes::acquire()
583 : : {
584 : 50186882 : return OStoreObject::acquire();
585 : : }
586 : :
587 : 49892994 : oslInterlockedCount SAL_CALL MappedLockBytes::release()
588 : : {
589 : 49892994 : return OStoreObject::release();
590 : : }
591 : :
592 : 0 : void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
593 : : {
594 : : OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
595 [ # # ][ # # ]: 0 : if ((ppPage != 0) && (pnSize != 0))
596 : 0 : *ppPage = 0, *pnSize = m_nPageSize;
597 : 0 : }
598 : :
599 : 342554 : void MappedLockBytes::deallocate_Impl (void * pPage)
600 : : {
601 : : OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
602 : : (void)pPage; // UNUSED
603 : 342554 : }
604 : :
605 : 11011 : storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
606 : : {
607 : 11011 : rxAllocator = this;
608 : 11011 : m_nPageSize = nPageSize;
609 : 11011 : return store_E_None;
610 : : }
611 : :
612 : 634189 : storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
613 : : {
614 : 634189 : sal_uInt8 * src_lo = m_pData + nOffset;
615 [ + - ][ - + ]: 634189 : if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
616 : 0 : return store_E_NotExists;
617 : :
618 : 634189 : sal_uInt8 * src_hi = src_lo + m_nPageSize;
619 [ + - ][ - + ]: 634189 : if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
620 : 0 : return store_E_CantRead;
621 : :
622 [ + - ][ + - ]: 634189 : PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
[ + - ]
623 [ + - ]: 634189 : page.swap (rPage);
624 : :
625 [ + - ]: 634189 : return store_E_None;
626 : : }
627 : :
628 : 0 : storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
629 : : {
630 : 0 : return store_E_AccessViolation;
631 : : }
632 : :
633 : 11410 : storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
634 : : {
635 : 11410 : sal_uInt8 const * src_lo = m_pData + nOffset;
636 [ + - ][ - + ]: 11410 : if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
637 : 0 : return store_E_NotExists;
638 : :
639 : 11410 : sal_uInt8 const * src_hi = src_lo + nBytes;
640 [ + - ][ - + ]: 11410 : if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
641 : 0 : return store_E_CantRead;
642 : :
643 : 11410 : memcpy (pBuffer, src_lo, (src_hi - src_lo));
644 : 11410 : return store_E_None;
645 : : }
646 : :
647 : 0 : storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
648 : : {
649 : 0 : return store_E_AccessViolation;
650 : : }
651 : :
652 : 0 : storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
653 : : {
654 : 0 : rnSize = m_nSize;
655 : 0 : return store_E_None;
656 : : }
657 : :
658 : 0 : storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
659 : : {
660 : 0 : return store_E_AccessViolation;
661 : : }
662 : :
663 : 0 : storeError MappedLockBytes::flush_Impl()
664 : : {
665 : 0 : return store_E_None;
666 : : }
667 : :
668 : : /*========================================================================
669 : : *
670 : : * MemoryLockBytes implementation.
671 : : *
672 : : *======================================================================*/
673 : : namespace store
674 : : {
675 : :
676 : : class MemoryLockBytes :
677 : : public store::OStoreObject,
678 : : public store::ILockBytes
679 : : {
680 : : /** Representation.
681 : : */
682 : : sal_uInt8 * m_pData;
683 : : sal_uInt32 m_nSize;
684 : : rtl::Reference< PageData::Allocator > m_xAllocator;
685 : :
686 : : /** ILockBytes implementation.
687 : : */
688 : : virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
689 : :
690 : : virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
691 : : virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
692 : :
693 : : virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
694 : : virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
695 : :
696 : : virtual storeError getSize_Impl (sal_uInt32 & rnSize);
697 : : virtual storeError setSize_Impl (sal_uInt32 nSize);
698 : :
699 : : virtual storeError flush_Impl();
700 : :
701 : : /** Not implemented.
702 : : */
703 : : MemoryLockBytes (MemoryLockBytes const &);
704 : : MemoryLockBytes& operator= (MemoryLockBytes const &);
705 : :
706 : : public:
707 : : /** Construction.
708 : : */
709 : : MemoryLockBytes();
710 : :
711 : : /** Delegate multiple inherited IReference.
712 : : */
713 : : virtual oslInterlockedCount SAL_CALL acquire();
714 : : virtual oslInterlockedCount SAL_CALL release();
715 : :
716 : : protected:
717 : : /** Destruction.
718 : : */
719 : : virtual ~MemoryLockBytes();
720 : : };
721 : :
722 : : } // namespace store
723 : :
724 : 128 : MemoryLockBytes::MemoryLockBytes()
725 : 128 : : m_pData (0), m_nSize (0), m_xAllocator()
726 : 128 : {}
727 : :
728 [ + - ]: 128 : MemoryLockBytes::~MemoryLockBytes()
729 : : {
730 : 128 : rtl_freeMemory (m_pData);
731 [ - + ]: 256 : }
732 : :
733 : 256 : oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void)
734 : : {
735 : 256 : return OStoreObject::acquire();
736 : : }
737 : :
738 : 256 : oslInterlockedCount SAL_CALL MemoryLockBytes::release (void)
739 : : {
740 : 256 : return OStoreObject::release();
741 : : }
742 : :
743 : 128 : storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
744 : : {
745 : 128 : storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
746 [ + - ]: 128 : if (result == store_E_None)
747 : : {
748 : : // @see readPageAt_Impl().
749 : 128 : m_xAllocator = rxAllocator;
750 : : }
751 : 128 : return result;
752 : : }
753 : :
754 : 128 : storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
755 : : {
756 [ + - ]: 128 : if (m_xAllocator.is())
757 : : {
758 [ + - ][ + - ]: 128 : PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
759 [ + - ][ + - ]: 128 : page.swap (rPage);
760 : : }
761 : :
762 [ - + ]: 128 : if (!m_xAllocator.is())
763 : 0 : return store_E_InvalidAccess;
764 [ - + ]: 128 : if (!rPage.get())
765 : 0 : return store_E_OutOfMemory;
766 : :
767 : 128 : PageData * pagedata = rPage.get();
768 : 128 : return readAt_Impl (nOffset, pagedata, pagedata->size());
769 : : }
770 : :
771 : 3916 : storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
772 : : {
773 : 3916 : PageData const * pagedata = rPage.get();
774 : : OSL_PRECOND(!(pagedata == 0), "contract violation");
775 : 3916 : return writeAt_Impl (nOffset, pagedata, pagedata->size());
776 : : }
777 : :
778 : 128 : storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
779 : : {
780 : 128 : sal_uInt8 const * src_lo = m_pData + nOffset;
781 [ + - ][ + - ]: 128 : if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
782 : 128 : return store_E_NotExists;
783 : :
784 : 0 : sal_uInt8 const * src_hi = src_lo + nBytes;
785 [ # # ][ # # ]: 0 : if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
786 : 0 : return store_E_CantRead;
787 : :
788 : 0 : memcpy (pBuffer, src_lo, (src_hi - src_lo));
789 : 128 : return store_E_None;
790 : : }
791 : :
792 : 4044 : storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
793 : : {
794 : 4044 : sal_uInt64 const dst_size = nOffset + nBytes;
795 : : OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
796 [ + + ]: 4044 : if (dst_size > m_nSize)
797 : : {
798 : 1960 : storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
799 [ - + ]: 1960 : if (eErrCode != store_E_None)
800 : 0 : return eErrCode;
801 : : }
802 : : OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation");
803 : :
804 : 4044 : sal_uInt8 * dst_lo = m_pData + nOffset;
805 [ - + ]: 4044 : if (dst_lo >= m_pData + m_nSize)
806 : 0 : return store_E_CantSeek;
807 : :
808 : 4044 : sal_uInt8 * dst_hi = dst_lo + nBytes;
809 [ - + ]: 4044 : if (dst_hi > m_pData + m_nSize)
810 : 0 : return store_E_CantWrite;
811 : :
812 : 4044 : memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
813 : 4044 : return store_E_None;
814 : : }
815 : :
816 : 1832 : storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
817 : : {
818 : 1832 : rnSize = m_nSize;
819 : 1832 : return store_E_None;
820 : : }
821 : :
822 : 2088 : storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
823 : : {
824 [ + + ]: 2088 : if (nSize != m_nSize)
825 : : {
826 : 1960 : sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
827 [ + - ]: 1960 : if (pData != 0)
828 : : {
829 [ + - ]: 1960 : if (nSize > m_nSize)
830 : 1960 : memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
831 : : }
832 : : else
833 : : {
834 [ # # ]: 0 : if (nSize != 0)
835 : 0 : return store_E_OutOfMemory;
836 : : }
837 : 1960 : m_pData = pData, m_nSize = nSize;
838 : : }
839 : 2088 : return store_E_None;
840 : : }
841 : :
842 : 0 : storeError MemoryLockBytes::flush_Impl()
843 : : {
844 : 0 : return store_E_None;
845 : : }
846 : :
847 : : /*========================================================================
848 : : *
849 : : * ILockBytes factory implementations.
850 : : *
851 : : *======================================================================*/
852 : : namespace store
853 : : {
854 : :
855 : : template< class T > struct ResourceHolder
856 : : {
857 : : typedef typename T::destructor_type destructor_type;
858 : :
859 : : T m_value;
860 : :
861 : 29543 : explicit ResourceHolder (T const & value = T()) : m_value (value) {}
862 [ + - ][ + - ]: 29543 : ~ResourceHolder() { reset(); }
863 : :
864 : 58623 : T & get() { return m_value; }
865 : : T const & get() const { return m_value; }
866 : :
867 : 58619 : void set (T const & value) { m_value = value; }
868 : 29543 : void reset (T const & value = T())
869 : : {
870 : 29543 : T tmp (m_value);
871 [ - + ][ - + ]: 29543 : if (tmp != value)
872 [ # # ][ # # ]: 0 : destructor_type()(tmp);
873 : 29543 : set (value);
874 : 29543 : }
875 : 29076 : T release()
876 : : {
877 : 29076 : T tmp (m_value);
878 : 29076 : set (T());
879 : 29076 : return tmp;
880 : : }
881 : :
882 : : ResourceHolder (ResourceHolder & rhs)
883 : : {
884 : : set (rhs.release());
885 : : }
886 : : ResourceHolder & operator= (ResourceHolder & rhs)
887 : : {
888 : : reset (rhs.release());
889 : : return *this;
890 : : }
891 : : };
892 : :
893 : : storeError
894 : 18129 : FileLockBytes_createInstance (
895 : : rtl::Reference< ILockBytes > & rxLockBytes,
896 : : rtl_uString * pFilename,
897 : : storeAccessMode eAccessMode
898 : : )
899 : : {
900 : : // Acquire file handle.
901 : 18129 : ResourceHolder<FileHandle> xFile;
902 [ + - ]: 18129 : storeError result = xFile.get().initialize (pFilename, eAccessMode);
903 [ + + ]: 18129 : if (result != store_E_None)
904 : 463 : return (result);
905 : :
906 [ + + ]: 17666 : if (eAccessMode == store_AccessReadOnly)
907 : : {
908 : 11414 : ResourceHolder<FileMapping> xMapping;
909 [ + + ][ + - ]: 11414 : if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
910 : : {
911 [ + - ][ + - ]: 11410 : rxLockBytes = new MappedLockBytes (xMapping.get());
[ + - ][ + - ]
912 [ - + ]: 11410 : if (!rxLockBytes.is())
913 : 0 : return store_E_OutOfMemory;
914 [ + - ]: 11410 : (void) xFile.release();
915 [ + - ]: 11414 : (void) xMapping.release();
916 [ + - ][ + - ]: 11414 : }
917 : : }
918 [ + + ]: 17666 : if (!rxLockBytes.is())
919 : : {
920 [ + - ][ + - ]: 6256 : rxLockBytes = new FileLockBytes (xFile.get());
[ + - ][ + - ]
921 [ - + ]: 6256 : if (!rxLockBytes.is())
922 : 0 : return store_E_OutOfMemory;
923 [ + - ]: 6256 : (void) xFile.release();
924 : : }
925 : :
926 [ + - ]: 18129 : return store_E_None;
927 : : }
928 : :
929 : : storeError
930 : 128 : MemoryLockBytes_createInstance (
931 : : rtl::Reference< ILockBytes > & rxLockBytes
932 : : )
933 : : {
934 [ + - ][ + - ]: 128 : rxLockBytes = new MemoryLockBytes();
935 [ - + ]: 128 : if (!rxLockBytes.is())
936 : 0 : return store_E_OutOfMemory;
937 : :
938 : 128 : return store_E_None;
939 : : }
940 : :
941 : : } // namespace store
942 : :
943 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|