1*046d9d1fSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*046d9d1fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*046d9d1fSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*046d9d1fSAndrew Rist * distributed with this work for additional information 6*046d9d1fSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*046d9d1fSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*046d9d1fSAndrew Rist * "License"); you may not use this file except in compliance 9*046d9d1fSAndrew Rist * with the License. You may obtain a copy of the License at 10*046d9d1fSAndrew Rist * 11*046d9d1fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*046d9d1fSAndrew Rist * 13*046d9d1fSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*046d9d1fSAndrew Rist * software distributed under the License is distributed on an 15*046d9d1fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*046d9d1fSAndrew Rist * KIND, either express or implied. See the License for the 17*046d9d1fSAndrew Rist * specific language governing permissions and limitations 18*046d9d1fSAndrew Rist * under the License. 19*046d9d1fSAndrew Rist * 20*046d9d1fSAndrew Rist *************************************************************/ 21*046d9d1fSAndrew Rist 22*046d9d1fSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_sot.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <string.h> // memcpy() 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include "sot/stg.hxx" 30cdf0e10cSrcweir #include "stgelem.hxx" 31cdf0e10cSrcweir #include "stgcache.hxx" 32cdf0e10cSrcweir #include "stgstrms.hxx" 33cdf0e10cSrcweir #include "stgdir.hxx" 34cdf0e10cSrcweir #include "stgio.hxx" 35cdf0e10cSrcweir 36cdf0e10cSrcweir 37cdf0e10cSrcweir //////////////////////////// class StgDirEntry ///////////////////////////// 38cdf0e10cSrcweir 39cdf0e10cSrcweir // This class holds the dir entry data and maintains dirty flags for both 40cdf0e10cSrcweir // the entry and the data. 41cdf0e10cSrcweir 42cdf0e10cSrcweir // Transacted mode for streams: On the first write, a temp stream pTmpStrm 43cdf0e10cSrcweir // is created and operated on. A commit moves pTmpStrm to pCurStrm, which 44cdf0e10cSrcweir // is used for subsequent reads. A new write creates a new copy of pTmpStrm 45cdf0e10cSrcweir // based on pCurStrm. Reverting throws away pTmpStrm. 46cdf0e10cSrcweir // Transacted mode for storages: A copy of the dir ents is kept in aSave. 47cdf0e10cSrcweir // Committing means copying aEntry to aSave. Reverting means to copy aSave 48cdf0e10cSrcweir // to aEntry, delete newly created entries and to reactivate removed entries. 49cdf0e10cSrcweir 50cdf0e10cSrcweir // Problem der Implementation: Keine Hierarchischen commits. Daher nur 51cdf0e10cSrcweir // insgesamt transaktionsorientert oder direkt. 52cdf0e10cSrcweir 53cdf0e10cSrcweir StgDirEntry::StgDirEntry( const void* pFrom, sal_Bool * pbOk ) : StgAvlNode() 54cdf0e10cSrcweir { 55cdf0e10cSrcweir *pbOk = aEntry.Load( pFrom ); 56cdf0e10cSrcweir 57cdf0e10cSrcweir InitMembers(); 58cdf0e10cSrcweir } 59cdf0e10cSrcweir 60cdf0e10cSrcweir StgDirEntry::StgDirEntry( const StgEntry& r ) : StgAvlNode(), aEntry( r ) 61cdf0e10cSrcweir { 62cdf0e10cSrcweir InitMembers(); 63cdf0e10cSrcweir } 64cdf0e10cSrcweir 65cdf0e10cSrcweir // Helper for all ctors 66cdf0e10cSrcweir 67cdf0e10cSrcweir void StgDirEntry::InitMembers() 68cdf0e10cSrcweir { 69cdf0e10cSrcweir aSave = aEntry; 70cdf0e10cSrcweir pUp = 71cdf0e10cSrcweir pDown = NULL; 72cdf0e10cSrcweir ppRoot = NULL; 73cdf0e10cSrcweir pStgStrm = NULL; 74cdf0e10cSrcweir pCurStrm = 75cdf0e10cSrcweir pTmpStrm = NULL; 76cdf0e10cSrcweir nPos = 77cdf0e10cSrcweir nEntry = 78cdf0e10cSrcweir nRefCnt = 0; 79cdf0e10cSrcweir nMode = STREAM_READ; 80cdf0e10cSrcweir bDirect = sal_True; 81cdf0e10cSrcweir bInvalid = 82cdf0e10cSrcweir bCreated = 83cdf0e10cSrcweir bRenamed = 84cdf0e10cSrcweir bRemoved = 85cdf0e10cSrcweir bTemp = 86cdf0e10cSrcweir bDirty = 87cdf0e10cSrcweir bZombie = sal_False; 88cdf0e10cSrcweir } 89cdf0e10cSrcweir 90cdf0e10cSrcweir StgDirEntry::~StgDirEntry() 91cdf0e10cSrcweir { 92cdf0e10cSrcweir Close(); 93cdf0e10cSrcweir delete pCurStrm; 94cdf0e10cSrcweir delete pStgStrm; 95cdf0e10cSrcweir delete pDown; 96cdf0e10cSrcweir } 97cdf0e10cSrcweir 98cdf0e10cSrcweir // Comparison function 99cdf0e10cSrcweir 100cdf0e10cSrcweir short StgDirEntry::Compare( const StgAvlNode* p ) const 101cdf0e10cSrcweir { 102cdf0e10cSrcweir const StgDirEntry* pEntry = (const StgDirEntry*) p; 103cdf0e10cSrcweir return aEntry.Compare( pEntry->aEntry ); 104cdf0e10cSrcweir } 105cdf0e10cSrcweir 106cdf0e10cSrcweir // Enumerate the entry numbers. 107cdf0e10cSrcweir // n is incremented to show the total # of entries. 108cdf0e10cSrcweir // These number are later used as page numbers when storing 109cdf0e10cSrcweir // the TOC tree into the TOC stream. Remember that aSave is 110cdf0e10cSrcweir // stored, not aEntry. 111cdf0e10cSrcweir 112cdf0e10cSrcweir void StgDirEntry::Enum( sal_Int32& n ) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir sal_Int32 nLeft = STG_FREE, nRight = STG_FREE, nDown = STG_FREE; 115cdf0e10cSrcweir nEntry = n++; 116cdf0e10cSrcweir if( pLeft ) 117cdf0e10cSrcweir { 118cdf0e10cSrcweir ((StgDirEntry*) pLeft)->Enum( n ); nLeft = ((StgDirEntry*) pLeft)->nEntry; 119cdf0e10cSrcweir } 120cdf0e10cSrcweir if( pRight ) 121cdf0e10cSrcweir { 122cdf0e10cSrcweir ((StgDirEntry*) pRight)->Enum( n ); nRight = ((StgDirEntry*) pRight)->nEntry; 123cdf0e10cSrcweir } 124cdf0e10cSrcweir if( pDown ) 125cdf0e10cSrcweir { 126cdf0e10cSrcweir pDown->Enum( n ); nDown = pDown->nEntry; 127cdf0e10cSrcweir } 128cdf0e10cSrcweir aSave.SetLeaf( STG_LEFT, nLeft ); 129cdf0e10cSrcweir aSave.SetLeaf( STG_RIGHT, nRight ); 130cdf0e10cSrcweir aSave.SetLeaf( STG_CHILD, nDown ); 131cdf0e10cSrcweir } 132cdf0e10cSrcweir 133cdf0e10cSrcweir // Delete all temporary entries before writing the TOC stream. 134cdf0e10cSrcweir // Until now Deltem is never called with bForce True 135cdf0e10cSrcweir 136cdf0e10cSrcweir void StgDirEntry::DelTemp( sal_Bool bForce ) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir if( pLeft ) 139cdf0e10cSrcweir ((StgDirEntry*) pLeft)->DelTemp( sal_False ); 140cdf0e10cSrcweir if( pRight ) 141cdf0e10cSrcweir ((StgDirEntry*) pRight)->DelTemp( sal_False ); 142cdf0e10cSrcweir if( pDown ) 143cdf0e10cSrcweir { 144cdf0e10cSrcweir // If the storage is dead, of course all elements are dead, too 145cdf0e10cSrcweir if( bInvalid && aEntry.GetType() == STG_STORAGE ) 146cdf0e10cSrcweir bForce = sal_True; 147cdf0e10cSrcweir pDown->DelTemp( bForce ); 148cdf0e10cSrcweir } 149cdf0e10cSrcweir if( ( bForce || bInvalid ) 150cdf0e10cSrcweir && ( aEntry.GetType() != STG_ROOT ) /* && ( nRefCnt <= 1 ) */ ) 151cdf0e10cSrcweir { 152cdf0e10cSrcweir Close(); 153cdf0e10cSrcweir if( pUp ) 154cdf0e10cSrcweir { 155cdf0e10cSrcweir // this deletes the element if refcnt == 0! 156cdf0e10cSrcweir sal_Bool bDel = nRefCnt == 0; 157cdf0e10cSrcweir StgAvlNode::Remove( (StgAvlNode**) &pUp->pDown, this, bDel ); 158cdf0e10cSrcweir if( !bDel ) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir pLeft = pRight = pDown = 0; 161cdf0e10cSrcweir bInvalid = bZombie = sal_True; 162cdf0e10cSrcweir } 163cdf0e10cSrcweir } 164cdf0e10cSrcweir } 165cdf0e10cSrcweir } 166cdf0e10cSrcweir 167cdf0e10cSrcweir // Save the tree into the given dir stream 168cdf0e10cSrcweir 169cdf0e10cSrcweir sal_Bool StgDirEntry::Store( StgDirStrm& rStrm ) 170cdf0e10cSrcweir { 171cdf0e10cSrcweir void* pEntry = rStrm.GetEntry( nEntry, sal_True ); 172cdf0e10cSrcweir if( !pEntry ) 173cdf0e10cSrcweir return sal_False; 174cdf0e10cSrcweir // Do not store the current (maybe not commited) entry 175cdf0e10cSrcweir aSave.Store( pEntry ); 176cdf0e10cSrcweir if( pLeft ) 177cdf0e10cSrcweir if( !((StgDirEntry*) pLeft)->Store( rStrm ) ) 178cdf0e10cSrcweir return sal_False; 179cdf0e10cSrcweir if( pRight ) 180cdf0e10cSrcweir if( !((StgDirEntry*) pRight)->Store( rStrm ) ) 181cdf0e10cSrcweir return sal_False; 182cdf0e10cSrcweir if( pDown ) 183cdf0e10cSrcweir if( !pDown->Store( rStrm ) ) 184cdf0e10cSrcweir return sal_False; 185cdf0e10cSrcweir return sal_True; 186cdf0e10cSrcweir } 187cdf0e10cSrcweir 188cdf0e10cSrcweir sal_Bool StgDirEntry::StoreStream( StgIo& rIo ) 189cdf0e10cSrcweir { 190cdf0e10cSrcweir if( aEntry.GetType() == STG_STREAM || aEntry.GetType() == STG_ROOT ) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir if( bInvalid ) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir // Delete the stream if needed 195cdf0e10cSrcweir if( !pStgStrm ) 196cdf0e10cSrcweir { 197cdf0e10cSrcweir OpenStream( rIo ); 198cdf0e10cSrcweir delete pStgStrm, pStgStrm = NULL; 199cdf0e10cSrcweir } 200cdf0e10cSrcweir else 201cdf0e10cSrcweir pStgStrm->SetSize( 0 ); 202cdf0e10cSrcweir } 203cdf0e10cSrcweir // or write the data stream 204cdf0e10cSrcweir else if( !Tmp2Strm() ) 205cdf0e10cSrcweir return sal_False; 206cdf0e10cSrcweir } 207cdf0e10cSrcweir return sal_True; 208cdf0e10cSrcweir } 209cdf0e10cSrcweir 210cdf0e10cSrcweir // Save all dirty streams 211cdf0e10cSrcweir 212cdf0e10cSrcweir sal_Bool StgDirEntry::StoreStreams( StgIo& rIo ) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir if( !StoreStream( rIo ) ) 215cdf0e10cSrcweir return sal_False; 216cdf0e10cSrcweir if( pLeft ) 217cdf0e10cSrcweir if( !((StgDirEntry*) pLeft)->StoreStreams( rIo ) ) 218cdf0e10cSrcweir return sal_False; 219cdf0e10cSrcweir if( pRight ) 220cdf0e10cSrcweir if( !((StgDirEntry*) pRight)->StoreStreams( rIo ) ) 221cdf0e10cSrcweir return sal_False; 222cdf0e10cSrcweir if( pDown ) 223cdf0e10cSrcweir if( !pDown->StoreStreams( rIo ) ) 224cdf0e10cSrcweir return sal_False; 225cdf0e10cSrcweir return sal_True; 226cdf0e10cSrcweir } 227cdf0e10cSrcweir 228cdf0e10cSrcweir // Revert all directory entries after failure to write the TOC stream 229cdf0e10cSrcweir 230cdf0e10cSrcweir void StgDirEntry::RevertAll() 231cdf0e10cSrcweir { 232cdf0e10cSrcweir aEntry = aSave; 233cdf0e10cSrcweir if( pLeft ) 234cdf0e10cSrcweir ((StgDirEntry*) pLeft)->RevertAll(); 235cdf0e10cSrcweir if( pRight ) 236cdf0e10cSrcweir ((StgDirEntry*) pRight)->RevertAll(); 237cdf0e10cSrcweir if( pDown ) 238cdf0e10cSrcweir pDown->RevertAll(); 239cdf0e10cSrcweir } 240cdf0e10cSrcweir 241cdf0e10cSrcweir // Look if any element of the tree is dirty 242cdf0e10cSrcweir 243cdf0e10cSrcweir sal_Bool StgDirEntry::IsDirty() 244cdf0e10cSrcweir { 245cdf0e10cSrcweir if( bDirty || bInvalid ) 246cdf0e10cSrcweir return sal_True; 247cdf0e10cSrcweir if( pLeft && ((StgDirEntry*) pLeft)->IsDirty() ) 248cdf0e10cSrcweir return sal_True; 249cdf0e10cSrcweir if( pRight && ((StgDirEntry*) pRight)->IsDirty() ) 250cdf0e10cSrcweir return sal_True; 251cdf0e10cSrcweir if( pDown && pDown->IsDirty() ) 252cdf0e10cSrcweir return sal_True; 253cdf0e10cSrcweir return sal_False; 254cdf0e10cSrcweir } 255cdf0e10cSrcweir 256cdf0e10cSrcweir // Set up a stream. 257cdf0e10cSrcweir 258cdf0e10cSrcweir void StgDirEntry::OpenStream( StgIo& rIo, sal_Bool bForceBig ) 259cdf0e10cSrcweir { 260cdf0e10cSrcweir sal_Int32 nThreshold = (sal_uInt16) rIo.aHdr.GetThreshold(); 261cdf0e10cSrcweir delete pStgStrm; 262cdf0e10cSrcweir if( !bForceBig && aEntry.GetSize() < nThreshold ) 263cdf0e10cSrcweir pStgStrm = new StgSmallStrm( rIo, this ); 264cdf0e10cSrcweir else 265cdf0e10cSrcweir pStgStrm = new StgDataStrm( rIo, this ); 266cdf0e10cSrcweir if( bInvalid && aEntry.GetSize() ) 267cdf0e10cSrcweir { 268cdf0e10cSrcweir // This entry has invalid data, so delete that data 269cdf0e10cSrcweir SetSize( 0L ); 270cdf0e10cSrcweir // bRemoved = bInvalid = sal_False; 271cdf0e10cSrcweir } 272cdf0e10cSrcweir nPos = 0; 273cdf0e10cSrcweir } 274cdf0e10cSrcweir 275cdf0e10cSrcweir // Close the open stream without committing. If the entry is marked as 276cdf0e10cSrcweir // temporary, delete it. 277cdf0e10cSrcweir // Do not delete pCurStrm here! 278cdf0e10cSrcweir // (TLX:??? Zumindest pStgStrm muss deleted werden.) 279cdf0e10cSrcweir 280cdf0e10cSrcweir void StgDirEntry::Close() 281cdf0e10cSrcweir { 282cdf0e10cSrcweir delete pTmpStrm; 283cdf0e10cSrcweir pTmpStrm = NULL; 284cdf0e10cSrcweir // nRefCnt = 0; 285cdf0e10cSrcweir bInvalid = bTemp; 286cdf0e10cSrcweir } 287cdf0e10cSrcweir 288cdf0e10cSrcweir // Get the current stream size 289cdf0e10cSrcweir 290cdf0e10cSrcweir sal_Int32 StgDirEntry::GetSize() 291cdf0e10cSrcweir { 292cdf0e10cSrcweir sal_Int32 n; 293cdf0e10cSrcweir if( pTmpStrm ) 294cdf0e10cSrcweir n = pTmpStrm->GetSize(); 295cdf0e10cSrcweir else if( pCurStrm ) 296cdf0e10cSrcweir n = pCurStrm->GetSize(); 297cdf0e10cSrcweir else n = aEntry.GetSize(); 298cdf0e10cSrcweir return n; 299cdf0e10cSrcweir } 300cdf0e10cSrcweir 301cdf0e10cSrcweir // Set the stream size. This means also creating a temp stream. 302cdf0e10cSrcweir 303cdf0e10cSrcweir sal_Bool StgDirEntry::SetSize( sal_Int32 nNewSize ) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir if ( 306cdf0e10cSrcweir !( nMode & STREAM_WRITE ) || 307cdf0e10cSrcweir (!bDirect && !pTmpStrm && !Strm2Tmp()) 308cdf0e10cSrcweir ) 309cdf0e10cSrcweir { 310cdf0e10cSrcweir return sal_False; 311cdf0e10cSrcweir } 312cdf0e10cSrcweir 313cdf0e10cSrcweir if( nNewSize < nPos ) 314cdf0e10cSrcweir nPos = nNewSize; 315cdf0e10cSrcweir if( pTmpStrm ) 316cdf0e10cSrcweir { 317cdf0e10cSrcweir pTmpStrm->SetSize( nNewSize ); 318cdf0e10cSrcweir pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); 319cdf0e10cSrcweir return sal_Bool( pTmpStrm->GetError() == SVSTREAM_OK ); 320cdf0e10cSrcweir } 321cdf0e10cSrcweir else 322cdf0e10cSrcweir { 323cdf0e10cSrcweir sal_Bool bRes = sal_False; 324cdf0e10cSrcweir StgIo& rIo = pStgStrm->GetIo(); 325cdf0e10cSrcweir sal_Int32 nThreshold = rIo.aHdr.GetThreshold(); 326cdf0e10cSrcweir // ensure the correct storage stream! 327cdf0e10cSrcweir StgStrm* pOld = NULL; 328cdf0e10cSrcweir sal_uInt16 nOldSize = 0; 329cdf0e10cSrcweir if( nNewSize >= nThreshold && pStgStrm->IsSmallStrm() ) 330cdf0e10cSrcweir { 331cdf0e10cSrcweir pOld = pStgStrm; 332cdf0e10cSrcweir nOldSize = (sal_uInt16) pOld->GetSize(); 333cdf0e10cSrcweir pStgStrm = new StgDataStrm( rIo, STG_EOF, 0 ); 334cdf0e10cSrcweir } 335cdf0e10cSrcweir else if( nNewSize < nThreshold && !pStgStrm->IsSmallStrm() ) 336cdf0e10cSrcweir { 337cdf0e10cSrcweir pOld = pStgStrm; 338cdf0e10cSrcweir nOldSize = (sal_uInt16) nNewSize; 339cdf0e10cSrcweir pStgStrm = new StgSmallStrm( rIo, STG_EOF, 0 ); 340cdf0e10cSrcweir } 341cdf0e10cSrcweir // now set the new size 342cdf0e10cSrcweir if( pStgStrm->SetSize( nNewSize ) ) 343cdf0e10cSrcweir { 344cdf0e10cSrcweir // did we create a new stream? 345cdf0e10cSrcweir if( pOld ) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir // if so, we probably need to copy the old data 348cdf0e10cSrcweir if( nOldSize ) 349cdf0e10cSrcweir { 350cdf0e10cSrcweir void* pBuf = new sal_uInt8[ nOldSize ]; 351cdf0e10cSrcweir pOld->Pos2Page( 0L ); 352cdf0e10cSrcweir pStgStrm->Pos2Page( 0L ); 353cdf0e10cSrcweir if( pOld->Read( pBuf, nOldSize ) 354cdf0e10cSrcweir && pStgStrm->Write( pBuf, nOldSize ) ) 355cdf0e10cSrcweir bRes = sal_True; 356cdf0e10cSrcweir delete[] static_cast<sal_uInt8*>(pBuf); 357cdf0e10cSrcweir } 358cdf0e10cSrcweir else 359cdf0e10cSrcweir bRes = sal_True; 360cdf0e10cSrcweir if( bRes ) 361cdf0e10cSrcweir { 362cdf0e10cSrcweir pOld->SetSize( 0 ); 363cdf0e10cSrcweir delete pOld; 364cdf0e10cSrcweir pStgStrm->Pos2Page( nPos ); 365cdf0e10cSrcweir pStgStrm->SetEntry( *this ); 366cdf0e10cSrcweir } 367cdf0e10cSrcweir else 368cdf0e10cSrcweir { 369cdf0e10cSrcweir pStgStrm->SetSize( 0 ); 370cdf0e10cSrcweir delete pStgStrm; 371cdf0e10cSrcweir pStgStrm = pOld; 372cdf0e10cSrcweir } 373cdf0e10cSrcweir } 374cdf0e10cSrcweir else 375cdf0e10cSrcweir { 376cdf0e10cSrcweir pStgStrm->Pos2Page( nPos ); 377cdf0e10cSrcweir bRes = sal_True; 378cdf0e10cSrcweir } 379cdf0e10cSrcweir } 380cdf0e10cSrcweir return bRes; 381cdf0e10cSrcweir } 382cdf0e10cSrcweir } 383cdf0e10cSrcweir 384cdf0e10cSrcweir // Seek. On negative values, seek to EOF. 385cdf0e10cSrcweir 386cdf0e10cSrcweir sal_Int32 StgDirEntry::Seek( sal_Int32 nNew ) 387cdf0e10cSrcweir { 388cdf0e10cSrcweir if( pTmpStrm ) 389cdf0e10cSrcweir { 390cdf0e10cSrcweir if( nNew < 0 ) 391cdf0e10cSrcweir nNew = pTmpStrm->GetSize(); 392cdf0e10cSrcweir nNew = pTmpStrm->Seek( nNew ); 393cdf0e10cSrcweir } 394cdf0e10cSrcweir else if( pCurStrm ) 395cdf0e10cSrcweir { 396cdf0e10cSrcweir if( nNew < 0 ) 397cdf0e10cSrcweir nNew = pCurStrm->GetSize(); 398cdf0e10cSrcweir nNew = pCurStrm->Seek( nNew ); 399cdf0e10cSrcweir } 400cdf0e10cSrcweir else 401cdf0e10cSrcweir { 402cdf0e10cSrcweir sal_Int32 nSize = aEntry.GetSize(); 403cdf0e10cSrcweir 404cdf0e10cSrcweir if( nNew < 0 ) 405cdf0e10cSrcweir nNew = nSize; 406cdf0e10cSrcweir 407cdf0e10cSrcweir // try to enlarge, the readonly streams should not allow this 408cdf0e10cSrcweir if( nNew > nSize ) 409cdf0e10cSrcweir { 410cdf0e10cSrcweir if ( !( nMode & STREAM_WRITE ) || !SetSize( nNew ) ) 411cdf0e10cSrcweir { 412cdf0e10cSrcweir OSL_ENSURE( nMode & STREAM_WRITE, "Trying to resize readonly stream by seeking, could be a wrong offset!" ); 413cdf0e10cSrcweir return nPos; 414cdf0e10cSrcweir } 415cdf0e10cSrcweir else 416cdf0e10cSrcweir return Seek( nNew ); 417cdf0e10cSrcweir } 418cdf0e10cSrcweir pStgStrm->Pos2Page( nNew ); 419cdf0e10cSrcweir nNew = pStgStrm->GetPos(); 420cdf0e10cSrcweir } 421cdf0e10cSrcweir return nPos = nNew; 422cdf0e10cSrcweir } 423cdf0e10cSrcweir 424cdf0e10cSrcweir // Read 425cdf0e10cSrcweir 426cdf0e10cSrcweir sal_Int32 StgDirEntry::Read( void* p, sal_Int32 nLen ) 427cdf0e10cSrcweir { 428cdf0e10cSrcweir if( nLen <= 0 ) 429cdf0e10cSrcweir return 0; 430cdf0e10cSrcweir if( pTmpStrm ) 431cdf0e10cSrcweir nLen = pTmpStrm->Read( p, nLen ); 432cdf0e10cSrcweir else if( pCurStrm ) 433cdf0e10cSrcweir nLen = pCurStrm->Read( p, nLen ); 434cdf0e10cSrcweir else 435cdf0e10cSrcweir nLen = pStgStrm->Read( p, nLen ); 436cdf0e10cSrcweir nPos += nLen; 437cdf0e10cSrcweir return nLen; 438cdf0e10cSrcweir } 439cdf0e10cSrcweir 440cdf0e10cSrcweir // Write 441cdf0e10cSrcweir 442cdf0e10cSrcweir sal_Int32 StgDirEntry::Write( const void* p, sal_Int32 nLen ) 443cdf0e10cSrcweir { 444cdf0e10cSrcweir if( nLen <= 0 || !( nMode & STREAM_WRITE ) ) 445cdf0e10cSrcweir return 0; 446cdf0e10cSrcweir 447cdf0e10cSrcweir // Was this stream committed internally and reopened in direct mode? 448cdf0e10cSrcweir if( bDirect && ( pCurStrm || pTmpStrm ) && !Tmp2Strm() ) 449cdf0e10cSrcweir return 0; 450cdf0e10cSrcweir // Is this stream opened in transacted mode? Do we have to make a copy? 451cdf0e10cSrcweir if( !bDirect && !pTmpStrm && !Strm2Tmp() ) 452cdf0e10cSrcweir return 0; 453cdf0e10cSrcweir if( pTmpStrm ) 454cdf0e10cSrcweir { 455cdf0e10cSrcweir nLen = pTmpStrm->Write( p, nLen ); 456cdf0e10cSrcweir pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); 457cdf0e10cSrcweir } 458cdf0e10cSrcweir else 459cdf0e10cSrcweir { 460cdf0e10cSrcweir sal_Int32 nNew = nPos + nLen; 461cdf0e10cSrcweir if( nNew > pStgStrm->GetSize() ) 462cdf0e10cSrcweir { 463cdf0e10cSrcweir if( !SetSize( nNew ) ) 464cdf0e10cSrcweir return 0L; 465cdf0e10cSrcweir pStgStrm->Pos2Page( nPos ); 466cdf0e10cSrcweir } 467cdf0e10cSrcweir nLen = pStgStrm->Write( p, nLen ); 468cdf0e10cSrcweir } 469cdf0e10cSrcweir nPos += nLen; 470cdf0e10cSrcweir return nLen; 471cdf0e10cSrcweir } 472cdf0e10cSrcweir 473cdf0e10cSrcweir // Copy the data of one entry into another entry. 474cdf0e10cSrcweir 475cdf0e10cSrcweir void StgDirEntry::Copy( StgDirEntry& rDest ) 476cdf0e10cSrcweir { 477cdf0e10cSrcweir sal_Int32 n = GetSize(); 478cdf0e10cSrcweir if( rDest.SetSize( n ) && n ) 479cdf0e10cSrcweir { 480cdf0e10cSrcweir sal_uInt8 aTempBytes[ 4096 ]; 481cdf0e10cSrcweir void* p = static_cast<void*>( aTempBytes ); 482cdf0e10cSrcweir Seek( 0L ); 483cdf0e10cSrcweir rDest.Seek( 0L ); 484cdf0e10cSrcweir while( n ) 485cdf0e10cSrcweir { 486cdf0e10cSrcweir sal_Int32 nn = n; 487cdf0e10cSrcweir if( nn > 4096 ) 488cdf0e10cSrcweir nn = 4096; 489cdf0e10cSrcweir if( Read( p, nn ) != nn ) 490cdf0e10cSrcweir break; 491cdf0e10cSrcweir if( rDest.Write( p, nn ) != nn ) 492cdf0e10cSrcweir break; 493cdf0e10cSrcweir n -= nn; 494cdf0e10cSrcweir } 495cdf0e10cSrcweir } 496cdf0e10cSrcweir } 497cdf0e10cSrcweir 498cdf0e10cSrcweir void StgDirEntry::Copy( BaseStorageStream& rDest ) 499cdf0e10cSrcweir { 500cdf0e10cSrcweir sal_Int32 n = GetSize(); 501cdf0e10cSrcweir if( rDest.SetSize( n ) && n ) 502cdf0e10cSrcweir { 503cdf0e10cSrcweir sal_uLong Pos = rDest.Tell(); 504cdf0e10cSrcweir sal_uInt8 aTempBytes[ 4096 ]; 505cdf0e10cSrcweir void* p = static_cast<void*>( aTempBytes ); 506cdf0e10cSrcweir Seek( 0L ); 507cdf0e10cSrcweir rDest.Seek( 0L ); 508cdf0e10cSrcweir while( n ) 509cdf0e10cSrcweir { 510cdf0e10cSrcweir sal_Int32 nn = n; 511cdf0e10cSrcweir if( nn > 4096 ) 512cdf0e10cSrcweir nn = 4096; 513cdf0e10cSrcweir if( Read( p, nn ) != nn ) 514cdf0e10cSrcweir break; 515cdf0e10cSrcweir if( sal::static_int_cast<sal_Int32>(rDest.Write( p, nn )) != nn ) 516cdf0e10cSrcweir break; 517cdf0e10cSrcweir n -= nn; 518cdf0e10cSrcweir } 519cdf0e10cSrcweir rDest.Seek( Pos ); // ?! Seems to be undocumented ! 520cdf0e10cSrcweir } 521cdf0e10cSrcweir } 522cdf0e10cSrcweir 523cdf0e10cSrcweir // Commit this entry 524cdf0e10cSrcweir 525cdf0e10cSrcweir sal_Bool StgDirEntry::Commit() 526cdf0e10cSrcweir { 527cdf0e10cSrcweir // OSL_ENSURE( nMode & STREAM_WRITE, "Trying to commit readonly stream!" ); 528cdf0e10cSrcweir 529cdf0e10cSrcweir aSave = aEntry; 530cdf0e10cSrcweir sal_Bool bRes = sal_True; 531cdf0e10cSrcweir if( aEntry.GetType() == STG_STREAM ) 532cdf0e10cSrcweir { 533cdf0e10cSrcweir if( pTmpStrm ) 534cdf0e10cSrcweir delete pCurStrm, pCurStrm = pTmpStrm, pTmpStrm = NULL; 535cdf0e10cSrcweir if( bRemoved ) 536cdf0e10cSrcweir // Delete the stream if needed 537cdf0e10cSrcweir if( pStgStrm ) 538cdf0e10cSrcweir pStgStrm->SetSize( 0 ); 539cdf0e10cSrcweir } 540cdf0e10cSrcweir else if( aEntry.GetType() == STG_STORAGE && bDirect && bRes ) 541cdf0e10cSrcweir { 542cdf0e10cSrcweir StgIterator aIter( *this ); 543cdf0e10cSrcweir for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() ) 544cdf0e10cSrcweir bRes = p->Commit(); 545cdf0e10cSrcweir } 546cdf0e10cSrcweir return bRes; 547cdf0e10cSrcweir } 548cdf0e10cSrcweir 549cdf0e10cSrcweir // Revert the entry 550cdf0e10cSrcweir 551cdf0e10cSrcweir sal_Bool StgDirEntry::Revert() 552cdf0e10cSrcweir { 553cdf0e10cSrcweir aEntry = aSave; 554cdf0e10cSrcweir switch( aEntry.GetType() ) 555cdf0e10cSrcweir { 556cdf0e10cSrcweir case STG_STREAM: 557cdf0e10cSrcweir if( pCurStrm ) 558cdf0e10cSrcweir delete pTmpStrm, pTmpStrm = pCurStrm, pCurStrm = NULL; 559cdf0e10cSrcweir break; 560cdf0e10cSrcweir case STG_STORAGE: 561cdf0e10cSrcweir { 562cdf0e10cSrcweir sal_Bool bSomeRenamed = sal_False; 563cdf0e10cSrcweir StgIterator aOIter( *this ); 564cdf0e10cSrcweir StgDirEntry* op = aOIter.First(); 565cdf0e10cSrcweir while( op ) 566cdf0e10cSrcweir { 567cdf0e10cSrcweir op->aEntry = op->aSave; 568cdf0e10cSrcweir op->bDirty = sal_False; 569cdf0e10cSrcweir bSomeRenamed = sal_Bool( bSomeRenamed | op->bRenamed ); 570cdf0e10cSrcweir // Remove any new entries 571cdf0e10cSrcweir if( op->bCreated ) 572cdf0e10cSrcweir { 573cdf0e10cSrcweir op->bCreated = sal_False; 574cdf0e10cSrcweir op->Close(); 575cdf0e10cSrcweir op->bInvalid = sal_True; 576cdf0e10cSrcweir } 577cdf0e10cSrcweir // Reactivate any removed entries 578cdf0e10cSrcweir else if( op->bRemoved ) 579cdf0e10cSrcweir op->bRemoved = op->bInvalid = op->bTemp = sal_False; 580cdf0e10cSrcweir op = aOIter.Next(); 581cdf0e10cSrcweir } 582cdf0e10cSrcweir // Resort all renamed entries 583cdf0e10cSrcweir if( bSomeRenamed ) 584cdf0e10cSrcweir { 585cdf0e10cSrcweir StgIterator aIter( *this ); 586cdf0e10cSrcweir StgDirEntry* p = aIter.First(); 587cdf0e10cSrcweir while( p ) 588cdf0e10cSrcweir { 589cdf0e10cSrcweir if( p->bRenamed ) 590cdf0e10cSrcweir { 591cdf0e10cSrcweir StgAvlNode::Move 592cdf0e10cSrcweir ( (StgAvlNode**) &p->pUp->pDown, 593cdf0e10cSrcweir (StgAvlNode**) &p->pUp->pDown, p ); 594cdf0e10cSrcweir p->bRenamed = sal_False; 595cdf0e10cSrcweir } 596cdf0e10cSrcweir p = aIter.Next(); 597cdf0e10cSrcweir } 598cdf0e10cSrcweir } 599cdf0e10cSrcweir DelTemp( sal_False ); 600cdf0e10cSrcweir break; 601cdf0e10cSrcweir } 602cdf0e10cSrcweir case STG_EMPTY: 603cdf0e10cSrcweir case STG_LOCKBYTES: 604cdf0e10cSrcweir case STG_PROPERTY: 605cdf0e10cSrcweir case STG_ROOT: 606cdf0e10cSrcweir break; 607cdf0e10cSrcweir } 608cdf0e10cSrcweir return sal_True; 609cdf0e10cSrcweir } 610cdf0e10cSrcweir 611cdf0e10cSrcweir // Copy the stg stream to the temp stream 612cdf0e10cSrcweir 613cdf0e10cSrcweir sal_Bool StgDirEntry::Strm2Tmp() 614cdf0e10cSrcweir { 615cdf0e10cSrcweir if( !pTmpStrm ) 616cdf0e10cSrcweir { 617cdf0e10cSrcweir sal_uLong n = 0; 618cdf0e10cSrcweir if( pCurStrm ) 619cdf0e10cSrcweir { 620cdf0e10cSrcweir // It was already commited once 621cdf0e10cSrcweir pTmpStrm = new StgTmpStrm; 622cdf0e10cSrcweir if( pTmpStrm->GetError() == SVSTREAM_OK && pTmpStrm->Copy( *pCurStrm ) ) 623cdf0e10cSrcweir return sal_True; 624cdf0e10cSrcweir n = 1; // indicates error 625cdf0e10cSrcweir } 626cdf0e10cSrcweir else 627cdf0e10cSrcweir { 628cdf0e10cSrcweir n = aEntry.GetSize(); 629cdf0e10cSrcweir pTmpStrm = new StgTmpStrm( n ); 630cdf0e10cSrcweir if( pTmpStrm->GetError() == SVSTREAM_OK ) 631cdf0e10cSrcweir { 632cdf0e10cSrcweir if( n ) 633cdf0e10cSrcweir { 634cdf0e10cSrcweir sal_uInt8 aTempBytes[ 4096 ]; 635cdf0e10cSrcweir void* p = static_cast<void*>( aTempBytes ); 636cdf0e10cSrcweir pStgStrm->Pos2Page( 0L ); 637cdf0e10cSrcweir while( n ) 638cdf0e10cSrcweir { 639cdf0e10cSrcweir sal_uLong nn = n; 640cdf0e10cSrcweir if( nn > 4096 ) 641cdf0e10cSrcweir nn = 4096; 642cdf0e10cSrcweir if( (sal_uLong) pStgStrm->Read( p, nn ) != nn ) 643cdf0e10cSrcweir break; 644cdf0e10cSrcweir if( pTmpStrm->Write( p, nn ) != nn ) 645cdf0e10cSrcweir break; 646cdf0e10cSrcweir n -= nn; 647cdf0e10cSrcweir } 648cdf0e10cSrcweir pStgStrm->Pos2Page( nPos ); 649cdf0e10cSrcweir pTmpStrm->Seek( nPos ); 650cdf0e10cSrcweir } 651cdf0e10cSrcweir } 652cdf0e10cSrcweir else 653cdf0e10cSrcweir n = 1; 654cdf0e10cSrcweir } 655cdf0e10cSrcweir if( n ) 656cdf0e10cSrcweir { 657cdf0e10cSrcweir pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); 658cdf0e10cSrcweir delete pTmpStrm; 659cdf0e10cSrcweir pTmpStrm = NULL; 660cdf0e10cSrcweir return sal_False; 661cdf0e10cSrcweir } 662cdf0e10cSrcweir } 663cdf0e10cSrcweir return sal_True; 664cdf0e10cSrcweir } 665cdf0e10cSrcweir 666cdf0e10cSrcweir // Copy the temp stream to the stg stream during the final commit 667cdf0e10cSrcweir 668cdf0e10cSrcweir sal_Bool StgDirEntry::Tmp2Strm() 669cdf0e10cSrcweir { 670cdf0e10cSrcweir // We did commit once, but have not written since then 671cdf0e10cSrcweir if( !pTmpStrm ) 672cdf0e10cSrcweir pTmpStrm = pCurStrm, pCurStrm = NULL; 673cdf0e10cSrcweir if( pTmpStrm ) 674cdf0e10cSrcweir { 675cdf0e10cSrcweir sal_uLong n = pTmpStrm->GetSize(); 676cdf0e10cSrcweir StgStrm* pNewStrm; 677cdf0e10cSrcweir StgIo& rIo = pStgStrm->GetIo(); 678cdf0e10cSrcweir sal_uLong nThreshold = (sal_uLong) rIo.aHdr.GetThreshold(); 679cdf0e10cSrcweir if( n < nThreshold ) 680cdf0e10cSrcweir pNewStrm = new StgSmallStrm( rIo, STG_EOF, 0 ); 681cdf0e10cSrcweir else 682cdf0e10cSrcweir pNewStrm = new StgDataStrm( rIo, STG_EOF, 0 ); 683cdf0e10cSrcweir if( pNewStrm->SetSize( n ) ) 684cdf0e10cSrcweir { 685cdf0e10cSrcweir sal_uInt8 p[ 4096 ]; 686cdf0e10cSrcweir pTmpStrm->Seek( 0L ); 687cdf0e10cSrcweir while( n ) 688cdf0e10cSrcweir { 689cdf0e10cSrcweir sal_uLong nn = n; 690cdf0e10cSrcweir if( nn > 4096 ) 691cdf0e10cSrcweir nn = 4096; 692cdf0e10cSrcweir if( pTmpStrm->Read( p, nn ) != nn ) 693cdf0e10cSrcweir break; 694cdf0e10cSrcweir if( (sal_uLong) pNewStrm->Write( p, nn ) != nn ) 695cdf0e10cSrcweir break; 696cdf0e10cSrcweir n -= nn; 697cdf0e10cSrcweir } 698cdf0e10cSrcweir if( n ) 699cdf0e10cSrcweir { 700cdf0e10cSrcweir pTmpStrm->Seek( nPos ); 701cdf0e10cSrcweir pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); 702cdf0e10cSrcweir delete pNewStrm; 703cdf0e10cSrcweir return sal_False; 704cdf0e10cSrcweir } 705cdf0e10cSrcweir else 706cdf0e10cSrcweir { 707cdf0e10cSrcweir pStgStrm->SetSize( 0L ); 708cdf0e10cSrcweir delete pStgStrm; 709cdf0e10cSrcweir pStgStrm = pNewStrm; 710cdf0e10cSrcweir pNewStrm->SetEntry( *this ); 711cdf0e10cSrcweir pNewStrm->Pos2Page( nPos ); 712cdf0e10cSrcweir delete pTmpStrm; 713cdf0e10cSrcweir delete pCurStrm; 714cdf0e10cSrcweir pTmpStrm = pCurStrm = NULL; 715cdf0e10cSrcweir aSave = aEntry; 716cdf0e10cSrcweir } 717cdf0e10cSrcweir } 718cdf0e10cSrcweir } 719cdf0e10cSrcweir return sal_True; 720cdf0e10cSrcweir } 721cdf0e10cSrcweir 722cdf0e10cSrcweir // Check if the given entry is contained in this entry 723cdf0e10cSrcweir 724cdf0e10cSrcweir sal_Bool StgDirEntry::IsContained( StgDirEntry* pStg ) 725cdf0e10cSrcweir { 726cdf0e10cSrcweir if( aEntry.GetType() == STG_STORAGE ) 727cdf0e10cSrcweir { 728cdf0e10cSrcweir StgIterator aIter( *this ); 729cdf0e10cSrcweir StgDirEntry* p = aIter.First(); 730cdf0e10cSrcweir while( p ) 731cdf0e10cSrcweir { 732cdf0e10cSrcweir if( !p->aEntry.Compare( pStg->aEntry ) ) 733cdf0e10cSrcweir return sal_False; 734cdf0e10cSrcweir if( p->aEntry.GetType() == STG_STORAGE ) 735cdf0e10cSrcweir if( !p->IsContained( pStg ) ) 736cdf0e10cSrcweir return sal_False; 737cdf0e10cSrcweir p = aIter.Next(); 738cdf0e10cSrcweir } 739cdf0e10cSrcweir } 740cdf0e10cSrcweir return sal_True; 741cdf0e10cSrcweir } 742cdf0e10cSrcweir 743cdf0e10cSrcweir // Invalidate all open entries by setting the RefCount to 0. If the bDel 744cdf0e10cSrcweir // flag is set, also set the invalid flag to indicate deletion during the 745cdf0e10cSrcweir // next dir stream flush. 746cdf0e10cSrcweir 747cdf0e10cSrcweir void StgDirEntry::Invalidate( sal_Bool bDel ) 748cdf0e10cSrcweir { 749cdf0e10cSrcweir // nRefCnt = 0; 750cdf0e10cSrcweir if( bDel ) 751cdf0e10cSrcweir bRemoved = bInvalid = sal_True; 752cdf0e10cSrcweir switch( aEntry.GetType() ) 753cdf0e10cSrcweir { 754cdf0e10cSrcweir case STG_STORAGE: 755cdf0e10cSrcweir case STG_ROOT: 756cdf0e10cSrcweir { 757cdf0e10cSrcweir StgIterator aIter( *this ); 758cdf0e10cSrcweir for( StgDirEntry* p = aIter.First(); p; p = aIter.Next() ) 759cdf0e10cSrcweir p->Invalidate( bDel ); 760cdf0e10cSrcweir break; 761cdf0e10cSrcweir } 762cdf0e10cSrcweir default: 763cdf0e10cSrcweir break; 764cdf0e10cSrcweir } 765cdf0e10cSrcweir } 766cdf0e10cSrcweir 767cdf0e10cSrcweir ///////////////////////////// class StgDirStrm //////////////////////////// 768cdf0e10cSrcweir 769cdf0e10cSrcweir // This specialized stream is the maintenance stream for the directory tree. 770cdf0e10cSrcweir 771cdf0e10cSrcweir StgDirStrm::StgDirStrm( StgIo& r ) 772cdf0e10cSrcweir : StgDataStrm( r, r.aHdr.GetTOCStart(), -1 ) 773cdf0e10cSrcweir , pRoot( NULL ) 774cdf0e10cSrcweir , nEntries( 0 ) 775cdf0e10cSrcweir { 776cdf0e10cSrcweir if( r.GetError() ) 777cdf0e10cSrcweir return; 778cdf0e10cSrcweir nEntries = nPageSize / STGENTRY_SIZE; 779cdf0e10cSrcweir if( nStart == STG_EOF ) 780cdf0e10cSrcweir { 781cdf0e10cSrcweir StgEntry aRoot; 782cdf0e10cSrcweir aRoot.Init(); 783cdf0e10cSrcweir aRoot.SetName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Root Entry" ) ) ); 784cdf0e10cSrcweir aRoot.SetType( STG_ROOT ); 785cdf0e10cSrcweir pRoot = new StgDirEntry( aRoot ); 786cdf0e10cSrcweir pRoot->SetDirty(); 787cdf0e10cSrcweir } 788cdf0e10cSrcweir else 789cdf0e10cSrcweir { 790cdf0e10cSrcweir // temporarily use this instance as owner, so 791cdf0e10cSrcweir // the TOC pages can be removed. 792cdf0e10cSrcweir pEntry = (StgDirEntry*) this; // just for a bit pattern 793cdf0e10cSrcweir SetupEntry( 0, pRoot ); 794cdf0e10cSrcweir rIo.Revert( pEntry ); 795cdf0e10cSrcweir pEntry = NULL; 796cdf0e10cSrcweir } 797cdf0e10cSrcweir } 798cdf0e10cSrcweir 799cdf0e10cSrcweir StgDirStrm::~StgDirStrm() 800cdf0e10cSrcweir { 801cdf0e10cSrcweir delete pRoot; 802cdf0e10cSrcweir } 803cdf0e10cSrcweir 804cdf0e10cSrcweir // Recursively parse the directory tree during reading the TOC stream 805cdf0e10cSrcweir 806cdf0e10cSrcweir void StgDirStrm::SetupEntry( sal_Int32 n, StgDirEntry* pUpper ) 807cdf0e10cSrcweir { 808cdf0e10cSrcweir void* p = ( n == STG_FREE ) ? NULL : GetEntry( n ); 809cdf0e10cSrcweir if( p ) 810cdf0e10cSrcweir { 811cdf0e10cSrcweir sal_Bool bOk(sal_False); 812cdf0e10cSrcweir StgDirEntry* pCur = new StgDirEntry( p, &bOk ); 813cdf0e10cSrcweir 814cdf0e10cSrcweir if( !bOk ) 815cdf0e10cSrcweir { 816cdf0e10cSrcweir delete pCur; 817cdf0e10cSrcweir rIo.SetError( SVSTREAM_GENERALERROR ); 818cdf0e10cSrcweir // an error occured 819cdf0e10cSrcweir return; 820cdf0e10cSrcweir } 821cdf0e10cSrcweir 822cdf0e10cSrcweir // better it is 823cdf0e10cSrcweir if( !pUpper ) 824cdf0e10cSrcweir pCur->aEntry.SetType( STG_ROOT ); 825cdf0e10cSrcweir 826cdf0e10cSrcweir sal_Int32 nLeft = pCur->aEntry.GetLeaf( STG_LEFT ); 827cdf0e10cSrcweir sal_Int32 nRight = pCur->aEntry.GetLeaf( STG_RIGHT ); 828cdf0e10cSrcweir // substorage? 829cdf0e10cSrcweir sal_Int32 nLeaf = STG_FREE; 830cdf0e10cSrcweir if( pCur->aEntry.GetType() == STG_STORAGE || pCur->aEntry.GetType() == STG_ROOT ) 831cdf0e10cSrcweir { 832cdf0e10cSrcweir nLeaf = pCur->aEntry.GetLeaf( STG_CHILD ); 833cdf0e10cSrcweir if (nLeaf != STG_FREE && nLeaf == n) 834cdf0e10cSrcweir { 835cdf0e10cSrcweir delete pCur; 836cdf0e10cSrcweir rIo.SetError( SVSTREAM_GENERALERROR ); 837cdf0e10cSrcweir return; 838cdf0e10cSrcweir } 839cdf0e10cSrcweir } 840cdf0e10cSrcweir 841cdf0e10cSrcweir if( nLeaf != 0 && nLeft != 0 && nRight != 0 ) 842cdf0e10cSrcweir { 843cdf0e10cSrcweir if( StgAvlNode::Insert 844cdf0e10cSrcweir ( (StgAvlNode**) ( pUpper ? &pUpper->pDown : &pRoot ), pCur ) ) 845cdf0e10cSrcweir { 846cdf0e10cSrcweir pCur->pUp = pUpper; 847cdf0e10cSrcweir pCur->ppRoot = &pRoot; 848cdf0e10cSrcweir } 849cdf0e10cSrcweir else 850cdf0e10cSrcweir { 851cdf0e10cSrcweir rIo.SetError( SVSTREAM_CANNOT_MAKE ); 852cdf0e10cSrcweir delete pCur; pCur = NULL; 853cdf0e10cSrcweir return; 854cdf0e10cSrcweir } 855cdf0e10cSrcweir SetupEntry( nLeft, pUpper ); 856cdf0e10cSrcweir SetupEntry( nRight, pUpper ); 857cdf0e10cSrcweir SetupEntry( nLeaf, pCur ); 858cdf0e10cSrcweir } 859cdf0e10cSrcweir } 860cdf0e10cSrcweir } 861cdf0e10cSrcweir 862cdf0e10cSrcweir // Extend or shrink the directory stream. 863cdf0e10cSrcweir 864cdf0e10cSrcweir sal_Bool StgDirStrm::SetSize( sal_Int32 nBytes ) 865cdf0e10cSrcweir { 866cdf0e10cSrcweir // Always allocate full pages 867cdf0e10cSrcweir nBytes = ( ( nBytes + nPageSize - 1 ) / nPageSize ) * nPageSize; 868cdf0e10cSrcweir return StgStrm::SetSize( nBytes ); 869cdf0e10cSrcweir } 870cdf0e10cSrcweir 871cdf0e10cSrcweir // Save the TOC stream into a new substream after saving all data streams 872cdf0e10cSrcweir 873cdf0e10cSrcweir sal_Bool StgDirStrm::Store() 874cdf0e10cSrcweir { 875cdf0e10cSrcweir if( !pRoot->IsDirty() ) 876cdf0e10cSrcweir return sal_True; 877cdf0e10cSrcweir if( !pRoot->StoreStreams( rIo ) ) 878cdf0e10cSrcweir return sal_False; 879cdf0e10cSrcweir // After writing all streams, the data FAT stream has changed, 880cdf0e10cSrcweir // so we have to commit the root again 881cdf0e10cSrcweir pRoot->Commit(); 882cdf0e10cSrcweir // We want a completely new stream, so fake an empty stream 883cdf0e10cSrcweir sal_Int32 nOldStart = nStart; // save for later deletion 884cdf0e10cSrcweir sal_Int32 nOldSize = nSize; 885cdf0e10cSrcweir nStart = nPage = STG_EOF; 886cdf0e10cSrcweir nSize = nPos = 0; 887cdf0e10cSrcweir nOffset = 0; 888cdf0e10cSrcweir // Delete all temporary entries 889cdf0e10cSrcweir pRoot->DelTemp( sal_False ); 890cdf0e10cSrcweir // set the entry numbers 891cdf0e10cSrcweir sal_Int32 n = 0; 892cdf0e10cSrcweir pRoot->Enum( n ); 893cdf0e10cSrcweir if( !SetSize( n * STGENTRY_SIZE ) ) 894cdf0e10cSrcweir { 895cdf0e10cSrcweir nStart = nOldStart; nSize = nOldSize; 896cdf0e10cSrcweir pRoot->RevertAll(); 897cdf0e10cSrcweir return sal_False; 898cdf0e10cSrcweir } 899cdf0e10cSrcweir // set up the cache elements for the new stream 900cdf0e10cSrcweir if( !Copy( STG_FREE, nSize ) ) 901cdf0e10cSrcweir { 902cdf0e10cSrcweir pRoot->RevertAll(); 903cdf0e10cSrcweir return sal_False; 904cdf0e10cSrcweir } 905cdf0e10cSrcweir // Write the data to the new stream 906cdf0e10cSrcweir if( !pRoot->Store( *this ) ) 907cdf0e10cSrcweir { 908cdf0e10cSrcweir pRoot->RevertAll(); 909cdf0e10cSrcweir return sal_False; 910cdf0e10cSrcweir } 911cdf0e10cSrcweir // fill any remaining entries with empty data 912cdf0e10cSrcweir sal_Int32 ne = nSize / STGENTRY_SIZE; 913cdf0e10cSrcweir StgEntry aEmpty; 914cdf0e10cSrcweir aEmpty.Init(); 915cdf0e10cSrcweir while( n < ne ) 916cdf0e10cSrcweir { 917cdf0e10cSrcweir void* p = GetEntry( n++, sal_True ); 918cdf0e10cSrcweir if( !p ) 919cdf0e10cSrcweir { 920cdf0e10cSrcweir pRoot->RevertAll(); 921cdf0e10cSrcweir return sal_False; 922cdf0e10cSrcweir } 923cdf0e10cSrcweir aEmpty.Store( p ); 924cdf0e10cSrcweir } 925cdf0e10cSrcweir // Now we can release the old stream 926cdf0e10cSrcweir pFat->FreePages( nOldStart, sal_True ); 927cdf0e10cSrcweir rIo.aHdr.SetTOCStart( nStart ); 928cdf0e10cSrcweir return sal_True; 929cdf0e10cSrcweir } 930cdf0e10cSrcweir 931cdf0e10cSrcweir // Get a dir entry. 932cdf0e10cSrcweir 933cdf0e10cSrcweir void* StgDirStrm::GetEntry( sal_Int32 n, sal_Bool bDirty ) 934cdf0e10cSrcweir { 935cdf0e10cSrcweir if( n < 0 ) 936cdf0e10cSrcweir return NULL; 937cdf0e10cSrcweir 938cdf0e10cSrcweir n *= STGENTRY_SIZE; 939cdf0e10cSrcweir if( n < 0 && n >= nSize ) 940cdf0e10cSrcweir return NULL; 941cdf0e10cSrcweir return GetPtr( n, sal_True, bDirty ); 942cdf0e10cSrcweir } 943cdf0e10cSrcweir 944cdf0e10cSrcweir // Find a dir entry. 945cdf0e10cSrcweir 946cdf0e10cSrcweir StgDirEntry* StgDirStrm::Find( StgDirEntry& rStg, const String& rName ) 947cdf0e10cSrcweir { 948cdf0e10cSrcweir if( rStg.pDown ) 949cdf0e10cSrcweir { 950cdf0e10cSrcweir StgEntry aEntry; 951cdf0e10cSrcweir aEntry.Init(); 952cdf0e10cSrcweir if( !aEntry.SetName( rName ) ) 953cdf0e10cSrcweir { 954cdf0e10cSrcweir rIo.SetError( SVSTREAM_GENERALERROR ); 955cdf0e10cSrcweir return NULL; 956cdf0e10cSrcweir } 957cdf0e10cSrcweir // Look in the directory attached to the entry 958cdf0e10cSrcweir StgDirEntry aTest( aEntry ); 959cdf0e10cSrcweir return (StgDirEntry*) rStg.pDown->Find( &aTest ); 960cdf0e10cSrcweir } 961cdf0e10cSrcweir else 962cdf0e10cSrcweir return NULL; 963cdf0e10cSrcweir } 964cdf0e10cSrcweir 965cdf0e10cSrcweir // Create a new entry. 966cdf0e10cSrcweir 967cdf0e10cSrcweir StgDirEntry* StgDirStrm::Create 968cdf0e10cSrcweir ( StgDirEntry& rStg, const String& rName, StgEntryType eType ) 969cdf0e10cSrcweir { 970cdf0e10cSrcweir StgEntry aEntry; 971cdf0e10cSrcweir aEntry.Init(); 972cdf0e10cSrcweir aEntry.SetType( eType ); 973cdf0e10cSrcweir if( !aEntry.SetName( rName ) ) 974cdf0e10cSrcweir { 975cdf0e10cSrcweir rIo.SetError( SVSTREAM_GENERALERROR ); 976cdf0e10cSrcweir return NULL; 977cdf0e10cSrcweir } 978cdf0e10cSrcweir StgDirEntry* pRes = Find( rStg, rName ); 979cdf0e10cSrcweir if( pRes ) 980cdf0e10cSrcweir { 981cdf0e10cSrcweir if( !pRes->bInvalid ) 982cdf0e10cSrcweir { 983cdf0e10cSrcweir rIo.SetError( SVSTREAM_CANNOT_MAKE ); 984cdf0e10cSrcweir return NULL; 985cdf0e10cSrcweir } 986cdf0e10cSrcweir pRes->bInvalid = 987cdf0e10cSrcweir pRes->bRemoved = 988cdf0e10cSrcweir pRes->bTemp = sal_False; 989cdf0e10cSrcweir pRes->bCreated = 990cdf0e10cSrcweir pRes->bDirty = sal_True; 991cdf0e10cSrcweir } 992cdf0e10cSrcweir else 993cdf0e10cSrcweir { 994cdf0e10cSrcweir pRes = new StgDirEntry( aEntry ); 995cdf0e10cSrcweir if( StgAvlNode::Insert( (StgAvlNode**) &rStg.pDown, pRes ) ) 996cdf0e10cSrcweir { 997cdf0e10cSrcweir pRes->pUp = &rStg; 998cdf0e10cSrcweir pRes->ppRoot = &pRoot; 999cdf0e10cSrcweir pRes->bCreated = 1000cdf0e10cSrcweir pRes->bDirty = sal_True; 1001cdf0e10cSrcweir } 1002cdf0e10cSrcweir else 1003cdf0e10cSrcweir { 1004cdf0e10cSrcweir rIo.SetError( SVSTREAM_CANNOT_MAKE ); 1005cdf0e10cSrcweir delete pRes; pRes = NULL; 1006cdf0e10cSrcweir } 1007cdf0e10cSrcweir } 1008cdf0e10cSrcweir return pRes; 1009cdf0e10cSrcweir } 1010cdf0e10cSrcweir 1011cdf0e10cSrcweir // Rename the given entry. 1012cdf0e10cSrcweir 1013cdf0e10cSrcweir sal_Bool StgDirStrm::Rename( StgDirEntry& rStg, const String& rOld, const String& rNew ) 1014cdf0e10cSrcweir { 1015cdf0e10cSrcweir StgDirEntry* p = Find( rStg, rOld ); 1016cdf0e10cSrcweir if( p ) 1017cdf0e10cSrcweir { 1018cdf0e10cSrcweir 1019cdf0e10cSrcweir if( !StgAvlNode::Remove( (StgAvlNode**) &rStg.pDown, p, sal_False ) ) 1020cdf0e10cSrcweir return sal_False; 1021cdf0e10cSrcweir p->aEntry.SetName( rNew ); 1022cdf0e10cSrcweir if( !StgAvlNode::Insert( (StgAvlNode**) &rStg.pDown, p ) ) 1023cdf0e10cSrcweir return sal_False; 1024cdf0e10cSrcweir p->bRenamed = p->bDirty = sal_True; 1025cdf0e10cSrcweir return sal_True; 1026cdf0e10cSrcweir } 1027cdf0e10cSrcweir else 1028cdf0e10cSrcweir { 1029cdf0e10cSrcweir rIo.SetError( SVSTREAM_FILE_NOT_FOUND ); 1030cdf0e10cSrcweir return sal_False; 1031cdf0e10cSrcweir } 1032cdf0e10cSrcweir } 1033cdf0e10cSrcweir 1034cdf0e10cSrcweir // Move the given entry to a different storage. 1035cdf0e10cSrcweir 1036cdf0e10cSrcweir sal_Bool StgDirStrm::Move( StgDirEntry& rStg1, StgDirEntry& rStg2, const String& rName ) 1037cdf0e10cSrcweir { 1038cdf0e10cSrcweir StgDirEntry* p = Find( rStg1, rName ); 1039cdf0e10cSrcweir if( p ) 1040cdf0e10cSrcweir { 1041cdf0e10cSrcweir if( !StgAvlNode::Move 1042cdf0e10cSrcweir ( (StgAvlNode**) &rStg1.pDown, (StgAvlNode**) &rStg2.pDown, p ) ) 1043cdf0e10cSrcweir return sal_False; 1044cdf0e10cSrcweir p->bDirty = sal_True; 1045cdf0e10cSrcweir return sal_True; 1046cdf0e10cSrcweir } 1047cdf0e10cSrcweir else 1048cdf0e10cSrcweir { 1049cdf0e10cSrcweir rIo.SetError( SVSTREAM_FILE_NOT_FOUND ); 1050cdf0e10cSrcweir return sal_False; 1051cdf0e10cSrcweir } 1052cdf0e10cSrcweir } 1053cdf0e10cSrcweir 1054