From affa2815bdf39e4fdbc8091224fbcc2d91db678e Mon Sep 17 00:00:00 2001 From: Victor Mocanu Date: Wed, 20 Dec 2017 11:29:49 +0100 Subject: [VBox] improved the .vdi file test s.t. it now checks the prefix and suffix of the header and accepts more .vdi versions --- src/main/java/org/openslx/util/vm/DiskImage.java | 107 ++++++++++++++--------- 1 file changed, 65 insertions(+), 42 deletions(-) (limited to 'src/main/java/org/openslx/util/vm/DiskImage.java') diff --git a/src/main/java/org/openslx/util/vm/DiskImage.java b/src/main/java/org/openslx/util/vm/DiskImage.java index 5f6d67d..5b29d55 100644 --- a/src/main/java/org/openslx/util/vm/DiskImage.java +++ b/src/main/java/org/openslx/util/vm/DiskImage.java @@ -5,21 +5,26 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; +import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.util.Util; - public class DiskImage { /** * Big endian representation of the 4 bytes 'KDMV' */ private static final int VMDK_MAGIC = 0x4b444d56; - private static final String VDI_MAGIC = "<<< Oracle VM VirtualBox Disk Image >>>"; + private static final String VDI_PREFIX = "<<< "; + private static final String VDI_SUFFIX = "Disk Image >>>"; + + private static final Logger LOGGER = Logger.getLogger( VboxMetaData.class ); public enum ImageFormat { - VMDK( "vmdk" ), QCOW2( "qcow2" ), VDI( "vdi" ); + VMDK( "vmdk" ), + QCOW2( "qcow2" ), + VDI( "vdi" ); public final String extension; @@ -54,58 +59,77 @@ public class DiskImage public final String subFormat; public final int hwVersion; - public ImageFormat getImageFormat() { + public ImageFormat getImageFormat() + { return format; } - - public DiskImage( File disk ) throws FileNotFoundException, IOException, - UnknownImageFormatException + + public DiskImage( File disk ) throws FileNotFoundException, IOException, UnknownImageFormatException { try ( RandomAccessFile file = new RandomAccessFile( disk, "r" ) ) { // vmdk if ( file.readInt() == VMDK_MAGIC ) { - file.seek( 512 ); - byte[] buffer = new byte[ 2048 ]; - file.readFully( buffer ); - VmwareConfig config; + file.seek( 512 ); + byte[] buffer = new byte[ 2048 ]; + file.readFully( buffer ); + VmwareConfig config; try { config = new VmwareConfig( buffer, findNull( buffer ) ); } catch ( UnsupportedVirtualizerFormatException e ) { config = null; } - if (config != null) { - subFormat = config.get( "createType" ); - String parent = config.get( "parentCID" ); - this.isStandalone = isStandaloneCreateType( subFormat, parent ); - this.isCompressed = subFormat != null - && subFormat.equalsIgnoreCase( "streamOptimized" ); - this.isSnapshot = parent != null - && !parent.equalsIgnoreCase( "ffffffff" ); - this.format = ImageFormat.VMDK; - String hwv = config.get( "ddb.virtualHWVersion" ); - if (hwv == null ) { - this.hwVersion = 10; - } else { - this.hwVersion = Util.parseInt( hwv, 10 ); - } - return; + if ( config != null ) { + subFormat = config.get( "createType" ); + String parent = config.get( "parentCID" ); + this.isStandalone = isStandaloneCreateType( subFormat, parent ); + this.isCompressed = subFormat != null && subFormat.equalsIgnoreCase( "streamOptimized" ); + this.isSnapshot = parent != null && !parent.equalsIgnoreCase( "ffffffff" ); + this.format = ImageFormat.VMDK; + String hwv = config.get( "ddb.virtualHWVersion" ); + if ( hwv == null ) { + this.hwVersion = 10; + } else { + this.hwVersion = Util.parseInt( hwv, 10 ); + } + return; } } // vdi file.seek( 0 ); - byte[] buffer = new byte[ VDI_MAGIC.length() ]; - file.readFully( buffer ); - String string = new String( buffer ); - if ( VDI_MAGIC.equals( string ) ) - { - this.isStandalone = true; - this.isCompressed = false; - this.isSnapshot = false; - this.format = ImageFormat.VDI; - this.subFormat = ""; - this.hwVersion = 0; - return; - + byte[] prefixBuffer = new byte[ VDI_PREFIX.length() ]; + file.readFully( prefixBuffer ); + String prefixString = new String( prefixBuffer ); + if ( VDI_PREFIX.equals( prefixString ) ) { + + byte[] localBuffer = new byte[ 1 ]; + byte[] suffixBuffer = new byte[ VDI_SUFFIX.length() - 1 ]; + // 30 in this case would be the remaining length of the vdi header + // the longest string to date would be "<<< QEMU VM Virtual Disk Image >>>" + // if the loop doesn't find the first letter of the VID_SUFFIX then we have another format on our hands and should throw exception + for ( int i = 0; i < 30; i++ ) { + file.readFully( localBuffer ); + String localString = new String( localBuffer ); + + LOGGER.debug( localString ); + if ( !localString.equals( VDI_SUFFIX.substring( 0, 1 ) ) ) { + continue; + } + file.readFully( suffixBuffer ); + String suffixString = new String( suffixBuffer ); + if ( suffixString.equals( VDI_SUFFIX.substring( 1 ) ) ) { + // TODO still don't know where they are found in a .vdi file + this.isStandalone = true; + this.isCompressed = false; + this.isSnapshot = false; + this.format = ImageFormat.VDI; + this.subFormat = ""; + this.hwVersion = 0; + return; + } else { + // this will ensure the search doesn't stop at the first D we find + file.seek( i + VDI_PREFIX.length() + 1 ); + } + } } } throw new UnknownImageFormatException(); @@ -126,8 +150,7 @@ public class DiskImage return false; if ( parent != null && !parent.equalsIgnoreCase( "ffffffff" ) ) return false; - return type.equalsIgnoreCase( "streamOptimized" ) - || type.equalsIgnoreCase( "monolithicSparse" ); + return type.equalsIgnoreCase( "streamOptimized" ) || type.equalsIgnoreCase( "monolithicSparse" ); } public static class UnknownImageFormatException extends Exception -- cgit v1.2.3-55-g7522