Ejemplo n.º 1
0
        private static void CreateExtent(Stream extentStream, long size, ExtentType type, long descriptorLength,
                                         out long descriptorStart)
        {
            if (type == ExtentType.Flat || type == ExtentType.Vmfs)
            {
                extentStream.SetLength(size);
                descriptorStart = 0;
                return;
            }

            if (type == ExtentType.Sparse)
            {
                CreateSparseExtent(extentStream, size, descriptorLength, out descriptorStart);
            }
            else if (type == ExtentType.VmfsSparse)
            {
                ServerSparseExtentHeader header = CreateServerSparseExtentHeader(size);

                extentStream.Position = 0;
                extentStream.Write(header.GetBytes(), 0, 4 * Sizes.Sector);

                byte[] blankGlobalDirectory = new byte[header.NumGdEntries * 4];
                extentStream.Write(blankGlobalDirectory, 0, blankGlobalDirectory.Length);

                descriptorStart = 0;
            }
            else
            {
                throw new NotImplementedException($"Extent type '{ExtentDescriptor.FormatExtentType(type)}' not implemented");
            }
        }
Ejemplo n.º 2
0
 public DiskExtent(ExtentDescriptor descriptor, long diskOffset, FileLocator fileLocator, FileAccess access)
 {
     _descriptor  = descriptor;
     _diskOffset  = diskOffset;
     _fileLocator = fileLocator;
     _access      = access;
 }
Ejemplo n.º 3
0
 public DiskExtent(ExtentDescriptor descriptor, long diskOffset, FileLocator fileLocator, FileAccess access)
 {
     _descriptor = descriptor;
     _diskOffset = diskOffset;
     _fileLocator = fileLocator;
     _access = access;
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Initiates the build process.
        /// </summary>
        /// <param name="baseName">The base name for the VMDK, for example 'foo' to create 'foo.vmdk'.</param>
        /// <returns>A set of one or more logical files that constitute the VMDK.  The first file is
        /// the 'primary' file that is normally attached to VMs.</returns>
        public override DiskImageFileSpecification[] Build(string baseName)
        {
            if (string.IsNullOrEmpty(baseName))
            {
                throw new ArgumentException("Invalid base file name", "baseName");
            }

            if (Content == null)
            {
                throw new InvalidOperationException("No content stream specified");
            }

            if (_diskType != DiskCreateType.Vmfs && _diskType != DiskCreateType.VmfsSparse && _diskType != DiskCreateType.MonolithicSparse)
            {
                throw new NotImplementedException("Only MonolithicSparse, Vmfs and VmfsSparse disks implemented");
            }

            List <DiskImageFileSpecification> fileSpecs = new List <DiskImageFileSpecification>();

            Geometry geometry     = Geometry ?? DiskImageFile.DefaultGeometry(Content.Length);
            Geometry biosGeometry = BiosGeometry ?? Geometry.LbaAssistedBiosGeometry(Content.Length);

            DescriptorFile baseDescriptor = DiskImageFile.CreateSimpleDiskDescriptor(geometry, biosGeometry, _diskType, _adapterType);

            if (_diskType == DiskCreateType.Vmfs)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.Vmfs, baseName + "-flat.vmdk", 0);
                baseDescriptor.Extents.Add(extent);

                MemoryStream ms = new MemoryStream();
                baseDescriptor.Write(ms);

                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new PassthroughStreamBuilder(ms)));
                fileSpecs.Add(new DiskImageFileSpecification(baseName + "-flat.vmdk", new PassthroughStreamBuilder(Content)));
            }
            else if (_diskType == DiskCreateType.VmfsSparse)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.VmfsSparse, baseName + "-sparse.vmdk", 0);
                baseDescriptor.Extents.Add(extent);

                MemoryStream ms = new MemoryStream();
                baseDescriptor.Write(ms);

                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new PassthroughStreamBuilder(ms)));
                fileSpecs.Add(new DiskImageFileSpecification(baseName + "-sparse.vmdk", new VmfsSparseExtentBuilder(Content)));
            }
            else if (_diskType == DiskCreateType.MonolithicSparse)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.Sparse, baseName + ".vmdk", 0);
                baseDescriptor.Extents.Add(extent);
                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new MonolithicSparseExtentBuilder(Content, baseDescriptor)));
            }

            return(fileSpecs.ToArray());
        }
Ejemplo n.º 5
0
        private SparseStream OpenExtent(ExtentDescriptor extent, long extentStart, SparseStream parent,
                                        Ownership ownsParent)
        {
            FileAccess access = FileAccess.Read;
            FileShare  share  = FileShare.Read;

            if (extent.Access == ExtentAccess.ReadWrite && _access != FileAccess.Read)
            {
                access = FileAccess.ReadWrite;
                share  = FileShare.None;
            }

            if (extent.Type != ExtentType.Sparse && extent.Type != ExtentType.VmfsSparse)
            {
                if (ownsParent == Ownership.Dispose && parent != null)
                {
                    parent.Dispose();
                }
            }

            switch (extent.Type)
            {
            case ExtentType.Flat:
            case ExtentType.Vmfs:
                return(SparseStream.FromStream(
                           _fileLocator.Open(extent.FileName, FileMode.Open, access, share),
                           Ownership.Dispose));

            case ExtentType.Zero:
                return(new ZeroStream(extent.SizeInSectors * Sizes.Sector));

            case ExtentType.Sparse:
                return(new HostedSparseExtentStream(
                           _fileLocator.Open(extent.FileName, FileMode.Open, access, share),
                           Ownership.Dispose,
                           extentStart,
                           parent,
                           ownsParent));

            case ExtentType.VmfsSparse:
                return(new ServerSparseExtentStream(
                           _fileLocator.Open(extent.FileName, FileMode.Open, access, share),
                           Ownership.Dispose,
                           extentStart,
                           parent,
                           ownsParent));

            default:
                throw new NotSupportedException();
            }
        }
Ejemplo n.º 6
0
        private void Load(Stream source)
        {
            if (source.Length - source.Position > MaxSize)
            {
                throw new IOException(string.Format(CultureInfo.InvariantCulture,
                                                    "Invalid VMDK descriptor file, more than {0} bytes in length", MaxSize));
            }

            StreamReader reader = new StreamReader(source);
            string       line   = reader.ReadLine();

            while (line != null)
            {
                line = line.Trim('\0');

                int commentPos = line.IndexOf('#');
                if (commentPos >= 0)
                {
                    line = line.Substring(0, commentPos);
                }

                if (line.Length > 0)
                {
                    if (line.StartsWith("RW", StringComparison.Ordinal) ||
                        line.StartsWith("RDONLY", StringComparison.Ordinal) ||
                        line.StartsWith("NOACCESS", StringComparison.Ordinal))
                    {
                        Extents.Add(ExtentDescriptor.Parse(line));
                    }
                    else
                    {
                        DescriptorFileEntry entry = DescriptorFileEntry.Parse(line);
                        if (entry.Key.StartsWith("ddb.", StringComparison.Ordinal))
                        {
                            _diskDataBase.Add(entry);
                        }
                        else
                        {
                            _header.Add(entry);
                        }
                    }
                }

                line = reader.ReadLine();
            }
        }
Ejemplo n.º 7
0
        public static ExtentDescriptor Parse(string descriptor)
        {
            string[] elems = SplitQuotedString(descriptor);
            if (elems.Length < 4)
            {
                throw new IOException(string.Format(CultureInfo.InvariantCulture, "Invalid extent descriptor: {0}", descriptor));
            }

            ExtentDescriptor result = new ExtentDescriptor();

            result._access        = ParseAccess(elems[0]);
            result._sizeInSectors = long.Parse(elems[1], CultureInfo.InvariantCulture);
            result._type          = ParseType(elems[2]);
            result._fileName      = elems[3].Trim('\"');
            if (elems.Length > 4)
            {
                result._offset = long.Parse(elems[4], CultureInfo.InvariantCulture);
            }

            return(result);
        }
