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