This project is read-only.

Writing to SparseStream from logical volume - Xva file

Oct 20, 2010 at 1:41 AM

Hi all (and Ken),

First off, like everyone else, I would like to say how handy this tool is and what a great job you have done on it.

I am trying to read a virtual disk (from a .xva file), identify a particular point in it, and modify the disk, and write it back. Everything is going well until I try and modify the disk's contents back to the SparseStream that I have been using to read the disk. The SparseStream is obtained from the disk's logical volume (not sure if that could cause the issue). I would bet the solution is right under my noes and im staring through it into space... The SparseStream's property of CanWrite is false, and cannot be set to true explicitly, so Im not sure if I am attacking this the correct way . Please take a look and let me know. All constructive help is appreciated.


I have: 

  FileStream fstream = File.Open(xvaFilePath,System.IO.FileMode.Open,FileAccess.ReadWrite);
            long startPosition = 0, endPosition = 0;
            bool startPositionSet = false;

            VirtualMachine vm = new VirtualMachine(fstream);         
            VolumeManager volumeManager = new VolumeManager();
            VirtualMachineBuilder vmBuilder = new VirtualMachineBuilder();

            Console.WriteLine("Starting time: " + DateTime.Now);

            int count = 0;
            foreach (Disk disk in vm.Disks)
                disk.Content.Position = 0;
            Console.WriteLine("Added {0} disk(s) to the volume manager\n", count);                       

            foreach (LogicalVolumeInfo logicalVolume in volumeManager.GetLogicalVolumes())

                byte[] buf = null;
                SparseStream sparseStream = logicalVolume.Open();                
                for (int i = 0; i < logicalVolume.BiosGeometry.TotalSectors; i++)

	            //READING DISK
                    buf = new byte[logicalVolume.BiosGeometry.BytesPerSector];
                    sparseStream.Read(buf, 0, logicalVolume.BiosGeometry.BytesPerSector);                                                

                    if (/*we found what were looking for*/)
			//gather information                                           

                if (/*we found what we were looking for above*/)
                    byte[] tarGz = File.ReadAllBytes(@"otherData");
                    //set start position that was found earlier
                    sparseStream.Position = startPosition;

                    //write new tar.gz
                    sparseStream.Write(tarGz, 0, tarGz.Length);  //WILL NOT WRITE HERE - sparseStream.CanWrite is false.

Oct 22, 2010 at 2:39 PM

After looking more carefully at the docs I see that XVA does not support modifying the disc at this point. Is this feature coming sometime soon?



Oct 23, 2010 at 8:28 PM

Hi ZeroTouch,

It's not really possible to insert / replace data into the middle of a compressed stream, so it's unlikely this support can be provided any time soon.

Not sure if it applies to what you're doing, but it might be work to export the VMs as OVF, rather than XVA?  You may have more luck with OVF because, although DiscUtils has no explicit support for OVF, IIRC, OVF uses VHD/VMDK/etc to actually store the disk image.




Oct 29, 2010 at 6:52 PM

Hi Ken,

Thanks for your response.

Yes, I ended up going along the lines that you were saying and modifying a VHD, instead of an XVA, with your utility. My VM contains multiple (2) VHD disks. I saw an example to convert the VM type (say from VHD to XVA) but from what I could recall it was limited to 1 disk. Am I mistaken? If so could you provide a quick reference as to which API's would be best suitable for this task.



Oct 29, 2010 at 6:59 PM

More specifically,


The VirtualDiskConvert Project was what I was referring to as the example. The segment:


using (VirtualDisk inDisk = VirtualDisk.OpenDisk(_inFile.Value, FileAccess.Read, UserName, Password))
            using (VirtualDisk outDisk = VirtualDisk.CreateDisk(OutputDiskType, OutputDiskVariant, _outFile.Value, inDisk.Capacity, inDisk.Geometry, UserName, Password, null))
                if (outDisk.Capacity < inDisk.Capacity)
                    Console.WriteLine("ERROR: The output disk is smaller than the input disk, conversion aborted");

                if (_wipe.IsPresent)
                    Pump(inDisk.Content, outDisk.Content);
                    SparseStream.Pump(inDisk.Content, outDisk.Content);

Seems to allow the copying of 1 disk to another. Since XVA can contain multiple disks, is it possible to pump multiple disks to another (XVA) disk?


Thanks again

Oct 29, 2010 at 10:08 PM

Again, as time goes on I seemed to find my own answer. I am able to add multiple disks (from a SparseStream) to a DiscUtils.XVA.VirtualMachienBuilder. 


Sorry for the brain lapse. Tgif ;-)