BlockAllocationTable.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /* Copyright (C) 2014-2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace DiskAccessLibrary.VHD
  12. {
  13. /// <summary>
  14. /// a.k.a. BAT
  15. /// </summary>
  16. public class BlockAllocationTable
  17. {
  18. public const uint UnusedEntry = 0xFFFFFFFF;
  19. public uint[] Entries;
  20. public BlockAllocationTable(uint maxTableEntries)
  21. {
  22. Entries = new uint[maxTableEntries];
  23. for (int index = 0; index < maxTableEntries; index++)
  24. {
  25. Entries[index] = UnusedEntry;
  26. }
  27. }
  28. public BlockAllocationTable(byte[] buffer, uint maxTableEntries)
  29. {
  30. Entries = new uint[maxTableEntries];
  31. for (int index = 0; index < maxTableEntries; index++)
  32. {
  33. Entries[index] = BigEndianConverter.ToUInt32(buffer, index * 4);
  34. }
  35. }
  36. public byte[] GetBytes()
  37. {
  38. // The BAT is always extended to a sector boundary
  39. int bufferLength = (int)Math.Ceiling((double)Entries.Length * 4 / VirtualHardDisk.BytesPerDiskSector) * VirtualHardDisk.BytesPerDiskSector;
  40. byte[] buffer = new byte[bufferLength];
  41. for (int index = 0; index < Entries.Length; index++)
  42. {
  43. BigEndianWriter.WriteUInt32(buffer, index * 4, Entries[index]);
  44. }
  45. return buffer;
  46. }
  47. public bool IsBlockInUse(uint blockIndex)
  48. {
  49. return Entries[blockIndex] != UnusedEntry;
  50. }
  51. public static BlockAllocationTable ReadBlockAllocationTable(string path, DynamicDiskHeader dynamicHeader)
  52. {
  53. uint maxTableEntries = dynamicHeader.MaxTableEntries;
  54. long sectorIndex = (long)(dynamicHeader.TableOffset / VirtualHardDisk.BytesPerDiskSector);
  55. int sectorCount = (int)Math.Ceiling((double)maxTableEntries * 4 / VirtualHardDisk.BytesPerDiskSector);
  56. byte[] buffer = new RawDiskImage(path, VirtualHardDisk.BytesPerDiskSector).ReadSectors(sectorIndex, sectorCount);
  57. return new BlockAllocationTable(buffer, maxTableEntries);
  58. }
  59. }
  60. }