Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

445 lines
10 KiB

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