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