BddInfo.cs 2.8 KB

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