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