Ejemplo n.º 8
0
        private SparseStream OpenExtent(ExtentDescriptor extent, long extentStart, SparseStream parent, Ownership ownsParent)
        {
            FileAccess access = FileAccess.Read;
            FileShare share = FileShare.Read;
            if(extent.Access == ExtentAccess.ReadWrite && _access != FileAccess.Read)
            {
                access = FileAccess.ReadWrite;
                share = FileShare.None;
            }

            if (extent.Type != ExtentType.Sparse && extent.Type != ExtentType.VmfsSparse)
            {
                if (ownsParent == Ownership.Dispose && parent != null)
                {
                    parent.Dispose();
                }
            }

            switch (extent.Type)
            {
                case ExtentType.Flat:
                case ExtentType.Vmfs:
                    return SparseStream.FromStream(
                        _fileLocator.Open(extent.FileName, FileMode.Open, access, share),
                        Ownership.Dispose);

                case ExtentType.Zero:
                    return new ZeroStream(extent.SizeInSectors * Utilities.SectorSize);

                case ExtentType.Sparse:
                    return new HostedSparseExtentStream(
                        _fileLocator.Open(extent.FileName, FileMode.Open, access, share),
                        Ownership.Dispose,
                        extentStart,
                        parent,
                        ownsParent);

                case ExtentType.VmfsSparse:
                    return new ServerSparseExtentStream(
                        _fileLocator.Open(extent.FileName, FileMode.Open, access, share),
                        Ownership.Dispose,
                        extentStart,
                        parent,
                        ownsParent);

                default:
                    throw new NotSupportedException();
            }
        }
