예제 #1
0
        /// <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();
        }
예제 #2
0
        /// <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));
        }
예제 #3
0
        /// <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));
        }
예제 #4
0
        /// <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));
        }
예제 #5
0
        /// <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;
            }
        }