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, §New));
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