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 10724 : 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 10724 : return initialize_Impl (rxAllocator, nPageSize);
47 : }
48 :
49 194921 : storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
50 : {
51 : OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
52 194921 : if (nOffset == STORE_PAGE_NULL)
53 0 : return store_E_CantSeek;
54 :
55 194921 : return readPageAt_Impl (rPage, nOffset);
56 : }
57 :
58 272807 : storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
59 : {
60 : // [SECURITY:ValInput]
61 272807 : PageData const * pagedata = rPage.get();
62 : OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
63 272807 : if (pagedata == 0)
64 0 : return store_E_InvalidParameter;
65 :
66 272807 : sal_uInt32 const offset = pagedata->location();
67 : OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
68 272807 : if (nOffset != offset)
69 0 : return store_E_InvalidParameter;
70 :
71 : OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
72 272807 : if (nOffset == STORE_PAGE_NULL)
73 0 : return store_E_CantSeek;
74 :
75 272807 : return writePageAt_Impl (rPage, nOffset);
76 : }
77 :
78 5542 : storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
79 : {
80 : // [SECURITY:ValInput]
81 5542 : sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
82 5542 : if (!(dst_lo != 0))
83 0 : return store_E_InvalidParameter;
84 :
85 5542 : sal_uInt8 * dst_hi = dst_lo + nBytes;
86 5542 : 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 5542 : if (nOffset == STORE_PAGE_NULL)
91 0 : return store_E_CantSeek;
92 :
93 5542 : sal_uInt64 const src_size = nOffset + nBytes;
94 5542 : if (src_size > SAL_MAX_UINT32)
95 0 : return store_E_CantSeek;
96 :
97 5542 : return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
98 : }
99 :
100 5222 : storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
101 : {
102 : // [SECURITY:ValInput]
103 5222 : sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
104 5222 : if (!(src_lo != 0))
105 0 : return store_E_InvalidParameter;
106 :
107 5222 : sal_uInt8 const * src_hi = src_lo + nBytes;
108 5222 : 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 5222 : if (nOffset == STORE_PAGE_NULL)
113 0 : return store_E_CantSeek;
114 :
115 5222 : sal_uInt64 const dst_size = nOffset + nBytes;
116 5222 : if (dst_size > SAL_MAX_UINT32)
117 0 : return store_E_CantSeek;
118 :
119 5222 : return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
120 : }
121 :
122 107714 : storeError ILockBytes::getSize (sal_uInt32 & rnSize)
123 : {
124 107714 : rnSize = 0;
125 107714 : return getSize_Impl (rnSize);
126 : }
127 :
128 5198 : storeError ILockBytes::setSize (sal_uInt32 nSize)
129 : {
130 5198 : return setSize_Impl (nSize);
131 : }
132 :
133 0 : storeError ILockBytes::flush()
134 : {
135 0 : 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 32198 : FileHandle() : m_handle(0) {}
151 :
152 10737 : bool operator != (FileHandle const & rhs)
153 : {
154 10737 : return (m_handle != rhs.m_handle);
155 : }
156 :
157 13 : static storeError errorFromNative (oslFileError eErrno)
158 : {
159 13 : switch (eErrno)
160 : {
161 : case osl_File_E_None:
162 0 : return store_E_None;
163 :
164 : case osl_File_E_NOENT:
165 13 : 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 0 : return store_E_Unknown;
192 : }
193 : }
194 :
195 10737 : static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
196 : {
197 10737 : sal_uInt32 nFlags = 0;
198 10737 : switch (eAccessMode)
199 : {
200 : case store_AccessCreate:
201 : case store_AccessReadCreate:
202 5198 : nFlags |= osl_File_OpenFlag_Create;
203 : // fall through
204 : case store_AccessReadWrite:
205 5211 : nFlags |= osl_File_OpenFlag_Write;
206 : // fall through
207 : case store_AccessReadOnly:
208 10737 : nFlags |= osl_File_OpenFlag_Read;
209 10737 : break;
210 : default:
211 : OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode");
212 : }
213 10737 : return nFlags;
214 : }
215 :
216 10737 : storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
217 : {
218 : // Verify arguments.
219 10737 : sal_uInt32 nFlags = modeToNative (eAccessMode);
220 10737 : if (!pFilename || !nFlags)
221 0 : return store_E_InvalidParameter;
222 :
223 : // Convert into FileUrl.
224 10737 : rtl::OUString aFileUrl;
225 10737 : if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
226 : {
227 : // Not system path. Assume file url.
228 10737 : rtl_uString_assign (&(aFileUrl.pData), pFilename);
229 : }
230 10737 : 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 10737 : oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
242 10737 : if (result == osl_File_E_EXIST)
243 : {
244 : // Already existing (O_CREAT | O_EXCL).
245 0 : result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
246 0 : if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
247 : {
248 : // Truncate existing file.
249 0 : result = osl_setFileSize (m_handle, 0);
250 : }
251 : }
252 10737 : if (result != osl_File_E_None)
253 13 : return errorFromNative(result);
254 10724 : return store_E_None;
255 : }
256 :
257 : /** @see FileLockBytes destructor
258 : */
259 5198 : static void closeFile (oslFileHandle hFile)
260 : {
261 5198 : (void) osl_closeFile (hFile);
262 5198 : }
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 5198 : FileLockBytes::FileLockBytes (FileHandle & rFile)
329 5198 : : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
330 : {
331 5198 : }
332 :
333 15594 : FileLockBytes::~FileLockBytes()
334 : {
335 5198 : FileHandle::closeFile (m_hFile);
336 10396 : }
337 :
338 10396 : oslInterlockedCount SAL_CALL FileLockBytes::acquire()
339 : {
340 10396 : return OStoreObject::acquire();
341 : }
342 :
343 10396 : oslInterlockedCount SAL_CALL FileLockBytes::release()
344 : {
345 10396 : return OStoreObject::release();
346 : }
347 :
348 5198 : 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 5198 : sal_uInt64 uSize = 0;
355 5198 : oslFileError result = osl_getFileSize (m_hFile, &uSize);
356 5198 : if (result != osl_File_E_None)
357 0 : return FileHandle::errorFromNative(result);
358 5198 : if (uSize > SAL_MAX_UINT32)
359 0 : return store_E_CantSeek;
360 :
361 5198 : rnSize = sal::static_int_cast<sal_uInt32>(uSize);
362 5198 : return store_E_None;
363 : }
364 :
365 5198 : storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
366 : {
367 5198 : storeError result = initSize_Impl (m_nSize);
368 5198 : if (result != store_E_None)
369 0 : return (result);
370 :
371 5198 : result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
372 5198 : if (result != store_E_None)
373 0 : return (result);
374 :
375 : // @see readPageAt_Impl().
376 5198 : m_xAllocator = rxAllocator;
377 5198 : return store_E_None;
378 : }
379 :
380 5198 : storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
381 : {
382 5198 : if (m_xAllocator.is())
383 : {
384 5198 : PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
385 5198 : page.swap (rPage);
386 : }
387 :
388 5198 : if (!m_xAllocator.is())
389 0 : return store_E_InvalidAccess;
390 5198 : if (!rPage.get())
391 0 : return store_E_OutOfMemory;
392 :
393 5198 : PageData * pagedata = rPage.get();
394 5198 : return readAt_Impl (nOffset, pagedata, pagedata->size());
395 : }
396 :
397 272807 : storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
398 : {
399 272807 : PageData const * pagedata = rPage.get();
400 : OSL_PRECOND(pagedata != 0, "contract violation");
401 272807 : return writeAt_Impl (nOffset, pagedata, pagedata->size());
402 : }
403 :
404 5214 : storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
405 : {
406 5214 : sal_uInt64 nDone = 0;
407 5214 : oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
408 5214 : if (result != osl_File_E_None)
409 0 : return FileHandle::errorFromNative(result);
410 5214 : if (nDone != nBytes)
411 5198 : return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
412 16 : return store_E_None;
413 : }
414 :
415 278029 : storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
416 : {
417 278029 : sal_uInt64 nDone = 0;
418 278029 : oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
419 278029 : if (result != osl_File_E_None)
420 0 : return FileHandle::errorFromNative(result);
421 278029 : if (nDone != nBytes)
422 0 : return store_E_CantWrite;
423 :
424 278029 : sal_uInt64 const uSize = nOffset + nBytes;
425 : OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
426 278029 : if (uSize > m_nSize)
427 112912 : m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
428 278029 : return store_E_None;
429 : }
430 :
431 107714 : storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
432 : {
433 107714 : rnSize = m_nSize;
434 107714 : return store_E_None;
435 : }
436 :
437 5198 : storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
438 : {
439 5198 : oslFileError result = osl_setFileSize (m_hFile, nSize);
440 5198 : if (result != osl_File_E_None)
441 0 : return FileHandle::errorFromNative(result);
442 :
443 5198 : m_nSize = nSize;
444 5198 : return store_E_None;
445 : }
446 :
447 0 : storeError FileLockBytes::flush_Impl()
448 : {
449 0 : oslFileError result = osl_syncFile (m_hFile);
450 0 : if (result != osl_File_E_None)
451 0 : return FileHandle::errorFromNative(result);
452 0 : 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 16578 : FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {}
470 :
471 5526 : bool operator != (FileMapping const & rhs) const
472 : {
473 5526 : return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
474 : }
475 :
476 5526 : oslFileError initialize (oslFileHandle hFile)
477 : {
478 : // Determine mapping size.
479 5526 : sal_uInt64 uSize = 0;
480 5526 : oslFileError result = osl_getFileSize (hFile, &uSize);
481 5526 : if (result != osl_File_E_None)
482 0 : return result;
483 :
484 : // [SECURITY:IntOver]
485 5526 : if (uSize > SAL_MAX_UINT32)
486 0 : return osl_File_E_OVERFLOW;
487 5526 : m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
488 :
489 5526 : m_hFile = hFile;
490 :
491 : // Acquire mapping.
492 5526 : return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
493 : }
494 :
495 : /** @see MappedLockBytes::destructor.
496 : */
497 5263 : static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
498 : {
499 5263 : (void) osl_unmapMappedFile (hFile, pAddr, nSize);
500 5263 : (void) osl_closeFile (hFile);
501 5263 : }
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 5526 : MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
573 5526 : : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
574 : {
575 5526 : }
576 :
577 15789 : MappedLockBytes::~MappedLockBytes()
578 : {
579 5263 : FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
580 10526 : }
581 :
582 21775887 : oslInterlockedCount SAL_CALL MappedLockBytes::acquire()
583 : {
584 21775887 : return OStoreObject::acquire();
585 : }
586 :
587 21711828 : oslInterlockedCount SAL_CALL MappedLockBytes::release()
588 : {
589 21711828 : 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 126453 : 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 126453 : }
604 :
605 5526 : storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
606 : {
607 5526 : rxAllocator = this;
608 5526 : m_nPageSize = nPageSize;
609 5526 : return store_E_None;
610 : }
611 :
612 189723 : storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
613 : {
614 189723 : sal_uInt8 * src_lo = m_pData + nOffset;
615 189723 : if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
616 0 : return store_E_NotExists;
617 :
618 189723 : sal_uInt8 * src_hi = src_lo + m_nPageSize;
619 189723 : if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
620 0 : return store_E_CantRead;
621 :
622 189723 : PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
623 189723 : page.swap (rPage);
624 :
625 189723 : 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 5526 : storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
634 : {
635 5526 : sal_uInt8 const * src_lo = m_pData + nOffset;
636 5526 : if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
637 0 : return store_E_NotExists;
638 :
639 5526 : sal_uInt8 const * src_hi = src_lo + nBytes;
640 5526 : if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
641 0 : return store_E_CantRead;
642 :
643 5526 : memcpy (pBuffer, src_lo, (src_hi - src_lo));
644 5526 : 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 0 : MemoryLockBytes::MemoryLockBytes()
725 0 : : m_pData (0), m_nSize (0), m_xAllocator()
726 0 : {}
727 :
728 0 : MemoryLockBytes::~MemoryLockBytes()
729 : {
730 0 : rtl_freeMemory (m_pData);
731 0 : }
732 :
733 0 : oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void)
734 : {
735 0 : return OStoreObject::acquire();
736 : }
737 :
738 0 : oslInterlockedCount SAL_CALL MemoryLockBytes::release (void)
739 : {
740 0 : return OStoreObject::release();
741 : }
742 :
743 0 : storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
744 : {
745 0 : storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
746 0 : if (result == store_E_None)
747 : {
748 : // @see readPageAt_Impl().
749 0 : m_xAllocator = rxAllocator;
750 : }
751 0 : return result;
752 : }
753 :
754 0 : storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
755 : {
756 0 : if (m_xAllocator.is())
757 : {
758 0 : PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
759 0 : page.swap (rPage);
760 : }
761 :
762 0 : if (!m_xAllocator.is())
763 0 : return store_E_InvalidAccess;
764 0 : if (!rPage.get())
765 0 : return store_E_OutOfMemory;
766 :
767 0 : PageData * pagedata = rPage.get();
768 0 : return readAt_Impl (nOffset, pagedata, pagedata->size());
769 : }
770 :
771 0 : storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
772 : {
773 0 : PageData const * pagedata = rPage.get();
774 : OSL_PRECOND(!(pagedata == 0), "contract violation");
775 0 : return writeAt_Impl (nOffset, pagedata, pagedata->size());
776 : }
777 :
778 0 : storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
779 : {
780 0 : sal_uInt8 const * src_lo = m_pData + nOffset;
781 0 : if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
782 0 : 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 0 : return store_E_None;
790 : }
791 :
792 0 : storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
793 : {
794 0 : sal_uInt64 const dst_size = nOffset + nBytes;
795 : OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
796 0 : if (dst_size > m_nSize)
797 : {
798 0 : storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
799 0 : 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 0 : sal_uInt8 * dst_lo = m_pData + nOffset;
805 0 : if (dst_lo >= m_pData + m_nSize)
806 0 : return store_E_CantSeek;
807 :
808 0 : sal_uInt8 * dst_hi = dst_lo + nBytes;
809 0 : if (dst_hi > m_pData + m_nSize)
810 0 : return store_E_CantWrite;
811 :
812 0 : memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
813 0 : return store_E_None;
814 : }
815 :
816 0 : storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
817 : {
818 0 : rnSize = m_nSize;
819 0 : return store_E_None;
820 : }
821 :
822 0 : storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
823 : {
824 0 : if (nSize != m_nSize)
825 : {
826 0 : sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
827 0 : if (pData != 0)
828 : {
829 0 : if (nSize > m_nSize)
830 0 : 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 0 : m_pData = pData, m_nSize = nSize;
838 : }
839 0 : 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 16263 : explicit ResourceHolder (T const & value = T()) : m_value (value) {}
862 16263 : ~ResourceHolder() { reset(); }
863 :
864 32513 : T & get() { return m_value; }
865 : T const & get() const { return m_value; }
866 :
867 32513 : void set (T const & value) { m_value = value; }
868 16263 : void reset (T const & value = T())
869 : {
870 16263 : T tmp (m_value);
871 16263 : if (tmp != value)
872 0 : destructor_type()(tmp);
873 16263 : set (value);
874 16263 : }
875 16250 : T release()
876 : {
877 16250 : T tmp (m_value);
878 16250 : set (T());
879 16250 : 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 10737 : FileLockBytes_createInstance (
895 : rtl::Reference< ILockBytes > & rxLockBytes,
896 : rtl_uString * pFilename,
897 : storeAccessMode eAccessMode
898 : )
899 : {
900 : // Acquire file handle.
901 10737 : ResourceHolder<FileHandle> xFile;
902 10737 : storeError result = xFile.get().initialize (pFilename, eAccessMode);
903 10737 : if (result != store_E_None)
904 13 : return (result);
905 :
906 10724 : if (eAccessMode == store_AccessReadOnly)
907 : {
908 5526 : ResourceHolder<FileMapping> xMapping;
909 5526 : if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
910 : {
911 5526 : rxLockBytes = new MappedLockBytes (xMapping.get());
912 5526 : if (!rxLockBytes.is())
913 0 : return store_E_OutOfMemory;
914 5526 : (void) xFile.release();
915 5526 : (void) xMapping.release();
916 5526 : }
917 : }
918 10724 : if (!rxLockBytes.is())
919 : {
920 5198 : rxLockBytes = new FileLockBytes (xFile.get());
921 5198 : if (!rxLockBytes.is())
922 0 : return store_E_OutOfMemory;
923 5198 : (void) xFile.release();
924 : }
925 :
926 10724 : return store_E_None;
927 : }
928 :
929 : storeError
930 0 : MemoryLockBytes_createInstance (
931 : rtl::Reference< ILockBytes > & rxLockBytes
932 : )
933 : {
934 0 : rxLockBytes = new MemoryLockBytes();
935 0 : if (!rxLockBytes.is())
936 0 : return store_E_OutOfMemory;
937 :
938 0 : return store_E_None;
939 : }
940 :
941 : } // namespace store
942 :
943 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|