VolumeManagerDatabaseHeader.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* Copyright (C) 2014 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.LogicalDiskManager
  12. {
  13. public class VolumeManagerDatabaseHeader // VMDB
  14. {
  15. public const int Length = 512;
  16. public const string VolumeManagerDatabaseSignature = "VMDB";
  17. public string Signature = VolumeManagerDatabaseSignature;
  18. public uint NumberOfVBlks; // Number of VBLK blocks in the database (This number includes the VMDB, which counts as 4 blocks)
  19. public uint BlockSize; // VBLK block size
  20. public uint HeaderSize;
  21. public DatabaseHeaderUpdateStatus UpdateStatus;
  22. // Versions: 4.10 for Windows XP \ Server 2003 \ Windows 7 \ Server 2008
  23. // 4.10 for Veritas Storage Foundation 4.0 (Windows Disk Management compatible group checked)
  24. // 4.12 for Veritas Storage Foundation 4.0 (Windows Disk Management compatible group unchecked)
  25. public ushort MajorVersion;
  26. public ushort MinorVersion;
  27. public string DiskGroupName = String.Empty;
  28. public string DiskGroupGuidString = String.Empty;
  29. public ulong CommitTransactionID; // ID of last commit transaction
  30. public ulong PendingTransactionID; // ID of transaction to be committed (should be equal to CommitTransactionID unless an update is taking place)
  31. public uint CommittedTotalNumberOfVolumeRecords; // Total number of Volume records already committed (before pending changes)
  32. public uint CommittedTotalNumberOfComponentRecords; // see above
  33. public uint CommittedTotalNumberOfExtentRecords; // see above
  34. public uint CommittedTotalNumberOfDiskRecords; // see above
  35. public uint CommittedTotalNumberOfDiskAccessRecords; // DMDiag reports this as nda (number of 'da', which use to represents disk access records in other Veritas products)
  36. // Unused 8 bytes
  37. public uint PendingTotalNumberOfVolumeRecords; // Total number of Volume records after pending changes
  38. public uint PendingTotalNumberOfComponentRecords; // see above
  39. public uint PendingTotalNumberOfExtentRecords; // see above
  40. public uint PendingTotalNumberOfDiskRecords; // see above
  41. public uint PendingTotalNumberOfDiskAccessRecords; // see above
  42. // Unused 8 bytes
  43. public DateTime LastModificationDT;
  44. public VolumeManagerDatabaseHeader(byte[] buffer)
  45. {
  46. Signature = ByteReader.ReadAnsiString(buffer, 0x00, 4);
  47. NumberOfVBlks = BigEndianConverter.ToUInt32(buffer, 0x04);
  48. BlockSize = BigEndianConverter.ToUInt32(buffer, 0x08);
  49. HeaderSize = BigEndianConverter.ToUInt32(buffer, 0x0C);
  50. UpdateStatus = (DatabaseHeaderUpdateStatus)BigEndianConverter.ToUInt16(buffer, 0x10);
  51. MajorVersion = BigEndianConverter.ToUInt16(buffer, 0x12);
  52. MinorVersion = BigEndianConverter.ToUInt16(buffer, 0x14);
  53. DiskGroupName = ByteReader.ReadAnsiString(buffer, 0x16, 31).Trim('\0');
  54. DiskGroupGuidString = ByteReader.ReadAnsiString(buffer, 0x35, 64).Trim('\0');
  55. CommitTransactionID = BigEndianConverter.ToUInt64(buffer, 0x75);
  56. PendingTransactionID = BigEndianConverter.ToUInt64(buffer, 0x7D);
  57. CommittedTotalNumberOfVolumeRecords = BigEndianConverter.ToUInt32(buffer, 0x85);
  58. CommittedTotalNumberOfComponentRecords = BigEndianConverter.ToUInt32(buffer, 0x89);
  59. CommittedTotalNumberOfExtentRecords = BigEndianConverter.ToUInt32(buffer, 0x8D);
  60. CommittedTotalNumberOfDiskRecords = BigEndianConverter.ToUInt32(buffer, 0x91);
  61. CommittedTotalNumberOfDiskAccessRecords = BigEndianConverter.ToUInt32(buffer, 0x95);
  62. // Unused 8 bytes
  63. PendingTotalNumberOfVolumeRecords = BigEndianConverter.ToUInt32(buffer, 0xA1);
  64. PendingTotalNumberOfComponentRecords = BigEndianConverter.ToUInt32(buffer, 0xA5);
  65. PendingTotalNumberOfExtentRecords = BigEndianConverter.ToUInt32(buffer, 0xA9);
  66. PendingTotalNumberOfDiskRecords = BigEndianConverter.ToUInt32(buffer, 0xAD);
  67. PendingTotalNumberOfDiskAccessRecords = BigEndianConverter.ToUInt32(buffer, 0xB1);
  68. // Unused 8 bytes
  69. LastModificationDT = DateTime.FromFileTimeUtc(BigEndianConverter.ToInt64(buffer, 0xBD));
  70. }
  71. public byte[] GetBytes()
  72. {
  73. byte[] buffer = new byte[Length];
  74. ByteWriter.WriteAnsiString(buffer, 0x00, Signature, 4);
  75. BigEndianWriter.WriteUInt32(buffer, 0x04, NumberOfVBlks);
  76. BigEndianWriter.WriteUInt32(buffer, 0x08, BlockSize);
  77. BigEndianWriter.WriteUInt32(buffer, 0x0C, HeaderSize);
  78. BigEndianWriter.WriteUInt16(buffer, 0x10, (ushort)UpdateStatus);
  79. BigEndianWriter.WriteUInt16(buffer, 0x12, MajorVersion);
  80. BigEndianWriter.WriteUInt16(buffer, 0x14, MinorVersion);
  81. ByteWriter.WriteAnsiString(buffer, 0x16, DiskGroupName, 31);
  82. ByteWriter.WriteAnsiString(buffer, 0x35, DiskGroupGuidString, 64);
  83. BigEndianWriter.WriteUInt64(buffer, 0x75, CommitTransactionID);
  84. BigEndianWriter.WriteUInt64(buffer, 0x7D, PendingTransactionID);
  85. BigEndianWriter.WriteUInt32(buffer, 0x85, CommittedTotalNumberOfVolumeRecords);
  86. BigEndianWriter.WriteUInt32(buffer, 0x89, CommittedTotalNumberOfComponentRecords);
  87. BigEndianWriter.WriteUInt32(buffer, 0x8D, CommittedTotalNumberOfExtentRecords);
  88. BigEndianWriter.WriteUInt32(buffer, 0x91, CommittedTotalNumberOfDiskRecords);
  89. BigEndianWriter.WriteUInt32(buffer, 0x95, CommittedTotalNumberOfDiskAccessRecords);
  90. BigEndianWriter.WriteUInt32(buffer, 0xA1, PendingTotalNumberOfVolumeRecords);
  91. BigEndianWriter.WriteUInt32(buffer, 0xA5, PendingTotalNumberOfComponentRecords);
  92. BigEndianWriter.WriteUInt32(buffer, 0xA9, PendingTotalNumberOfExtentRecords);
  93. BigEndianWriter.WriteUInt32(buffer, 0xAD, PendingTotalNumberOfDiskRecords);
  94. BigEndianWriter.WriteUInt32(buffer, 0xB1, PendingTotalNumberOfDiskAccessRecords);
  95. BigEndianWriter.WriteInt64(buffer, 0xBD, LastModificationDT.ToFileTimeUtc());
  96. return buffer;
  97. }
  98. public Guid DiskGroupGuid
  99. {
  100. get
  101. {
  102. return new Guid(DiskGroupGuidString);
  103. }
  104. set
  105. {
  106. DiskGroupGuidString = value.ToString();
  107. }
  108. }
  109. public static VolumeManagerDatabaseHeader ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock)
  110. {
  111. ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart;
  112. byte[] sector = disk.ReadSector((long)sectorIndex);
  113. string signature = ByteReader.ReadAnsiString(sector, 0x00, 4);
  114. if (signature == VolumeManagerDatabaseSignature)
  115. {
  116. return new VolumeManagerDatabaseHeader(sector);
  117. }
  118. else
  119. {
  120. return null;
  121. }
  122. }
  123. public static void WriteToDisk(DynamicDisk disk, VolumeManagerDatabaseHeader header)
  124. {
  125. WriteToDisk(disk.Disk, disk.PrivateHeader, disk.TOCBlock, header);
  126. }
  127. public static void WriteToDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock, VolumeManagerDatabaseHeader header)
  128. {
  129. ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart;
  130. byte[] bytes = header.GetBytes();
  131. disk.WriteSectors((long)sectorIndex, bytes);
  132. }
  133. }
  134. }