File: | store/source/storpage.cxx |
Location: | line 163, column 46 |
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 "storpage.hxx" |
22 | |
23 | #include "sal/types.h" |
24 | #include "rtl/string.h" |
25 | #include "rtl/ref.hxx" |
26 | #include "osl/diagnose.h" |
27 | #include "osl/mutex.hxx" |
28 | |
29 | #include "store/types.h" |
30 | |
31 | #include "object.hxx" |
32 | #include "lockbyte.hxx" |
33 | |
34 | #include "storbase.hxx" |
35 | #include "stordata.hxx" |
36 | #include "stortree.hxx" |
37 | |
38 | using namespace store; |
39 | |
40 | /*======================================================================== |
41 | * |
42 | * OStorePageManager implementation. |
43 | * |
44 | *======================================================================*/ |
45 | const sal_uInt32 OStorePageManager::m_nTypeId = sal_uInt32(0x62190120); |
46 | |
47 | /* |
48 | * OStorePageManager. |
49 | */ |
50 | OStorePageManager::OStorePageManager (void) |
51 | { |
52 | } |
53 | |
54 | /* |
55 | * ~OStorePageManager. |
56 | */ |
57 | OStorePageManager::~OStorePageManager (void) |
58 | { |
59 | } |
60 | |
61 | /* |
62 | * isKindOf. |
63 | */ |
64 | sal_Bool SAL_CALL OStorePageManager::isKindOf (sal_uInt32 nTypeId) |
65 | { |
66 | return (nTypeId == m_nTypeId); |
67 | } |
68 | |
69 | /* |
70 | * initialize (two-phase construction). |
71 | * Precond: none. |
72 | */ |
73 | storeError OStorePageManager::initialize ( |
74 | ILockBytes * pLockBytes, |
75 | storeAccessMode eAccessMode, |
76 | sal_uInt16 & rnPageSize) |
77 | { |
78 | // Acquire exclusive access. |
79 | osl::MutexGuard aGuard(*this); |
80 | |
81 | // Check arguments. |
82 | if (!pLockBytes) |
83 | return store_E_InvalidParameter; |
84 | |
85 | // Initialize base. |
86 | storeError eErrCode = base::initialize (pLockBytes, eAccessMode, rnPageSize); |
87 | if (eErrCode != store_E_None) |
88 | return eErrCode; |
89 | |
90 | // Check for (not) writeable. |
91 | if (!base::isWriteable()) |
92 | { |
93 | // Readonly. Load RootNode. |
94 | return base::loadObjectAt (m_aRoot, rnPageSize); |
95 | } |
96 | |
97 | // Writeable. Load or Create RootNode. |
98 | eErrCode = m_aRoot.loadOrCreate (rnPageSize, *this); |
99 | if (eErrCode == store_E_Pending) |
100 | { |
101 | // Creation notification. |
102 | PageHolderObject< page > xRoot (m_aRoot.get()); |
103 | |
104 | // Pre-allocate left most entry (ugly, but we can't insert to left). |
105 | OStorePageKey aKey (rtl_crc32 (0, "/", 1), 0); |
106 | xRoot->insert (0, entry(aKey)); |
107 | |
108 | // Save RootNode. |
109 | eErrCode = base::saveObjectAt (m_aRoot, rnPageSize); |
110 | } |
111 | |
112 | // Done. |
113 | return eErrCode; |
114 | } |
115 | |
116 | /* |
117 | * find_lookup (w/o split()). |
118 | * Internal: Precond: initialized, readable, exclusive access. |
119 | */ |
120 | storeError OStorePageManager::find_lookup ( |
121 | OStoreBTreeNodeObject & rNode, |
122 | sal_uInt16 & rIndex, |
123 | OStorePageKey const & rKey) |
124 | { |
125 | // Find Node and Index. |
126 | storeError eErrCode = m_aRoot.find_lookup (rNode, rIndex, rKey, *this); |
127 | if (eErrCode != store_E_None) |
128 | return eErrCode; |
129 | |
130 | // Greater or Equal. |
131 | PageHolderObject< page > xPage (rNode.get()); |
132 | OSL_POSTCOND(rIndex < xPage->usageCount(), "store::PageManager::find_lookup(): logic error")do { if (true && (!(rIndex < xPage->usageCount( )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/storpage.cxx" ":" "132" ": "), "%s", "store::PageManager::find_lookup(): logic error" ); } } while (false); |
133 | entry e (xPage->m_pData[rIndex]); |
134 | |
135 | // Check for exact match. |
136 | if (e.compare(entry(rKey)) != entry::COMPARE_EQUAL) |
137 | { |
138 | // Page not present. |
139 | return store_E_NotExists; |
140 | } |
141 | |
142 | // Check address. |
143 | if (e.m_aLink.location() == STORE_PAGE_NULL((sal_uInt32)(~0))) |
144 | { |
145 | // Page not present. |
146 | return store_E_NotExists; |
147 | } |
148 | |
149 | return store_E_None; |
150 | } |
151 | |
152 | /* |
153 | * remove_Impl (possibly down from root). |
154 | * Internal: Precond: initialized, writeable, exclusive access. |
155 | */ |
156 | |
157 | storeError OStorePageManager::remove_Impl (entry & rEntry) |
158 | { |
159 | OStoreBTreeNodeObject aNode (m_aRoot.get()); |
160 | |
161 | // Check current page index. |
162 | PageHolderObject< page > xPage (aNode.get()); |
163 | sal_uInt16 i = xPage->find (rEntry), n = xPage->usageCount(); |
Called C++ object pointer is null | |
164 | if (!(i < n)) |
165 | { |
166 | // Path to entry not exists (Must not happen(?)). |
167 | return store_E_NotExists; |
168 | } |
169 | |
170 | // Compare entry. |
171 | entry::CompareResult result = rEntry.compare (xPage->m_pData[i]); |
172 | |
173 | // Iterate down until equal match. |
174 | while ((result == entry::COMPARE_GREATER) && (xPage->depth() > 0)) |
175 | { |
176 | // Check link address. |
177 | sal_uInt32 const nAddr = xPage->m_pData[i].m_aLink.location(); |
178 | if (nAddr == STORE_PAGE_NULL((sal_uInt32)(~0))) |
179 | { |
180 | // Path to entry not exists (Must not happen(?)). |
181 | return store_E_NotExists; |
182 | } |
183 | |
184 | // Load link page. |
185 | storeError eErrCode = loadObjectAt (aNode, nAddr); |
186 | if (eErrCode != store_E_None) |
187 | return eErrCode; |
188 | |
189 | PageHolderObject< page > xNext (aNode.get()); |
190 | xNext.swap (xPage); |
191 | |
192 | // Check index. |
193 | i = xPage->find (rEntry), n = xPage->usageCount(); |
194 | if (!(i < n)) |
195 | { |
196 | // Path to entry not exists (Must not happen(?)). |
197 | return store_E_NotExists; |
198 | } |
199 | |
200 | // Compare entry. |
201 | result = rEntry.compare (xPage->m_pData[i]); |
202 | } |
203 | |
204 | OSL_POSTCOND(do { if (true && (!(result != entry::COMPARE_LESS))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/storpage.cxx" ":" "206" ": "), "%s", "OStorePageManager::remove(): find failed" ); } } while (false) |
205 | result != entry::COMPARE_LESS,do { if (true && (!(result != entry::COMPARE_LESS))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/storpage.cxx" ":" "206" ": "), "%s", "OStorePageManager::remove(): find failed" ); } } while (false) |
206 | "OStorePageManager::remove(): find failed")do { if (true && (!(result != entry::COMPARE_LESS))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/usr/local/src/libreoffice/store/source/storpage.cxx" ":" "206" ": "), "%s", "OStorePageManager::remove(): find failed" ); } } while (false); |
207 | |
208 | // Check entry comparison. |
209 | if (result == entry::COMPARE_LESS) |
210 | { |
211 | // Must not happen. |
212 | return store_E_Unknown; |
213 | } |
214 | |
215 | // Remove down from current page (recursive). |
216 | return aNode.remove (i, rEntry, *this); |
217 | } |
218 | |
219 | /* |
220 | * namei. |
221 | * Precond: none (static). |
222 | */ |
223 | storeError OStorePageManager::namei ( |
224 | const rtl_String *pPath, const rtl_String *pName, OStorePageKey &rKey) |
225 | { |
226 | // Check parameter. |
227 | if (!(pPath && pName)) |
228 | return store_E_InvalidParameter; |
229 | |
230 | // Check name length. |
231 | if (!(pName->length < STORE_MAXIMUM_NAMESIZE256)) |
232 | return store_E_NameTooLong; |
233 | |
234 | // Transform pathname into key. |
235 | rKey.m_nLow = store::htonl(rtl_crc32 (0, pName->buffer, pName->length)); |
236 | rKey.m_nHigh = store::htonl(rtl_crc32 (0, pPath->buffer, pPath->length)); |
237 | |
238 | // Done. |
239 | return store_E_None; |
240 | } |
241 | |
242 | /* |
243 | * iget. |
244 | * Precond: initialized. |
245 | */ |
246 | storeError OStorePageManager::iget ( |
247 | OStoreDirectoryPageObject & rPage, |
248 | sal_uInt32 nAttrib, |
249 | const rtl_String * pPath, |
250 | const rtl_String * pName, |
251 | storeAccessMode eMode) |
252 | { |
253 | // Acquire exclusive access. |
254 | osl::MutexGuard aGuard(*this); |
255 | |
256 | // Check precond. |
257 | if (!self::isValid()) |
258 | return store_E_InvalidAccess; |
259 | |
260 | // Setup inode page key. |
261 | OStorePageKey aKey; |
262 | storeError eErrCode = namei (pPath, pName, aKey); |
263 | if (eErrCode != store_E_None) |
264 | return eErrCode; |
265 | |
266 | // Check for directory. |
267 | if (nAttrib & STORE_ATTRIB_ISDIR((sal_uInt32)0x20000000)) |
268 | { |
269 | // Ugly, but necessary (backward compatibility). |
270 | aKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aKey.m_nLow), "/", 1)); |
271 | } |
272 | |
273 | // Load inode page. |
274 | eErrCode = load_dirpage_Impl (aKey, rPage); |
275 | if (eErrCode != store_E_None) |
276 | { |
277 | // Check mode and reason. |
278 | if (eErrCode != store_E_NotExists) |
279 | return eErrCode; |
280 | |
281 | if (eMode == store_AccessReadWrite) |
282 | return store_E_NotExists; |
283 | if (eMode == store_AccessReadOnly) |
284 | return store_E_NotExists; |
285 | |
286 | if (!base::isWriteable()) |
287 | return store_E_AccessViolation; |
288 | |
289 | // Create inode page. |
290 | eErrCode = rPage.construct< inode >(base::allocator()); |
291 | if (eErrCode != store_E_None) |
292 | return eErrCode; |
293 | |
294 | // Setup inode nameblock. |
295 | PageHolderObject< inode > xPage (rPage.get()); |
296 | |
297 | rPage.key (aKey); |
298 | rPage.attrib (nAttrib); |
299 | |
300 | memcpy ( |
301 | &(xPage->m_aNameBlock.m_pData[0]), |
302 | pName->buffer, pName->length); |
303 | |
304 | // Save inode page. |
305 | eErrCode = save_dirpage_Impl (aKey, rPage); |
306 | if (eErrCode != store_E_None) |
307 | return eErrCode; |
308 | } |
309 | |
310 | // Check for symbolic link. |
311 | if (rPage.attrib() & STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000)) |
312 | { |
313 | // Obtain 'Destination' page key. |
314 | PageHolderObject< inode > xPage (rPage.get()); |
315 | OStorePageKey aDstKey; |
316 | memcpy (&aDstKey, &(xPage->m_pData[0]), sizeof(aDstKey)); |
317 | |
318 | // Load 'Destination' inode. |
319 | eErrCode = load_dirpage_Impl (aDstKey, rPage); |
320 | if (eErrCode != store_E_None) |
321 | return eErrCode; |
322 | } |
323 | |
324 | // Done. |
325 | return store_E_None; |
326 | } |
327 | |
328 | /* |
329 | * iterate. |
330 | * Precond: initialized. |
331 | * ToDo: skip hardlink entries. |
332 | */ |
333 | storeError OStorePageManager::iterate ( |
334 | OStorePageKey & rKey, |
335 | OStorePageLink & rLink, |
336 | sal_uInt32 & rAttrib) |
337 | { |
338 | // Acquire exclusive access. |
339 | osl::MutexGuard aGuard(*this); |
340 | |
341 | // Check precond. |
342 | if (!self::isValid()) |
343 | return store_E_InvalidAccess; |
344 | |
345 | // Find NodePage and Index. |
346 | OStoreBTreeNodeObject aNode; |
347 | sal_uInt16 i = 0; |
348 | storeError eErrCode = m_aRoot.find_lookup (aNode, i, rKey, *this); |
349 | if (eErrCode != store_E_None) |
350 | return eErrCode; |
351 | |
352 | // GreaterEqual. Found next entry. |
353 | PageHolderObject< page > xNode (aNode.get()); |
354 | entry e (xNode->m_pData[i]); |
355 | |
356 | // Setup result. |
357 | rKey = e.m_aKey; |
358 | rLink = e.m_aLink; |
359 | rAttrib = store::ntohl(e.m_nAttrib); |
360 | |
361 | // Done. |
362 | return store_E_None; |
363 | } |
364 | |
365 | /* |
366 | * load => private: iget() @@@ |
367 | * Internal: Precond: initialized, exclusive access. |
368 | */ |
369 | storeError OStorePageManager::load_dirpage_Impl ( |
370 | const OStorePageKey &rKey, |
371 | OStoreDirectoryPageObject &rPage) |
372 | { |
373 | // Find Node and Index. |
374 | OStoreBTreeNodeObject aNode; |
375 | sal_uInt16 i = 0; |
376 | storeError eErrCode = find_lookup (aNode, i, rKey); |
377 | if (eErrCode != store_E_None) |
378 | return eErrCode; |
379 | |
380 | // Existing entry. Load page. |
381 | PageHolderObject< page > xNode (aNode.get()); |
382 | entry e (xNode->m_pData[i]); |
383 | return loadObjectAt (rPage, e.m_aLink.location()); |
384 | } |
385 | |
386 | /* |
387 | * save => private: iget(), rebuild() @@@ |
388 | * Internal: Precond: initialized, writeable, exclusive access. |
389 | */ |
390 | storeError OStorePageManager::save_dirpage_Impl ( |
391 | const OStorePageKey &rKey, |
392 | OStoreDirectoryPageObject &rPage) |
393 | { |
394 | // Find NodePage and Index. |
395 | node aNode; |
396 | sal_uInt16 i = 0; |
397 | |
398 | storeError eErrCode = m_aRoot.find_insert (aNode, i, rKey, *this); |
399 | PageHolderObject< page > xNode (aNode.get()); |
400 | if (eErrCode != store_E_None) |
401 | { |
402 | if (eErrCode != store_E_AlreadyExists) |
403 | return eErrCode; |
404 | |
405 | // Existing entry. |
406 | entry e (xNode->m_pData[i]); |
407 | if (e.m_aLink.location() != STORE_PAGE_NULL((sal_uInt32)(~0))) |
408 | { |
409 | // Save page to existing location. |
410 | return saveObjectAt (rPage, e.m_aLink.location()); |
411 | } |
412 | |
413 | // Allocate page. |
414 | eErrCode = base::allocate (rPage); |
415 | if (eErrCode != store_E_None) |
416 | return eErrCode; |
417 | |
418 | // Update page location. |
419 | xNode->m_pData[i].m_aLink = rPage.location(); |
420 | |
421 | // Save modified NodePage. |
422 | return saveObjectAt (aNode, aNode.location()); |
423 | } |
424 | |
425 | // Allocate page. |
426 | eErrCode = base::allocate (rPage); |
427 | if (eErrCode != store_E_None) |
428 | return eErrCode; |
429 | |
430 | // Insert. |
431 | OStorePageLink aLink (rPage.location()); |
432 | xNode->insert (i + 1, entry (rKey, aLink)); |
433 | |
434 | // Save modified NodePage. |
435 | return saveObjectAt (aNode, aNode.location()); |
436 | } |
437 | |
438 | /* |
439 | * attrib [nAttrib = ((nAttrib & ~nMask1) | nMask2)]. |
440 | * Precond: initialized. |
441 | */ |
442 | storeError OStorePageManager::attrib ( |
443 | const OStorePageKey &rKey, |
444 | sal_uInt32 nMask1, |
445 | sal_uInt32 nMask2, |
446 | sal_uInt32 &rAttrib) |
447 | { |
448 | // Acquire exclusive access. |
449 | osl::MutexGuard aGuard(*this); |
450 | |
451 | // Check precond. |
452 | if (!self::isValid()) |
453 | return store_E_InvalidAccess; |
454 | |
455 | // Find NodePage and index. |
456 | OStoreBTreeNodeObject aNode; |
457 | sal_uInt16 i = 0; |
458 | storeError eErrCode = find_lookup (aNode, i, rKey); |
459 | if (eErrCode != store_E_None) |
460 | return eErrCode; |
461 | |
462 | // Existing entry. |
463 | PageHolderObject< page > xNode (aNode.get()); |
464 | entry e (xNode->m_pData[i]); |
465 | if (nMask1 != nMask2) |
466 | { |
467 | // Evaluate new attributes. |
468 | sal_uInt32 nAttrib = store::ntohl(e.m_nAttrib); |
469 | |
470 | nAttrib &= ~nMask1; |
471 | nAttrib |= nMask2; |
472 | |
473 | if (store::htonl(nAttrib) != e.m_nAttrib) |
474 | { |
475 | // Check access mode. |
476 | if (base::isWriteable()) |
477 | { |
478 | // Set new attributes. |
479 | e.m_nAttrib = store::htonl(nAttrib); |
480 | xNode->m_pData[i] = e; |
481 | |
482 | // Save modified NodePage. |
483 | eErrCode = saveObjectAt (aNode, aNode.location()); |
484 | } |
485 | else |
486 | { |
487 | // Access denied. |
488 | eErrCode = store_E_AccessViolation; |
489 | } |
490 | } |
491 | } |
492 | |
493 | // Obtain current attributes. |
494 | rAttrib = store::ntohl(e.m_nAttrib); |
495 | return eErrCode; |
496 | } |
497 | |
498 | /* |
499 | * link (insert 'Source' as hardlink to 'Destination'). |
500 | * Precond: initialized, writeable. |
501 | */ |
502 | storeError OStorePageManager::link ( |
503 | const OStorePageKey &rSrcKey, |
504 | const OStorePageKey &rDstKey) |
505 | { |
506 | // Acquire exclusive access. |
507 | osl::MutexGuard aGuard(*this); |
508 | |
509 | // Check precond. |
510 | if (!self::isValid()) |
511 | return store_E_InvalidAccess; |
512 | |
513 | if (!base::isWriteable()) |
514 | return store_E_AccessViolation; |
515 | |
516 | // Find 'Destination' NodePage and Index. |
517 | OStoreBTreeNodeObject aDstNode; |
518 | sal_uInt16 i = 0; |
519 | storeError eErrCode = find_lookup (aDstNode, i, rDstKey); |
520 | if (eErrCode != store_E_None) |
521 | return eErrCode; |
522 | |
523 | // Existing 'Destination' entry. |
524 | PageHolderObject< page > xDstNode (aDstNode.get()); |
525 | entry e (xDstNode->m_pData[i]); |
526 | OStorePageLink aDstLink (e.m_aLink); |
527 | |
528 | // Find 'Source' NodePage and Index. |
529 | OStoreBTreeNodeObject aSrcNode; |
530 | eErrCode = m_aRoot.find_insert (aSrcNode, i, rSrcKey, *this); |
531 | if (eErrCode != store_E_None) |
532 | return eErrCode; |
533 | |
534 | // Insert 'Source' entry. |
535 | PageHolderObject< page > xSrcNode (aSrcNode.get()); |
536 | xSrcNode->insert (i + 1, entry (rSrcKey, aDstLink, STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000))); |
537 | return saveObjectAt (aSrcNode, aSrcNode.location()); |
538 | } |
539 | |
540 | /* |
541 | * symlink (insert 'Source' DirectoryPage as symlink to 'Destination'). |
542 | * Precond: initialized, writeable. |
543 | */ |
544 | storeError OStorePageManager::symlink ( |
545 | const rtl_String *pSrcPath, |
546 | const rtl_String *pSrcName, |
547 | const OStorePageKey &rDstKey) |
548 | { |
549 | // Acquire exclusive access. |
550 | osl::MutexGuard aGuard(*this); |
551 | |
552 | // Check precond. |
553 | if (!self::isValid()) |
554 | return store_E_InvalidAccess; |
555 | |
556 | if (!base::isWriteable()) |
557 | return store_E_AccessViolation; |
558 | |
559 | // Check 'Source' parameter. |
560 | storeError eErrCode = store_E_InvalidParameter; |
561 | if (!(pSrcPath && pSrcName)) |
562 | return eErrCode; |
563 | |
564 | // Setup 'Source' page key. |
565 | OStorePageKey aSrcKey; |
566 | eErrCode = namei (pSrcPath, pSrcName, aSrcKey); |
567 | if (eErrCode != store_E_None) |
568 | return eErrCode; |
569 | |
570 | // Find 'Source' NodePage and Index. |
571 | OStoreBTreeNodeObject aSrcNode; |
572 | sal_uInt16 i = 0; |
573 | eErrCode = m_aRoot.find_insert (aSrcNode, i, aSrcKey, *this); |
574 | if (eErrCode != store_E_None) |
575 | return eErrCode; |
576 | |
577 | // Initialize directory page. |
578 | OStoreDirectoryPageObject aPage; |
579 | eErrCode = aPage.construct< inode >(base::allocator()); |
580 | if (eErrCode != store_E_None) |
581 | return eErrCode; |
582 | |
583 | // Setup as 'Source' directory page. |
584 | inode_holder_type xNode (aPage.get()); |
585 | aPage.key (aSrcKey); |
586 | memcpy ( |
587 | &(xNode->m_aNameBlock.m_pData[0]), |
588 | pSrcName->buffer, pSrcName->length); |
589 | |
590 | // Store 'Destination' page key. |
591 | OStorePageKey aDstKey (rDstKey); |
592 | memcpy (&(xNode->m_pData[0]), &aDstKey, sizeof(aDstKey)); |
593 | |
594 | // Mark 'Source' as symbolic link to 'Destination'. |
595 | aPage.attrib (STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000)); |
596 | aPage.dataLength (sal_uInt32(sizeof(aDstKey))); |
597 | |
598 | // Allocate and save 'Source' directory page. |
599 | eErrCode = base::allocate (aPage); |
600 | if (eErrCode != store_E_None) |
601 | return eErrCode; |
602 | |
603 | // Insert 'Source' entry. |
604 | PageHolderObject< page > xSrcNode (aSrcNode.get()); |
605 | OStorePageLink aSrcLink (aPage.location()); |
606 | xSrcNode->insert (i + 1, entry(aSrcKey, aSrcLink)); |
607 | |
608 | // Save modified NodePage. |
609 | return saveObjectAt (aSrcNode, aSrcNode.location()); |
610 | } |
611 | |
612 | /* |
613 | * rename. |
614 | * Precond: initialized, writeable. |
615 | */ |
616 | storeError OStorePageManager::rename ( |
617 | const OStorePageKey &rSrcKey, |
618 | const rtl_String *pDstPath, |
619 | const rtl_String *pDstName) |
620 | { |
621 | // Acquire exclusive access. |
622 | osl::MutexGuard aGuard(*this); |
623 | |
624 | // Check precond. |
625 | if (!self::isValid()) |
626 | return store_E_InvalidAccess; |
627 | |
628 | if (!base::isWriteable()) |
629 | return store_E_AccessViolation; |
630 | |
631 | // Check 'Destination' parameter. |
632 | storeError eErrCode = store_E_InvalidParameter; |
633 | if (!(pDstPath && pDstName)) |
634 | return eErrCode; |
635 | |
636 | // Setup 'Destination' page key. |
637 | OStorePageKey aDstKey; |
638 | eErrCode = namei (pDstPath, pDstName, aDstKey); |
639 | if (eErrCode != store_E_None) |
640 | return eErrCode; |
641 | |
642 | // Find 'Source' NodePage and Index. |
643 | OStoreBTreeNodeObject aSrcNode; |
644 | sal_uInt16 i = 0; |
645 | eErrCode = find_lookup (aSrcNode, i, rSrcKey); |
646 | if (eErrCode != store_E_None) |
647 | return eErrCode; |
648 | |
649 | // Existing 'Source' entry. |
650 | PageHolderObject< page > xSrcNode (aSrcNode.get()); |
651 | entry e (xSrcNode->m_pData[i]); |
652 | |
653 | // Check for (not a) hardlink. |
654 | OStoreDirectoryPageObject aPage; |
655 | if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000))) |
656 | { |
657 | // Load directory page. |
658 | eErrCode = base::loadObjectAt (aPage, e.m_aLink.location()); |
659 | if (eErrCode != store_E_None) |
660 | return eErrCode; |
661 | |
662 | // Check for directory. |
663 | if (aPage.attrib() & STORE_ATTRIB_ISDIR((sal_uInt32)0x20000000)) |
664 | { |
665 | // Ugly, but necessary (backward compatibility). |
666 | aDstKey.m_nLow = store::htonl(rtl_crc32 (store::ntohl(aDstKey.m_nLow), "/", 1)); |
667 | } |
668 | } |
669 | |
670 | // Let 'Source' entry be 'Destination' entry. |
671 | e.m_aKey = aDstKey; |
672 | |
673 | // Find 'Destination' NodePage and Index. |
674 | OStoreBTreeNodeObject aDstNode; |
675 | eErrCode = m_aRoot.find_insert (aDstNode, i, e.m_aKey, *this); |
676 | if (eErrCode != store_E_None) |
677 | return eErrCode; |
678 | |
679 | // Insert 'Destination' entry. |
680 | PageHolderObject< page > xDstNode (aDstNode.get()); |
681 | xDstNode->insert (i + 1, e); |
682 | |
683 | eErrCode = saveObjectAt (aDstNode, aDstNode.location()); |
684 | if (eErrCode != store_E_None) |
685 | return eErrCode; |
686 | |
687 | // Check for (not a) hardlink. |
688 | if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000))) |
689 | { |
690 | // Modify 'Source' directory page. |
691 | inode_holder_type xNode (aPage.get()); |
692 | |
693 | // Setup 'Destination' NameBlock. |
694 | sal_Int32 nDstLen = pDstName->length; |
695 | memcpy ( |
696 | &(xNode->m_aNameBlock.m_pData[0]), |
697 | pDstName->buffer, pDstName->length); |
698 | memset ( |
699 | &(xNode->m_aNameBlock.m_pData[nDstLen]), |
700 | 0, STORE_MAXIMUM_NAMESIZE256 - nDstLen); |
701 | aPage.key (e.m_aKey); |
702 | |
703 | // Save directory page. |
704 | eErrCode = base::saveObjectAt (aPage, e.m_aLink.location()); |
705 | if (eErrCode != store_E_None) |
706 | return eErrCode; |
707 | } |
708 | |
709 | // Remove 'Source' entry. |
710 | e.m_aKey = rSrcKey; |
711 | return remove_Impl (e); |
712 | } |
713 | |
714 | /* |
715 | * remove. |
716 | * Precond: initialized, writeable. |
717 | */ |
718 | storeError OStorePageManager::remove (const OStorePageKey &rKey) |
719 | { |
720 | // Acquire exclusive access. |
721 | osl::MutexGuard aGuard(*this); |
722 | |
723 | // Check precond. |
724 | if (!self::isValid()) |
725 | return store_E_InvalidAccess; |
726 | |
727 | if (!base::isWriteable()) |
728 | return store_E_AccessViolation; |
729 | |
730 | // Find NodePage and index. |
731 | OStoreBTreeNodeObject aNodePage; |
732 | sal_uInt16 i = 0; |
733 | storeError eErrCode = find_lookup (aNodePage, i, rKey); |
734 | if (eErrCode != store_E_None) |
735 | return eErrCode; |
736 | |
737 | // Existing entry. |
738 | PageHolderObject< page > xNodePage (aNodePage.get()); |
739 | entry e (xNodePage->m_pData[i]); |
740 | |
741 | // Check for (not a) hardlink. |
742 | if (!(store::ntohl(e.m_nAttrib) & STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000))) |
743 | { |
744 | // Load directory page. |
745 | OStoreDirectoryPageObject aPage; |
746 | eErrCode = base::loadObjectAt (aPage, e.m_aLink.location()); |
747 | if (eErrCode != store_E_None) |
748 | return eErrCode; |
749 | |
750 | inode_holder_type xNode (aPage.get()); |
751 | |
752 | // Acquire page write access. |
753 | OStorePageDescriptor aDescr (xNode->m_aDescr); |
754 | eErrCode = base::acquirePage (aDescr, store_AccessReadWrite); |
755 | if (eErrCode != store_E_None) |
756 | return eErrCode; |
757 | |
758 | // Check for symbolic link. |
759 | if (!(aPage.attrib() & STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000))) |
760 | { |
761 | // Ordinary inode. Determine 'Data' scope. |
762 | inode::ChunkScope eScope = xNode->scope (aPage.dataLength()); |
763 | if (eScope == inode::SCOPE_EXTERNAL) |
764 | { |
765 | // External 'Data' scope. Truncate all external data pages. |
766 | eErrCode = aPage.truncate (0, *this); |
767 | if (eErrCode != store_E_None) |
768 | return eErrCode; |
769 | } |
770 | |
771 | // Truncate internal data page. |
772 | memset (&(xNode->m_pData[0]), 0, xNode->capacity()); |
773 | aPage.dataLength (0); |
774 | } |
775 | |
776 | // Release page write access. |
777 | eErrCode = base::releasePage (aDescr); |
778 | |
779 | // Release and free directory page. |
780 | eErrCode = base::free (aPage.location()); |
781 | } |
782 | |
783 | // Remove entry. |
784 | return remove_Impl (e); |
785 | } |
786 | |
787 | /* |
788 | * RebuildContext. |
789 | */ |
790 | struct RebuildContext |
791 | { |
792 | /** Representation. |
793 | */ |
794 | rtl::Reference<OStorePageBIOS> m_xBIOS; |
795 | OStorePageBIOS::ScanContext m_aCtx; |
796 | sal_uInt16 m_nPageSize; |
797 | |
798 | /** Construction. |
799 | */ |
800 | RebuildContext (void) |
801 | : m_xBIOS (new OStorePageBIOS()), |
802 | m_nPageSize (0) |
803 | {} |
804 | |
805 | /** initialize (PageBIOS and ScanContext). |
806 | */ |
807 | storeError initialize (ILockBytes *pLockBytes, sal_uInt32 nMagic = 0) |
808 | { |
809 | storeError eErrCode = store_E_InvalidParameter; |
810 | if (pLockBytes) |
811 | { |
812 | m_xBIOS->initialize (pLockBytes, store_AccessReadOnly, m_nPageSize); |
813 | eErrCode = m_xBIOS->scanBegin (m_aCtx, nMagic); |
814 | } |
815 | return eErrCode; |
816 | } |
817 | |
818 | /** initialize (ScanContext). |
819 | */ |
820 | storeError initialize (sal_uInt32 nMagic = 0) |
821 | { |
822 | return m_xBIOS->scanBegin (m_aCtx, nMagic); |
823 | } |
824 | |
825 | /** load (next ScanContext matching page). |
826 | */ |
827 | storeError load (OStorePageObject &rPage) |
828 | { |
829 | if (m_aCtx.isValid()) |
830 | return m_xBIOS->scanNext (m_aCtx, rPage); |
831 | else |
832 | return store_E_CantSeek; |
833 | } |
834 | }; |
835 | |
836 | /* |
837 | * rebuild. |
838 | * Precond: none. |
839 | */ |
840 | storeError OStorePageManager::rebuild ( |
841 | ILockBytes *pSrcLB, ILockBytes *pDstLB) |
842 | { |
843 | // Acquire exclusive access. |
844 | osl::MutexGuard aGuard(*this); |
845 | |
846 | // Check arguments. |
847 | storeError eErrCode = store_E_InvalidParameter; |
848 | if (!(pSrcLB && pDstLB)) |
849 | return eErrCode; |
850 | |
851 | // Initialize 'Source' rebuild context. |
852 | RebuildContext aCtx; |
853 | eErrCode = aCtx.initialize (pSrcLB, STORE_MAGIC_DIRECTORYPAGEsal_uInt32(0x62190120)); |
854 | if (eErrCode != store_E_None) |
855 | return eErrCode; |
856 | rtl::Reference<OStorePageBIOS> xSrcBIOS (aCtx.m_xBIOS); |
857 | |
858 | // Initialize as 'Destination' with 'Source' page size. |
859 | eErrCode = self::initialize (pDstLB, store_AccessCreate, aCtx.m_nPageSize); |
860 | if (eErrCode != store_E_None) |
861 | return eErrCode; |
862 | |
863 | // Pass One: Scan 'Source' directory pages. |
864 | { |
865 | // Scan 'Source' directory pages. |
866 | OStoreDirectoryPageObject aSrcPage; |
867 | while ((eErrCode = aCtx.load(aSrcPage)) == store_E_None) |
868 | { |
869 | OStoreDirectoryPageObject aDstPage; |
870 | eErrCode = aDstPage.construct< inode >(base::allocator()); |
871 | if (eErrCode != store_E_None) |
872 | break; |
873 | |
874 | inode_holder_type xSrcDir (aSrcPage.get()); |
875 | inode_holder_type xDstDir (aDstPage.get()); |
876 | |
877 | // Copy NameBlock @@@ OLD @@@ |
878 | memcpy (&(xDstDir->m_aNameBlock), &(xSrcDir->m_aNameBlock), sizeof(xSrcDir->m_aNameBlock)); |
879 | |
880 | // Obtain 'Source' data length. |
881 | sal_uInt32 nDataLen = aSrcPage.dataLength(); |
882 | if (nDataLen > 0) |
883 | { |
884 | // Copy internal data area @@@ OLD @@@ |
885 | memcpy (&(xDstDir->m_pData[0]), &(xSrcDir->m_pData[0]), xSrcDir->capacity()); |
886 | } |
887 | |
888 | // Insert 'Destination' directory page. |
889 | eErrCode = save_dirpage_Impl (aDstPage.key(), aDstPage); |
890 | if (eErrCode != store_E_None) |
891 | break; |
892 | |
893 | // Check for external data page scope. |
894 | if (xSrcDir->scope(nDataLen) != inode::SCOPE_INTERNAL) |
895 | { |
896 | // Initialize 'Destination' data page. |
897 | typedef OStoreDataPageData data; |
898 | PageHolderObject< data > xData; |
899 | if (!xData.construct(base::allocator())) |
900 | return store_E_OutOfMemory; |
901 | |
902 | // Determine data page count. |
903 | inode::ChunkDescriptor aDescr ( |
904 | nDataLen - xDstDir->capacity(), xData->capacity()); |
905 | |
906 | sal_uInt32 i, n = aDescr.m_nPage; |
907 | if (aDescr.m_nOffset) n += 1; |
908 | |
909 | // Copy data pages. |
910 | OStoreDataPageObject aData; |
911 | for (i = 0; i < n; i++) |
912 | { |
913 | // Read 'Source' data page. |
914 | osl::MutexGuard aSrcGuard (*xSrcBIOS); |
915 | |
916 | eErrCode = aSrcPage.read (i, aData, *xSrcBIOS); |
917 | if (eErrCode != store_E_None) |
918 | continue; |
919 | |
920 | // Write 'Destination' data page. @@@ READONLY @@@ |
921 | eErrCode = aDstPage.write (i, aData, *this); |
922 | } |
923 | } |
924 | |
925 | // Update 'Destination' directory page. |
926 | aDstPage.dataLength (nDataLen); |
927 | eErrCode = base::saveObjectAt (aDstPage, aDstPage.location()); |
928 | } |
929 | |
930 | // Save directory scan results. |
931 | flush(); |
932 | } |
933 | |
934 | // Pass Two: Scan 'Source' BTree nodes. |
935 | { |
936 | // Re-start 'Source' rebuild context. |
937 | aCtx.initialize (STORE_MAGIC_BTREENODEsal_uInt32(0x58190322)); |
938 | |
939 | // Scan 'Source' BTree nodes. |
940 | OStoreBTreeNodeObject aNode; |
941 | while ((eErrCode = aCtx.load(aNode)) == store_E_None) |
942 | { |
943 | // Check for leaf node. |
944 | PageHolderObject< page > xNode (aNode.get()); |
945 | if (xNode->depth() == 0) |
946 | { |
947 | sal_uInt16 i, n = xNode->usageCount(); |
948 | for (i = 0; i < n; i++) |
949 | { |
950 | entry e (xNode->m_pData[i]); |
951 | |
952 | // Check for Hard link. |
953 | if (e.m_nAttrib & STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000)) |
954 | { |
955 | // Load the hard link destination. |
956 | OStoreDirectoryPageObject aSrcPage; |
957 | eErrCode = xSrcBIOS->loadObjectAt (aSrcPage, e.m_aLink.location()); |
958 | if (eErrCode == store_E_None) |
959 | { |
960 | OStorePageKey aDstKey (aSrcPage.key()); |
961 | eErrCode = link (e.m_aKey, aDstKey); |
962 | } |
963 | e.m_nAttrib &= ~STORE_ATTRIB_ISLINK((sal_uInt32)0x10000000); |
964 | } |
965 | |
966 | if (e.m_nAttrib) |
967 | { |
968 | // Ordinary attributes. |
969 | sal_uInt32 nAttrib = 0; |
970 | eErrCode = attrib (e.m_aKey, 0, e.m_nAttrib, nAttrib); |
971 | } |
972 | } |
973 | } |
974 | } |
975 | |
976 | // Save BTree node scan results. |
977 | flush(); |
978 | } |
979 | |
980 | // Done. |
981 | return store_E_None; |
982 | } |
983 | |
984 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |