File: | store/source/stordata.cxx |
Location: | line 462, column 5 |
Description: | Dereference of null pointer |
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 | |
30 | using namespace store; |
31 | |
32 | /*======================================================================== |
33 | * |
34 | * OStoreDataPageObject implementation. |
35 | * |
36 | *======================================================================*/ |
37 | /* |
38 | * guard. |
39 | */ |
40 | storeError OStoreDataPageObject::guard (sal_uInt32 nAddr) |
41 | { |
42 | return PageHolderObject< page >::guard (m_xPage, nAddr); |
43 | } |
44 | |
45 | /* |
46 | * verify. |
47 | */ |
48 | storeError 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 | */ |
61 | static 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 | */ |
99 | static 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 | */ |
138 | static 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 | */ |
173 | storeError 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 | */ |
196 | storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr) |
197 | { |
198 | return PageHolderObject< page >::guard (m_xPage, nAddr); |
199 | } |
200 | |
201 | /* |
202 | * verify. |
203 | */ |
204 | storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const |
205 | { |
206 | return PageHolderObject< page >::verify (m_xPage, nAddr); |
207 | } |
208 | |
209 | /* |
210 | * read (single indirect). |
211 | */ |
212 | storeError 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 | */ |
237 | storeError 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 | */ |
269 | storeError 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 | */ |
302 | storeError 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 | */ |
340 | storeError 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 | */ |
375 | storeError 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 | */ |
411 | storeError 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 | */ |
456 | storeError 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 | */ |
510 | storeError 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 | */ |
570 | storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr) |
571 | { |
572 | return PageHolderObject< page >::guard (m_xPage, nAddr); |
573 | } |
574 | |
575 | /* |
576 | * verify. |
577 | */ |
578 | storeError 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 | */ |
587 | OStoreDirectoryPageData::ChunkScope |
588 | OStoreDirectoryPageObject::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 | */ |
719 | storeError 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 | */ |
795 | storeError 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 | */ |
882 | storeError 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 | */ |
1004 | storeError 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: */ |