Bug Summary

File:store/source/stordata.cxx
Location:line 462, column 5
Description:Dereference of null pointer

Annotated 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 "stordata.hxx"
22
23#include "sal/types.h"
24#include "osl/diagnose.h"
25
26#include "store/types.h"
27#include "storbase.hxx"
28#include "storbios.hxx"
29
30using namespace store;
31
32/*========================================================================
33 *
34 * OStoreDataPageObject implementation.
35 *
36 *======================================================================*/
37/*
38 * guard.
39 */
40storeError OStoreDataPageObject::guard (sal_uInt32 nAddr)
41{
42 return PageHolderObject< page >::guard (m_xPage, nAddr);
43}
44
45/*
46 * verify.
47 */
48storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const
49{
50 return PageHolderObject< page >::verify (m_xPage, nAddr);
51}
52
53/*========================================================================
54 *
55 * OStoreIndirectionPageObject implementation.
56 *
57 *======================================================================*/
58/*
59 * store_truncate_Impl (single indirect page).
60 */
61static storeError store_truncate_Impl (
62 sal_uInt32 nAddr,
63 sal_uInt16 nSingle,
64 OStorePageBIOS &rBIOS)
65{
66 if (nAddr != STORE_PAGE_NULL((sal_uInt32)(~0)))
67 {
68 // Load single indirect page.
69 OStoreIndirectionPageObject aSingle;
70 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
71 if (eErrCode == store_E_None)
72 {
73 // Truncate to 'nSingle' direct pages.
74 eErrCode = aSingle.truncate (nSingle, rBIOS);
75 if (eErrCode != store_E_None)
76 return eErrCode;
77 }
78 else
79 {
80 if (eErrCode != store_E_InvalidChecksum)
81 return eErrCode;
82 }
83
84 // Check for complete truncation.
85 if (nSingle == 0)
86 {
87 // Free single indirect page.
88 eErrCode = rBIOS.free (nAddr);
89 if (eErrCode != store_E_None)
90 return eErrCode;
91 }
92 }
93 return store_E_None;
94}
95
96/*
97 * store_truncate_Impl (double indirect page).
98 */
99static storeError store_truncate_Impl (
100 sal_uInt32 nAddr,
101 sal_uInt16 nDouble,
102 sal_uInt16 nSingle,
103 OStorePageBIOS &rBIOS)
104{
105 if (nAddr != STORE_PAGE_NULL((sal_uInt32)(~0)))
106 {
107 // Load double indirect page.
108 OStoreIndirectionPageObject aDouble;
109 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
110 if (eErrCode == store_E_None)
111 {
112 // Truncate to 'nDouble', 'nSingle' pages.
113 eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS);
114 if (eErrCode != store_E_None)
115 return eErrCode;
116 }
117 else
118 {
119 if (eErrCode != store_E_InvalidChecksum)
120 return eErrCode;
121 }
122
123 // Check for complete truncation.
124 if ((nDouble + nSingle) == 0)
125 {
126 // Free double indirect page.
127 eErrCode = rBIOS.free (nAddr);
128 if (eErrCode != store_E_None)
129 return eErrCode;
130 }
131 }
132 return store_E_None;
133}
134
135/*
136 * store_truncate_Impl (triple indirect page).
137 */
138static storeError store_truncate_Impl (
139 sal_uInt32 nAddr,
140 sal_uInt16 nTriple,
141 sal_uInt16 nDouble,
142 sal_uInt16 nSingle,
143 OStorePageBIOS &rBIOS)
144{
145 if (nAddr != STORE_PAGE_NULL((sal_uInt32)(~0)))
146 {
147 // Load triple indirect page.
148 OStoreIndirectionPageObject aTriple;
149 storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
150 if (eErrCode != store_E_None)
151 return eErrCode;
152
153 // Truncate to 'nTriple', 'nDouble', 'nSingle' pages.
154 eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS);
155 if (eErrCode != store_E_None)
156 return eErrCode;
157
158 // Check for complete truncation.
159 if ((nTriple + nDouble + nSingle) == 0)
160 {
161 // Free triple indirect page.
162 eErrCode = rBIOS.free (nAddr);
163 if (eErrCode != store_E_None)
164 return eErrCode;
165 }
166 }
167 return store_E_None;
168}
169
170/*
171 * loadOrCreate.
172 */
173storeError OStoreIndirectionPageObject::loadOrCreate (
174 sal_uInt32 nAddr,
175 OStorePageBIOS & rBIOS)
176{
177 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
178 {
179 storeError eErrCode = construct<page>(rBIOS.allocator());
180 if (eErrCode != store_E_None)
181 return eErrCode;
182
183 eErrCode = rBIOS.allocate (*this);
184 if (eErrCode != store_E_None)
185 return eErrCode;
186
187 // Save location pending at caller.
188 return store_E_Pending;
189 }
190 return rBIOS.loadObjectAt (*this, nAddr);
191}
192
193/*
194 * guard.
195 */
196storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr)
197{
198 return PageHolderObject< page >::guard (m_xPage, nAddr);
199}
200
201/*
202 * verify.
203 */
204storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const
205{
206 return PageHolderObject< page >::verify (m_xPage, nAddr);
207}
208
209/*
210 * read (single indirect).
211 */
212storeError OStoreIndirectionPageObject::read (
213 sal_uInt16 nSingle,
214 OStoreDataPageObject &rData,
215 OStorePageBIOS &rBIOS)
216{
217 PageHolderObject< page > xImpl (m_xPage);
218 page const & rPage = (*xImpl);
219
220 // Check arguments.
221 sal_uInt16 const nLimit = rPage.capacityCount();
222 if (!(nSingle < nLimit))
223 return store_E_InvalidAccess;
224
225 // Obtain data page location.
226 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
227 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
228 return store_E_NotExists;
229
230 // Load data page and leave.
231 return rBIOS.loadObjectAt (rData, nAddr);
232}
233
234/*
235 * read (double indirect).
236 */
237storeError OStoreIndirectionPageObject::read (
238 sal_uInt16 nDouble,
239 sal_uInt16 nSingle,
240 OStoreDataPageObject &rData,
241 OStorePageBIOS &rBIOS)
242{
243 PageHolderObject< page > xImpl (m_xPage);
244 page const & rPage = (*xImpl);
245
246 // Check arguments.
247 sal_uInt16 const nLimit = rPage.capacityCount();
248 if (!((nDouble < nLimit) && (nSingle < nLimit)))
249 return store_E_InvalidAccess;
250
251 // Check single indirect page location.
252 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]);
253 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
254 return store_E_NotExists;
255
256 // Load single indirect page.
257 OStoreIndirectionPageObject aSingle;
258 storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
259 if (eErrCode != store_E_None)
260 return eErrCode;
261
262 // Read single indirect and leave.
263 return aSingle.read (nSingle, rData, rBIOS);
264}
265
266/*
267 * read (triple indirect).
268 */
269storeError OStoreIndirectionPageObject::read (
270 sal_uInt16 nTriple,
271 sal_uInt16 nDouble,
272 sal_uInt16 nSingle,
273 OStoreDataPageObject &rData,
274 OStorePageBIOS &rBIOS)
275{
276 PageHolderObject< page > xImpl (m_xPage);
277 page const & rPage = (*xImpl);
278
279 // Check arguments.
280 sal_uInt16 const nLimit = rPage.capacityCount();
281 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
282 return store_E_InvalidAccess;
283
284 // Check double indirect page location.
285 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]);
286 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
287 return store_E_NotExists;
288
289 // Load double indirect page.
290 OStoreIndirectionPageObject aDouble;
291 storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
292 if (eErrCode != store_E_None)
293 return eErrCode;
294
295 // Read double indirect and leave.
296 return aDouble.read (nDouble, nSingle, rData, rBIOS);
297}
298
299/*
300 * write (single indirect).
301 */
302storeError OStoreIndirectionPageObject::write (
303 sal_uInt16 nSingle,
304 OStoreDataPageObject &rData,
305 OStorePageBIOS &rBIOS)
306{
307 PageHolderObject< page > xImpl (m_xPage);
308 page & rPage = (*xImpl);
309
310 // Check arguments.
311 sal_uInt16 const nLimit = rPage.capacityCount();
312 if (!(nSingle < nLimit))
313 return store_E_InvalidAccess;
314
315 // Obtain data page location.
316 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]);
317 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
318 {
319 // Allocate data page.
320 storeError eErrCode = rBIOS.allocate (rData);
321 if (eErrCode != store_E_None)
322 return eErrCode;
323
324 // Store data page location.
325 rPage.m_pData[nSingle] = store::htonl(rData.location());
326
327 // Save this page.
328 return rBIOS.saveObjectAt (*this, location());
329 }
330 else
331 {
332 // Save data page.
333 return rBIOS.saveObjectAt (rData, nAddr);
334 }
335}
336
337/*
338 * write (double indirect).
339 */
340storeError OStoreIndirectionPageObject::write (
341 sal_uInt16 nDouble,
342 sal_uInt16 nSingle,
343 OStoreDataPageObject &rData,
344 OStorePageBIOS &rBIOS)
345{
346 PageHolderObject< page > xImpl (m_xPage);
347 page & rPage = (*xImpl);
348
349 // Check arguments.
350 sal_uInt16 const nLimit = rPage.capacityCount();
351 if (!((nDouble < nLimit) && (nSingle < nLimit)))
352 return store_E_InvalidAccess;
353
354 // Load or create single indirect page.
355 OStoreIndirectionPageObject aSingle;
356 storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS);
357 if (eErrCode != store_E_None)
358 {
359 if (eErrCode != store_E_Pending)
360 return eErrCode;
361 rPage.m_pData[nDouble] = store::htonl(aSingle.location());
362
363 eErrCode = rBIOS.saveObjectAt (*this, location());
364 if (eErrCode != store_E_None)
365 return eErrCode;
366 }
367
368 // Write single indirect and leave.
369 return aSingle.write (nSingle, rData, rBIOS);
370}
371
372/*
373 * write (triple indirect).
374 */
375storeError OStoreIndirectionPageObject::write (
376 sal_uInt16 nTriple,
377 sal_uInt16 nDouble,
378 sal_uInt16 nSingle,
379 OStoreDataPageObject &rData,
380 OStorePageBIOS &rBIOS)
381{
382 PageHolderObject< page > xImpl (m_xPage);
383 page & rPage = (*xImpl);
384
385 // Check arguments.
386 sal_uInt16 const nLimit = rPage.capacityCount();
387 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
388 return store_E_InvalidAccess;
389
390 // Load or create double indirect page.
391 OStoreIndirectionPageObject aDouble;
392 storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS);
393 if (eErrCode != store_E_None)
394 {
395 if (eErrCode != store_E_Pending)
396 return eErrCode;
397 rPage.m_pData[nTriple] = store::htonl(aDouble.location());
398
399 eErrCode = rBIOS.saveObjectAt (*this, location());
400 if (eErrCode != store_E_None)
401 return eErrCode;
402 }
403
404 // Write double indirect and leave.
405 return aDouble.write (nDouble, nSingle, rData, rBIOS);
406}
407
408/*
409 * truncate (single indirect).
410 */
411storeError OStoreIndirectionPageObject::truncate (
412 sal_uInt16 nSingle,
413 OStorePageBIOS & rBIOS)
414{
415 PageHolderObject< page > xImpl (m_xPage);
416 page & rPage = (*xImpl);
417
418 // Check arguments.
419 sal_uInt16 const nLimit = rPage.capacityCount();
420 if (!(nSingle < nLimit))
421 return store_E_InvalidAccess;
422
423 // Truncate.
424 storeError eErrCode = store_E_None;
425 for (sal_uInt16 i = nLimit; i > nSingle; i--)
426 {
427 // Obtain data page location.
428 sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]);
429 if (nAddr != STORE_PAGE_NULL((sal_uInt32)(~0)))
430 {
431 // Free data page.
432 eErrCode = rBIOS.free (nAddr);
433 if (eErrCode != store_E_None)
434 return eErrCode;
435
436 // Clear pointer to data page.
437 rPage.m_pData[i - 1] = STORE_PAGE_NULL((sal_uInt32)(~0));
438 touch();
439 }
440 }
441
442 // Check for modified page.
443 if (dirty())
444 {
445 // Save this page.
446 eErrCode = rBIOS.saveObjectAt (*this, location());
447 }
448
449 // Done.
450 return eErrCode;
451}
452
453/*
454 * truncate (double indirect).
455 */
456storeError OStoreIndirectionPageObject::truncate (
457 sal_uInt16 nDouble,
458 sal_uInt16 nSingle,
459 OStorePageBIOS &rBIOS)
460{
461 PageHolderObject< page > xImpl (m_xPage);
462 page & rPage = (*xImpl);
Dereference of null pointer
463
464 // Check arguments.
465 sal_uInt16 const nLimit = rPage.capacityCount();
466 if (!((nDouble < nLimit) && (nSingle < nLimit)))
467 return store_E_InvalidAccess;
468
469 // Truncate.
470 storeError eErrCode = store_E_None;
471 for (sal_uInt16 i = nLimit; i > nDouble + 1; i--)
472 {
473 // Truncate single indirect page to zero direct pages.
474 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS);
475 if (eErrCode != store_E_None)
476 return eErrCode;
477
478 // Clear pointer to single indirect page.
479 rPage.m_pData[i - 1] = STORE_PAGE_NULL((sal_uInt32)(~0));
480 touch();
481 }
482
483 // Truncate last single indirect page to 'nSingle' direct pages.
484 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS);
485 if (eErrCode != store_E_None)
486 return eErrCode;
487
488 // Check for complete truncation.
489 if (nSingle == 0)
490 {
491 // Clear pointer to last single indirect page.
492 rPage.m_pData[nDouble] = STORE_PAGE_NULL((sal_uInt32)(~0));
493 touch();
494 }
495
496 // Check for modified page.
497 if (dirty())
498 {
499 // Save this page.
500 eErrCode = rBIOS.saveObjectAt (*this, location());
501 }
502
503 // Done.
504 return eErrCode;
505}
506
507/*
508 * truncate (triple indirect).
509 */
510storeError OStoreIndirectionPageObject::truncate (
511 sal_uInt16 nTriple,
512 sal_uInt16 nDouble,
513 sal_uInt16 nSingle,
514 OStorePageBIOS &rBIOS)
515{
516 PageHolderObject< page > xImpl (m_xPage);
517 page & rPage = (*xImpl);
518
519 // Check arguments.
520 sal_uInt16 const nLimit = rPage.capacityCount();
521 if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit)))
522 return store_E_InvalidAccess;
523
524 // Truncate.
525 storeError eErrCode = store_E_None;
526 for (sal_uInt16 i = nLimit; i > nTriple + 1; i--)
527 {
528 // Truncate double indirect page to zero single indirect pages.
529 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS);
530 if (eErrCode != store_E_None)
531 return eErrCode;
532
533 // Clear pointer to double indirect page.
534 rPage.m_pData[i - 1] = STORE_PAGE_NULL((sal_uInt32)(~0));
535 touch();
536 }
537
538 // Truncate last double indirect page to 'nDouble', 'nSingle' pages.
539 eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS);
540 if (eErrCode != store_E_None)
541 return eErrCode;
542
543 // Check for complete truncation.
544 if ((nDouble + nSingle) == 0)
545 {
546 // Clear pointer to last double indirect page.
547 rPage.m_pData[nTriple] = STORE_PAGE_NULL((sal_uInt32)(~0));
548 touch();
549 }
550
551 // Check for modified page.
552 if (dirty())
553 {
554 // Save this page.
555 eErrCode = rBIOS.saveObjectAt (*this, location());
556 }
557
558 // Done.
559 return eErrCode;
560}
561
562/*========================================================================
563 *
564 * OStoreDirectoryPageObject implementation.
565 *
566 *======================================================================*/
567/*
568 * guard.
569 */
570storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr)
571{
572 return PageHolderObject< page >::guard (m_xPage, nAddr);
573}
574
575/*
576 * verify.
577 */
578storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const
579{
580 return PageHolderObject< page >::verify (m_xPage, nAddr);
581 // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE);
582}
583
584/*
585 * scope (external data page; private).
586 */
587OStoreDirectoryPageData::ChunkScope
588OStoreDirectoryPageObject::scope (
589 sal_uInt32 nPage,
590 page::DataBlock::LinkDescriptor &rDescr) const
591{
592 page const & rPage = PAGE();
593 OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock;
594
595 sal_uInt32 index0, index1, index2, index3;
596
597 // direct.
598 sal_uInt32 nCount = rDataBlock.directCount();
599 sal_uInt32 nLimit = nCount;
600 if (nPage < nLimit)
601 {
602 // Page to index reduction.
603 index0 = nPage;
604
605 // Setup LinkDescriptor indices.
606 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
607
608 // Done.
609 return page::SCOPE_DIRECT;
610 }
611 nPage -= nLimit;
612
613 // single indirect.
614 sal_uInt32 const nCapacity = indirect::capacityCount(rPage.m_aDescr);
615 nCount = rDataBlock.singleCount();
616 nLimit = nCount * nCapacity;
617 if (nPage < nLimit)
618 {
619 // Page to index reduction.
620 sal_uInt32 n = nPage;
621
622 // Reduce to single indirect i(1), direct n = i(0).
623 index1 = n / nCapacity;
624 index0 = n % nCapacity;
625
626 // Verify reduction.
627 n = index1 * nCapacity + index0;
628 OSL_POSTCOND(n == nPage, "wrong math on indirect indices")do { if (true && (!(n == nPage))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/stordata.cxx"
":" "628" ": "), "%s", "wrong math on indirect indices"); } }
while (false)
;
629 if (n != nPage)
630 return page::SCOPE_UNKNOWN;
631
632 // Setup LinkDescriptor indices.
633 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
634 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
635
636 // Done.
637 return page::SCOPE_SINGLE;
638 }
639 nPage -= nLimit;
640
641 // double indirect.
642 nCount = rDataBlock.doubleCount();
643 nLimit = nCount * nCapacity * nCapacity;
644 if (nPage < nLimit)
645 {
646 // Page to index reduction.
647 sal_uInt32 n = nPage;
648
649 // Reduce to double indirect i(2), single indirect n = i(0).
650 index2 = n / (nCapacity * nCapacity);
651 n = n % (nCapacity * nCapacity);
652
653 // Reduce to single indirect i(1), direct n = i(0).
654 index1 = n / nCapacity;
655 index0 = n % nCapacity;
656
657 // Verify reduction.
658 n = index2 * nCapacity * nCapacity +
659 index1 * nCapacity + index0;
660 OSL_POSTCOND(n == nPage, "wrong math on double indirect indices")do { if (true && (!(n == nPage))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/stordata.cxx"
":" "660" ": "), "%s", "wrong math on double indirect indices"
); } } while (false)
;
661 if (n != nPage)
662 return page::SCOPE_UNKNOWN;
663
664 // Setup LinkDescriptor indices.
665 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
666 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
667 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
668
669 // Done.
670 return page::SCOPE_DOUBLE;
671 }
672 nPage -= nLimit;
673
674 // triple indirect.
675 nCount = rDataBlock.tripleCount();
676 nLimit = nCount * nCapacity * nCapacity * nCapacity;
677 if (nPage < nLimit)
678 {
679 // Page to index reduction.
680 sal_uInt32 n = nPage;
681
682 // Reduce to triple indirect i(3), double indirect n.
683 index3 = n / (nCapacity * nCapacity * nCapacity);
684 n = n % (nCapacity * nCapacity * nCapacity);
685
686 // Reduce to double indirect i(2), single indirect n.
687 index2 = n / (nCapacity * nCapacity);
688 n = n % (nCapacity * nCapacity);
689
690 // Reduce to single indirect i(1), direct n = i(0).
691 index1 = n / nCapacity;
692 index0 = n % nCapacity;
693
694 // Verify reduction.
695 n = index3 * nCapacity * nCapacity * nCapacity +
696 index2 * nCapacity * nCapacity +
697 index1 * nCapacity + index0;
698 OSL_POSTCOND(n == nPage, "wrong math on triple indirect indices")do { if (true && (!(n == nPage))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/stordata.cxx"
":" "698" ": "), "%s", "wrong math on triple indirect indices"
); } } while (false)
;
699 if (n != nPage)
700 return page::SCOPE_UNKNOWN;
701
702 // Setup LinkDescriptor indices.
703 rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff);
704 rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff);
705 rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff);
706 rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff);
707
708 // Done.
709 return page::SCOPE_TRIPLE;
710 }
711
712 // Unreachable (more than triple indirect).
713 return page::SCOPE_UNREACHABLE;
714}
715
716/*
717 * read (external data page).
718 */
719storeError OStoreDirectoryPageObject::read (
720 sal_uInt32 nPage,
721 OStoreDataPageObject &rData,
722 OStorePageBIOS &rBIOS)
723{
724 // Determine scope and link indices.
725 page::DataBlock::LinkDescriptor aLink;
726 page::ChunkScope eScope = scope (nPage, aLink);
727
728 storeError eErrCode = store_E_None;
729 if (eScope == page::SCOPE_DIRECT)
730 {
731 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
732 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
733 return store_E_NotExists;
734
735 eErrCode = rBIOS.loadObjectAt (rData, nAddr);
736 }
737 else if (eScope == page::SCOPE_SINGLE)
738 {
739 sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1);
740 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
741 return store_E_NotExists;
742
743 OStoreIndirectionPageObject aSingle;
744 eErrCode = rBIOS.loadObjectAt (aSingle, nAddr);
745 if (eErrCode != store_E_None)
746 return eErrCode;
747
748 eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS);
749 }
750 else if (eScope == page::SCOPE_DOUBLE)
751 {
752 sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2);
753 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
754 return store_E_NotExists;
755
756 OStoreIndirectionPageObject aDouble;
757 eErrCode = rBIOS.loadObjectAt (aDouble, nAddr);
758 if (eErrCode != store_E_None)
759 return eErrCode;
760
761 eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
762 }
763 else if (eScope == page::SCOPE_TRIPLE)
764 {
765 sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3);
766 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
767 return store_E_NotExists;
768
769 OStoreIndirectionPageObject aTriple;
770 eErrCode = rBIOS.loadObjectAt (aTriple, nAddr);
771 if (eErrCode != store_E_None)
772 return eErrCode;
773
774 eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
775 }
776 else if (eScope == page::SCOPE_UNREACHABLE)
777 {
778 // Out of scope.
779 eErrCode = store_E_CantSeek;
780 }
781 else
782 {
783 // Unknown scope.
784 OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed")do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/stordata.cxx"
":" "784" ": "), "OStoreDirectoryPageObject::get(): scope failed"
); } } while (false)
;
785 eErrCode = store_E_Unknown;
786 }
787
788 // Leave.
789 return eErrCode;
790}
791
792/*
793 * write (external data page).
794 */
795storeError OStoreDirectoryPageObject::write (
796 sal_uInt32 nPage,
797 OStoreDataPageObject &rData,
798 OStorePageBIOS &rBIOS)
799{
800 // Determine scope and link indices.
801 page::DataBlock::LinkDescriptor aLink;
802 page::ChunkScope eScope = scope (nPage, aLink);
803
804 storeError eErrCode = store_E_None;
805 if (eScope == page::SCOPE_DIRECT)
806 {
807 sal_uInt32 const nAddr = directLink (aLink.m_nIndex0);
808 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0)))
809 {
810 // Allocate data page.
811 eErrCode = rBIOS.allocate (rData);
812 if (eErrCode != store_E_None)
813 return eErrCode;
814
815 // Store data page location.
816 directLink (aLink.m_nIndex0, rData.location());
817 }
818 else
819 {
820 // Save data page.
821 eErrCode = rBIOS.saveObjectAt (rData, nAddr);
822 }
823 }
824 else if (eScope == page::SCOPE_SINGLE)
825 {
826 OStoreIndirectionPageObject aSingle;
827 eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS);
828 if (eErrCode != store_E_None)
829 {
830 if (eErrCode != store_E_Pending)
831 return eErrCode;
832 singleLink (aLink.m_nIndex1, aSingle.location());
833 }
834
835 eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS);
836 }
837 else if (eScope == page::SCOPE_DOUBLE)
838 {
839 OStoreIndirectionPageObject aDouble;
840 eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS);
841 if (eErrCode != store_E_None)
842 {
843 if (eErrCode != store_E_Pending)
844 return eErrCode;
845 doubleLink (aLink.m_nIndex2, aDouble.location());
846 }
847
848 eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
849 }
850 else if (eScope == page::SCOPE_TRIPLE)
851 {
852 OStoreIndirectionPageObject aTriple;
853 eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS);
854 if (eErrCode != store_E_None)
855 {
856 if (eErrCode != store_E_Pending)
857 return eErrCode;
858 tripleLink (aLink.m_nIndex3, aTriple.location());
859 }
860
861 eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS);
862 }
863 else if (eScope == page::SCOPE_UNREACHABLE)
864 {
865 // Out of scope.
866 eErrCode = store_E_CantSeek;
867 }
868 else
869 {
870 // Unknown scope.
871 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed")do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/stordata.cxx"
":" "871" ": "), "OStoreDirectoryPageObject::put(): scope failed"
); } } while (false)
;
872 eErrCode = store_E_Unknown;
873 }
874
875 // Leave.
876 return eErrCode;
877}
878
879/*
880 * truncate (external data page).
881 */
882storeError OStoreDirectoryPageObject::truncate (
883 sal_uInt32 nPage,
884 OStorePageBIOS &rBIOS)
885{
886 // Determine scope and link indices.
887 page::DataBlock::LinkDescriptor aLink;
888 page::ChunkScope eScope = scope (nPage, aLink);
889
890 storeError eErrCode = store_E_None;
891 if (eScope == page::SCOPE_DIRECT)
892 {
893 // Truncate all triple indirect pages.
894 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
895 if (eErrCode != store_E_None)
896 return eErrCode;
897
898 // Truncate all double indirect pages.
899 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
900 if (eErrCode != store_E_None)
901 return eErrCode;
902
903 // Truncate all single indirect pages.
904 eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS);
905 if (eErrCode != store_E_None)
906 return eErrCode;
907
908 // Truncate direct pages, including 'aLink.m_nIndex0'.
909 eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS);
910 }
911 else if (eScope == page::SCOPE_SINGLE)
912 {
913 // Truncate all triple indirect pages.
914 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
915 if (eErrCode != store_E_None)
916 return eErrCode;
917
918 // Truncate all double indirect pages.
919 eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS);
920 if (eErrCode != store_E_None)
921 return eErrCode;
922
923 // Truncate single indirect pages, downto 'aLink.m_nIndex1'.
924 eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS);
925 if (eErrCode != store_E_None)
926 return eErrCode;
927
928 // Truncate last single indirect page to ... pages.
929 eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS);
930 if (eErrCode != store_E_None)
931 return eErrCode;
932
933 // Check for complete truncation.
934 if (aLink.m_nIndex0 == 0)
935 {
936 // Clear pointer to last single indirect page.
937 singleLink (aLink.m_nIndex1, STORE_PAGE_NULL((sal_uInt32)(~0)));
938 }
939 }
940 else if (eScope == page::SCOPE_DOUBLE)
941 {
942 // Truncate all triple indirect pages.
943 eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS);
944 if (eErrCode != store_E_None)
945 return eErrCode;
946
947 // Truncate double indirect pages, downto 'aLink.m_nIndex2'.
948 eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS);
949 if (eErrCode != store_E_None)
950 return eErrCode;
951
952 // Truncate last double indirect page to ... pages.
953 eErrCode = store_truncate_Impl (
954 doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
955 if (eErrCode != store_E_None)
956 return eErrCode;
957
958 // Check for complete truncation.
959 if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
960 {
961 // Clear pointer to last double indirect page.
962 doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL((sal_uInt32)(~0)));
963 }
964 }
965 else if (eScope == page::SCOPE_TRIPLE)
966 {
967 // Truncate triple indirect pages, downto 'aLink.m_nIndex3'.
968 eErrCode = truncate (eScope, aLink.m_nIndex3 + 1, rBIOS);
969 if (eErrCode != store_E_None)
970 return eErrCode;
971
972 // Truncate last triple indirect page to ... pages.
973 eErrCode = store_truncate_Impl (
974 tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS);
975 if (eErrCode != store_E_None)
976 return eErrCode;
977
978 // Check for complete truncation.
979 if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0)
980 {
981 // Clear pointer to last triple indirect page.
982 tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL((sal_uInt32)(~0)));
983 }
984 }
985 else if (eScope == page::SCOPE_UNREACHABLE)
986 {
987 // Out of scope.
988 eErrCode = store_E_CantSeek;
989 }
990 else
991 {
992 // Unknown scope.
993 OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed")do { if (true && (1 > 0)) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_INFO), ("legacy.osl"), ("/usr/local/src/libreoffice/store/source/stordata.cxx"
":" "993" ": "), "OStoreDirectoryPageObject::put(): scope failed"
); } } while (false)
;
994 eErrCode = store_E_Unknown;
995 }
996
997 // Leave.
998 return eErrCode;
999}
1000
1001/*
1002 * truncate (external data page scope; private).
1003 */
1004storeError OStoreDirectoryPageObject::truncate (
1005 page::ChunkScope eScope,
1006 sal_uInt16 nRemain,
1007 OStorePageBIOS &rBIOS)
1008{
1009 OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock;
1010
1011 // Enter.
1012 storeError eErrCode = store_E_None;
1013 if (eScope == page::SCOPE_DIRECT)
1014 {
1015 // Truncate direct data pages.
1016 sal_uInt16 i, n = rDataBlock.directCount();
1017 for (i = n; i > nRemain; i--)
1018 {
1019 // Obtain data page location.
1020 sal_uInt32 nAddr = directLink (i - 1);
1021 if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0))) continue;
1022
1023 // Free data page.
1024 eErrCode = rBIOS.free (nAddr);
1025 if (eErrCode != store_E_None)
1026 break;
1027
1028 // Clear pointer to data page.
1029 directLink (i - 1, STORE_PAGE_NULL((sal_uInt32)(~0)));
1030 }
1031
1032 // Done.
1033 return eErrCode;
1034 }
1035
1036 if (eScope == page::SCOPE_SINGLE)
1037 {
1038 // Truncate single indirect pages.
1039 sal_uInt16 i, n = rDataBlock.singleCount();
1040 for (i = n; i > nRemain; i--)
1041 {
1042 // Truncate single indirect page to zero data pages.
1043 eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS);
1044 if (eErrCode != store_E_None)
1045 break;
1046
1047 // Clear pointer to single indirect page.
1048 singleLink (i - 1, STORE_PAGE_NULL((sal_uInt32)(~0)));
1049 }
1050
1051 // Done.
1052 return eErrCode;
1053 }
1054
1055 if (eScope == page::SCOPE_DOUBLE)
1056 {
1057 // Truncate double indirect pages.
1058 sal_uInt16 i, n = rDataBlock.doubleCount();
1059 for (i = n; i > nRemain; i--)
1060 {
1061 // Truncate double indirect page to zero single indirect pages.
1062 eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS);
1063 if (eErrCode != store_E_None)
1064 break;
1065
1066 // Clear pointer to double indirect page.
1067 doubleLink (i - 1, STORE_PAGE_NULL((sal_uInt32)(~0)));
1068 }
1069
1070 // Done.
1071 return eErrCode;
1072 }
1073
1074 if (eScope == page::SCOPE_TRIPLE)
1075 {
1076 // Truncate triple indirect pages.
1077 sal_uInt16 i, n = rDataBlock.tripleCount();
1078 for (i = n; i > nRemain; i--)
1079 {
1080 // Truncate to zero double indirect pages.
1081 eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS);
1082 if (eErrCode != store_E_None)
1083 break;
1084
1085 // Clear pointer to triple indirect page.
1086 tripleLink (i - 1, STORE_PAGE_NULL((sal_uInt32)(~0)));
1087 }
1088
1089 // Done.
1090 return eErrCode;
1091 }
1092
1093 // Invalid scope.
1094 return store_E_InvalidAccess;
1095}
1096
1097/* vim:set shiftwidth=4 softtabstop=4 expandtab: */