|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: difat.cxx
//
// Contents: Double Indirected Fat Code
//
// Classes: None.
//
// Functions:
//
//--------------------------------------------------------------------------
#include "msfhead.cxx"
#include "h/difat.hxx"
#include "mread.hxx"
//+-------------------------------------------------------------------------
//
// Method: CDIFat::CDIFat, public
//
// Synopsis: CDIFat constructor
//
// Arguments: [cbSector] -- size of a sector
//
//--------------------------------------------------------------------------
CDIFat::CDIFat(USHORT cbSector) : _pmsParent(NULL), _fv( SIDDIF, (FSOFFSET) (cbSector / sizeof(SECT)), (FSOFFSET) ((cbSector / sizeof(SECT)) - 1) ) { msfDebugOut((DEB_TRACE,"In CDIFat constructor\n")); _cfsTable = 0; msfDebugOut((DEB_TRACE,"Out CDIFat constructor\n")); }
//+---------------------------------------------------------------------------
//
// Member: CDIFat::Empty, public
//
// Synopsis: Empty all the control structures of this instance
//
// Arguments: None.
//
// Returns: void.
//
//----------------------------------------------------------------------------
void CDIFat::Empty(void) { _fv.Empty(); _pmsParent = NULL; _cfsTable = 0; }
//+-------------------------------------------------------------------------
//
// Method: CIDFat::Flush, private
//
// Synopsis: Flush a sector to disk
//
// Arguments: none
//
// Returns: S_OK if call completed OK.
//
// Algorithm: Write sector up to parent mstream.
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE CDIFat::Flush(void) { return _fv.Flush(); }
//+-------------------------------------------------------------------------
//
// Method: CDIFat::GetFatSect, public
//
// Synopsis: Given an offset into the Fat chain, return the sector
// value for that FatSect.
//
// Arguments: [oSect] -- offset in Fat chain
// [psect] -- pointer to returned sector
//
// Modifies: [*psect]
//
// Returns: Sector value of FatSect.
//
// Algorithm: If sector is stored in the header, retrieve it from
// there.
// If not, retrieve it from the FatVector.
//
//--------------------------------------------------------------------------
SCODE CDIFat::GetFatSect(const FSINDEX oSect, SECT *psect) { SCODE sc = S_OK; SECT sectReturn;
msfDebugOut((DEB_TRACE,"In CDIFat::GetFatSect(%lu)\n",oSect)); if (oSect < CSECTFAT) { msfDebugOut((DEB_ITRACE,"Getting sect from header\n")); sectReturn = _pmsParent->GetHeader()->GetFatSect(oSect); } else { FSINDEX ipfs; FSOFFSET isect;
SectToPair(oSect,&ipfs,&isect);
msfAssert(ipfs < _cfsTable);
CFatSect *pfs; msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs)); sectReturn = pfs->GetSect(isect); _fv.ReleaseTable(ipfs); }
msfDebugOut((DEB_TRACE,"Out CDIFat::GetFatSect(%lu)=>%lu\n",oSect,sectReturn)); *psect = sectReturn;
Err: return sc; }
//+-------------------------------------------------------------------------
//
// Method: CDIFat::SetFatSect, public
//
// Synopsis: Given an offset into the Fat chain, set the sector
// value.
//
// Arguments: [oSect] -- Offset into fat chain
// [sect] -- New sector value for that offset.
//
// Returns: S_OK if call completed OK.
//
// Algorithm: If the sector is stored in the header, set it and
// flush the header.
// Otherwise, if the sector will not fit in the current
// CFatVector, resize it.
// Set the sector in the FatVector and flush it.
//
//--------------------------------------------------------------------------
SCODE CDIFat::SetFatSect(const FSINDEX oSect, const SECT sect) { msfDebugOut((DEB_TRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect)); SCODE sc = S_OK;
if (oSect < CSECTFAT) { msfDebugOut((DEB_ITRACE,"Setting sect in header: %lu, %lu\n",oSect,sect)); _pmsParent->GetHeader()->SetFatSect(oSect, sect); } else { FSINDEX ipfs; FSOFFSET isect;
SectToPair(oSect,&ipfs,&isect); if (ipfs >= _cfsTable) { msfChk(Resize(_cfsTable + 1)); }
CFatSect *pfs; msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
pfs->SetSect(isect, sect); _fv.ReleaseTable(ipfs); msfDebugOut((DEB_TRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect)); }
Err: return sc; }
//+-------------------------------------------------------------------------
//
// Method: CDIFat::GetSect, public
//
// Synopsis: Given an offset into the DIFat chain, return the
// sector value
//
// Arguments: [oSect] -- Offset into DIFat chain.
// [psect] -- pointer to returned sector
//
// Modifies: [*psect]
//
// Returns: Sector value for given offset.
//
// Algorithm: Retrieve the information from the NextFat fields of
// the CFatVector
//
//--------------------------------------------------------------------------
SCODE CDIFat::GetSect(const FSINDEX oSect, SECT *psect) { SCODE sc = S_OK;
SECT sectReturn;
msfDebugOut((DEB_TRACE,"In CDIFat::GetSect(%lu)\n",oSect)); msfAssert(oSect < _cfsTable);
if (oSect == 0) { sectReturn = _pmsParent->GetHeader()->GetDifStart(); } else { CFatSect *pfs; msfChk(_fv.GetTable(oSect - 1, FB_NONE, &pfs));
sectReturn = pfs->GetNextFat(_fv.GetSectTable()); _fv.ReleaseTable(oSect - 1); }
msfDebugOut((DEB_TRACE,"Out CDIFat::GetSect(%lu)=>%lu\n",oSect,sectReturn)); *psect = sectReturn;
Err: return sc; }
//+-------------------------------------------------------------------------
//
// Method: CDIFat::Init, public
//
// Synopsis: Init function for previously stored DIFat.
//
// Arguments: [pmsParent] -- pointer to stream parent
// [cFatSect] -- Length of DIFat in sectors
//
// Returns: S_OK if call completed properly.
//
// Algorithm: Initialize all the variables
//
//--------------------------------------------------------------------------
SCODE CDIFat::Init(CMStream * pmsParent, const FSINDEX cFatSect) { msfDebugOut((DEB_TRACE,"In CDIFat::Init(%lu)\n",cFatSect)); SCODE sc;
_pmsParent = pmsParent; msfChk(_fv.Init(_pmsParent, cFatSect));
_cfsTable = cFatSect;
msfDebugOut((DEB_TRACE,"Out CDIFat::Init(%lu)\n",cFatSect));
Err: return sc; }
//+-------------------------------------------------------------------------
//
// Method: CDIFat::InitConvert, public
//
// Synopsis: Init function for conversion
//
// Arguments: [pmsParent] -- pointer to stream parent
// [sectMax] -- Last used sector in existing file
//
// Returns: S_OK if call completed OK.
//
// Algorithm: See below
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE CDIFat::InitConvert(CMStream *pmsParent, SECT sectMax) { msfDebugOut((DEB_TRACE,"In CDIFat::InitConvert(%lu)\n",sectMax)); SCODE sc;
_pmsParent = pmsParent;
USHORT cbSector = _pmsParent->GetSectorSize(); FSOFFSET csectPer = (FSOFFSET) (cbSector / sizeof(SECT));
FSINDEX csectFat = 0; FSINDEX csectFatLast; FSINDEX csectDif = 0; FSINDEX csectDifLast; do { //Number of fat sectors needed to represent:
// Number of Data Sectors (sectMax) +
// Number of Fat Sectors (csectFat) +
// Number of DIF sectors (csectDif) +
// Number of Directory Sectors (1)
//We must use a loop here, since the fat must be large
// enough to represent itself and the DIFat. See
// CFat::InitConvert for a more lengthy discussion of
// this method.
csectFatLast = csectFat; csectFat = (sectMax + csectFatLast + csectDif + 1 + csectPer - 1) / csectPer; csectDifLast = csectDif;
if (csectFat < CSECTFAT) { csectDif = 0; } else { FSOFFSET ciSect;
SectToPair(csectFat, &csectDif, &ciSect); csectDif++; } } while ((csectDif != csectDifLast) || (csectFat != csectFatLast));
_cfsTable = csectDif; msfChk(_fv.Init(_pmsParent, _cfsTable));
_pmsParent->GetHeader()->SetDifLength(_cfsTable);
if (_cfsTable > 0) { _pmsParent->GetHeader()->SetDifStart(sectMax);
FSINDEX i; for (i = 0; i < _cfsTable; i++) { CFatSect *pfs;
msfChk(_fv.GetTable(i, FB_NEW, &pfs)); _fv.SetSect(i, sectMax); sectMax++; pfs->SetNextFat(_fv.GetSectTable(),sectMax); _fv.ReleaseTable(i); } }
msfDebugOut((DEB_TRACE,"Out CDIFat::InitConvert()\n"));
Err: return sc; }
//+-------------------------------------------------------------------------
//
// Method: CDIFat::Resize, private
//
// Synopsis: Resize an existing DIFat.
//
// Arguments: [fsiSize] -- New size for object
//
// Returns: S_OK if success
//
// Algorithm:
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE CDIFat::Resize(FSINDEX fsiSize) { msfDebugOut((DEB_TRACE,"In CDIFat::Resize(%lu)\n",fsiSize)); msfAssert(fsiSize == _cfsTable + 1);
SCODE sc;
msfChk(_fv.Resize(fsiSize)); ULONG ipfs; ipfs = fsiSize - 1;
CFatSect *pfs; msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
FSINDEX csect; csect = _cfsTable; _cfsTable = fsiSize;
SECT sectNew;
msfChk(_pmsParent->GetFat()->GetFree(1, §New)); msfChk(_pmsParent->GetFat()->SetNext(sectNew, DIFSECT)); _fv.SetSect(ipfs, sectNew); _fv.ReleaseTable(ipfs);
if (csect == 0) { _pmsParent->GetHeader()->SetDifStart(sectNew); } else { CFatSect *pfs; msfChk(_fv.GetTable(csect - 1, FB_DIRTY, &pfs));
pfs->SetNextFat(_fv.GetSectTable(),sectNew); _fv.ReleaseTable(csect - 1); }
_pmsParent->GetHeader()->SetDifLength(_cfsTable); msfDebugOut((DEB_TRACE,"Out CDIFat::Resize(%lu)\n",fsiSize));
Err: return sc; }
|