File: | store/source/lockbyte.cxx |
Location: | line 775, column 45 |
Description: | Called C++ object pointer is null |
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 | 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")do { if (true && (!((((sal_uInt16)0x0200) <= nPageSize ) && (nPageSize <= ((sal_uInt16)0x8000))))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "45" ": "), "%s", "invalid PageSize"); } } while (false); | |||
46 | return initialize_Impl (rxAllocator, nPageSize); | |||
47 | } | |||
48 | ||||
49 | storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset) | |||
50 | { | |||
51 | OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset")do { if (true && (!(!(nOffset == ((sal_uInt32)(~0)))) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "51" ": "), "%s", "store::ILockBytes::readPageAt(): invalid Offset" ); } } while (false); | |||
52 | if (nOffset == STORE_PAGE_NULL((sal_uInt32)(~0))) | |||
53 | return store_E_CantSeek; | |||
54 | ||||
55 | return readPageAt_Impl (rPage, nOffset); | |||
56 | } | |||
57 | ||||
58 | storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset) | |||
59 | { | |||
60 | // [SECURITY:ValInput] | |||
61 | PageData const * pagedata = rPage.get(); | |||
62 | OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page")do { if (true && (!(!(pagedata == 0)))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "62" ": "), "%s", "store::ILockBytes::writePageAt(): invalid Page" ); } } while (false); | |||
63 | if (pagedata == 0) | |||
64 | return store_E_InvalidParameter; | |||
65 | ||||
66 | sal_uInt32 const offset = pagedata->location(); | |||
67 | OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset")do { if (true && (!(!(nOffset != offset)))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "67" ": "), "%s", "store::ILockBytes::writePageAt(): inconsistent Offset" ); } } while (false); | |||
68 | if (nOffset != offset) | |||
69 | return store_E_InvalidParameter; | |||
70 | ||||
71 | OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset")do { if (true && (!(!(nOffset == ((sal_uInt32)(~0)))) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "71" ": "), "%s", "store::ILockBytes::writePageAt(): invalid Offset" ); } } while (false); | |||
72 | if (nOffset == STORE_PAGE_NULL((sal_uInt32)(~0))) | |||
73 | return store_E_CantSeek; | |||
74 | ||||
75 | return writePageAt_Impl (rPage, nOffset); | |||
76 | } | |||
77 | ||||
78 | storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) | |||
79 | { | |||
80 | // [SECURITY:ValInput] | |||
81 | sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer); | |||
82 | if (!(dst_lo != 0)) | |||
83 | return store_E_InvalidParameter; | |||
84 | ||||
85 | sal_uInt8 * dst_hi = dst_lo + nBytes; | |||
86 | if (!(dst_lo < dst_hi)) | |||
87 | return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None; | |||
88 | ||||
89 | OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset")do { if (true && (!(!(nOffset == ((sal_uInt32)(~0)))) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "89" ": "), "%s", "store::ILockBytes::readAt(): invalid Offset" ); } } while (false); | |||
90 | if (nOffset == STORE_PAGE_NULL((sal_uInt32)(~0))) | |||
91 | return store_E_CantSeek; | |||
92 | ||||
93 | sal_uInt64 const src_size = nOffset + nBytes; | |||
94 | if (src_size > SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF)) | |||
95 | return store_E_CantSeek; | |||
96 | ||||
97 | return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo)); | |||
98 | } | |||
99 | ||||
100 | storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) | |||
101 | { | |||
102 | // [SECURITY:ValInput] | |||
103 | sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer); | |||
104 | if (!(src_lo != 0)) | |||
105 | return store_E_InvalidParameter; | |||
106 | ||||
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; | |||
110 | ||||
111 | OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset")do { if (true && (!(!(nOffset == ((sal_uInt32)(~0)))) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "111" ": "), "%s", "store::ILockBytes::writeAt(): invalid Offset" ); } } while (false); | |||
112 | if (nOffset == STORE_PAGE_NULL((sal_uInt32)(~0))) | |||
113 | return store_E_CantSeek; | |||
114 | ||||
115 | sal_uInt64 const dst_size = nOffset + nBytes; | |||
116 | if (dst_size > SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF)) | |||
117 | return store_E_CantSeek; | |||
118 | ||||
119 | return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo)); | |||
120 | } | |||
121 | ||||
122 | storeError ILockBytes::getSize (sal_uInt32 & rnSize) | |||
123 | { | |||
124 | rnSize = 0; | |||
125 | return getSize_Impl (rnSize); | |||
126 | } | |||
127 | ||||
128 | storeError ILockBytes::setSize (sal_uInt32 nSize) | |||
129 | { | |||
130 | return setSize_Impl (nSize); | |||
131 | } | |||
132 | ||||
133 | storeError ILockBytes::flush() | |||
134 | { | |||
135 | 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 | FileHandle() : m_handle(0) {} | |||
151 | ||||
152 | bool operator != (FileHandle const & rhs) | |||
153 | { | |||
154 | return (m_handle != rhs.m_handle); | |||
155 | } | |||
156 | ||||
157 | static storeError errorFromNative (oslFileError eErrno) | |||
158 | { | |||
159 | switch (eErrno) | |||
160 | { | |||
161 | case osl_File_E_None: | |||
162 | return store_E_None; | |||
163 | ||||
164 | case osl_File_E_NOENT: | |||
165 | return store_E_NotExists; | |||
166 | ||||
167 | case osl_File_E_ACCES: | |||
168 | case osl_File_E_PERM: | |||
169 | return store_E_AccessViolation; | |||
170 | ||||
171 | case osl_File_E_AGAIN: | |||
172 | case osl_File_E_DEADLK: | |||
173 | return store_E_LockingViolation; | |||
174 | ||||
175 | case osl_File_E_BADF: | |||
176 | return store_E_InvalidHandle; | |||
177 | ||||
178 | case osl_File_E_INVAL: | |||
179 | return store_E_InvalidParameter; | |||
180 | ||||
181 | case osl_File_E_NOMEM: | |||
182 | return store_E_OutOfMemory; | |||
183 | ||||
184 | case osl_File_E_NOSPC: | |||
185 | return store_E_OutOfSpace; | |||
186 | ||||
187 | case osl_File_E_OVERFLOW: | |||
188 | return store_E_CantSeek; | |||
189 | ||||
190 | default: | |||
191 | return store_E_Unknown; | |||
192 | } | |||
193 | } | |||
194 | ||||
195 | static sal_uInt32 modeToNative (storeAccessMode eAccessMode) | |||
196 | { | |||
197 | sal_uInt32 nFlags = 0; | |||
198 | switch (eAccessMode) | |||
199 | { | |||
200 | case store_AccessCreate: | |||
201 | case store_AccessReadCreate: | |||
202 | nFlags |= osl_File_OpenFlag_Create0x00000004L; | |||
203 | // fall through | |||
204 | case store_AccessReadWrite: | |||
205 | nFlags |= osl_File_OpenFlag_Write0x00000002L; | |||
206 | // fall through | |||
207 | case store_AccessReadOnly: | |||
208 | nFlags |= osl_File_OpenFlag_Read0x00000001L; | |||
209 | break; | |||
210 | default: | |||
211 | OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode")do { if (true && (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "211" ": "), "%s", "store::FileHandle: unknown storeAccessMode" ); } } while (false); | |||
212 | } | |||
213 | return nFlags; | |||
214 | } | |||
215 | ||||
216 | storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode) | |||
217 | { | |||
218 | // Verify arguments. | |||
219 | sal_uInt32 nFlags = modeToNative (eAccessMode); | |||
220 | if (!pFilename || !nFlags) | |||
221 | return store_E_InvalidParameter; | |||
222 | ||||
223 | // Convert into FileUrl. | |||
224 | rtl::OUString aFileUrl; | |||
225 | if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None) | |||
226 | { | |||
227 | // Not system path. Assume file url. | |||
228 | rtl_uString_assign (&(aFileUrl.pData), pFilename); | |||
229 | } | |||
230 | if (aFileUrl.compareToAscii("file://", 7) != 0) | |||
231 | { | |||
232 | // Not file url. Assume relative path. | |||
233 | rtl::OUString aCwdUrl; | |||
234 | (void) osl_getProcessWorkingDir (&(aCwdUrl.pData)); | |||
235 | ||||
236 | // Absolute file url. | |||
237 | (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData)); | |||
238 | } | |||
239 | ||||
240 | // Acquire handle. | |||
241 | oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags); | |||
242 | if (result == osl_File_E_EXIST) | |||
243 | { | |||
244 | // Already existing (O_CREAT | O_EXCL). | |||
245 | result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read0x00000001L | osl_File_OpenFlag_Write0x00000002L); | |||
246 | if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate)) | |||
247 | { | |||
248 | // Truncate existing file. | |||
249 | result = osl_setFileSize (m_handle, 0); | |||
250 | } | |||
251 | } | |||
252 | if (result != osl_File_E_None) | |||
253 | return errorFromNative(result); | |||
254 | return store_E_None; | |||
255 | } | |||
256 | ||||
257 | /** @see FileLockBytes destructor | |||
258 | */ | |||
259 | static void closeFile (oslFileHandle hFile) | |||
260 | { | |||
261 | (void) osl_closeFile (hFile); | |||
262 | } | |||
263 | ||||
264 | /** @see ResourceHolder<T>::destructor_type | |||
265 | */ | |||
266 | struct CloseFile | |||
267 | { | |||
268 | void operator()(FileHandle & rFile) const | |||
269 | { | |||
270 | // Release handle. | |||
271 | closeFile (rFile.m_handle); | |||
272 | rFile.m_handle = 0; | |||
273 | } | |||
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 | FileLockBytes::FileLockBytes (FileHandle & rFile) | |||
329 | : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF)), m_xAllocator() | |||
330 | { | |||
331 | } | |||
332 | ||||
333 | FileLockBytes::~FileLockBytes() | |||
334 | { | |||
335 | FileHandle::closeFile (m_hFile); | |||
336 | } | |||
337 | ||||
338 | oslInterlockedCount SAL_CALL FileLockBytes::acquire() | |||
339 | { | |||
340 | return OStoreObject::acquire(); | |||
341 | } | |||
342 | ||||
343 | oslInterlockedCount SAL_CALL FileLockBytes::release() | |||
344 | { | |||
345 | return OStoreObject::release(); | |||
346 | } | |||
347 | ||||
348 | 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 | sal_uInt64 uSize = 0; | |||
355 | oslFileError result = osl_getFileSize (m_hFile, &uSize); | |||
356 | if (result != osl_File_E_None) | |||
357 | return FileHandle::errorFromNative(result); | |||
358 | if (uSize > SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF)) | |||
359 | return store_E_CantSeek; | |||
360 | ||||
361 | rnSize = sal::static_int_cast<sal_uInt32>(uSize); | |||
362 | return store_E_None; | |||
363 | } | |||
364 | ||||
365 | storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) | |||
366 | { | |||
367 | storeError result = initSize_Impl (m_nSize); | |||
368 | if (result != store_E_None) | |||
369 | return (result); | |||
370 | ||||
371 | result = PageData::Allocator::createInstance (rxAllocator, nPageSize); | |||
372 | if (result != store_E_None) | |||
373 | return (result); | |||
374 | ||||
375 | // @see readPageAt_Impl(). | |||
376 | m_xAllocator = rxAllocator; | |||
377 | return store_E_None; | |||
378 | } | |||
379 | ||||
380 | storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) | |||
381 | { | |||
382 | if (m_xAllocator.is()) | |||
383 | { | |||
384 | PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator); | |||
385 | page.swap (rPage); | |||
386 | } | |||
387 | ||||
388 | if (!m_xAllocator.is()) | |||
389 | return store_E_InvalidAccess; | |||
390 | if (!rPage.get()) | |||
391 | return store_E_OutOfMemory; | |||
392 | ||||
393 | PageData * pagedata = rPage.get(); | |||
394 | return readAt_Impl (nOffset, pagedata, pagedata->size()); | |||
395 | } | |||
396 | ||||
397 | storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) | |||
398 | { | |||
399 | PageData const * pagedata = rPage.get(); | |||
400 | OSL_PRECOND(pagedata != 0, "contract violation")do { if (true && (!(pagedata != 0))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "400" ": "), "%s", "contract violation"); } } while (false ); | |||
401 | return writeAt_Impl (nOffset, pagedata, pagedata->size()); | |||
402 | } | |||
403 | ||||
404 | storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) | |||
405 | { | |||
406 | sal_uInt64 nDone = 0; | |||
407 | oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone); | |||
408 | if (result != osl_File_E_None) | |||
409 | return FileHandle::errorFromNative(result); | |||
410 | if (nDone != nBytes) | |||
411 | return (nDone != 0) ? store_E_CantRead : store_E_NotExists; | |||
412 | return store_E_None; | |||
413 | } | |||
414 | ||||
415 | storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) | |||
416 | { | |||
417 | sal_uInt64 nDone = 0; | |||
418 | oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone); | |||
419 | if (result != osl_File_E_None) | |||
420 | return FileHandle::errorFromNative(result); | |||
421 | if (nDone != nBytes) | |||
422 | return store_E_CantWrite; | |||
423 | ||||
424 | sal_uInt64 const uSize = nOffset + nBytes; | |||
425 | OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation")do { if (true && (!(uSize < ((sal_uInt32) 0xFFFFFFFF )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "425" ": "), "%s", "store::ILockBytes::writeAt() contract violation" ); } } while (false); | |||
426 | if (uSize > m_nSize) | |||
427 | m_nSize = sal::static_int_cast<sal_uInt32>(uSize); | |||
428 | return store_E_None; | |||
429 | } | |||
430 | ||||
431 | storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize) | |||
432 | { | |||
433 | rnSize = m_nSize; | |||
434 | return store_E_None; | |||
435 | } | |||
436 | ||||
437 | storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize) | |||
438 | { | |||
439 | oslFileError result = osl_setFileSize (m_hFile, nSize); | |||
440 | if (result != osl_File_E_None) | |||
441 | return FileHandle::errorFromNative(result); | |||
442 | ||||
443 | m_nSize = nSize; | |||
444 | return store_E_None; | |||
445 | } | |||
446 | ||||
447 | storeError FileLockBytes::flush_Impl() | |||
448 | { | |||
449 | oslFileError result = osl_syncFile (m_hFile); | |||
450 | if (result != osl_File_E_None) | |||
451 | return FileHandle::errorFromNative(result); | |||
452 | 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 | FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {} | |||
470 | ||||
471 | bool operator != (FileMapping const & rhs) const | |||
472 | { | |||
473 | return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize)); | |||
474 | } | |||
475 | ||||
476 | oslFileError initialize (oslFileHandle hFile) | |||
477 | { | |||
478 | // Determine mapping size. | |||
479 | sal_uInt64 uSize = 0; | |||
480 | oslFileError result = osl_getFileSize (hFile, &uSize); | |||
481 | if (result != osl_File_E_None) | |||
482 | return result; | |||
483 | ||||
484 | // [SECURITY:IntOver] | |||
485 | if (uSize > SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF)) | |||
486 | return osl_File_E_OVERFLOW; | |||
487 | m_nSize = sal::static_int_cast<sal_uInt32>(uSize); | |||
488 | ||||
489 | m_hFile = hFile; | |||
490 | ||||
491 | // Acquire mapping. | |||
492 | return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess((sal_uInt32)(0x1))); | |||
493 | } | |||
494 | ||||
495 | /** @see MappedLockBytes::destructor. | |||
496 | */ | |||
497 | static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize) | |||
498 | { | |||
499 | (void) osl_unmapMappedFile (hFile, pAddr, nSize); | |||
500 | (void) osl_closeFile (hFile); | |||
501 | } | |||
502 | ||||
503 | /** @see ResourceHolder<T>::destructor_type | |||
504 | */ | |||
505 | struct UnmapFile | |||
506 | { | |||
507 | void operator ()(FileMapping & rMapping) const | |||
508 | { | |||
509 | // Release mapping. | |||
510 | unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize); | |||
511 | rMapping.m_pAddr = 0, rMapping.m_nSize = 0; | |||
512 | } | |||
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 | MappedLockBytes::MappedLockBytes (FileMapping & rMapping) | |||
573 | : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile) | |||
574 | { | |||
575 | } | |||
576 | ||||
577 | MappedLockBytes::~MappedLockBytes() | |||
578 | { | |||
579 | FileMapping::unmapFile (m_hFile, m_pData, m_nSize); | |||
580 | } | |||
581 | ||||
582 | oslInterlockedCount SAL_CALL MappedLockBytes::acquire() | |||
583 | { | |||
584 | return OStoreObject::acquire(); | |||
585 | } | |||
586 | ||||
587 | oslInterlockedCount SAL_CALL MappedLockBytes::release() | |||
588 | { | |||
589 | return OStoreObject::release(); | |||
590 | } | |||
591 | ||||
592 | void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) | |||
593 | { | |||
594 | OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation")do { if (true && (!((ppPage != 0) && (pnSize != 0)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "594" ": "), "%s", "contract violation"); } } while (false); | |||
595 | if ((ppPage != 0) && (pnSize != 0)) | |||
596 | *ppPage = 0, *pnSize = m_nPageSize; | |||
597 | } | |||
598 | ||||
599 | void MappedLockBytes::deallocate_Impl (void * pPage) | |||
600 | { | |||
601 | OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation")do { if (true && (!((m_pData <= pPage) && ( pPage < m_pData + m_nSize)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "601" ": "), "%s", "contract violation"); } } while (false ); | |||
602 | (void)pPage; // UNUSED | |||
603 | } | |||
604 | ||||
605 | storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) | |||
606 | { | |||
607 | rxAllocator = this; | |||
608 | m_nPageSize = nPageSize; | |||
609 | return store_E_None; | |||
610 | } | |||
611 | ||||
612 | storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) | |||
613 | { | |||
614 | sal_uInt8 * src_lo = m_pData + nOffset; | |||
615 | if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) | |||
616 | return store_E_NotExists; | |||
617 | ||||
618 | sal_uInt8 * src_hi = src_lo + m_nPageSize; | |||
619 | if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) | |||
620 | return store_E_CantRead; | |||
621 | ||||
622 | PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this)); | |||
623 | page.swap (rPage); | |||
624 | ||||
625 | return store_E_None; | |||
626 | } | |||
627 | ||||
628 | storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/) | |||
629 | { | |||
630 | return store_E_AccessViolation; | |||
631 | } | |||
632 | ||||
633 | storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) | |||
634 | { | |||
635 | sal_uInt8 const * src_lo = m_pData + nOffset; | |||
636 | if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) | |||
637 | return store_E_NotExists; | |||
638 | ||||
639 | sal_uInt8 const * src_hi = src_lo + nBytes; | |||
640 | if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) | |||
641 | return store_E_CantRead; | |||
642 | ||||
643 | memcpy (pBuffer, src_lo, (src_hi - src_lo)); | |||
644 | return store_E_None; | |||
645 | } | |||
646 | ||||
647 | storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/) | |||
648 | { | |||
649 | return store_E_AccessViolation; | |||
650 | } | |||
651 | ||||
652 | storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize) | |||
653 | { | |||
654 | rnSize = m_nSize; | |||
655 | return store_E_None; | |||
656 | } | |||
657 | ||||
658 | storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/) | |||
659 | { | |||
660 | return store_E_AccessViolation; | |||
661 | } | |||
662 | ||||
663 | storeError MappedLockBytes::flush_Impl() | |||
664 | { | |||
665 | 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 | MemoryLockBytes::MemoryLockBytes() | |||
725 | : m_pData (0), m_nSize (0), m_xAllocator() | |||
726 | {} | |||
727 | ||||
728 | MemoryLockBytes::~MemoryLockBytes() | |||
729 | { | |||
730 | rtl_freeMemory (m_pData); | |||
731 | } | |||
732 | ||||
733 | oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void) | |||
734 | { | |||
735 | return OStoreObject::acquire(); | |||
736 | } | |||
737 | ||||
738 | oslInterlockedCount SAL_CALL MemoryLockBytes::release (void) | |||
739 | { | |||
740 | return OStoreObject::release(); | |||
741 | } | |||
742 | ||||
743 | storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) | |||
744 | { | |||
745 | storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize); | |||
746 | if (result == store_E_None) | |||
747 | { | |||
748 | // @see readPageAt_Impl(). | |||
749 | m_xAllocator = rxAllocator; | |||
750 | } | |||
751 | return result; | |||
752 | } | |||
753 | ||||
754 | storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) | |||
755 | { | |||
756 | if (m_xAllocator.is()) | |||
757 | { | |||
758 | PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator); | |||
759 | page.swap (rPage); | |||
760 | } | |||
761 | ||||
762 | if (!m_xAllocator.is()) | |||
763 | return store_E_InvalidAccess; | |||
764 | if (!rPage.get()) | |||
765 | return store_E_OutOfMemory; | |||
766 | ||||
767 | PageData * pagedata = rPage.get(); | |||
768 | return readAt_Impl (nOffset, pagedata, pagedata->size()); | |||
769 | } | |||
770 | ||||
771 | storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) | |||
772 | { | |||
773 | PageData const * pagedata = rPage.get(); | |||
| ||||
774 | OSL_PRECOND(!(pagedata == 0), "contract violation")do { if (true && (!(!(pagedata == 0)))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "774" ": "), "%s", "contract violation"); } } while (false ); | |||
775 | return writeAt_Impl (nOffset, pagedata, pagedata->size()); | |||
| ||||
776 | } | |||
777 | ||||
778 | storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) | |||
779 | { | |||
780 | sal_uInt8 const * src_lo = m_pData + nOffset; | |||
781 | if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) | |||
782 | return store_E_NotExists; | |||
783 | ||||
784 | sal_uInt8 const * src_hi = src_lo + nBytes; | |||
785 | if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) | |||
786 | return store_E_CantRead; | |||
787 | ||||
788 | memcpy (pBuffer, src_lo, (src_hi - src_lo)); | |||
789 | return store_E_None; | |||
790 | } | |||
791 | ||||
792 | storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) | |||
793 | { | |||
794 | sal_uInt64 const dst_size = nOffset + nBytes; | |||
795 | OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation")do { if (true && (!(dst_size < ((sal_uInt32) 0xFFFFFFFF )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "795" ": "), "%s", "store::ILockBytes::writeAt() contract violation" ); } } while (false); | |||
796 | if (dst_size > m_nSize) | |||
797 | { | |||
798 | storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size)); | |||
799 | if (eErrCode != store_E_None) | |||
800 | return eErrCode; | |||
801 | } | |||
802 | OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation")do { if (true && (!(dst_size <= m_nSize))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/lockbyte.cxx" ":" "802" ": "), "%s", "store::MemoryLockBytes::setSize_Impl() contract violation" ); } } while (false); | |||
803 | ||||
804 | sal_uInt8 * dst_lo = m_pData + nOffset; | |||
805 | if (dst_lo >= m_pData + m_nSize) | |||
806 | return store_E_CantSeek; | |||
807 | ||||
808 | sal_uInt8 * dst_hi = dst_lo + nBytes; | |||
809 | if (dst_hi > m_pData + m_nSize) | |||
810 | return store_E_CantWrite; | |||
811 | ||||
812 | memcpy (dst_lo, pBuffer, (dst_hi - dst_lo)); | |||
813 | return store_E_None; | |||
814 | } | |||
815 | ||||
816 | storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize) | |||
817 | { | |||
818 | rnSize = m_nSize; | |||
819 | return store_E_None; | |||
820 | } | |||
821 | ||||
822 | storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize) | |||
823 | { | |||
824 | if (nSize != m_nSize) | |||
825 | { | |||
826 | sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize)); | |||
827 | if (pData != 0) | |||
828 | { | |||
829 | if (nSize > m_nSize) | |||
830 | memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize)); | |||
831 | } | |||
832 | else | |||
833 | { | |||
834 | if (nSize != 0) | |||
835 | return store_E_OutOfMemory; | |||
836 | } | |||
837 | m_pData = pData, m_nSize = nSize; | |||
838 | } | |||
839 | return store_E_None; | |||
840 | } | |||
841 | ||||
842 | storeError MemoryLockBytes::flush_Impl() | |||
843 | { | |||
844 | 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 | explicit ResourceHolder (T const & value = T()) : m_value (value) {} | |||
862 | ~ResourceHolder() { reset(); } | |||
863 | ||||
864 | T & get() { return m_value; } | |||
865 | T const & get() const { return m_value; } | |||
866 | ||||
867 | void set (T const & value) { m_value = value; } | |||
868 | void reset (T const & value = T()) | |||
869 | { | |||
870 | T tmp (m_value); | |||
871 | if (tmp != value) | |||
872 | destructor_type()(tmp); | |||
873 | set (value); | |||
874 | } | |||
875 | T release() | |||
876 | { | |||
877 | T tmp (m_value); | |||
878 | set (T()); | |||
879 | 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 | FileLockBytes_createInstance ( | |||
895 | rtl::Reference< ILockBytes > & rxLockBytes, | |||
896 | rtl_uString * pFilename, | |||
897 | storeAccessMode eAccessMode | |||
898 | ) | |||
899 | { | |||
900 | // Acquire file handle. | |||
901 | ResourceHolder<FileHandle> xFile; | |||
902 | storeError result = xFile.get().initialize (pFilename, eAccessMode); | |||
903 | if (result != store_E_None) | |||
904 | return (result); | |||
905 | ||||
906 | if (eAccessMode == store_AccessReadOnly) | |||
907 | { | |||
908 | ResourceHolder<FileMapping> xMapping; | |||
909 | if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None) | |||
910 | { | |||
911 | rxLockBytes = new MappedLockBytes (xMapping.get()); | |||
912 | if (!rxLockBytes.is()) | |||
913 | return store_E_OutOfMemory; | |||
914 | (void) xFile.release(); | |||
915 | (void) xMapping.release(); | |||
916 | } | |||
917 | } | |||
918 | if (!rxLockBytes.is()) | |||
919 | { | |||
920 | rxLockBytes = new FileLockBytes (xFile.get()); | |||
921 | if (!rxLockBytes.is()) | |||
922 | return store_E_OutOfMemory; | |||
923 | (void) xFile.release(); | |||
924 | } | |||
925 | ||||
926 | return store_E_None; | |||
927 | } | |||
928 | ||||
929 | storeError | |||
930 | MemoryLockBytes_createInstance ( | |||
931 | rtl::Reference< ILockBytes > & rxLockBytes | |||
932 | ) | |||
933 | { | |||
934 | rxLockBytes = new MemoryLockBytes(); | |||
935 | if (!rxLockBytes.is()) | |||
936 | return store_E_OutOfMemory; | |||
937 | ||||
938 | return store_E_None; | |||
939 | } | |||
940 | ||||
941 | } // namespace store | |||
942 | ||||
943 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |