|
From: <fd...@us...> - 2007-03-19 00:35:35
|
Revision: 3141
http://jnode.svn.sourceforge.net/jnode/?rev=3141&view=rev
Author: fduminy
Date: 2007-03-18 12:26:26 -0700 (Sun, 18 Mar 2007)
Log Message:
-----------
vmware disk read/write access : alpha version
Added Paths:
-----------
trunk/distr/src/apps/org/jnode/apps/vmware/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/extent/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/extent/Extent.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/simple/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/simple/SimpleExtentFactory.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTable.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/GrainTable.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestVMWareDisk.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/Utils.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/disks/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/disks/others/
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/extent/Extent.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/extent/Extent.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/extent/Extent.java 2007-03-18 19:26:26 UTC (rev 3141)
@@ -0,0 +1,104 @@
+package org.jnode.apps.vmware.disk.extent;
+
+import java.io.File;
+
+import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.ExtentDeclaration;
+import org.jnode.apps.vmware.disk.IOUtils;
+import org.jnode.apps.vmware.disk.descriptor.Descriptor;
+import org.jnode.apps.vmware.disk.handler.sparse.SparseExtentFactory;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class Extent {
+ private static final Logger LOG = Logger.getLogger(Extent.class);
+
+ private Descriptor descriptor;
+
+ final private Access access;
+ final private long sizeInSectors; // a sector is 512 bytes
+ final private ExtentType extentType;
+ final private String fileName; // relative to the location of the descriptor
+ final private File file;
+ final private long offset;
+
+ public Extent(Descriptor descriptor, ExtentDeclaration extentDecl)
+ {
+ this.descriptor = descriptor;
+ this.access = extentDecl.getAccess();
+ this.sizeInSectors = extentDecl.getSizeInSectors();
+ this.extentType = extentDecl.getExtentType();
+ this.fileName = extentDecl.getFileName();
+ this.file = extentDecl.getExtentFile();
+ this.offset = extentDecl.getOffset();
+
+ LOG.debug("created extent for file "+file.getAbsolutePath()+
+ " offset="+offset+" fileSize="+file.length());
+ }
+
+ public Access getAccess() {
+ return access;
+ }
+
+ public long getSizeInSectors() {
+ return sizeInSectors;
+ }
+
+ public ExtentType getExtentType() {
+ return extentType;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public long getOffset() {
+ return offset;
+ }
+
+ final public Descriptor getDescriptor() {
+ return descriptor;
+ }
+
+ public void setDescriptor(Descriptor descriptor) {
+ if(this.descriptor != null)
+ {
+ throw new IllegalStateException("descriptor already assigned");
+ }
+
+ this.descriptor = descriptor;
+ }
+
+
+
+ public File getFile() {
+ return file;
+ }
+
+ @Override
+ public String toString() {
+ return "Extent["+fileName+"]";
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if(!(obj instanceof Extent))
+ {
+ return false;
+ }
+
+ Extent e = (Extent) obj;
+
+ return this.access.equals(e.access) &&
+ (this.sizeInSectors == e.sizeInSectors) &&
+ this.extentType.equals(e.extentType) &&
+ this.fileName.equals(e.fileName) &&
+ this.file.equals(e.file) &&
+ (this.offset == e.offset);
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/simple/SimpleExtentFactory.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/simple/SimpleExtentFactory.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/simple/SimpleExtentFactory.java 2007-03-18 19:26:26 UTC (rev 3141)
@@ -0,0 +1,49 @@
+package org.jnode.apps.vmware.disk.handler.simple;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+
+import org.jnode.apps.vmware.disk.ExtentDeclaration;
+import org.jnode.apps.vmware.disk.descriptor.Descriptor;
+import org.jnode.apps.vmware.disk.extent.Extent;
+import org.jnode.apps.vmware.disk.handler.ExtentFactory;
+import org.jnode.apps.vmware.disk.handler.FileDescriptor;
+import org.jnode.apps.vmware.disk.handler.IOHandler;
+import org.jnode.apps.vmware.disk.handler.UnsupportedFormatException;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class SimpleExtentFactory extends ExtentFactory
+{
+ protected FileDescriptor createFileDescriptor(File file,
+ RandomAccessFile raf, ByteBuffer bb,
+ boolean isMain)
+ throws IOException, UnsupportedFormatException
+ {
+ Descriptor descriptor = READER.read(file, bb, this);
+ return new FileDescriptor(descriptor, raf, this);
+ }
+
+ public Extent createMainExtent(Descriptor desc, ExtentDeclaration extentDecl)
+ {
+ return new Extent(desc, extentDecl);
+ }
+
+ public Extent createExtent(FileDescriptor fileDescriptor, ExtentDeclaration extentDecl)
+ throws IOException, UnsupportedFormatException
+ {
+ Descriptor desc = (fileDescriptor == null) ? null :
+ fileDescriptor.getDescriptor();
+ return createMainExtent(desc, extentDecl);
+ }
+
+ public IOHandler createIOHandler(FileDescriptor fileDescriptor) throws IOException, UnsupportedFormatException {
+ return new SimpleIOHandler(fileDescriptor);
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTable.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTable.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTable.java 2007-03-18 19:26:26 UTC (rev 3141)
@@ -0,0 +1,52 @@
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class AllocationTable {
+ private final GrainDirectory grainDirectory;
+ private final GrainTable[] grainTables;
+
+ public AllocationTable(RandomAccessFile raf, SparseExtentHeader header)
+ throws IOException
+ {
+ long nbGrains = header.getCapacity() / header.getGrainSize();
+ int nbGrainTables = (int) (nbGrains / header.getNumGTEsPerGT());
+
+ grainDirectory = new GrainDirectory(raf, nbGrainTables);
+ grainTables = new GrainTable[nbGrainTables];
+ for(int i = 0 ; i < grainTables.length ; i++)
+ {
+ grainTables[i] = new GrainTable(raf, header.getNumGTEsPerGT());
+ }
+ }
+
+ public void write(RandomAccessFile raf) throws IOException
+ {
+ grainDirectory.write(raf);
+ for(GrainTable gt : grainTables)
+ {
+ gt.write(raf);
+ }
+ }
+
+ public GrainDirectory getGrainDirectory() {
+ return grainDirectory;
+ }
+
+ public int getNbGrainTables()
+ {
+ return grainTables.length;
+ }
+
+ public GrainTable getGrainTable(int tableNum)
+ {
+ return grainTables[tableNum];
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/GrainTable.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/GrainTable.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/GrainTable.java 2007-03-18 19:26:26 UTC (rev 3141)
@@ -0,0 +1,18 @@
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class GrainTable extends EntryArray
+{
+ public GrainTable(RandomAccessFile raf, int nbEntries) throws IOException
+ {
+ super(raf, nbEntries);
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestVMWareDisk.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestVMWareDisk.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestVMWareDisk.java 2007-03-18 19:26:26 UTC (rev 3141)
@@ -0,0 +1,141 @@
+package org.jnode.apps.vmware.disk.test;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.jnode.apps.vmware.disk.VMWareDisk;
+import org.jnode.apps.vmware.disk.handler.IOHandler;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+@RunWith(value = Parameterized.class)
+public class TestVMWareDisk {
+ private static final String DISKS_PATH = "/home/fabien/data/Projets/JNode/jnode/distr/src/apps/org/jnode/apps/vmware/disk/test/disks/";
+ private static final String DISK_BASE_NAME = "Menuet32-";
+
+ private static final String RESTRICT_TO_FILE_NAME = "Menuet32-0";
+ //private static final String RESTRICT_TO_FILE_NAME = null;
+
+ @Parameters
+ public static List<File[]> data()
+ {
+ File directory = new File(DISKS_PATH);
+ File[] files = directory.listFiles(new FilenameFilter()
+ {
+ public boolean accept(File dir, String name) {
+ boolean ok = name.matches(DISK_BASE_NAME + "[0-9]*.vmdk");
+
+ if(RESTRICT_TO_FILE_NAME != null)
+ {
+ ok &= name.startsWith(RESTRICT_TO_FILE_NAME);
+ }
+
+ return ok;
+ }
+ });
+ List<File[]> list = new ArrayList<File[]>(files.length);
+ for(File f : files)
+ {
+ list.add(new File[]{f});
+ }
+
+ return list;
+ }
+
+ final private File originalDiskFile;
+ private File diskFile;
+
+ public TestVMWareDisk(File diskFile) throws IOException
+ {
+ super();
+ this.originalDiskFile = diskFile;
+ }
+
+ @Before
+ public void setUp() throws IOException
+ {
+ this.diskFile = Utils.copyDisk(originalDiskFile);
+ }
+
+ @After
+ public void tearDown() throws IOException
+ {
+ Utils.clearTempDir(true);
+ }
+
+ @Test
+ public void read() throws Exception
+ {
+ VMWareDisk disk = new VMWareDisk(diskFile);
+
+ ByteBuffer data = ByteBuffer.allocate(IOHandler.SECTOR_SIZE * 100);
+ disk.read(0, data);
+
+ Assert.assertEquals(toString()+": buffer should be filled", 0, data.remaining());
+ }
+
+ @Test
+ public void write() throws Exception
+ {
+ VMWareDisk disk = new VMWareDisk(diskFile);
+
+ ByteBuffer data = ByteBuffer.allocate(IOHandler.SECTOR_SIZE * 100);
+ disk.write(0, data);
+
+ Assert.assertEquals(toString()+": buffer should be fully copied", 0, data.remaining());
+ }
+
+ @Test
+ public void writeAndRead() throws Exception
+ {
+ VMWareDisk disk = new VMWareDisk(diskFile);
+
+ // write
+ int size = IOHandler.SECTOR_SIZE * 100;
+ ByteBuffer expectedData = ByteBuffer.allocate(size);
+ for(int i = 0 ; i < (size / 4) ; i++)
+ {
+ expectedData.putInt(i);
+ }
+ expectedData.rewind();
+ disk.write(0, expectedData);
+ disk.flush();
+
+ // read
+ VMWareDisk disk2 = new VMWareDisk(diskFile);
+ Assert.assertEquals("disk has different size", disk.getLength(), disk2.getLength());
+ Assert.assertEquals("disk has different descriptor", disk.getDescriptor(), disk2.getDescriptor());
+
+ expectedData.rewind();
+ ByteBuffer actualData = ByteBuffer.allocate(size);
+ disk2.read(0, actualData);
+ for(int i = 0 ; i < (size / 4) ; i++)
+ {
+ int actual = actualData.getInt(i);
+ int expected = expectedData.getInt();
+ Assert.assertEquals("bad data at index "+(i*4), expected, actual);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return diskFile.getName();
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/Utils.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/Utils.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/Utils.java 2007-03-18 19:26:26 UTC (rev 3141)
@@ -0,0 +1,135 @@
+package org.jnode.apps.vmware.disk.test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class Utils {
+ private static final Logger LOG = Logger.getLogger(Utils.class);
+
+ private static final String TEMP_DIR = "VMWareDisk";
+
+ public static File createTempDir() throws IOException
+ {
+ String tmpDir = System.getProperty("java.io.tmpdir");
+ File dir = new File(tmpDir, TEMP_DIR);
+ if(!dir.exists())
+ {
+ if(!dir.mkdir())
+ {
+ throw new IOException("can't create directory "+dir);
+ }
+ }
+ else
+ {
+ clearTempDir(false);
+ }
+
+ return dir;
+ }
+
+ public static void clearTempDir(boolean deleteDir) throws IOException
+ {
+ String tmpDir = System.getProperty("java.io.tmpdir");
+ File dir = new File(tmpDir, TEMP_DIR);
+ if(dir.exists())
+ {
+ for(File tmpFile : dir.listFiles())
+ {
+ LOG.debug("deleting file "+tmpFile);
+ tmpFile.delete();
+ }
+ }
+
+ if(deleteDir)
+ {
+ dir.delete();
+ }
+ }
+
+ public static File copyDisk(final File mainFile) throws IOException
+ {
+ final String name = mainFile.getName();
+ final int idx = name.lastIndexOf('.');
+ final String beginName = name.substring(0, idx);
+ final String endName = name.substring(idx);
+
+ final File parentDir = mainFile.getParentFile();
+ File[] files = parentDir.listFiles(new FilenameFilter()
+ {
+ public boolean accept(File dir, String name) {
+ boolean ok = name.startsWith(beginName) &&
+ name.endsWith(endName);
+ return ok;
+ }
+ });
+
+ File tmpDir = createTempDir();
+
+ File mainFileCopy = null;
+ for(File file : files)
+ {
+ File f = copyFile(file, tmpDir);
+ if(file.getName().equals(mainFile.getName()))
+ {
+ mainFileCopy = f;
+ }
+ }
+
+ return mainFileCopy;
+ }
+
+ public static File copyFile(File file, File dir) throws IOException
+ {
+ LOG.debug("copying file "+file.getName()+" to "+dir.getName());
+ FileInputStream fis = null;
+ FileOutputStream fos = null;
+ File outFile = null;
+
+ try
+ {
+ fis = new FileInputStream(file);
+ FileChannel inCh = fis.getChannel();
+
+ outFile = new File(dir, file.getName());
+ fos = new FileOutputStream(outFile);
+ FileChannel outCh = fos.getChannel();
+
+ outCh.transferFrom(inCh, 0, inCh.size());
+
+ return outFile;
+ }
+ catch(IOException ioe)
+ {
+ ioe.printStackTrace();
+ throw ioe;
+ }
+ finally
+ {
+ try {
+ if(fos != null)
+ {
+ fos.close();
+ }
+ }
+ finally
+ {
+ if(fis != null)
+ {
+ fis.close();
+ }
+ }
+ }
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|