VirtualMachineDiskDescriptor.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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.IO;
  10. using System.Text;
  11. using Utilities;
  12. namespace DiskAccessLibrary.VMDK
  13. {
  14. public class VirtualMachineDiskDescriptor
  15. {
  16. public int Version;
  17. public uint ContentID;
  18. public uint ParentContentID;
  19. public VirtualMachineDiskType DiskType;
  20. public List<VirtualMachineDiskExtentEntry> ExtentEntries;
  21. public string Adapter;
  22. public long Cylinders;
  23. public int TracksPerCylinder; // heads
  24. public int SectorsPerTrack;
  25. public VirtualMachineDiskDescriptor(List<string> lines)
  26. {
  27. ParseDescriptor(lines);
  28. }
  29. private void ParseDescriptor(List<string> lines)
  30. {
  31. ExtentEntries = new List<VirtualMachineDiskExtentEntry>();
  32. foreach (string line in lines)
  33. {
  34. if (line.StartsWith("version", StringComparison.InvariantCultureIgnoreCase))
  35. {
  36. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  37. Version = Conversion.ToInt32(value);
  38. }
  39. else if (line.StartsWith("CID", StringComparison.InvariantCultureIgnoreCase))
  40. {
  41. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  42. ContentID = UInt32.Parse(value, System.Globalization.NumberStyles.HexNumber);
  43. }
  44. else if (line.StartsWith("ParentCID", StringComparison.InvariantCultureIgnoreCase))
  45. {
  46. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  47. ParentContentID = UInt32.Parse(value, System.Globalization.NumberStyles.HexNumber);
  48. }
  49. else if (line.StartsWith("createType", StringComparison.InvariantCultureIgnoreCase))
  50. {
  51. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  52. value = QuotedStringUtils.Unquote(value);
  53. DiskType = GetFromString(value);
  54. }
  55. else if (line.StartsWith("RW", StringComparison.InvariantCultureIgnoreCase) ||
  56. line.StartsWith("RDONLY", StringComparison.InvariantCultureIgnoreCase) ||
  57. line.StartsWith("NOACCESS", StringComparison.InvariantCultureIgnoreCase))
  58. {
  59. VirtualMachineDiskExtentEntry entry = VirtualMachineDiskExtentEntry.ParseEntry(line);
  60. ExtentEntries.Add(entry);
  61. }
  62. else if (line.StartsWith("ddb.adapterType", StringComparison.InvariantCultureIgnoreCase))
  63. {
  64. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  65. value = QuotedStringUtils.Unquote(value);
  66. Adapter = value;
  67. }
  68. else if (line.StartsWith("ddb.geometry.sectors", StringComparison.InvariantCultureIgnoreCase))
  69. {
  70. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  71. value = QuotedStringUtils.Unquote(value);
  72. SectorsPerTrack = Conversion.ToInt32(value);
  73. }
  74. else if (line.StartsWith("ddb.geometry.heads", StringComparison.InvariantCultureIgnoreCase))
  75. {
  76. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  77. value = QuotedStringUtils.Unquote(value);
  78. TracksPerCylinder = Conversion.ToInt32(value);
  79. }
  80. else if (line.StartsWith("ddb.geometry.cylinders", StringComparison.InvariantCultureIgnoreCase))
  81. {
  82. string value = line.Substring(line.IndexOf('=') + 1).Trim();
  83. value = QuotedStringUtils.Unquote(value);
  84. Cylinders = Conversion.ToInt64(value);
  85. }
  86. }
  87. }
  88. public void UpdateExtentEntries(List<string> lines)
  89. {
  90. int startIndex = -1;
  91. // Remove previous extent entries
  92. for (int index = 0; index < lines.Count; index++)
  93. {
  94. string line = lines[index];
  95. if (line.StartsWith("RW", StringComparison.InvariantCultureIgnoreCase) ||
  96. line.StartsWith("RDONLY", StringComparison.InvariantCultureIgnoreCase) ||
  97. line.StartsWith("NOACCESS", StringComparison.InvariantCultureIgnoreCase))
  98. {
  99. if (startIndex == -1)
  100. {
  101. startIndex = index;
  102. }
  103. lines.RemoveAt(index);
  104. index--;
  105. }
  106. }
  107. if (startIndex >= 0)
  108. {
  109. foreach (VirtualMachineDiskExtentEntry entry in ExtentEntries)
  110. {
  111. lines.Insert(startIndex, entry.GetEntryLine());
  112. startIndex++;
  113. }
  114. }
  115. }
  116. public static VirtualMachineDiskDescriptor ReadFromFile(string descriptorPath)
  117. {
  118. List<string> lines = ReadASCIITextLines(descriptorPath);
  119. if (lines == null)
  120. {
  121. return null;
  122. }
  123. return new VirtualMachineDiskDescriptor(lines);
  124. }
  125. private static VirtualMachineDiskType GetFromString(string createType)
  126. {
  127. switch (createType.ToLower())
  128. {
  129. case "custom":
  130. return VirtualMachineDiskType.Custom;
  131. case "monolithicsparse":
  132. return VirtualMachineDiskType.MonolithicSparse;
  133. case "monolithicflat":
  134. return VirtualMachineDiskType.MonolithicFlat;
  135. case "2Gbmaxextentsparse":
  136. return VirtualMachineDiskType.TwoGbMaxExtentSparse;
  137. case "2Gbmaxextentflat":
  138. return VirtualMachineDiskType.TwoGbMaxExtentFlat;
  139. case "fulldevice":
  140. return VirtualMachineDiskType.FullDevice;
  141. case "partitioneddevice":
  142. return VirtualMachineDiskType.PartitionedDevice;
  143. case "vmfspreallocated":
  144. return VirtualMachineDiskType.VmfsPreallocated;
  145. case "vmfseagerzeroedthick":
  146. return VirtualMachineDiskType.VmfsEagerZeroedThick;
  147. case "vmfsthin":
  148. return VirtualMachineDiskType.VmfsThin;
  149. case "vmfssparse":
  150. return VirtualMachineDiskType.VmfsSparse;
  151. case "vmfsrdm":
  152. return VirtualMachineDiskType.VmfsRDM;
  153. case "vmfsRDMP":
  154. return VirtualMachineDiskType.VmfsRDMP;
  155. case "vmfsraw":
  156. return VirtualMachineDiskType.VmfsRaw;
  157. case "streamoptimized":
  158. return VirtualMachineDiskType.StreamOptimized;
  159. default:
  160. return VirtualMachineDiskType.Custom;
  161. }
  162. }
  163. public static List<string> ReadASCIITextLines(string path)
  164. {
  165. string text = ReadASCIIText(path);
  166. if (text == null)
  167. {
  168. return null;
  169. }
  170. return GetLines(text);
  171. }
  172. public static List<string> GetLines(string text)
  173. {
  174. List<string> result = new List<string>();
  175. StringReader reader = new StringReader(text);
  176. string line;
  177. while ((line = reader.ReadLine()) != null)
  178. {
  179. result.Add(line);
  180. }
  181. return result;
  182. }
  183. public static string ReadASCIIText(string path)
  184. {
  185. StringBuilder builder = new StringBuilder();
  186. FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
  187. int bufferSize = 0x1000; // default FileStream buffer size
  188. byte[] buffer = new byte[bufferSize];
  189. int bytesRead = stream.Read(buffer, 0, buffer.Length);
  190. string temp = ASCIIEncoding.ASCII.GetString(buffer, 0, bytesRead);
  191. while (bytesRead > 0)
  192. {
  193. foreach (char c in temp)
  194. {
  195. if (char.IsControl(c) && c != '\r' && c != '\n')
  196. {
  197. stream.Close();
  198. return null;
  199. }
  200. }
  201. builder.Append(temp);
  202. if (bytesRead == bufferSize)
  203. {
  204. bytesRead = stream.Read(buffer, 0, buffer.Length);
  205. temp = ASCIIEncoding.ASCII.GetString(buffer, 0, bytesRead);
  206. }
  207. else
  208. {
  209. break;
  210. }
  211. }
  212. stream.Close();
  213. return builder.ToString();
  214. }
  215. }
  216. }