LCOV - code coverage report
Current view: top level - sot/source/sdstor - stgdir.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 340 552 61.6 %
Date: 2012-08-25 Functions: 33 38 86.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 318 744 42.7 %

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

Generated by: LCOV version 1.10