Ejemplo n.º 9
0
        private static DiskImageFile DoInitialize(FileLocator fileLocator, string file, long capacity, DiskCreateType type, DescriptorFile baseDescriptor)
        {
            if (type == DiskCreateType.MonolithicSparse)
            {
                // MonolithicSparse is a special case, the descriptor is embedded in the file itself...
                using (Stream fs = fileLocator.Open(file, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    long descriptorStart;
                    CreateExtent(fs, capacity, ExtentType.Sparse, 10 * Sizes.OneKiB, out descriptorStart);

                    ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, capacity / Sizes.Sector, ExtentType.Sparse, file, 0);
                    fs.Position = descriptorStart * Sizes.Sector;
                    baseDescriptor.Extents.Add(extent);
                    baseDescriptor.Write(fs);
                }
            }
            else
            {
                ExtentType extentType = CreateTypeToExtentType(type);
                long totalSize = 0;
                List<ExtentDescriptor> extents = new List<ExtentDescriptor>();
                if (type == DiskCreateType.MonolithicFlat || type == DiskCreateType.VmfsSparse || type == DiskCreateType.Vmfs)
                {
                    string adornment = "flat";
                    if(type == DiskCreateType.VmfsSparse)
                    {
                        adornment = string.IsNullOrEmpty(baseDescriptor.ParentFileNameHint) ? "sparse" : "delta";
                    }

                    string fileName = AdornFileName(file, adornment);

                    using(Stream fs = fileLocator.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                    {
                        CreateExtent(fs, capacity, extentType);
                        extents.Add(new ExtentDescriptor(ExtentAccess.ReadWrite, capacity / Sizes.Sector, extentType, fileName, 0));
                        totalSize = capacity;
                    }
                }
                else if (type == DiskCreateType.TwoGbMaxExtentFlat || type == DiskCreateType.TwoGbMaxExtentSparse)
                {
                    int i = 1;
                    while (totalSize < capacity)
                    {
                        string adornment;
                        if (type == DiskCreateType.TwoGbMaxExtentSparse)
                        {
                            adornment = string.Format(CultureInfo.InvariantCulture, "s{0:x3}", i);
                        }
                        else
                        {
                            adornment = string.Format(CultureInfo.InvariantCulture, "{0:x6}", i);
                        }

                        string fileName = AdornFileName(file, adornment);

                        using (Stream fs = fileLocator.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                        {
                            long extentSize = Math.Min(2 * Sizes.OneGiB - Sizes.OneMiB, capacity - totalSize);
                            CreateExtent(fs, extentSize, extentType);
                            extents.Add(new ExtentDescriptor(ExtentAccess.ReadWrite, extentSize / Sizes.Sector, extentType, fileName, 0));
                            totalSize += extentSize;
                        }

                        ++i;
                    }
                }
                else
                {
                    throw new NotSupportedException("Creating disks of this type is not supported");
                }

                using (Stream fs = fileLocator.Open(file, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    baseDescriptor.Extents.AddRange(extents);
                    baseDescriptor.Write(fs);
                }
            }

            return new DiskImageFile(fileLocator, file, FileAccess.ReadWrite);
        }
Ejemplo n.º 10
0
 public DiskExtent(ExtentDescriptor descriptor, long diskOffset, Stream monolithicStream)
 {
     _descriptor       = descriptor;
     _diskOffset       = diskOffset;
     _monolithicStream = monolithicStream;
 }
Ejemplo n.º 11
0
 public DiskExtent(ExtentDescriptor descriptor, long diskOffset, Stream monolithicStream)
 {
     _descriptor = descriptor;
     _diskOffset = diskOffset;
     _monolithicStream = monolithicStream;
 }
Ejemplo n.º 12
0
        private static DiskImageFile DoInitialize(FileLocator fileLocator, string file, long capacity, DiskCreateType type, DescriptorFile baseDescriptor)
        {
            if (type == DiskCreateType.MonolithicSparse)
            {
                // MonolithicSparse is a special case, the descriptor is embedded in the file itself...
                using (Stream fs = fileLocator.Open(file, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    long descriptorStart;
                    CreateExtent(fs, capacity, ExtentType.Sparse, 10 * Sizes.OneKiB, out descriptorStart);

                    ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, capacity / Sizes.Sector, ExtentType.Sparse, file, 0);
                    fs.Position = descriptorStart * Sizes.Sector;
                    baseDescriptor.Extents.Add(extent);
                    baseDescriptor.Write(fs);
                }
            }
            else
            {
                ExtentType extentType           = CreateTypeToExtentType(type);
                long       totalSize            = 0;
                List <ExtentDescriptor> extents = new List <ExtentDescriptor>();
                if (type == DiskCreateType.MonolithicFlat || type == DiskCreateType.VmfsSparse || type == DiskCreateType.Vmfs)
                {
                    string adornment = "flat";
                    if (type == DiskCreateType.VmfsSparse)
                    {
                        adornment = string.IsNullOrEmpty(baseDescriptor.ParentFileNameHint) ? "sparse" : "delta";
                    }

                    string fileName = AdornFileName(file, adornment);

                    using (Stream fs = fileLocator.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                    {
                        CreateExtent(fs, capacity, extentType);
                        extents.Add(new ExtentDescriptor(ExtentAccess.ReadWrite, capacity / Sizes.Sector, extentType, fileName, 0));
                        totalSize = capacity;
                    }
                }
                else if (type == DiskCreateType.TwoGbMaxExtentFlat || type == DiskCreateType.TwoGbMaxExtentSparse)
                {
                    int i = 1;
                    while (totalSize < capacity)
                    {
                        string adornment;
                        if (type == DiskCreateType.TwoGbMaxExtentSparse)
                        {
                            adornment = string.Format(CultureInfo.InvariantCulture, "s{0:x3}", i);
                        }
                        else
                        {
                            adornment = string.Format(CultureInfo.InvariantCulture, "{0:x6}", i);
                        }

                        string fileName = AdornFileName(file, adornment);

                        using (Stream fs = fileLocator.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                        {
                            long extentSize = Math.Min(2 * Sizes.OneGiB - Sizes.OneMiB, capacity - totalSize);
                            CreateExtent(fs, extentSize, extentType);
                            extents.Add(new ExtentDescriptor(ExtentAccess.ReadWrite, extentSize / Sizes.Sector, extentType, fileName, 0));
                            totalSize += extentSize;
                        }

                        ++i;
                    }
                }
                else
                {
                    throw new NotSupportedException("Creating disks of this type is not supported");
                }

                using (Stream fs = fileLocator.Open(file, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    baseDescriptor.Extents.AddRange(extents);
                    baseDescriptor.Write(fs);
                }
            }

            return(new DiskImageFile(fileLocator, file, FileAccess.ReadWrite));
        }
Ejemplo n.º 13
0
        public static ExtentDescriptor Parse(string descriptor)
        {
            string[] elems = SplitQuotedString(descriptor);
            if (elems.Length < 4)
            {
                throw new IOException(string.Format(CultureInfo.InvariantCulture, "Invalid extent descriptor: {0}", descriptor));
            }

            ExtentDescriptor result = new ExtentDescriptor();

            result._access = ParseAccess(elems[0]);
            result._sizeInSectors = long.Parse(elems[1], CultureInfo.InvariantCulture);
            result._type = ParseType(elems[2]);
            result._fileName = elems[3].Trim('\"');
            if (elems.Length > 4)
            {
                result._offset = long.Parse(elems[4], CultureInfo.InvariantCulture);
            }

            return result;
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Initiates the build process.
        /// </summary>
        /// <param name="baseName">The base name for the VMDK, for example 'foo' to create 'foo.vmdk'.</param>
        /// <returns>A set of one or more logical files that constitute the VMDK.  The first file is
        /// the 'primary' file that is normally attached to VMs.</returns>
        public override DiskImageFileSpecification[] Build(string baseName)
        {
            if (string.IsNullOrEmpty(baseName))
            {
                throw new ArgumentException("Invalid base file name", "baseName");
            }

            if (Content == null)
            {
                throw new InvalidOperationException("No content stream specified");
            }

            if (_diskType != DiskCreateType.Vmfs && _diskType != DiskCreateType.VmfsSparse && _diskType != DiskCreateType.MonolithicSparse)
            {
                throw new NotImplementedException("Only MonolithicSparse, Vmfs and VmfsSparse disks implemented");
            }

            List<DiskImageFileSpecification> fileSpecs = new List<DiskImageFileSpecification>();

            Geometry geometry = Geometry ?? DiskImageFile.DefaultGeometry(Content.Length);
            Geometry biosGeometry = BiosGeometry ?? Geometry.LbaAssistedBiosGeometry(Content.Length);

            DescriptorFile baseDescriptor = DiskImageFile.CreateSimpleDiskDescriptor(geometry, biosGeometry, _diskType, _adapterType);

            if (_diskType == DiskCreateType.Vmfs)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.Vmfs, baseName + "-flat.vmdk", 0);
                baseDescriptor.Extents.Add(extent);

                MemoryStream ms = new MemoryStream();
                baseDescriptor.Write(ms);

                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new PassthroughStreamBuilder(ms)));
                fileSpecs.Add(new DiskImageFileSpecification(baseName + "-flat.vmdk", new PassthroughStreamBuilder(Content)));
            }
            else if (_diskType == DiskCreateType.VmfsSparse)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.VmfsSparse, baseName + "-sparse.vmdk", 0);
                baseDescriptor.Extents.Add(extent);

                MemoryStream ms = new MemoryStream();
                baseDescriptor.Write(ms);

                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new PassthroughStreamBuilder(ms)));
                fileSpecs.Add(new DiskImageFileSpecification(baseName + "-sparse.vmdk", new VmfsSparseExtentBuilder(Content)));
            }
            else if (_diskType == DiskCreateType.MonolithicSparse)
            {
                ExtentDescriptor extent = new ExtentDescriptor(ExtentAccess.ReadWrite, Content.Length / 512, ExtentType.Sparse, baseName + ".vmdk", 0);
                baseDescriptor.Extents.Add(extent);
                fileSpecs.Add(new DiskImageFileSpecification(baseName + ".vmdk", new MonolithicSparseExtentBuilder(Content, baseDescriptor)));
            }

            return fileSpecs.ToArray();
        }