1 //-------------------------------------------------------------------------
2 //
3 //  For conditions of distribution and use, see copyright notice
4 //  in Flashpix.h
5 //
6 //  Copyright (c) 1999 Digital Imaging Group, Inc.
7 //
8 //  Contents:   Double Indirected Fat Code
9 //
10 //  Classes:    None.
11 //
12 //  Functions:
13 //
14 //--------------------------------------------------------------------------
15 
16 #include "msfhead.cxx"
17 
18 
19 #include "h/difat.hxx"
20 #include "mread.hxx"
21 
22 
23 //+-------------------------------------------------------------------------
24 //
25 //  Method:     CDIFat::CDIFat, public
26 //
27 //  Synopsis:   CDIFat constructor
28 //
29 //  Arguments:  [cbSector] -- size of a sector
30 //
31 //--------------------------------------------------------------------------
32 
CDIFat(USHORT cbSector)33 CDIFat::CDIFat(USHORT cbSector)
34   : _fv( SIDDIF,
35          (FSOFFSET) (cbSector / sizeof(SECT)),
36          (FSOFFSET) ((cbSector / sizeof(SECT)) - 1) ),
37     _pmsParent(NULL)
38 {
39     msfDebugOut((DEB_TRACE,"In CDIFat constructor\n"));
40     _cfsTable = 0;
41     msfDebugOut((DEB_TRACE,"Out CDIFat constructor\n"));
42 }
43 
44 
45 //+---------------------------------------------------------------------------
46 //
47 //  Member: CDIFat::Empty, public
48 //
49 //  Synopsis: Empty all the control structures of this instance
50 //
51 //  Arguments:  None.
52 //
53 //  Returns:  void.
54 //
55 //----------------------------------------------------------------------------
56 
Empty(void)57 void CDIFat::Empty(void)
58 {
59     _fv.Empty();
60     _pmsParent = NULL;
61     _cfsTable = 0;
62 }
63 
64 
65 //+-------------------------------------------------------------------------
66 //
67 //  Method:     CIDFat::Flush, private
68 //
69 //  Synopsis:   Flush a sector to disk
70 //
71 //  Arguments:  none
72 //
73 //  Returns:    S_OK if call completed OK.
74 //
75 //  Algorithm:  Write sector up to parent mstream.
76 //
77 //  Notes:
78 //
79 //--------------------------------------------------------------------------
80 
Flush(void)81 SCODE CDIFat::Flush(void)
82 {
83     return _fv.Flush();
84 }
85 
86 
87 //+-------------------------------------------------------------------------
88 //
89 //  Method:     CDIFat::GetFatSect, public
90 //
91 //  Synopsis:   Given an offset into the Fat chain, return the sector
92 //              value for that FatSect.
93 //
94 //  Arguments:  [oSect] -- offset in Fat chain
95 //              [psect]  -- pointer to returned sector
96 //
97 //  Modifies:   [*psect]
98 //
99 //  Returns:    Sector value of FatSect.
100 //
101 //  Algorithm:  If sector is stored in the header, retrieve it from
102 //                  there.
103 //              If not, retrieve it from the FatVector.
104 //
105 //--------------------------------------------------------------------------
106 
GetFatSect(const FSINDEX oSect,SECT * psect)107 SCODE CDIFat::GetFatSect(const FSINDEX oSect, SECT *psect)
108 {
109     SCODE sc = S_OK;
110     SECT sectReturn;
111 
112     msfDebugOut((DEB_TRACE,"In CDIFat::GetFatSect(%lu)\n",oSect));
113     if (oSect < CSECTFAT)
114     {
115         msfDebugOut((DEB_ITRACE,"Getting sect from header\n"));
116         sectReturn = _pmsParent->GetHeader()->GetFatSect(oSect);
117     }
118     else
119     {
120         FSINDEX ipfs;
121         FSOFFSET isect;
122 
123         SectToPair(oSect,&ipfs,&isect);
124 
125         msfAssert(ipfs < _cfsTable);
126 
127         CFatSect *pfs;
128         msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
129         sectReturn = pfs->GetSect(isect);
130         _fv.ReleaseTable(ipfs);
131     }
132 
133     msfDebugOut((DEB_TRACE,"Out CDIFat::GetFatSect(%lu)=>%lu\n",oSect,sectReturn));
134     *psect = sectReturn;
135 
136 Err:
137     return sc;
138 }
139 
140 
141 
142 //+-------------------------------------------------------------------------
143 //
144 //  Method:     CDIFat::SetFatSect, public
145 //
146 //  Synopsis:   Given an offset into the Fat chain, set the sector
147 //              value.
148 //
149 //  Arguments:  [oSect] -- Offset into fat chain
150 //              [sect] -- New sector value for that offset.
151 //
152 //  Returns:    S_OK if call completed OK.
153 //
154 //  Algorithm:  If the sector is stored in the header, set it and
155 //                  flush the header.
156 //              Otherwise, if the sector will not fit in the current
157 //                  CFatVector, resize it.
158 //              Set the sector in the FatVector and flush it.
159 //
160 //--------------------------------------------------------------------------
161 
SetFatSect(const FSINDEX oSect,const SECT sect)162 SCODE CDIFat::SetFatSect(const FSINDEX oSect, const SECT sect)
163 {
164     msfDebugOut((DEB_TRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
165     SCODE sc = S_OK;
166 
167     if (oSect < CSECTFAT)
168     {
169         msfDebugOut((DEB_ITRACE,"Setting sect in header: %lu, %lu\n",oSect,sect));
170         _pmsParent->GetHeader()->SetFatSect(oSect, sect);
171     }
172     else
173     {
174         FSINDEX ipfs;
175         FSOFFSET isect;
176 
177         SectToPair(oSect,&ipfs,&isect);
178         if (ipfs >= _cfsTable)
179         {
180             msfChk(Resize(_cfsTable + 1));
181         }
182 
183         CFatSect *pfs;
184         msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
185 
186         pfs->SetSect(isect, sect);
187         _fv.ReleaseTable(ipfs);
188 
189         msfDebugOut((DEB_TRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
190     }
191 
192 Err:
193     return sc;
194 }
195 
196 
197 //+-------------------------------------------------------------------------
198 //
199 //  Method:     CDIFat::GetSect, public
200 //
201 //  Synopsis:   Given an offset into the DIFat chain, return the
202 //              sector value
203 //
204 //  Arguments:  [oSect] -- Offset into DIFat chain.
205 //              [psect] -- pointer to returned sector
206 //
207 //  Modifies:   [*psect]
208 //
209 //  Returns:    Sector value for given offset.
210 //
211 //  Algorithm:  Retrieve the information from the NextFat fields of
212 //                  the CFatVector
213 //
214 //--------------------------------------------------------------------------
215 
GetSect(const FSINDEX oSect,SECT * psect)216 SCODE CDIFat::GetSect(const FSINDEX oSect, SECT *psect)
217 {
218     SCODE sc = S_OK;
219 
220     SECT sectReturn;
221 
222     msfDebugOut((DEB_TRACE,"In CDIFat::GetSect(%lu)\n",oSect));
223     msfAssert(oSect < _cfsTable);
224 
225     if (oSect == 0)
226     {
227         sectReturn = _pmsParent->GetHeader()->GetDifStart();
228     }
229     else
230     {
231         CFatSect *pfs;
232         msfChk(_fv.GetTable(oSect - 1, FB_NONE, &pfs));
233 
234         sectReturn = pfs->GetNextFat(_fv.GetSectTable());
235         _fv.ReleaseTable(oSect - 1);
236     }
237 
238     msfDebugOut((DEB_TRACE,"Out CDIFat::GetSect(%lu)=>%lu\n",oSect,sectReturn));
239     *psect = sectReturn;
240 
241 Err:
242     return sc;
243 }
244 
245 
246 //+-------------------------------------------------------------------------
247 //
248 //  Method:     CDIFat::Init, public
249 //
250 //  Synopsis:   Init function for previously stored DIFat.
251 //
252 //  Arguments:  [pmsParent] -- pointer to stream parent
253 //              [cFatSect] -- Length of DIFat in sectors
254 //
255 //  Returns:    S_OK if call completed properly.
256 //
257 //  Algorithm:  Initialize all the variables
258 //
259 //--------------------------------------------------------------------------
260 
Init(CMStream * pmsParent,const FSINDEX cFatSect)261 SCODE CDIFat::Init(CMStream * pmsParent, const FSINDEX cFatSect)
262 {
263     msfDebugOut((DEB_TRACE,"In CDIFat::Init(%lu)\n",cFatSect));
264     SCODE sc;
265 
266     _pmsParent = pmsParent;
267 
268     msfChk(_fv.Init(_pmsParent, cFatSect));
269 
270     _cfsTable = cFatSect;
271 
272     msfDebugOut((DEB_TRACE,"Out CDIFat::Init(%lu)\n",cFatSect));
273 
274 Err:
275     return sc;
276 }
277 
278 
279 //+-------------------------------------------------------------------------
280 //
281 //  Method:     CDIFat::InitConvert, public
282 //
283 //  Synopsis:   Init function for conversion
284 //
285 //  Arguments:  [pmsParent] -- pointer to stream parent
286 //              [sectMax] -- Last used sector in existing file
287 //
288 //  Returns:    S_OK if call completed OK.
289 //
290 //  Algorithm:  See below
291 //
292 //  Notes:
293 //
294 //--------------------------------------------------------------------------
295 
InitConvert(CMStream * pmsParent,SECT sectMax)296 SCODE CDIFat::InitConvert(CMStream *pmsParent, SECT sectMax)
297 {
298     msfDebugOut((DEB_TRACE,"In CDIFat::InitConvert(%lu)\n",sectMax));
299     SCODE sc;
300 
301     _pmsParent = pmsParent;
302 
303     USHORT cbSector = _pmsParent->GetSectorSize();
304     FSOFFSET csectPer = (FSOFFSET) (cbSector / sizeof(SECT));
305 
306     FSINDEX csectFat = 0;
307     FSINDEX csectFatLast;
308 
309     FSINDEX csectDif = 0;
310     FSINDEX csectDifLast;
311     do
312     {
313         //Number of fat sectors needed to represent:
314         //    Number of Data Sectors (sectMax) +
315         //    Number of Fat Sectors (csectFat) +
316         //    Number of DIF sectors (csectDif) +
317         //    Number of Directory Sectors (1)
318 
319         //We must use a loop here, since the fat must be large
320         //    enough to represent itself and the DIFat.  See
321         //    CFat::InitConvert for a more lengthy discussion of
322         //    this method.
323 
324         csectFatLast = csectFat;
325 
326         csectFat = (sectMax + csectFatLast + csectDif + 1 + csectPer - 1) /
327             csectPer;
328 
329         csectDifLast = csectDif;
330 
331         if (csectFat < CSECTFAT)
332         {
333             csectDif = 0;
334         }
335         else
336         {
337             FSOFFSET ciSect;
338 
339             SectToPair(csectFat, &csectDif, &ciSect);
340             csectDif++;
341         }
342     }
343     while ((csectDif != csectDifLast) || (csectFat != csectFatLast));
344 
345 
346     _cfsTable = csectDif;
347 
348     msfChk(_fv.Init(_pmsParent, _cfsTable));
349 
350     _pmsParent->GetHeader()->SetDifLength(_cfsTable);
351 
352     if (_cfsTable > 0)
353     {
354         _pmsParent->GetHeader()->SetDifStart(sectMax);
355 
356         FSINDEX i;
357         for (i = 0; i < _cfsTable; i++)
358         {
359             CFatSect *pfs;
360 
361             msfChk(_fv.GetTable(i, FB_NEW, &pfs));
362             _fv.SetSect(i, sectMax);
363 
364             sectMax++;
365             pfs->SetNextFat(_fv.GetSectTable(),sectMax);
366             _fv.ReleaseTable(i);
367         }
368     }
369 
370     msfDebugOut((DEB_TRACE,"Out CDIFat::InitConvert()\n"));
371 
372 Err:
373     return sc;
374 }
375 
376 
377 
378 
379 
380 //+-------------------------------------------------------------------------
381 //
382 //  Method:     CDIFat::Resize, private
383 //
384 //  Synopsis:   Resize an existing DIFat.
385 //
386 //  Arguments:  [fsiSize] -- New size for object
387 //
388 //  Returns:    S_OK if success
389 //
390 //  Algorithm:
391 //
392 //  Notes:
393 //
394 //--------------------------------------------------------------------------
395 
Resize(FSINDEX fsiSize)396 SCODE CDIFat::Resize(FSINDEX fsiSize)
397 {
398     msfDebugOut((DEB_TRACE,"In CDIFat::Resize(%lu)\n",fsiSize));
399     msfAssert(fsiSize == _cfsTable + 1);
400 
401     SCODE sc;
402 
403     msfChk(_fv.Resize(fsiSize));
404     ULONG ipfs;
405     ipfs = fsiSize - 1;
406 
407     CFatSect *pfs;
408     msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
409 
410     FSINDEX csect;
411     csect = _cfsTable;
412     _cfsTable = fsiSize;
413 
414     SECT sectNew;
415 
416     msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew));
417     msfChk(_pmsParent->GetFat()->SetNext(sectNew, DIFSECT));
418 
419     _fv.SetSect(ipfs, sectNew);
420     _fv.ReleaseTable(ipfs);
421 
422     if (csect == 0)
423     {
424         _pmsParent->GetHeader()->SetDifStart(sectNew);
425     }
426     else
427     {
428         CFatSect *pfs;
429         msfChk(_fv.GetTable(csect - 1, FB_DIRTY, &pfs));
430 
431         pfs->SetNextFat(_fv.GetSectTable(),sectNew);
432         _fv.ReleaseTable(csect - 1);
433     }
434 
435     _pmsParent->GetHeader()->SetDifLength(_cfsTable);
436 
437     msfDebugOut((DEB_TRACE,"Out CDIFat::Resize(%lu)\n",fsiSize));
438 
439 Err:
440     return sc;
441 }
442 
443 
444 
445 
446