xref: /aoo41x/main/sot/source/sdstor/stgdir.cxx (revision 046d9d1f)
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