diff options
author | Dan Galpin <dgalpin@google.com> | 2012-08-27 14:56:37 -0700 |
---|---|---|
committer | Dan Galpin <dgalpin@google.com> | 2012-08-27 14:56:37 -0700 |
commit | 8053088ccd55a94d6643a12660e967a5e8dfd5de (patch) | |
tree | a77cad7ba45423528ad67b2c0f7b12eeb1e1fc36 /src/main/java/de/waldheinz/fs/util | |
parent | 6950a7fcfda2d03446514e315b6bf6bd5c476496 (diff) | |
download | fat32lib-8053088ccd55a94d6643a12660e967a5e8dfd5de.tar.gz |
External library with modifications. fat32-lib.
Signed-off-by: Dan Galpin <dgalpin@google.com>
Change-Id: Ie59bda0c04d629c4b2723f77478957105761e5cf
Diffstat (limited to 'src/main/java/de/waldheinz/fs/util')
-rw-r--r-- | src/main/java/de/waldheinz/fs/util/FileDisk.java | 181 | ||||
-rw-r--r-- | src/main/java/de/waldheinz/fs/util/RamDisk.java | 199 | ||||
-rw-r--r-- | src/main/java/de/waldheinz/fs/util/package-info.java | 24 |
3 files changed, 404 insertions, 0 deletions
diff --git a/src/main/java/de/waldheinz/fs/util/FileDisk.java b/src/main/java/de/waldheinz/fs/util/FileDisk.java new file mode 100644 index 0000000..0f3f0bb --- /dev/null +++ b/src/main/java/de/waldheinz/fs/util/FileDisk.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2009,2010 Matthias Treydte <mt@waldheinz.de> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package de.waldheinz.fs.util; + +import de.waldheinz.fs.BlockDevice; +import de.waldheinz.fs.ReadOnlyException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +/** + * This is a {@code BlockDevice} that uses a {@link File} as it's backing store. + * + * @author Matthias Treydte <matthias.treydte at meetwise.com> + */ +public final class FileDisk implements BlockDevice { + + /** + * The number of bytes per sector for all {@code FileDisk} instances. + */ + public final static int BYTES_PER_SECTOR = 512; + + private final RandomAccessFile raf; + private final FileChannel fc; + private final boolean readOnly; + private boolean closed; + + /** + * Creates a new instance of {@code FileDisk} for the specified + * {@code File}. + * + * @param file the file that holds the disk contents + * @param readOnly if the file should be opened in read-only mode, which + * will result in a read-only {@code FileDisk} instance + * @throws FileNotFoundException if the specified file does not exist + * @see #isReadOnly() + */ + public FileDisk(File file, boolean readOnly) throws FileNotFoundException { + if (!file.exists()) throw new FileNotFoundException(); + + this.readOnly = readOnly; + this.closed = false; + final String modeString = readOnly ? "r" : "rw"; //NOI18N + this.raf = new RandomAccessFile(file, modeString); + this.fc = raf.getChannel(); + } + + public FileDisk(RandomAccessFile raf, FileChannel fc, boolean readOnly) { + this.closed = false; + this.raf = raf; + this.fc = fc; + this.readOnly = readOnly; + } + + private FileDisk(RandomAccessFile raf, boolean readOnly) { + this.closed = false; + this.raf = raf; + this.fc = raf.getChannel(); + this.readOnly = readOnly; + } + + /** + * Creates a new {@code FileDisk} of the specified size. The + * {@code FileDisk} returned by this method will be writable. + * + * @param file the file to hold the {@code FileDisk} contents + * @param size the size of the new {@code FileDisk} + * @return the created {@code FileDisk} instance + * @throws IOException on error creating the {@code FileDisk} + */ + public static FileDisk create(File file, long size) throws IOException { + try { + final RandomAccessFile raf = + new RandomAccessFile(file, "rw"); //NOI18N + raf.setLength(size); + + return new FileDisk(raf, false); + } catch (FileNotFoundException ex) { + throw new IOException(ex); + } + } + + @Override + public long getSize() throws IOException { + checkClosed(); + + return raf.length(); + } + + @Override + public void read(long devOffset, ByteBuffer dest) throws IOException { + checkClosed(); + + int toRead = dest.remaining(); + if ((devOffset + toRead) > getSize()) throw new IOException( + "reading past end of device"); + + while (toRead > 0) { + final int read = fc.read(dest, devOffset); + if (read < 0) throw new IOException(); + toRead -= read; + devOffset += read; + } + } + + @Override + public void write(long devOffset, ByteBuffer src) throws IOException { + checkClosed(); + + if (this.readOnly) throw new ReadOnlyException(); + + int toWrite = src.remaining(); + + if ((devOffset + toWrite) > getSize()) throw new IOException( + "writing past end of file"); + + while (toWrite > 0) { + final int written = fc.write(src, devOffset); + if (written < 0) throw new IOException(); + toWrite -= written; + devOffset += written; + } + } + + @Override + public void flush() throws IOException { + checkClosed(); + } + + @Override + public int getSectorSize() { + checkClosed(); + + return BYTES_PER_SECTOR; + } + + @Override + public void close() throws IOException { + if (isClosed()) return; + + this.closed = true; + this.fc.close(); + this.raf.close(); + } + + @Override + public boolean isClosed() { + return this.closed; + } + + private void checkClosed() { + if (closed) throw new IllegalStateException("device already closed"); + } + + @Override + public boolean isReadOnly() { + checkClosed(); + + return this.readOnly; + } + +} diff --git a/src/main/java/de/waldheinz/fs/util/RamDisk.java b/src/main/java/de/waldheinz/fs/util/RamDisk.java new file mode 100644 index 0000000..51a1be1 --- /dev/null +++ b/src/main/java/de/waldheinz/fs/util/RamDisk.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2009,2010 Matthias Treydte <mt@waldheinz.de> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package de.waldheinz.fs.util; + +import de.waldheinz.fs.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.zip.GZIPInputStream; + +/** + * A {@link BlockDevice} that lives entirely in heap memory. This is basically + * a RAM disk. A {@code RamDisk} is always writable. + * + * @author Matthias Treydte <waldheinz at gmail.com> + */ +public final class RamDisk implements BlockDevice { + + /** + * The default sector size for {@code RamDisk}s. + */ + public final static int DEFAULT_SECTOR_SIZE = 512; + + private final int sectorSize; + private final ByteBuffer data; + private final int size; + private boolean closed; + + /** + * Reads a GZIP compressed disk image from the specified input stream and + * returns a {@code RamDisk} holding the decompressed image. + * + * @param in the stream to read the disk image from + * @return the decompressed {@code RamDisk} + * @throws IOException on read or decompression error + */ + public static RamDisk readGzipped(InputStream in) throws IOException { + final GZIPInputStream zis = new GZIPInputStream(in); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + final byte[] buffer = new byte[4096]; + + int read = zis.read(buffer); + int total = 0; + + while (read >= 0) { + total += read; + bos.write(buffer, 0, read); + read = zis.read(buffer); + } + + if (total < DEFAULT_SECTOR_SIZE) throw new IOException( + "read only " + total + " bytes"); //NOI18N + + final ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray(), 0, total); + return new RamDisk(bb, DEFAULT_SECTOR_SIZE); + } + + private RamDisk(ByteBuffer buffer, int sectorSize) { + this.size = buffer.limit(); + this.sectorSize = sectorSize; + this.data = buffer; + this.closed = false; + } + + /** + * Creates a new instance of {@code RamDisk} of this specified + * size and using the {@link #DEFAULT_SECTOR_SIZE}. + * + * @param size the size of the new block device + */ + public RamDisk(int size) { + this(size, DEFAULT_SECTOR_SIZE); + } + + /** + * Creates a new instance of {@code RamDisk} of this specified + * size and sector size + * + * @param size the size of the new block device + * @param sectorSize the sector size of the new block device + */ + public RamDisk(int size, int sectorSize) { + if (sectorSize < 1) throw new IllegalArgumentException( + "invalid sector size"); //NOI18N + + this.sectorSize = sectorSize; + this.size = size; + this.data = ByteBuffer.allocate(size); + } + + @Override + public long getSize() { + checkClosed(); + return this.size; + } + + @Override + public void read(long devOffset, ByteBuffer dest) throws IOException { + checkClosed(); + + if (devOffset > getSize()){ + final StringBuilder sb = new StringBuilder(); + sb.append("read at ").append(devOffset); + sb.append(" is off size (").append(getSize()).append(")"); + + throw new IllegalArgumentException(sb.toString()); + } + + data.limit((int) (devOffset + dest.remaining())); + data.position((int) devOffset); + + dest.put(data); + } + + @Override + public void write(long devOffset, ByteBuffer src) throws IOException { + checkClosed(); + + if (devOffset + src.remaining() > getSize()) throw new + IllegalArgumentException( + "offset=" + devOffset + + ", length=" + src.remaining() + + ", size=" + getSize()); + + data.limit((int) (devOffset + src.remaining())); + data.position((int) devOffset); + + + data.put(src); + } + + /** + * Returns a slice of the {@code ByteBuffer} that is used by this + * {@code RamDisk} as it's backing store. The returned buffer will be + * live (reflecting any changes made through the + * {@link #write(long, java.nio.ByteBuffer) method}, but read-only. + * + * @return a buffer holding the contents of this {@code RamDisk} + */ + public ByteBuffer getBuffer() { + return this.data.asReadOnlyBuffer(); + } + + @Override + public void flush() throws IOException { + checkClosed(); + } + + @Override + public int getSectorSize() { + checkClosed(); + return this.sectorSize; + } + + @Override + public void close() throws IOException { + this.closed = true; + } + + @Override + public boolean isClosed() { + return this.closed; + } + + private void checkClosed() { + if (closed) throw new IllegalStateException("device already closed"); + } + + /** + * Returns always {@code false}, as a {@code RamDisk} is always writable. + * + * @return always {@code false} + */ + @Override + public boolean isReadOnly() { + checkClosed(); + + return false; + } + +} diff --git a/src/main/java/de/waldheinz/fs/util/package-info.java b/src/main/java/de/waldheinz/fs/util/package-info.java new file mode 100644 index 0000000..afde34e --- /dev/null +++ b/src/main/java/de/waldheinz/fs/util/package-info.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2009,2010 Matthias Treydte <mt@waldheinz.de> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * Contains some utility classes that are useful independent of the file system + * type. + */ +package de.waldheinz.fs.util; + |