LCOV - code coverage report
Current view: top level - libreoffice/sot/source/sdstor - stgio.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 68 197 34.5 %
Date: 2012-12-27 Functions: 10 22 45.5 %
Legend: Lines: hit not hit

          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 "sot/stg.hxx"
      22             : #include "stgelem.hxx"
      23             : #include "stgcache.hxx"
      24             : #include "stgstrms.hxx"
      25             : #include "stgdir.hxx"
      26             : #include "stgio.hxx"
      27             : #include <rtl/instance.hxx>
      28             : 
      29             : ///////////////////////////// class StgIo //////////////////////////////
      30             : 
      31             : // This class holds the storage header and all internal streams.
      32             : 
      33         102 : StgIo::StgIo() : StgCache()
      34             : {
      35         102 :     pTOC      = NULL;
      36         102 :     pDataFAT  = NULL;
      37         102 :     pDataStrm = NULL;
      38         102 :     pFAT      = NULL;
      39         102 :     bCopied   = sal_False;
      40         102 : }
      41             : 
      42         204 : StgIo::~StgIo()
      43             : {
      44         102 :     delete pTOC;
      45         102 :     delete pDataFAT;
      46         102 :     delete pDataStrm;
      47         102 :     delete pFAT;
      48         102 : }
      49             : 
      50             : // Load the header. Do not set an error code if the header is invalid.
      51             : 
      52          86 : sal_Bool StgIo::Load()
      53             : {
      54          86 :     if( pStrm )
      55             :     {
      56          86 :         if( aHdr.Load( *this ) )
      57             :         {
      58          86 :             if( aHdr.Check() )
      59          86 :                 SetupStreams();
      60             :             else
      61           0 :                 return sal_False;
      62             :         }
      63             :         else
      64           0 :             return sal_False;
      65             :     }
      66          86 :     return Good();
      67             : }
      68             : 
      69             : // Set up an initial, empty storage
      70             : 
      71          16 : sal_Bool StgIo::Init()
      72             : {
      73          16 :     aHdr.Init();
      74          16 :     SetupStreams();
      75          16 :     return CommitAll();
      76             : }
      77             : 
      78         102 : void StgIo::SetupStreams()
      79             : {
      80         102 :     delete pTOC;
      81         102 :     delete pDataFAT;
      82         102 :     delete pDataStrm;
      83         102 :     delete pFAT;
      84         102 :     pTOC      = NULL;
      85         102 :     pDataFAT  = NULL;
      86         102 :     pDataStrm = NULL;
      87         102 :     pFAT      = NULL;
      88         102 :     ResetError();
      89         102 :     SetPhysPageSize( 1 << aHdr.GetPageSize() );
      90         102 :     pFAT = new StgFATStrm( *this );
      91         102 :     pTOC = new StgDirStrm( *this );
      92         102 :     if( !GetError() )
      93             :     {
      94          99 :         StgDirEntry* pRoot = pTOC->GetRoot();
      95          99 :         if( pRoot )
      96             :         {
      97          99 :             pDataFAT = new StgDataStrm( *this, aHdr.GetDataFATStart(), -1 );
      98          99 :             pDataStrm = new StgDataStrm( *this, *pRoot );
      99          99 :             pDataFAT->SetIncrement( 1 << aHdr.GetPageSize() );
     100          99 :             pDataStrm->SetIncrement( GetDataPageSize() );
     101          99 :             pDataStrm->SetEntry( *pRoot );
     102             :         }
     103             :         else
     104           0 :             SetError( SVSTREAM_FILEFORMAT_ERROR );
     105             :     }
     106         102 : }
     107             : 
     108             : // get the logical data page size
     109             : 
     110         983 : short StgIo::GetDataPageSize()
     111             : {
     112         983 :     return 1 << aHdr.GetDataPageSize();
     113             : }
     114             : 
     115             : // Commit everything
     116             : 
     117          35 : sal_Bool StgIo::CommitAll()
     118             : {
     119             :     // Store the data (all streams and the TOC)
     120          35 :     if( pTOC && pTOC->Store() && pDataFAT )
     121             :     {
     122          35 :         if( Commit() )
     123             :         {
     124          32 :             aHdr.SetDataFATStart( pDataFAT->GetStart() );
     125          32 :             aHdr.SetDataFATSize( pDataFAT->GetPages() );
     126          32 :             aHdr.SetTOCStart( pTOC->GetStart() );
     127          32 :             if( aHdr.Store( *this ) )
     128             :             {
     129          32 :                 pStrm->Flush();
     130          32 :                 sal_uLong n = pStrm->GetError();
     131          32 :                 SetError( n );
     132             : #ifdef DBG_UTIL
     133             :                 if( n==0 ) ValidateFATs();
     134             : #endif
     135          32 :                 return sal_Bool( n == 0 );
     136             :             }
     137             :         }
     138             :     }
     139           3 :     SetError( SVSTREAM_WRITE_ERROR );
     140           3 :     return sal_False;
     141             : }
     142             : 
     143             : 
     144             : class EasyFat
     145             : {
     146             :     sal_Int32 *pFat;
     147             :     sal_Bool  *pFree;
     148             :     sal_Int32 nPages;
     149             :     sal_Int32 nPageSize;
     150             : 
     151             : public:
     152             :     EasyFat( StgIo & rIo, StgStrm *pFatStream, sal_Int32 nPSize );
     153           0 :     ~EasyFat() { delete[] pFat; delete[] pFree; }
     154             : 
     155           0 :     sal_Int32 GetPageSize() { return nPageSize; }
     156             :     sal_Int32 Count() { return nPages; }
     157             :     sal_Int32 operator[]( sal_Int32 nOffset )
     158             :     {
     159             :         OSL_ENSURE( nOffset >= 0 && nOffset < nPages, "Unexpected offset!" );
     160             :         return nOffset >= 0 && nOffset < nPages ? pFat[ nOffset ] : -2;
     161             :     }
     162             : 
     163             :     sal_uLong Mark( sal_Int32 nPage, sal_Int32 nCount, sal_Int32 nExpect );
     164             :     sal_Bool HasUnrefChains();
     165             : };
     166             : 
     167           0 : EasyFat::EasyFat( StgIo& rIo, StgStrm* pFatStream, sal_Int32 nPSize )
     168             : {
     169           0 :     nPages = pFatStream->GetSize() >> 2;
     170           0 :     nPageSize = nPSize;
     171           0 :     pFat = new sal_Int32[ nPages ];
     172           0 :     pFree = new sal_Bool[ nPages ];
     173             : 
     174           0 :     rtl::Reference< StgPage > pPage;
     175           0 :     sal_Int32 nFatPageSize = (1 << rIo.aHdr.GetPageSize()) - 2;
     176             : 
     177           0 :     for( sal_Int32 nPage = 0; nPage < nPages; nPage++ )
     178             :     {
     179           0 :         if( ! (nPage % nFatPageSize) )
     180             :         {
     181           0 :             pFatStream->Pos2Page( nPage << 2 );
     182           0 :             sal_Int32 nPhysPage = pFatStream->GetPage();
     183           0 :             pPage = rIo.Get( nPhysPage, sal_True );
     184             :         }
     185             : 
     186           0 :         pFat[ nPage ] = rIo.GetFromPage( pPage, short( nPage % nFatPageSize ) );
     187           0 :         pFree[ nPage ] = sal_True;
     188           0 :     }
     189           0 : }
     190             : 
     191           0 : sal_Bool EasyFat::HasUnrefChains()
     192             : {
     193           0 :     for( sal_Int32 nPage = 0; nPage < nPages; nPage++ )
     194             :     {
     195           0 :         if( pFree[ nPage ] && pFat[ nPage ] != -1 )
     196           0 :             return sal_True;
     197             :     }
     198           0 :     return sal_False;
     199             : }
     200             : 
     201           0 : sal_uLong EasyFat::Mark( sal_Int32 nPage, sal_Int32 nCount, sal_Int32 nExpect )
     202             : {
     203           0 :     if( nCount > 0 )
     204           0 :         --nCount /= GetPageSize(), nCount++;
     205             : 
     206           0 :     sal_Int32 nCurPage = nPage;
     207           0 :     while( nCount != 0 )
     208             :     {
     209           0 :         if( nCurPage < 0 || nCurPage >= nPages )
     210           0 :             return FAT_OUTOFBOUNDS;
     211           0 :         pFree[ nCurPage ] = sal_False;
     212           0 :         nCurPage = pFat[ nCurPage ];
     213             :         //Stream zu lang
     214           0 :         if( nCurPage != nExpect && nCount == 1 )
     215           0 :             return FAT_WRONGLENGTH;
     216             :         //Stream zu kurz
     217           0 :         if( nCurPage == nExpect && nCount != 1 && nCount != -1 )
     218           0 :             return FAT_WRONGLENGTH;
     219             :         // letzter Block bei Stream ohne Laenge
     220           0 :         if( nCurPage == nExpect && nCount == -1 )
     221           0 :             nCount = 1;
     222           0 :         if( nCount != -1 )
     223           0 :             nCount--;
     224             :     }
     225           0 :     return FAT_OK;
     226             : }
     227             : 
     228           0 : class Validator
     229             : {
     230             :     sal_uLong nError;
     231             : 
     232             :     EasyFat aSmallFat;
     233             :     EasyFat aFat;
     234             : 
     235             :     StgIo &rIo;
     236             : 
     237             :     sal_uLong ValidateMasterFATs();
     238             :     sal_uLong ValidateDirectoryEntries();
     239             :     sal_uLong FindUnrefedChains();
     240             :     sal_uLong MarkAll( StgDirEntry *pEntry );
     241             : 
     242             : public:
     243             : 
     244             :     Validator( StgIo &rIo );
     245           0 :     sal_Bool IsError() { return nError != 0; }
     246             : };
     247             : 
     248           0 : Validator::Validator( StgIo &rIoP )
     249           0 :     : aSmallFat( rIoP, rIoP.pDataFAT, 1 << rIoP.aHdr.GetDataPageSize() ),
     250           0 :       aFat( rIoP, rIoP.pFAT, 1 << rIoP.aHdr.GetPageSize() ),
     251           0 :       rIo( rIoP )
     252             : {
     253           0 :     sal_uLong nErr = nError = FAT_OK;
     254             : 
     255           0 :     if( ( nErr = ValidateMasterFATs() ) != FAT_OK )
     256           0 :         nError = nErr;
     257           0 :     else if(    ( nErr = ValidateDirectoryEntries() ) != FAT_OK )
     258           0 :         nError = nErr;
     259           0 :     else if(    ( nErr = FindUnrefedChains()) != FAT_OK )
     260           0 :         nError = nErr;
     261           0 : }
     262             : 
     263           0 : sal_uLong Validator::ValidateMasterFATs()
     264             : {
     265           0 :     sal_Int32 nCount = rIo.aHdr.GetFATSize();
     266             :     sal_uLong nErr;
     267           0 :     if ( !rIo.pFAT )
     268           0 :         return FAT_INMEMORYERROR;
     269             : 
     270           0 :     for( sal_Int32 i = 0; i < nCount; i++ )
     271             :     {
     272           0 :         if( ( nErr = aFat.Mark(rIo.pFAT->GetPage( short(i), sal_False ), aFat.GetPageSize(), -3 )) != FAT_OK )
     273           0 :             return nErr;
     274             :     }
     275           0 :     if( rIo.aHdr.GetMasters() )
     276           0 :         if( ( nErr = aFat.Mark(rIo.aHdr.GetFATChain( ), aFat.GetPageSize(), -4 )) != FAT_OK )
     277           0 :             return nErr;
     278             : 
     279           0 :     return FAT_OK;
     280             : }
     281             : 
     282           0 : sal_uLong Validator::MarkAll( StgDirEntry *pEntry )
     283             : {
     284           0 :     if ( !pEntry )
     285           0 :         return FAT_INMEMORYERROR;
     286             : 
     287           0 :     StgIterator aIter( *pEntry );
     288           0 :     sal_uLong nErr = FAT_OK;
     289           0 :     for( StgDirEntry* p = aIter.First(); p ; p = aIter.Next() )
     290             :     {
     291           0 :         if( p->aEntry.GetType() == STG_STORAGE )
     292             :         {
     293           0 :             nErr = MarkAll( p );
     294           0 :             if( nErr != FAT_OK )
     295           0 :                 return nErr;
     296             :         }
     297             :         else
     298             :         {
     299           0 :             sal_Int32 nSize = p->aEntry.GetSize();
     300           0 :             if( nSize < rIo.aHdr.GetThreshold()  )
     301           0 :                 nErr = aSmallFat.Mark( p->aEntry.GetStartPage(),nSize, -2 );
     302             :             else
     303           0 :                 nErr = aFat.Mark( p->aEntry.GetStartPage(),nSize, -2 );
     304           0 :             if( nErr != FAT_OK )
     305           0 :                 return nErr;
     306             :         }
     307             :     }
     308           0 :     return FAT_OK;
     309             : }
     310             : 
     311           0 : sal_uLong Validator::ValidateDirectoryEntries()
     312             : {
     313           0 :     if ( !rIo.pTOC )
     314           0 :         return FAT_INMEMORYERROR;
     315             : 
     316             :     // Normale DirEntries
     317           0 :     sal_uLong nErr = MarkAll( rIo.pTOC->GetRoot() );
     318           0 :     if( nErr != FAT_OK )
     319           0 :         return nErr;
     320             :     // Small Data
     321           0 :     nErr = aFat.Mark( rIo.pTOC->GetRoot()->aEntry.GetStartPage(),
     322           0 :                  rIo.pTOC->GetRoot()->aEntry.GetSize(), -2 );
     323           0 :     if( nErr != FAT_OK )
     324           0 :         return nErr;
     325             :     // Small Data FAT
     326             :     nErr = aFat.Mark(
     327             :         rIo.aHdr.GetDataFATStart(),
     328           0 :         rIo.aHdr.GetDataFATSize() * aFat.GetPageSize(), -2 );
     329           0 :     if( nErr != FAT_OK )
     330           0 :         return nErr;
     331             :     // TOC
     332             :     nErr = aFat.Mark(
     333           0 :         rIo.aHdr.GetTOCStart(), -1, -2 );
     334           0 :     return nErr;
     335             : }
     336             : 
     337           0 : sal_uLong Validator::FindUnrefedChains()
     338             : {
     339           0 :     if( aSmallFat.HasUnrefChains() ||
     340           0 :         aFat.HasUnrefChains() )
     341           0 :         return FAT_UNREFCHAIN;
     342             :     else
     343           0 :         return FAT_OK;
     344             : }
     345             : 
     346             : namespace { struct ErrorLink : public rtl::Static<Link, ErrorLink > {}; }
     347             : 
     348           4 : void StgIo::SetErrorLink( const Link& rLink )
     349             : {
     350           4 :     ErrorLink::get() = rLink;
     351           4 : }
     352             : 
     353           4 : const Link& StgIo::GetErrorLink()
     354             : {
     355           4 :     return ErrorLink::get();
     356             : }
     357             : 
     358           4 : sal_uLong StgIo::ValidateFATs()
     359             : {
     360           4 :     if( bFile )
     361             :     {
     362           0 :         Validator *pV = new Validator( *this );
     363           0 :         sal_Bool bRet1 = !pV->IsError(), bRet2 = sal_True ;
     364           0 :         delete pV;
     365             : 
     366           0 :         SvFileStream *pFileStrm = ( SvFileStream *) GetStrm();
     367           0 :         if ( !pFileStrm )
     368           0 :             return FAT_INMEMORYERROR;
     369             : 
     370           0 :         StgIo aIo;
     371           0 :         if( aIo.Open( pFileStrm->GetFileName(),
     372           0 :                       STREAM_READ  | STREAM_SHARE_DENYNONE) &&
     373           0 :             aIo.Load() )
     374             :         {
     375           0 :             pV = new Validator( aIo );
     376           0 :             bRet2 = !pV->IsError();
     377           0 :             delete pV;
     378             :         }
     379             : 
     380             :         sal_uLong nErr;
     381           0 :         if( bRet1 != bRet2 )
     382           0 :             nErr = bRet1 ? FAT_ONFILEERROR : FAT_INMEMORYERROR;
     383           0 :         else nErr = bRet1 ? FAT_OK : FAT_BOTHERROR;
     384           0 :         if( nErr != FAT_OK && !bCopied )
     385             :         {
     386           0 :             StgLinkArg aArg;
     387           0 :             aArg.aFile = pFileStrm->GetFileName();
     388           0 :             aArg.nErr = nErr;
     389           0 :             ErrorLink::get().Call( &aArg );
     390           0 :             bCopied = sal_True;
     391             :         }
     392             : //      DBG_ASSERT( nErr == FAT_OK ,"Storage kaputt");
     393           0 :         return nErr;
     394             :     }
     395             : //  OSL_FAIL("Validiere nicht (kein FileStorage)");
     396           4 :     return FAT_OK;
     397             : }
     398             : 
     399             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10