/// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.IO.InvalidDataException"></exception> /// <exception cref="System.NotImplementedException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public VirtualHardDisk(string virtualHardDiskPath) : base(virtualHardDiskPath) { // We can't read the VHD footer using this.ReadSector() because it's out of the disk boundaries m_file = new RawDiskImage(virtualHardDiskPath, BytesPerDiskSector); byte[] buffer = m_file.ReadSector(m_file.Size / BytesPerDiskSector - 1); m_vhdFooter = new VHDFooter(buffer); if (!m_vhdFooter.IsValid) { // check to see if a header is present (dynamic VHD) and use it instead buffer = m_file.ReadSector(0); m_vhdFooter = new VHDFooter(buffer); if (!m_vhdFooter.IsValid) { throw new InvalidDataException("Invalid VHD footer"); } } if (m_vhdFooter.DiskType == VirtualHardDiskType.Fixed) { } else if (m_vhdFooter.DiskType == VirtualHardDiskType.Dynamic) { buffer = m_file.ReadSectors(1, 2); m_dynamicHeader = new DynamicDiskHeader(buffer); m_blockAllocationTable = BlockAllocationTable.ReadBlockAllocationTable(virtualHardDiskPath, m_dynamicHeader); } else { throw new NotImplementedException("Differencing VHD is not supported"); } SetGeometry(); }
/// <param name="size">In bytes</param> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public static VirtualHardDisk Create(string path, long size) { VHDFooter footer = new VHDFooter(); footer.OriginalSize = (ulong)size; footer.CurrentSize = (ulong)size; footer.SetCurrentTimeStamp(); footer.SetDiskGeometry((ulong)size / BytesPerDiskSector); RawDiskImage diskImage = RawDiskImage.Create(path, size + VHDFooter.Length, BytesPerDiskSector); diskImage.WriteSectors(size / BytesPerDiskSector, footer.GetBytes()); return(new VirtualHardDisk(path)); }
/// <param name="diskSize">In bytes</param> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public static VirtualHardDisk CreateFixedDisk(string path, long diskSize) { if (diskSize % BytesPerDiskSector > 0) { throw new ArgumentException("diskSize must be a multiple of sector size"); } VHDFooter footer = new VHDFooter(); footer.OriginalSize = (ulong)diskSize; footer.CurrentSize = (ulong)diskSize; footer.SetCurrentTimeStamp(); footer.SetDiskGeometry((ulong)diskSize / BytesPerDiskSector); RawDiskImage diskImage = RawDiskImage.Create(path, diskSize + VHDFooter.Length, BytesPerDiskSector); diskImage.WriteSectors(diskSize / BytesPerDiskSector, footer.GetBytes()); return(new VirtualHardDisk(path)); }
/// <param name="diskSize">In bytes</param> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public static VirtualHardDisk CreateDynamicDisk(string path, long diskSize) { const int BlockSizeInBytes = 4096 * BytesPerDiskSector; if (diskSize % BlockSizeInBytes > 0) { // All blocks within a given image must be the same size throw new ArgumentException("Dynamic VHD disk size must be a multiple of 2MiB"); } VHDFooter footer = new VHDFooter(); footer.OriginalSize = (ulong)diskSize; footer.CurrentSize = (ulong)diskSize; footer.SetCurrentTimeStamp(); footer.SetDiskGeometry((ulong)diskSize / BytesPerDiskSector); footer.DiskType = VirtualHardDiskType.Dynamic; DynamicDiskHeader header = new DynamicDiskHeader(); header.TableOffset = VHDFooter.Length + DynamicDiskHeader.Length; header.BlockSize = BlockSizeInBytes; header.MaxTableEntries = (uint)Math.Ceiling((double)diskSize / BlockSizeInBytes); BlockAllocationTable blockAllocationTable = new BlockAllocationTable(header.MaxTableEntries); byte[] footerBytes = footer.GetBytes(); byte[] headerBytes = header.GetBytes(); byte[] blockAllocationTableBytes = blockAllocationTable.GetBytes(); int fileSize = VHDFooter.Length + DynamicDiskHeader.Length + blockAllocationTableBytes.Length + VHDFooter.Length; RawDiskImage diskImage = RawDiskImage.Create(path, fileSize, BytesPerDiskSector); diskImage.WriteSectors(0, footerBytes); diskImage.WriteSectors(1, headerBytes); diskImage.WriteSectors(3, blockAllocationTableBytes); diskImage.WriteSectors(fileSize / BytesPerDiskSector - 1, footerBytes); return(new VirtualHardDisk(path)); }
/// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.IO.InvalidDataException"></exception> /// <exception cref="System.NotImplementedException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public VirtualMachineDisk(string descriptorPath, bool isReadOnly) : base(descriptorPath) { m_descriptorPath = descriptorPath; m_descriptor = VirtualMachineDiskDescriptor.ReadFromFile(m_descriptorPath); bool isDescriptorEmbedded = false; if (m_descriptor == null) { SparseExtent sparse; try { sparse = new SparseExtent(m_descriptorPath); } catch (InvalidDataException) { throw new InvalidDataException("Missing VMDK descriptor"); } if (sparse.Descriptor != null) { isDescriptorEmbedded = true; m_descriptor = sparse.Descriptor; m_extent = sparse; } else { throw new InvalidDataException("Missing VMDK descriptor"); } } if (m_descriptor.Version != 1) { throw new NotImplementedException("Unsupported VMDK descriptor version"); } if (m_descriptor.ParentContentID != BaseDiskParentCID) { throw new InvalidDataException("VMDK descriptor ParentContentID does not match BaseDiskParentCID"); } if (!isDescriptorEmbedded && m_descriptor.DiskType != VirtualMachineDiskType.MonolithicFlat) { throw new NotImplementedException("Unsupported VMDK disk type"); } if (isDescriptorEmbedded && m_descriptor.DiskType != VirtualMachineDiskType.MonolithicSparse) { throw new NotImplementedException("Unsupported VMDK disk type"); } foreach (VirtualMachineDiskExtentEntry extentEntry in m_descriptor.ExtentEntries) { if (!isDescriptorEmbedded && extentEntry.ExtentType != ExtentType.Flat) { throw new NotImplementedException("Unsupported VMDK extent type"); } if (isDescriptorEmbedded && extentEntry.ExtentType != ExtentType.Sparse) { throw new NotImplementedException("Unsupported VMDK extent type"); } } if (m_descriptor.ExtentEntries.Count != 1) { throw new NotImplementedException("Unsupported number of VMDK extents"); } if (m_descriptor.DiskType == VirtualMachineDiskType.MonolithicFlat) { VirtualMachineDiskExtentEntry entry = m_descriptor.ExtentEntries[0]; string directory = System.IO.Path.GetDirectoryName(descriptorPath); string extentPath = directory + @"\" + entry.FileName; DiskImage extent = new RawDiskImage(extentPath, BytesPerDiskSector, isReadOnly); m_extent = extent; } }