BddInfo.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Text;
  4. using DiskAccessLibrary.Mod.Utility;
  5. namespace DiskAccessLibrary
  6. {
  7. public class BddInfo
  8. {
  9. public const int BlockIndexEntrySize = 8;
  10. public string BasedImagePath { get; }
  11. public string SnapshotImagePath { get; }
  12. public long Length { get; }
  13. public int BlockSize { get; }
  14. public int NumberOfBlocks { get; }
  15. public long DataOffset { get; }
  16. public long EntryTableOffset { get; }
  17. public BlockEntryAllocateFlagIndexer Allocated { get; }
  18. public BlockEntryOffsetIndexer Offset { get; set; }
  19. public IReadOnlyList<ulong> Entries { get; }
  20. public BddInfo(string snapshotImagePath, bool readEntries = true)
  21. {
  22. SnapshotImagePath = snapshotImagePath;
  23. using var fs = new FileStream(snapshotImagePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  24. using var reader = new BinaryReader(fs);
  25. int basedPathLength = reader.ReadUInt16(); //2
  26. if (basedPathLength != 0) BasedImagePath = Encoding.UTF8.GetString(reader.ReadBytes(basedPathLength)); //N
  27. BlockSize = reader.ReadInt32(); //4
  28. NumberOfBlocks = reader.ReadInt32(); //4
  29. var snapMatchLength = NumberOfBlocks * (long)BlockSize;
  30. Length = snapMatchLength;
  31. if (false == readEntries) return;
  32. if (null != BasedImagePath)
  33. {
  34. if (false == File.Exists(BasedImagePath)) throw new FileNotFoundException("based image not found", BasedImagePath);
  35. var bfl=IoUtility.GetRealFileSize(BasedImagePath);
  36. if (snapMatchLength != bfl) throw new InvalidDataException("Snapshot size no match to based image");
  37. }
  38. EntryTableOffset = fs.Position;
  39. var arr = new ulong[NumberOfBlocks];
  40. for (var i = 0; i < NumberOfBlocks; i++)
  41. {
  42. arr[i] = reader.ReadUInt64();
  43. }
  44. Entries = arr;
  45. DataOffset = fs.Position;
  46. Allocated = new BlockEntryAllocateFlagIndexer(arr);
  47. Offset = new BlockEntryOffsetIndexer(arr);
  48. }
  49. public static int CalcHeaderSize(string basedImagePath, int blockSize, out int blocks)
  50. {
  51. var baseLength = new FileInfo(basedImagePath).Length;
  52. blocks = (int)(baseLength / blockSize);
  53. return 2 + Encoding.UTF8.GetByteCount(basedImagePath) + 8 + blocks * BlockIndexEntrySize;
  54. }
  55. public static int CalcHeaderSize(long baseLength, int blockSize, out int blocks)
  56. {
  57. blocks = (int)(baseLength / blockSize);
  58. return 2 + +8 + blocks * BlockIndexEntrySize;
  59. }
  60. }
  61. }