|
From: <fd...@us...> - 2007-03-31 16:18:52
|
Revision: 3146
http://jnode.svn.sourceforge.net/jnode/?rev=3146&view=rev
Author: fduminy
Date: 2007-03-31 09:18:50 -0700 (Sat, 31 Mar 2007)
Log Message:
-----------
new version with some refactoring, more tests ...
- working disk type detection
- working read/write of headers only
- read/write of sectors still buggy
Modified Paths:
--------------
trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/VMWareDisk.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentFactory.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentIO.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/IOHandler.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/UnsupportedFormatException.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/simple/SimpleExtentFactory.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTable.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/EntryArray.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/GrainDirectory.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/GrainTable.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtent.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentFactory.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeader.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseIOHandler.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/Utils.java
Added Paths:
-----------
trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java
Removed Paths:
-------------
trunk/distr/src/apps/org/jnode/apps/vmware/disk/DescriptorReader.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestVMWareDisk.java
Deleted: trunk/distr/src/apps/org/jnode/apps/vmware/disk/DescriptorReader.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/DescriptorReader.java 2007-03-26 20:42:13 UTC (rev 3145)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/DescriptorReader.java 2007-03-31 16:18:50 UTC (rev 3146)
@@ -1,190 +0,0 @@
-package org.jnode.apps.vmware.disk;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import org.jnode.apps.vmware.disk.IOUtils.KeyValue;
-import org.jnode.apps.vmware.disk.descriptor.AdapterType;
-import org.jnode.apps.vmware.disk.descriptor.CreateType;
-import org.jnode.apps.vmware.disk.descriptor.Descriptor;
-import org.jnode.apps.vmware.disk.descriptor.DiskDatabase;
-import org.jnode.apps.vmware.disk.descriptor.Header;
-import org.jnode.apps.vmware.disk.extent.Access;
-import org.jnode.apps.vmware.disk.extent.Extent;
-import org.jnode.apps.vmware.disk.extent.ExtentType;
-import org.jnode.apps.vmware.disk.handler.ExtentFactory;
-import org.jnode.apps.vmware.disk.handler.FileDescriptor;
-import org.jnode.apps.vmware.disk.handler.UnsupportedFormatException;
-import org.jnode.util.ByteBufferInputStream;
-
-/**
- * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
- *
- * @author Fabien DUMINY (fduminy at jnode dot org)
- *
- */
-public class DescriptorReader {
- private static final String VERSION = "version";
- private static final String CID = "CID";
- private static final String PARENT_CID = "parentCID";
- private static final String CREATE_TYPE = "createType";
-
- private static final String DDB = "ddb";
- private static final String ADAPTER_TYPE = "ddb.adapterType";
- private static final String SECTORS = "ddb.geometry.sectors";
- private static final String HEADS = "ddb.geometry.heads";
- private static final String CYLINDERS = "ddb.geometry.cylinders";
-
- //protected
-
- public Descriptor read(File file, ByteBuffer bb,
- ExtentFactory factory)
- throws IOException, UnsupportedFormatException
- {
- BufferedReader br = null;
-
- try {
-
- Reader r = new InputStreamReader(new ByteBufferInputStream(bb));
- br = new BufferedReader(r);
-
- Header header = readHeader(br);
-
- List<String> extentDecls = new ArrayList<String>();
- String lastLine = readExtents(br, factory, extentDecls);
- DiskDatabase diskDatabase = readDiskDatabase(br, lastLine);
-
- List<Extent> extents = new ArrayList<Extent>();
- boolean isMain = true;
- ExtentDeclaration mainExtentDecl = null;
- for(String decl : extentDecls)
- {
- ExtentDeclaration extentDecl = readExtentDeclaration(decl, file);
- if(isMain)
- {
- isMain = false;
- mainExtentDecl = extentDecl;
- }
- else
- {
- Extent extent = createExtent(factory, extentDecl);
- extents.add(extent);
- }
- }
-
- Descriptor desc = new Descriptor(file, header, extents, diskDatabase);
-
- Extent mainExtent = factory.createMainExtent(desc, mainExtentDecl);
- extents.add(0, mainExtent);
-
- return desc;
- }
- finally
- {
- if(br != null)
- {
- br.close();
- }
- }
- }
-
- protected DiskDatabase readDiskDatabase(BufferedReader br, String lastLine) throws IOException
- {
- DiskDatabase ddb = new DiskDatabase();
-
- Map<String, String> values = IOUtils.readValuesMap(lastLine, br, true,
- ADAPTER_TYPE, SECTORS, HEADS, CYLINDERS);
-
- String value = values.get(ADAPTER_TYPE);
- ddb.setAdapterType(AdapterType.valueOf(value));
-
- value = values.get(SECTORS);
- ddb.setSectors(Integer.valueOf(value));
-
- value = values.get(HEADS);
- ddb.setHeads(Integer.valueOf(value));
-
- value = values.get(CYLINDERS);
- ddb.setCylinders(Integer.valueOf(value));
-
- return ddb;
- }
-
- protected String readExtents(BufferedReader br,
- ExtentFactory factory,
- List<String> extentDecls)
- throws IOException, UnsupportedFormatException
- {
- String line;
-
- while(!(line = IOUtils.readLine(br)).startsWith(DDB))
- {
- extentDecls.add(line);
- }
-
- return line;
- }
-
- protected Extent createExtent(ExtentFactory factory, ExtentDeclaration extentDecl)
- throws IOException, UnsupportedFormatException
- {
- FileDescriptor fileDescriptor = IOUtils.readFileDescriptor(
- extentDecl.getExtentFile(), false);
-
- Extent extent = factory.createExtent(fileDescriptor, extentDecl);
-
- return extent;
- }
-
- protected ExtentDeclaration readExtentDeclaration(String line, File mainFile)
- {
- StringTokenizer st = new StringTokenizer(line, " ", false);
-
- final Access access = Access.valueOf(st.nextToken());
- final long sizeInSectors = Long.valueOf(st.nextToken());
- final ExtentType extentType = ExtentType.valueOf(st.nextToken());
-
- final String fileName = IOUtils.removeQuotes(st.nextToken());
-
- long offset = 0L;
- if(st.hasMoreTokens())
- {
- offset = Long.valueOf(st.nextToken());
- }
-
- final File extentFile = IOUtils.getExtentFile(mainFile, fileName);
- final boolean isMainExtent = extentFile.getName().equals(mainFile.getName());
- return new ExtentDeclaration(access, sizeInSectors, extentType, fileName, extentFile, offset, isMainExtent);
- }
-
- protected Header readHeader(BufferedReader reader) throws IOException, UnsupportedFormatException
- {
- Header header = new Header();
-
- KeyValue keyValue = IOUtils.readValue(reader, null, VERSION, false);
- if(!"1".equals(keyValue.getValue()))
- {
- throw new UnsupportedFormatException("expected version 1 (found:"+keyValue.getValue()+")");
- }
- header.setVersion(keyValue.getValue());
-
- keyValue = IOUtils.readValue(reader, keyValue, CID, false);
- header.setContentID(Long.valueOf(keyValue.getValue(), 16));
-
- keyValue = IOUtils.readValue(reader, keyValue, PARENT_CID, false);
- header.setParentContentID(Long.parseLong(keyValue.getValue(), 16));
-
- keyValue = IOUtils.readValue(reader, keyValue, CREATE_TYPE, true);
- header.setCreateType(CreateType.valueOf(keyValue.getValue()));
-
- return header;
- }
-}
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java 2007-03-26 20:42:13 UTC (rev 3145)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java 2007-03-31 16:18:50 UTC (rev 3146)
@@ -3,13 +3,18 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
-import org.jnode.apps.vmware.disk.descriptor.AdapterType;
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;
import org.jnode.apps.vmware.disk.handler.simple.SimpleExtentFactory;
import org.jnode.apps.vmware.disk.handler.sparse.SparseExtentFactory;
@@ -21,7 +26,7 @@
*
*/
public class IOUtils {
- private static final Logger LOG = Logger.getLogger(SparseExtentFactory.class);
+ private static final Logger LOG = Logger.getLogger(IOUtils.class);
private static final String COMMENT = "#";
private static final String EQUAL = "=";
@@ -31,11 +36,15 @@
new SparseExtentFactory(),
new SimpleExtentFactory(),
};
+
+ public static final int INT_SIZE = 4;
+ public static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
public static class KeyValue
{
private String key;
private String value;
+
public String getKey() {
return key;
}
@@ -48,6 +57,20 @@
public void setValue(String value) {
this.value = value;
}
+
+ @Override
+ public String toString() {
+ return "KeyValue[key:"+key+", value:"+value+"]";
+ }
+ public void setNull() {
+ setKey(null);
+ setValue(null);
+ }
+
+ public boolean isNull()
+ {
+ return (key == null) && (value == null);
+ }
}
public static String readLine(BufferedReader reader) throws IOException
@@ -65,7 +88,7 @@
}
}
- //throw new IOException("no more lines");
+ LOG.debug("no more lines");
return null;
}
@@ -80,12 +103,20 @@
throws IOException
{
keyValue = readValue(readLine(reader), keyValue, wantedKey);
+ if(keyValue.isNull())
+ {
+ return keyValue;
+ }
if(wantedKey != null)
{
while(keyValue.getValue() == null)
{
keyValue = readValue(readLine(reader), keyValue, wantedKey);
+ if(keyValue.isNull())
+ {
+ return keyValue;
+ }
}
}
@@ -100,8 +131,7 @@
{
keyValue = (keyValue == null) ? new KeyValue() : keyValue;
- keyValue.setKey(null);
- keyValue.setValue(null);
+ keyValue.setNull();
if(line == null)
{
@@ -115,18 +145,22 @@
return keyValue;
}
+
keyValue.setKey(line.substring(0, idx).trim());
keyValue.setValue(line.substring(idx + 1).trim());
+ LOG.debug("readValue: line="+line+" idx="+idx+" -> KeyValue="+keyValue);
if((wantedKey != null) && !keyValue.getKey().equals(wantedKey))
{
+ LOG.debug("readValue: KeyValue="+keyValue);
+ LOG.fatal("************");
throw new IOException("excepted key("+wantedKey+") not found (actual:"+keyValue.getKey()+")");
}
return keyValue;
}
- public static FileDescriptor readFileDescriptor(File file, boolean isMain)
+ public static FileDescriptor readFileDescriptor(File file)
throws IOException, UnsupportedFormatException
{
FileDescriptor fileDescriptor = null;
@@ -135,7 +169,7 @@
{
try {
LOG.debug("trying with factory "+f.getClass().getName());
- FileDescriptor fd = f.createFileDescriptor(file, isMain);
+ FileDescriptor fd = f.createFileDescriptor(file);
// we have found the factory for that format
fileDescriptor = fd;
@@ -143,7 +177,7 @@
break;
} catch (UnsupportedFormatException e) {
// ignore, we will try with the next factory
- LOG.debug(f.getClass().getName()+":"+file+" not supported "+e.getMessage());
+ LOG.debug(f.getClass().getName()+":"+file+" not supported. reason: "+e.getMessage());
}
}
@@ -152,6 +186,8 @@
throw new UnsupportedFormatException("format not supported for file "+file);
}
+ LOG.info("descriptor for "+file.getName()+" is "+fileDescriptor.getClass().getName());
+
return fileDescriptor;
}
@@ -202,4 +238,70 @@
{
return (o1 == null) ? (o2 == null) : o1.equals(o2);
}
+
+ public static ByteBuffer allocate(int capacity)
+ {
+ ByteBuffer bb = ByteBuffer.allocate(capacity);
+ bb.order(BYTE_ORDER);
+ return bb;
+ }
+
+ public static ByteBuffer getSectorsByteBuffer(RandomAccessFile raf, int firstSector, int nbSectors) throws IOException
+ {
+ IOUtils.positionSector(raf.getChannel(), firstSector);
+ return IOUtils.getByteBuffer(raf, nbSectors * IOHandler.SECTOR_SIZE);
+ }
+
+ public static ByteBuffer getByteBuffer(RandomAccessFile raf, int size) throws IOException
+ {
+ FileChannel ch = raf.getChannel();
+
+// int capacity = Math.min(size, (int) (raf.length() - ch.position()));
+// if(capacity == 0)
+// {
+// throw new IOException("empty file");
+// }
+//
+ if((ch.position() + size) > ch.size())
+ {
+ //TODO fix the bug
+ LOG.fatal("getByteBuffer: FATAL: size too big. size="+size+" position="+ch.position()+" channel.size="+ch.size());
+ size = (int) (ch.size() - ch.position());
+ }
+
+ LOG.debug("getByteBuffer: pos="+ch.position()+" size="+size+" channel.size="+ch.size());
+ ByteBuffer bb = ch.map(MapMode.READ_ONLY, ch.position(), size);
+ bb.order(BYTE_ORDER);
+
+ if(LOG.isDebugEnabled())
+ {
+ LOG.debug("bb="+bb.toString()+" content="+bb.duplicate().asCharBuffer());
+ }
+
+ return bb;
+ }
+
+ public static void positionSector(FileChannel channel, long sector) throws IOException {
+ channel.position(sector * IOHandler.SECTOR_SIZE);
+ LOG.debug("positionSector(sector="+sector+") -> "+channel.position());
+ }
+
+ public static boolean isPowerOf2(long value) {
+ long val = 1;
+ if(val == value)
+ {
+ return true;
+ }
+
+ for(int i = 0 ; i < 64 ; i++)
+ {
+ val <<= 1;
+ if(val == value)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/VMWareDisk.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/VMWareDisk.java 2007-03-26 20:42:13 UTC (rev 3145)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/VMWareDisk.java 2007-03-31 16:18:50 UTC (rev 3146)
@@ -26,15 +26,18 @@
private final Descriptor descriptor;
private final IOHandler handler;
+ private final long length;
+
public VMWareDisk(File file) throws IOException, UnsupportedFormatException
{
- FileDescriptor fd = IOUtils.readFileDescriptor(file, true);
+ FileDescriptor fd = IOUtils.readFileDescriptor(file);
ExtentFactory factory = fd.getExtentFactory();
this.handler = factory.createIOHandler(fd);
this.descriptor = fd.getDescriptor();
+ this.length = handler.getNbSectors() * IOHandler.SECTOR_SIZE;
LOG.debug("handler for file "+file.getName()+" : "+handler.getClass().getName());
}
@@ -54,9 +57,7 @@
}
public long getLength() {
- DiskDatabase ddb = descriptor.getDiskDatabase();
- return ddb.getCylinders() * ddb.getHeads() * ddb.getSectors() *
- IOHandler.SECTOR_SIZE;
+ return length;
}
public Descriptor getDescriptor() {
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java 2007-03-31 16:18:50 UTC (rev 3146)
@@ -0,0 +1,197 @@
+package org.jnode.apps.vmware.disk.descriptor;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.RandomAccessFile;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel.MapMode;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+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.IOUtils.KeyValue;
+import org.jnode.apps.vmware.disk.extent.Access;
+import org.jnode.apps.vmware.disk.extent.Extent;
+import org.jnode.apps.vmware.disk.extent.ExtentType;
+import org.jnode.apps.vmware.disk.handler.ExtentFactory;
+import org.jnode.apps.vmware.disk.handler.FileDescriptor;
+import org.jnode.apps.vmware.disk.handler.UnsupportedFormatException;
+import org.jnode.apps.vmware.disk.handler.sparse.SparseExtentHeader;
+import org.jnode.util.ByteBufferInputStream;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+abstract public class DescriptorRW {
+ private static final Logger LOG = Logger.getLogger(DescriptorRW.class);
+
+ private static final String VERSION = "version";
+ private static final String CID = "CID";
+ private static final String PARENT_CID = "parentCID";
+ private static final String CREATE_TYPE = "createType";
+
+ private static final String DDB = "ddb";
+ private static final String ADAPTER_TYPE = "ddb.adapterType";
+ private static final String SECTORS = "ddb.geometry.sectors";
+ private static final String HEADS = "ddb.geometry.heads";
+ private static final String CYLINDERS = "ddb.geometry.cylinders";
+
+ public Descriptor read(File file, int firstSector, int nbSectors)
+ throws IOException, UnsupportedFormatException
+ {
+ RandomAccessFile raf = null;
+ BufferedReader br = null;
+
+ try {
+ raf = new RandomAccessFile(file, "r");
+ ByteBuffer bb = IOUtils.getSectorsByteBuffer(raf, firstSector, nbSectors);
+
+ Reader r = new InputStreamReader(new ByteBufferInputStream(bb));
+ br = new BufferedReader(r);
+
+ Header header = readHeader(br);
+
+ List<String> extentDecls = new ArrayList<String>();
+ String lastLine = readExtents(br, extentDecls);
+ DiskDatabase diskDatabase = readDiskDatabase(br, lastLine);
+
+ List<Extent> extents = new ArrayList<Extent>(extentDecls.size());
+ ExtentDeclaration mainExtentDecl = null;
+ for(String decl : extentDecls)
+ {
+ ExtentDeclaration extentDecl = readExtentDeclaration(decl, file);
+ if(extentDecl.isMainExtent())
+ {
+ mainExtentDecl = extentDecl;
+ }
+ else
+ {
+ FileDescriptor fileDescriptor = IOUtils.readFileDescriptor(
+ extentDecl.getExtentFile());
+
+ Extent extent = createExtent(fileDescriptor, extentDecl);
+ extents.add(extent);
+ }
+ }
+
+ Descriptor desc = new Descriptor(file, header, extents, diskDatabase);
+
+ Extent mainExtent = createMainExtent(desc, mainExtentDecl);
+ extents.add(0, mainExtent);
+
+ return desc;
+ }
+ finally
+ {
+ if(br != null)
+ {
+ br.close();
+ }
+
+ if(raf != null)
+ {
+ raf.close();
+ }
+ }
+ }
+
+ protected DiskDatabase readDiskDatabase(BufferedReader br, String lastLine) throws IOException
+ {
+ DiskDatabase ddb = new DiskDatabase();
+
+ Map<String, String> values = IOUtils.readValuesMap(lastLine, br, true,
+ ADAPTER_TYPE, SECTORS, HEADS, CYLINDERS);
+
+ String value = values.get(ADAPTER_TYPE);
+ ddb.setAdapterType(AdapterType.valueOf(value));
+
+ value = values.get(SECTORS);
+ ddb.setSectors(Integer.valueOf(value));
+
+ value = values.get(HEADS);
+ ddb.setHeads(Integer.valueOf(value));
+
+ value = values.get(CYLINDERS);
+ ddb.setCylinders(Integer.valueOf(value));
+
+ return ddb;
+ }
+
+ protected String readExtents(BufferedReader br,
+ List<String> extentDecls)
+ throws IOException, UnsupportedFormatException
+ {
+ String line;
+
+ while( ((line = IOUtils.readLine(br)) != null) &&
+ !line.startsWith(DDB))
+ {
+ extentDecls.add(line);
+ }
+
+ return line;
+ }
+
+ protected ExtentDeclaration readExtentDeclaration(String line, File mainFile)
+ {
+ StringTokenizer st = new StringTokenizer(line, " ", false);
+
+ final Access access = Access.valueOf(st.nextToken());
+ final long sizeInSectors = Long.valueOf(st.nextToken());
+ final ExtentType extentType = ExtentType.valueOf(st.nextToken());
+
+ final String fileName = IOUtils.removeQuotes(st.nextToken());
+
+ long offset = 0L;
+ if(st.hasMoreTokens())
+ {
+ offset = Long.valueOf(st.nextToken());
+ }
+
+ final File extentFile = IOUtils.getExtentFile(mainFile, fileName);
+ final boolean isMainExtent = extentFile.getName().equals(mainFile.getName());
+ return new ExtentDeclaration(access, sizeInSectors, extentType, fileName, extentFile, offset, isMainExtent);
+ }
+
+ protected Header readHeader(BufferedReader reader) throws IOException, UnsupportedFormatException
+ {
+ Header header = new Header();
+
+ LOG.debug("trying to read VERSION");
+ KeyValue keyValue = IOUtils.readValue(reader, null, VERSION, false);
+ if(!"1".equals(keyValue.getValue()))
+ {
+ throw new UnsupportedFormatException("expected version 1 (found:"+keyValue.getValue()+")");
+ }
+ header.setVersion(keyValue.getValue());
+
+ keyValue = IOUtils.readValue(reader, keyValue, CID, false);
+ header.setContentID(Long.valueOf(keyValue.getValue(), 16));
+
+ keyValue = IOUtils.readValue(reader, keyValue, PARENT_CID, false);
+ header.setParentContentID(Long.parseLong(keyValue.getValue(), 16));
+
+ keyValue = IOUtils.readValue(reader, keyValue, CREATE_TYPE, true);
+ header.setCreateType(CreateType.valueOf(keyValue.getValue()));
+
+ return header;
+ }
+
+ abstract protected Extent createMainExtent(Descriptor desc,
+ ExtentDeclaration mainExtentDecl) throws IOException, UnsupportedFormatException;
+
+ abstract protected Extent createExtent(FileDescriptor fileDescriptor, ExtentDeclaration extentDecl)
+ throws IOException, UnsupportedFormatException;
+
+}
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentFactory.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentFactory.java 2007-03-26 20:42:13 UTC (rev 3145)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentFactory.java 2007-03-31 16:18:50 UTC (rev 3146)
@@ -5,11 +5,13 @@
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.nio.channels.FileChannel.MapMode;
import org.apache.log4j.Logger;
-import org.jnode.apps.vmware.disk.DescriptorReader;
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.descriptor.DescriptorRW;
import org.jnode.apps.vmware.disk.extent.Extent;
import org.jnode.apps.vmware.disk.handler.sparse.SparseExtentFactory;
@@ -22,21 +24,17 @@
abstract public class ExtentFactory
{
private static final Logger LOG = Logger.getLogger(SparseExtentFactory.class);
-
- protected static final DescriptorReader READER = new DescriptorReader();
-
- public FileDescriptor createFileDescriptor(File file, boolean isMain)
+
+ public FileDescriptor createFileDescriptor(File file)
throws IOException, UnsupportedFormatException
{
RandomAccessFile raf = null;
FileDescriptor fileDescriptor = null;
- ByteBuffer bb = null;
-
+
try {
raf = new RandomAccessFile(file, "rw");
- bb = readHeaderForDiskType(raf);
- fileDescriptor = createFileDescriptor(file, raf, bb, isMain);
+ fileDescriptor = createFileDescriptor(file, raf);
}
finally
{
@@ -46,45 +44,18 @@
// been created, then close it
raf.close();
}
- else if((bb != null) && (raf != null))
- {
- // synchronize the RandomAccessFile with what
- // has been actually read in the ByteBuffer
- raf.seek(bb.position());
- }
}
return fileDescriptor;
}
- protected ByteBuffer readHeaderForDiskType(RandomAccessFile raf) throws IOException
- {
- //TODO optimise the size
- int capacity = Math.min(1024, (int) raf.length());
- if(capacity == 0)
- {
- throw new IOException("empty file");
- }
-
- ByteBuffer bb = ByteBuffer.allocate(capacity);
- bb.order(ByteOrder.LITTLE_ENDIAN);
- raf.getChannel().read(bb);
- bb.rewind();
- LOG.debug("bb="+bb.toString());
- return bb;
- }
+ abstract protected DescriptorRW getDescriptorRW();
abstract protected FileDescriptor createFileDescriptor(File file,
- RandomAccessFile raf, ByteBuffer bb,
- boolean isMain)
+ RandomAccessFile raf)
throws IOException, UnsupportedFormatException;
- abstract public Extent createExtent(FileDescriptor fileDescriptor, ExtentDeclaration extentDecl)
- throws IOException, UnsupportedFormatException;
-
- abstract public Extent createMainExtent(Descriptor desc, ExtentDeclaration extentDecl) throws IOException, UnsupportedFormatException;
-
abstract public IOHandler createIOHandler(FileDescriptor fileDescriptor)
throws IOException, UnsupportedFormatException;
}
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentIO.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentIO.java 2007-03-26 20:42:13 UTC (rev 3145)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/ExtentIO.java 2007-03-31 16:18:50 UTC (rev 3146)
@@ -6,6 +6,7 @@
import java.nio.channels.FileChannel;
import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.extent.Extent;
import org.jnode.apps.vmware.disk.handler.sparse.SparseExtentFactory;
/**
@@ -18,13 +19,15 @@
{
private static final Logger LOG = Logger.getLogger(ExtentIO.class);
- private final RandomAccessFile raf;
- private final FileChannel channel;
+ protected final RandomAccessFile raf;
+ protected final FileChannel channel;
+ protected final Extent extent;
- public ExtentIO(RandomAccessFile raf)
+ public ExtentIO(RandomAccessFile raf, Extent extent)
{
this.raf = raf;
- this.channel = raf.getChannel();
+ this.channel = raf.getChannel();
+ this.extent = extent;
}
public void read(long sector, ByteBuffer dst) throws IOException
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/IOHandler.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/IOHandler.java 2007-03-26 20:42:13 UTC (rev 3145)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/IOHandler.java 2007-03-31 16:18:50 UTC (rev 3146)
@@ -8,6 +8,7 @@
import org.apache.log4j.Logger;
import org.jnode.apps.vmware.disk.descriptor.Descriptor;
+import org.jnode.apps.vmware.disk.descriptor.DescriptorRW;
import org.jnode.apps.vmware.disk.descriptor.DiskDatabase;
import org.jnode.apps.vmware.disk.extent.Extent;
@@ -22,6 +23,9 @@
public static final int SECTOR_SIZE = 512;
+ protected static final boolean READ = true;
+ protected static final boolean WRITE = false;
+
final protected Descriptor descriptor;
final private long nbSectors;
@@ -83,9 +87,9 @@
}
}
- protected ExtentIO getExtentIO(long sector) throws IOException
+ protected ExtentIO getExtentIO(long sector, boolean mode) throws IOException
{
- Extent extent = getExtent(sector);
+ Extent extent = getExtent(sector, mode);
return getExtentIO(extent);
}
@@ -97,19 +101,24 @@
{
RandomAccessFile raf = new RandomAccessFile(extent.getFile(), "rw");
LOG.debug("length for file "+extent.getFileName()+" : "+raf.length());
- io = new ExtentIO(raf);
+ io = createExtentIO(raf, extent);
extentIOCache.put(extent, io);
}
return io;
}
- protected Extent getExtent(long sector) throws IOException
+ protected ExtentIO createExtentIO(RandomAccessFile raf, Extent extent)
{
+ return new ExtentIO(raf, extent);
+ }
+
+ protected Extent getExtent(long sector, boolean mode) throws IOException
+ {
Extent handler = null;
for(Extent extent : descriptor.getExtents())
{
- LOG.debug(extent.getFileName()+": SizeInSectors="+extent.getSizeInSectors());
+ //LOG.debug(extent.getFileName()+": SizeInSectors="+extent.getSizeInSectors());
if(sector < extent.getSizeInSectors())
{
@@ -123,18 +132,34 @@
}
public void readImpl(long sector, int nbSectors, ByteBuffer dst)
- throws IOException {
- for(int i = 0 ; i < nbSectors ; i++, sector++)
- {
- getExtentIO(sector).read(sector, dst);
- }
- }
+ throws IOException
+ {
+ LOG.debug("readImpl: sector="+sector+" nbSectors="+nbSectors+
+ " buffer.remaining="+dst.remaining());
+ for(int i = 0 ; i < nbSectors ; i++, sector++)
+ {
+ final ExtentIO io = getExtentIO(sector, READ);
+ dst.limit(dst.position() + SECTOR_SIZE);
+ io.read(sector, dst);
+ }
+ }
public void writeImpl(long sector, int nbSectors, ByteBuffer src)
- throws IOException {
- for(int i = 0 ; i < nbSectors ; i++, sector++)
- {
- getExtentIO(sector).write(sector, src);
- }
- }
+ throws IOException
+ {
+ LOG.debug("writeImpl: sector="+sector+" nbSectors="+nbSectors+
+ " buffer.remaining="+src.remaining());
+ for(int i = 0 ; i < nbSectors ; i++, sector++)
+ {
+ final ExtentIO io = getExtentIO(sector, WRITE);
+ src.limit(src.position() + SECTOR_SIZE);
+ io.write(sector, src);
+ }
+ }
+
+ public long getNbSectors() {
+ return nbSectors;
+ }
+
+
}
Modified: trunk/dist...
[truncated message content] |
|
From: <fd...@us...> - 2007-03-31 16:51:38
|
Revision: 3147
http://jnode.svn.sourceforge.net/jnode/?rev=3147&view=rev
Author: fduminy
Date: 2007-03-31 09:51:34 -0700 (Sat, 31 Mar 2007)
Log Message:
-----------
new version with some refactoring, more tests ...
- working disk type detection
- working read/write of headers only
- read/write of sectors still buggy
Added Paths:
-----------
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTableRW.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDescriptorRW.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentIO.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentRW.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/BaseTest.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestCreation.java
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTableRW.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTableRW.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTableRW.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,95 @@
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.channels.FileChannel;
+
+import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.IOUtils;
+import org.jnode.apps.vmware.disk.handler.IOHandler;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class AllocationTableRW {
+ private static final Logger LOG = Logger.getLogger(SparseExtentRW.class);
+
+ public AllocationTable read(RandomAccessFile raf, SparseExtentHeader header)
+ throws IOException
+ {
+ long nbGrains = header.getCapacity() / header.getGrainSize();
+ int nbGrainTables = (int) (nbGrains / header.getNumGTEsPerGT());
+ LOG.debug("read: capacity="+header.getCapacity()+" grainSize="+header.getGrainSize()+
+ " NumGTEsPerGT="+header.getNumGTEsPerGT()+" => nbGrainTables="+nbGrainTables);
+
+ GrainDirectory grainDirectory = new GrainDirectory(readEntries(raf, nbGrainTables));
+ GrainTable[] grainTables = new GrainTable[nbGrainTables];
+ for(int i = 0 ; i < grainTables.length ; i++)
+ {
+ if(LOG.isDebugEnabled())
+ {
+ long pos = raf.getChannel().position();
+ if((pos % IOHandler.SECTOR_SIZE) != 0)
+ {
+ LOG.fatal("read: FATAL: pos not begin of a sector");
+ }
+
+ final long gtOffset = (pos / IOHandler.SECTOR_SIZE);
+ final long gde = grainDirectory.getEntry(i);
+ if(gde != gtOffset)
+ {
+ LOG.fatal("read: FATAL: grainTables["+i+"] (value:"+gtOffset+") doesn't match to GrainDirectoryEntry #"+i+ "(value:"+gde+")");
+ }
+
+ raf.getChannel().position(gde);
+ }
+
+ grainTables[i] = new GrainTable(readEntries(raf, header.getNumGTEsPerGT()));
+ }
+
+ return new AllocationTable(grainDirectory, grainTables);
+ }
+
+ public void write(FileChannel channel, AllocationTable table) throws IOException
+ {
+ write(channel, table.getGrainDirectory());
+ for(int gtNum = 0 ; gtNum < table.getNbGrainTables() ; gtNum++)
+ {
+ write(channel, table.getGrainTable(gtNum));
+ }
+ }
+
+ protected void write(FileChannel channel, EntryArray ea) throws IOException
+ {
+ ByteBuffer b = IOUtils.allocate(ea.getSize() * IOUtils.INT_SIZE);
+ IntBuffer ib = b.asIntBuffer();
+ for(int i = 0 ; i < ea.getSize() ; i++)
+ {
+ ib.put(ea.getEntry(i));
+ }
+ ib.rewind();
+ channel.write(b);
+ }
+
+ protected int[] readEntries(RandomAccessFile raf, int nbEntries) throws IOException
+ {
+ IntBuffer bb = IOUtils.getByteBuffer(raf, nbEntries * IOUtils.INT_SIZE).asIntBuffer();
+
+ int[] entries = new int[nbEntries];
+ for(int entryNumber = 0 ; entryNumber < nbEntries ; entryNumber++)
+ {
+ int entry = bb.get();
+ if(entry > 0)
+ {
+ LOG.debug("readEntries: entry["+entryNumber+"]="+entry);
+ }
+ entries[entryNumber] = entry;
+ }
+ return entries;
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDescriptorRW.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDescriptorRW.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDescriptorRW.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,50 @@
+/**
+ *
+ */
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+
+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.descriptor.DescriptorRW;
+import org.jnode.apps.vmware.disk.extent.Extent;
+import org.jnode.apps.vmware.disk.handler.FileDescriptor;
+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)
+ *
+ */
+final class SparseDescriptorRW extends DescriptorRW {
+ static final Logger LOG = Logger.getLogger(SparseDescriptorRW.class);
+
+ @Override
+ public SparseExtent createMainExtent(Descriptor desc, ExtentDeclaration extentDecl) throws IOException, UnsupportedFormatException
+ {
+ SparseExtentFactory factory = new SparseExtentFactory();
+
+ RandomAccessFile raf = new RandomAccessFile(extentDecl.getExtentFile(), "rw");
+ ByteBuffer bb = IOUtils.getByteBuffer(raf, 1024);
+
+ SparseExtentHeaderRW reader = new SparseExtentHeaderRW();
+ SparseExtentHeader header = reader.read(bb);
+ SparseFileDescriptor sfd = new SparseFileDescriptor(desc, raf, factory, header);
+ return createExtent(sfd, extentDecl);
+ }
+
+ @Override
+ public SparseExtent createExtent(FileDescriptor fileDescriptor,
+ ExtentDeclaration extentDecl)
+ throws IOException, UnsupportedFormatException
+ {
+ SparseFileDescriptor sfd = (SparseFileDescriptor) fileDescriptor;
+ return new SparseExtentRW().read(sfd.getRandomAccessFile().getChannel(), sfd, extentDecl);
+ }
+}
\ No newline at end of file
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,20 @@
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.File;
+
+import org.jnode.apps.vmware.disk.tools.DiskFactory;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class SparseDiskFactory extends DiskFactory
+{
+ @Override
+ protected boolean createDiskImpl(File mainFile, long size)
+ {
+ return true;
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,178 @@
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channel;
+import java.nio.channels.FileChannel;
+
+import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.IOUtils;
+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 SparseExtentHeaderRW
+{
+ static final Logger LOG = Logger.getLogger(SparseExtentHeaderRW.class);
+
+ private static final byte singleEndLineChar = '\n';
+ private static final byte nonEndLineChar = ' ';
+ private static final byte doubleEndLineChar1 = '\r';
+ private static final byte doubleEndLineChar2 = '\n';
+
+ private static final int PAD_SIZE = 435;
+ private static final int MAGIC_NUMBER = 0x564d444b;
+ private static final int VERSION = 1;
+
+ private static final byte TRUE = (byte)1;
+ private static final byte FALSE = (byte)0;
+
+ private static final int numGTEsPerGT = 512;
+
+ public SparseExtentHeader read(ByteBuffer bb)
+ throws IOException, UnsupportedFormatException
+ {
+ //TODO optimise the size
+ //ByteBuffer bb = IOUtils.getByteBuffer(raf, 1024);
+
+ SparseExtentHeader header = new SparseExtentHeader();
+
+ int magicNum = bb.getInt();
+ LOG.debug("magicNum="+Long.toHexString(magicNum));
+ if(magicNum != MAGIC_NUMBER)
+ {
+ throw new UnsupportedFormatException("not the magic number");
+ }
+
+ int version = bb.getInt();
+ if(version != VERSION)
+ {
+ throw new IOException("bad version number (found:" + version + ")");
+ }
+
+ int flags = bb.getInt();
+ header.setValidNewLineDetectionTest((flags & 0x01) == 0x01); // bit 0
+ header.setRedundantGrainTableWillBeUsed((flags & 0x02) == 0x02); // bit 1
+
+ header.setCapacity(bb.getLong());
+ header.setGrainSize(bb.getLong());
+ header.setDescriptorOffset(bb.getLong());
+ header.setDescriptorSize(bb.getLong());
+
+ LOG.debug("read: offset(NumGTEsPerGT)="+bb.position());
+ int nb = bb.getInt();
+ if(nb != numGTEsPerGT)
+ {
+ throw new IOException("bad number of entries per grain table (found:" + nb + ")");
+ }
+ header.setNumGTEsPerGT(nb);
+
+ header.setRgdOffset(bb.getLong());
+
+ LOG.debug("read: offset(GdOffset)="+bb.position());
+ header.setGdOffset(bb.getLong());
+ header.setOverHead(bb.getLong());
+ header.setUncleanShutdown(bb.get() == TRUE);
+
+ LOG.debug("read: offset(singleEndLineChar)="+bb.position());
+ byte b = bb.get();
+ if(b != singleEndLineChar)
+ {
+ throw new IOException("file corrupted after a FTP (singleEndLineChar="+b+")");
+ }
+ b = bb.get();
+ if(b != nonEndLineChar)
+ {
+ throw new IOException("file corrupted after a FTP (nonEndLineChar="+b+")");
+ }
+ b = bb.get();
+ if(b != doubleEndLineChar1)
+ {
+ throw new IOException("file corrupted after a FTP (doubleEndLineChar1="+b+")");
+ }
+ b = bb.get();
+ if(b != doubleEndLineChar2)
+ {
+ throw new IOException("file corrupted after a FTP (doubleEndLineChar2="+b+")");
+ }
+
+ if(bb.remaining() < PAD_SIZE)
+ {
+ throw new UnsupportedFormatException("bad pad size (size="+bb.remaining()+")");
+ }
+
+ // additional/computed attributes
+ header.setGrainTableCoverage(header.getNumGTEsPerGT() * header.getGrainSize());
+
+ if(header.getGrainSize() <= 8)
+ {
+ throw new IOException("grainSize must be greater than 8 (actual:"+header.getGrainSize()+")");
+ }
+ if(!IOUtils.isPowerOf2(header.getGrainSize()))
+ {
+ throw new IOException("grainSize must be a power of 2 (actual:"+header.getGrainSize()+")");
+ }
+
+//TODO: according to the spec the following test shouldn't fail but **it is actually failing**
+// if((header.getCapacity() % header.getGrainSize()) != 0)
+// {
+// throw new IOException("capacity must be a multiple of grainSize (actual grainSize:"+header.getGrainSize()+", actual capacity="+header.getCapacity()+")");
+// }
+
+ LOG.debug("header="+header);
+
+ return header;
+ }
+
+ public void write(FileChannel channel, SparseExtentHeader header) throws IOException {
+ ByteBuffer bb = IOUtils.allocate(1024);
+ bb.putInt(MAGIC_NUMBER);
+ bb.putInt(VERSION);
+
+ int flags = 0;
+ if(header.isValidNewLineDetectionTest())
+ {
+ flags &= 0x01; // bit 0
+ }
+ if(header.isRedundantGrainTableWillBeUsed())
+ {
+ flags &= 0x02; // bit 1
+ }
+ bb.putInt(flags);
+
+ bb.putLong(header.getCapacity());
+ bb.putLong(header.getGrainSize());
+ bb.putLong(header.getDescriptorOffset());
+ bb.putLong(header.getDescriptorSize());
+
+ LOG.debug("write: offset(NumGTEsPerGT)="+bb.position());
+ bb.putInt(header.getNumGTEsPerGT());
+ bb.putLong(header.getRgdOffset());
+
+ LOG.debug("write: offset(GdOffset)="+bb.position());
+ bb.putLong(header.getGdOffset());
+ bb.putLong(header.getOverHead());
+ bb.put(header.isUncleanShutdown() ? TRUE : FALSE);
+
+ LOG.debug("write: offset(singleEndLineChar)="+bb.position());
+ bb.put(singleEndLineChar);
+ bb.put(nonEndLineChar);
+ bb.put(doubleEndLineChar1);
+ bb.put(doubleEndLineChar2);
+
+ for(int i = 0 ; i < PAD_SIZE ; i++)
+ {
+ bb.put((byte) 0);
+ }
+
+ bb.limit(bb.position());
+ bb.rewind();
+ LOG.debug("write: buffer="+bb);
+
+ channel.write(bb);
+ }
+}
\ No newline at end of file
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentIO.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentIO.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentIO.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,75 @@
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+
+import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.extent.Extent;
+import org.jnode.apps.vmware.disk.handler.ExtentIO;
+import org.jnode.apps.vmware.disk.handler.IOHandler;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class SparseExtentIO extends ExtentIO {
+ private static final Logger LOG = Logger.getLogger(SparseExtentIO.class);
+
+ public SparseExtentIO(RandomAccessFile raf, Extent extent) {
+ super(raf, extent);
+ }
+
+ @Override
+ public void read(long sector, ByteBuffer dst) throws IOException {
+ SparseExtent spe = (SparseExtent) extent;
+
+ int oldLimit = dst.limit();
+ dst.limit((int) (dst.position() + IOHandler.SECTOR_SIZE));
+
+ int offset = spe.getOffset(sector, false, raf); // false: don't allocate
+ if(offset < 0)
+ {
+ // grain not yet allocated
+ // this is the vmware disk behavior : we don't allocate new grains on read
+ // we put zeros in the buffer
+ for(int i = 0 ; i < IOHandler.SECTOR_SIZE; i++)
+ {
+ dst.put((byte) 0);
+ }
+ }
+ else
+ {
+ LOG.debug("read: sector="+sector+" offset="+offset+" size="+dst.remaining());
+ channel.position(offset);
+ int read = channel.read(dst);
+ LOG.debug("read: nbRead="+read);
+ }
+
+ dst.limit(oldLimit);
+ }
+
+ @Override
+ public void write(long sector, ByteBuffer src) throws IOException
+ {
+ SparseExtent spe = (SparseExtent) extent;
+
+ // true: allocate if necessary
+ int offset = spe.getOffset(sector, true, raf);
+
+ LOG.debug("write: sector="+sector+" offset="+offset+" size="+src.remaining());
+ channel.position(offset);
+ channel.write(src);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ SparseExtent spe = (SparseExtent) extent;
+
+ new SparseExtentRW().write(channel, spe);
+
+ super.flush();
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentRW.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentRW.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentRW.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,61 @@
+package org.jnode.apps.vmware.disk.handler.sparse;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+
+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;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class SparseExtentRW {
+ private static final Logger LOG = Logger.getLogger(SparseExtentRW.class);
+
+ private static final AllocationTableRW ALLOC_TABLE_RW = new AllocationTableRW();
+ private static final SparseExtentHeaderRW SPARSE_EXT_HEADER_RW = new SparseExtentHeaderRW();
+
+ public void write(FileChannel channel, SparseExtent extent) throws IOException {
+ channel.position(0L);
+ SPARSE_EXT_HEADER_RW.write(channel, extent.getHeader());
+
+ IOUtils.positionSector(channel, extent.getHeader().getRgdOffset());
+ LOG.debug("write: position(redundantAllocTable)="+channel.position());
+ ALLOC_TABLE_RW.write(channel, extent.getRedundantAllocationTable());
+
+ IOUtils.positionSector(channel, extent.getHeader().getGdOffset());
+ LOG.debug("write: position(allocTable)="+channel.position());
+ ALLOC_TABLE_RW.write(channel, extent.getAllocationTable());
+
+ LOG.debug("write: position="+channel.position());
+ }
+
+ public SparseExtent read(FileChannel channel,
+ SparseFileDescriptor fileDescriptor, ExtentDeclaration extentDecl)
+ throws IOException
+ {
+ LOG.debug("fileDescriptor="+fileDescriptor);
+ Descriptor descriptor = fileDescriptor.getDescriptor();
+
+ RandomAccessFile raf = fileDescriptor.getRandomAccessFile();
+ SparseExtentHeader header = fileDescriptor.getHeader();
+
+ IOUtils.positionSector(raf.getChannel(), header.getRgdOffset());
+ LOG.debug("read: position(redundantAllocTable)="+channel.position());
+ AllocationTable redundantAllocationTable = ALLOC_TABLE_RW.read(raf, header);
+
+ IOUtils.positionSector(raf.getChannel(), header.getGdOffset());
+ LOG.debug("read: position(allocTable)="+channel.position());
+ AllocationTable allocationTable = ALLOC_TABLE_RW.read(raf, header);
+
+ return new SparseExtent(descriptor, extentDecl,
+ header, redundantAllocationTable,
+ allocationTable);
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/BaseTest.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/BaseTest.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/BaseTest.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,44 @@
+package org.jnode.apps.vmware.disk.test;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.jnode.apps.vmware.disk.IOUtils;
+import org.jnode.apps.vmware.disk.tools.DiskCopier;
+import org.junit.After;
+import org.junit.Before;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+abstract public class BaseTest {
+
+ protected final File originalDiskFile;
+ protected final boolean copyDisk;
+ protected File diskFile;
+
+ public BaseTest(File diskFile, boolean copyDisk) {
+ this.originalDiskFile = diskFile;
+ this.copyDisk = copyDisk;
+ }
+
+ @Before
+ public void setUp() throws IOException {
+ this.diskFile = copyDisk ? DiskCopier.copyDisk(originalDiskFile, Utils.createTempDir()) : originalDiskFile;
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ Utils.clearTempDir(true);
+ Utils.DO_CLEAR = true;
+ }
+
+ @Override
+ public String toString() {
+ return diskFile.getName();
+ }
+
+}
\ No newline at end of file
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestCreation.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestCreation.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/TestCreation.java 2007-03-31 16:51:34 UTC (rev 3147)
@@ -0,0 +1,31 @@
+package org.jnode.apps.vmware.disk.test;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.IOUtils;
+import org.junit.Test;
+
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+public class TestCreation extends BaseTest
+{
+ private static final Logger LOG = Logger.getLogger(TestCreation.class);
+
+ public TestCreation() throws IOException
+ {
+ super(Utils.createTempFile("create"), false);
+ }
+
+ @Test
+ public void createSparseDisk() throws Exception
+ {
+
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fd...@us...> - 2007-03-31 16:55:19
|
Revision: 3148
http://jnode.svn.sourceforge.net/jnode/?rev=3148&view=rev
Author: fduminy
Date: 2007-03-31 09:55:17 -0700 (Sat, 31 Mar 2007)
Log Message:
-----------
new version with some refactoring, more tests ...
- working disk type detection
- working read/write of headers only
- read/write of sectors still buggy
Added Paths:
-----------
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/BaseReadWriteTest.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/TestHeader.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/
trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/BaseReadWriteTest.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/BaseReadWriteTest.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/BaseReadWriteTest.java 2007-03-31 16:55:17 UTC (rev 3148)
@@ -0,0 +1,163 @@
+package org.jnode.apps.vmware.disk.test.readwrite;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.IOUtils;
+import org.jnode.apps.vmware.disk.VMWareDisk;
+import org.jnode.apps.vmware.disk.handler.IOHandler;
+import org.jnode.apps.vmware.disk.test.BaseTest;
+import org.jnode.apps.vmware.disk.test.Utils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+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)
+abstract public class BaseReadWriteTest extends BaseTest {
+ private static final Logger LOG = Logger.getLogger(BaseReadWriteTest.class);
+
+ private static final String DISKS_PACKAGE = "/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;
+
+ private static final String DISKS_PATH;
+ static
+ {
+ String classpath = System.getProperty("java.class.path");
+ StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator, false);
+ File foundPath = null;
+ while(tokenizer.hasMoreTokens())
+ {
+ File path = new File(tokenizer.nextToken());
+ if(path.isDirectory())
+ {
+ path = new File(path, DISKS_PACKAGE);
+ if(path.exists())
+ {
+ foundPath = path;
+ break;
+ }
+ }
+ }
+ if(foundPath == null)
+ {
+ throw new RuntimeException("directory not found for package "+DISKS_PACKAGE);
+ }
+
+ DISKS_PATH = foundPath.getAbsolutePath();
+
+ System.out.println("\ndirectory for package "+DISKS_PACKAGE+" : "+DISKS_PATH);
+ }
+
+ @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;
+ }
+
+ public BaseReadWriteTest(File diskFile) throws IOException
+ {
+ super(diskFile, true);
+ }
+
+ @Test
+ @Ignore
+ public void read() throws Exception
+ {
+ VMWareDisk disk = new VMWareDisk(diskFile);
+
+ ByteBuffer data = IOUtils.allocate(IOHandler.SECTOR_SIZE * 100);
+ disk.read(0, data);
+
+ Assert.assertEquals(toString()+": buffer should be filled", 0, data.remaining());
+ }
+
+ @Test
+ @Ignore
+ public void write() throws Exception
+ {
+ VMWareDisk disk = new VMWareDisk(diskFile);
+
+ ByteBuffer data = IOUtils.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
+ {
+ Utils.DO_CLEAR = false;
+
+ LOG.info("BEGIN writeAndRead");
+ VMWareDisk disk = new VMWareDisk(diskFile);
+
+ // write
+ LOG.info("writeAndRead: writing...");
+ int size = IOHandler.SECTOR_SIZE * 100;
+ ByteBuffer expectedData = IOUtils.allocate(size);
+ for(int i = 0 ; i < (size / 4) ; i++)
+ {
+ expectedData.putInt(i);
+ }
+ expectedData.rewind();
+ disk.write(0, expectedData);
+ disk.flush();
+
+ // read
+ LOG.info("writeAndRead: reading...");
+ 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 = IOUtils.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);
+ }
+ LOG.info("END writeAndRead");
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/TestHeader.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/TestHeader.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/test/readwrite/TestHeader.java 2007-03-31 16:55:17 UTC (rev 3148)
@@ -0,0 +1,73 @@
+package org.jnode.apps.vmware.disk.test.readwrite;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.IOUtils;
+import org.jnode.apps.vmware.disk.VMWareDisk;
+import org.jnode.apps.vmware.disk.handler.IOHandler;
+import org.jnode.apps.vmware.disk.test.Utils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+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)
+ *
+ */
+public class TestHeader extends BaseReadWriteTest
+{
+ private static final Logger LOG = Logger.getLogger(TestHeader.class);
+
+ public TestHeader(File diskFile) throws IOException
+ {
+ super(diskFile);
+ }
+
+ @Test
+ public void read() throws Exception
+ {
+ VMWareDisk disk = new VMWareDisk(diskFile);
+ disk.flush();
+ }
+
+ @Test
+ public void write() throws Exception
+ {
+ VMWareDisk disk = new VMWareDisk(diskFile);
+ disk.flush();
+ }
+
+ @Test
+ public void writeAndRead() throws Exception
+ {
+ Utils.DO_CLEAR = false;
+
+ LOG.info("BEGIN writeAndRead");
+ VMWareDisk disk = new VMWareDisk(diskFile);
+
+ // write
+ LOG.info("writeAndRead: writing...");
+ disk.flush();
+
+ // read
+ LOG.info("writeAndRead: reading...");
+ 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());
+ disk2.flush();
+ LOG.info("END writeAndRead");
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java 2007-03-31 16:55:17 UTC (rev 3148)
@@ -0,0 +1,90 @@
+package org.jnode.apps.vmware.disk.tools;
+
+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;
+import org.jnode.apps.vmware.disk.test.Utils;
+
+public class DiskCopier {
+ private static final Logger LOG = Logger.getLogger(Utils.class);
+
+ public static File copyDisk(final File mainFile, final File toDirectory)
+ 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 mainFileCopy = null;
+ for(File file : files)
+ {
+ File f = copyFile(file, toDirectory);
+ 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();
+ }
+ }
+ }
+ }
+}
Added: trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java (rev 0)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java 2007-03-31 16:55:17 UTC (rev 3148)
@@ -0,0 +1,42 @@
+package org.jnode.apps.vmware.disk.tools;
+
+import java.io.File;
+
+import org.jnode.apps.vmware.disk.handler.sparse.SparseDiskFactory;
+
+/**
+ * Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
+ *
+ * @author Fabien DUMINY (fduminy at jnode dot org)
+ *
+ */
+abstract public class DiskFactory
+{
+ private static final SparseDiskFactory SPARSE_FACTORY = new SparseDiskFactory();
+
+ public static File createSparseDisk(File directory, String name, long size)
+ {
+ return SPARSE_FACTORY.createDisk(directory, name, size);
+ }
+
+ public File createDisk(File directory, String name, long size)
+ {
+ if(!directory.isDirectory())
+ {
+ throw new IllegalArgumentException(directory.getAbsolutePath()+" is not a directory");
+ }
+ if(!directory.canWrite())
+ {
+ throw new IllegalArgumentException(directory.getAbsolutePath()+" must be writable");
+ }
+
+ File mainFile = new File(directory, name);
+ if(!createDiskImpl(mainFile, size))
+ {
+ mainFile = null;
+ }
+ return mainFile;
+ }
+
+ abstract protected boolean createDiskImpl(File mainFile, long size);
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fd...@us...> - 2007-04-15 18:11:12
|
Revision: 3158
http://jnode.svn.sourceforge.net/jnode/?rev=3158&view=rev
Author: fduminy
Date: 2007-04-15 11:10:57 -0700 (Sun, 15 Apr 2007)
Log Message:
-----------
update of VMWareDisk
Modified Paths:
--------------
trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTable.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java
trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java 2007-04-15 18:09:27 UTC (rev 3157)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/IOUtils.java 2007-04-15 18:10:57 UTC (rev 3158)
@@ -12,12 +12,15 @@
import java.util.Map;
import org.apache.log4j.Logger;
+import org.jnode.apps.vmware.disk.extent.Access;
+import org.jnode.apps.vmware.disk.extent.ExtentType;
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;
import org.jnode.apps.vmware.disk.handler.simple.SimpleExtentFactory;
import org.jnode.apps.vmware.disk.handler.sparse.SparseExtentFactory;
+import org.jnode.apps.vmware.disk.handler.sparse.SparseExtentHeader;
/**
* Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
@@ -191,6 +194,13 @@
return fileDescriptor;
}
+ public static ExtentDeclaration createExtentDeclaration(File mainFile, String fileName, Access access, long sizeInSectors, ExtentType extentType, long offset)
+ {
+ final File extentFile = IOUtils.getExtentFile(mainFile, fileName);
+ final boolean isMainExtent = extentFile.getName().equals(mainFile.getName());
+ return new ExtentDeclaration(access, sizeInSectors, extentType, fileName, extentFile, offset, isMainExtent);
+ }
+
public static File getExtentFile(File mainFile, String extentFileName) {
String path = mainFile.getParentFile().getAbsolutePath();
return new File(path, extentFileName);
@@ -304,4 +314,8 @@
return false;
}
+
+ public static void computeGrainTableCoverage(SparseExtentHeader header) {
+ header.setGrainTableCoverage(header.getNumGTEsPerGT() * header.getGrainSize());
+ }
}
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java 2007-04-15 18:09:27 UTC (rev 3157)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/descriptor/DescriptorRW.java 2007-04-15 18:10:57 UTC (rev 3158)
@@ -159,9 +159,7 @@
offset = Long.valueOf(st.nextToken());
}
- final File extentFile = IOUtils.getExtentFile(mainFile, fileName);
- final boolean isMainExtent = extentFile.getName().equals(mainFile.getName());
- return new ExtentDeclaration(access, sizeInSectors, extentType, fileName, extentFile, offset, isMainExtent);
+ return IOUtils.createExtentDeclaration(mainFile, fileName, access, sizeInSectors, extentType, offset);
}
protected Header readHeader(BufferedReader reader) throws IOException, UnsupportedFormatException
Modified: 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 2007-04-15 18:09:27 UTC (rev 3157)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/AllocationTable.java 2007-04-15 18:10:57 UTC (rev 3158)
@@ -18,7 +18,6 @@
private final GrainTable[] grainTables;
public AllocationTable(GrainDirectory grainDirectory, GrainTable[] grainTables)
- throws IOException
{
this.grainDirectory = grainDirectory;
this.grainTables = grainTables;
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java 2007-04-15 18:09:27 UTC (rev 3157)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseDiskFactory.java 2007-04-15 18:10:57 UTC (rev 3158)
@@ -1,8 +1,26 @@
package org.jnode.apps.vmware.disk.handler.sparse;
import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+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.AdapterType;
+import org.jnode.apps.vmware.disk.descriptor.CreateType;
+import org.jnode.apps.vmware.disk.descriptor.Descriptor;
+import org.jnode.apps.vmware.disk.descriptor.DiskDatabase;
+import org.jnode.apps.vmware.disk.descriptor.Header;
+import org.jnode.apps.vmware.disk.extent.Access;
+import org.jnode.apps.vmware.disk.extent.Extent;
+import org.jnode.apps.vmware.disk.extent.ExtentType;
import org.jnode.apps.vmware.disk.tools.DiskFactory;
+import org.jnode.driver.bus.ide.IDEConstants;
/**
* Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare)
@@ -12,9 +30,120 @@
*/
public class SparseDiskFactory extends DiskFactory
{
+ private static final Logger LOG = Logger.getLogger(SparseDiskFactory.class);
+
@Override
- protected boolean createDiskImpl(File mainFile, long size)
+ protected File createDiskImpl(File directory, String name, long size) throws IOException
{
- return true;
+ File mainFile = createMainFile(directory, name, size);
+ return mainFile;
}
+
+ protected File createMainFile(File directory, String name, long size) throws IOException
+ {
+ File mainFile = new File(directory, createDiskFileName(name, 0));
+ RandomAccessFile raf = new RandomAccessFile(mainFile, "rw");
+ FileChannel channel = raf.getChannel();
+
+ Descriptor descriptor = buildDescriptor(mainFile, size);
+ SparseExtentHeader header = new SparseExtentHeader();
+
+
+ return mainFile;
+ }
+
+ protected Descriptor buildDescriptor(File mainFile, long size)
+ {
+ LOG.info("buildDescriptor: wanted size="+size);
+ long sizeInSectors = size / IDEConstants.SECTOR_SIZE;
+ if((size % IDEConstants.SECTOR_SIZE) != 0)
+ {
+ LOG.debug("buildDescriptor: adding 1 more sector to fit size");
+ sizeInSectors ++;
+ }
+
+ // build DiskDatabase
+ DiskDatabase ddb = new DiskDatabase();
+ ddb.setAdapterType(AdapterType.ide);
+ ddb.setSectors(64);
+ ddb.setHeads(32);
+
+ int cylinderCapacity = ddb.getSectors() * ddb.getHeads();
+ int cylinders = (int) (sizeInSectors / cylinderCapacity);
+ if((sizeInSectors % cylinderCapacity) != 0)
+ {
+ LOG.debug("buildDescriptor: adding 1 more cylinder to fit size");
+ cylinders++;
+ }
+ ddb.setCylinders(cylinders);
+
+ int nbSectors = ddb.getCylinders() * ddb.getHeads() * ddb.getSectors();
+ LOG.info("buildDescriptor: allocated size="+(nbSectors * IDEConstants.SECTOR_SIZE));
+
+ // build Header
+ Header header = new Header();
+ header.setVersion("1");
+ header.setContentID(0);
+ header.setParentContentID(Header.CID_NOPARENT);
+ header.setCreateType(CreateType.monolithicSparse);
+ header.setParentFileNameHint("");
+
+ // build extents
+ List<Extent> extents = new ArrayList<Extent>();
+ SparseExtent mainExtent = createMainExtent(mainFile, nbSectors);
+ extents.add(mainExtent);
+
+ Descriptor descriptor = new Descriptor(mainFile, header, extents, ddb);
+ mainExtent.setDescriptor(descriptor);
+ return descriptor;
+ }
+
+ private SparseExtent createMainExtent(File mainFile, int nbSectors)
+ {
+ long offset = 0L; //TODO should be changed ?
+ ExtentDeclaration extentDecl = IOUtils.createExtentDeclaration(mainFile, mainFile.getName(), Access.RW, nbSectors, ExtentType.SPARSE, offset);
+
+ // create extent header
+ SparseExtentHeader sparseHeader = new SparseExtentHeader();
+ sparseHeader.setValidNewLineDetectionTest(true);
+ sparseHeader.setRedundantGrainTableWillBeUsed(false);
+
+ sparseHeader.setGrainSize(16);
+ sparseHeader.setDescriptorOffset(0); //TODO set value
+ sparseHeader.setDescriptorSize(0); //TODO set value
+ sparseHeader.setRgdOffset(0); //TODO set value
+
+ sparseHeader.setNumGTEsPerGT(512);
+ sparseHeader.setGdOffset(0); //TODO set value
+ sparseHeader.setOverHead(0); //TODO set value
+ sparseHeader.setUncleanShutdown(false);
+
+
+ int nbGrains = (int) (nbSectors / sparseHeader.getGrainSize());
+ int modulo = (int) (nbSectors % sparseHeader.getGrainSize());
+ if(modulo != 0)
+ {
+ nbGrains++;
+ nbSectors += (sparseHeader.getGrainSize() - modulo);
+ }
+ sparseHeader.setCapacity(nbSectors);
+
+ IOUtils.computeGrainTableCoverage(sparseHeader);
+
+ // create allocation table
+ int nbEntries = (int) (nbSectors / sparseHeader.getGrainTableCoverage());
+ int[] entries = new int[nbEntries];
+ Arrays.fill(entries, 0);
+ GrainDirectory gd = new GrainDirectory(entries);
+ GrainTable[] gTables = null;
+ AllocationTable allocationTable = new AllocationTable(gd, gTables);
+
+ SparseExtent mainExtent = new SparseExtent(null, extentDecl, sparseHeader, allocationTable, allocationTable);
+ return mainExtent;
+ }
+
+ protected String createDiskFileName(String name, int index)
+ {
+ return name + "-" + index + ".vmdk";
+ }
}
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java 2007-04-15 18:09:27 UTC (rev 3157)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/handler/sparse/SparseExtentHeaderRW.java 2007-04-15 18:10:57 UTC (rev 3158)
@@ -106,7 +106,7 @@
}
// additional/computed attributes
- header.setGrainTableCoverage(header.getNumGTEsPerGT() * header.getGrainSize());
+ IOUtils.computeGrainTableCoverage(header);
if(header.getGrainSize() <= 8)
{
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java 2007-04-15 18:09:27 UTC (rev 3157)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskCopier.java 2007-04-15 18:10:57 UTC (rev 3158)
@@ -67,7 +67,7 @@
}
catch(IOException ioe)
{
- ioe.printStackTrace();
+ LOG.error(ioe);
throw ioe;
}
finally
Modified: trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java
===================================================================
--- trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java 2007-04-15 18:09:27 UTC (rev 3157)
+++ trunk/distr/src/apps/org/jnode/apps/vmware/disk/tools/DiskFactory.java 2007-04-15 18:10:57 UTC (rev 3158)
@@ -1,6 +1,7 @@
package org.jnode.apps.vmware.disk.tools;
import java.io.File;
+import java.io.IOException;
import org.jnode.apps.vmware.disk.handler.sparse.SparseDiskFactory;
@@ -14,12 +15,12 @@
{
private static final SparseDiskFactory SPARSE_FACTORY = new SparseDiskFactory();
- public static File createSparseDisk(File directory, String name, long size)
+ public static File createSparseDisk(File directory, String name, long size) throws IOException
{
return SPARSE_FACTORY.createDisk(directory, name, size);
}
- public File createDisk(File directory, String name, long size)
+ public File createDisk(File directory, String name, long size) throws IOException
{
if(!directory.isDirectory())
{
@@ -30,13 +31,8 @@
throw new IllegalArgumentException(directory.getAbsolutePath()+" must be writable");
}
- File mainFile = new File(directory, name);
- if(!createDiskImpl(mainFile, size))
- {
- mainFile = null;
- }
- return mainFile;
+ return createDiskImpl(directory, name, size);
}
- abstract protected boolean createDiskImpl(File mainFile, long size);
+ abstract protected File createDiskImpl(File directory, String name, long size) throws IOException;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|