|
From: <ga...@us...> - 2012-12-19 08:38:19
|
Revision: 5936
http://jnode.svn.sourceforge.net/jnode/?rev=5936&view=rev
Author: galatnm
Date: 2012-12-19 08:38:08 +0000 (Wed, 19 Dec 2012)
Log Message:
-----------
Various fs patches from Luke Quinane's repository + migrate to intellij 12
Modified Paths:
--------------
trunk/JNode.ipr
trunk/all/all.iml
trunk/builder/builder.iml
trunk/core/core.iml
trunk/distr/distr.iml
trunk/fs/fs.iml
trunk/fs/src/fs/org/jnode/fs/FileSystem.java
trunk/fs/src/fs/org/jnode/fs/ext2/Ext2File.java
trunk/fs/src/fs/org/jnode/fs/ext2/Ext2FileSystem.java
trunk/fs/src/fs/org/jnode/fs/fat/FatFileSystem.java
trunk/fs/src/fs/org/jnode/fs/ftpfs/FTPFileSystem.java
trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFile.java
trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystem.java
trunk/fs/src/fs/org/jnode/fs/hfsplus/HfsPlusFileSystemType.java
trunk/fs/src/fs/org/jnode/fs/iso9660/ISO9660FileSystem.java
trunk/fs/src/fs/org/jnode/fs/jarfs/JarFileSystem.java
trunk/fs/src/fs/org/jnode/fs/jfat/CodePage.java
trunk/fs/src/fs/org/jnode/fs/jfat/FatFile.java
trunk/fs/src/fs/org/jnode/fs/jfat/FatFileSystem.java
trunk/fs/src/fs/org/jnode/fs/jifs/JIFileSystem.java
trunk/fs/src/fs/org/jnode/fs/nfs/nfs2/NFS2FileSystem.java
trunk/fs/src/fs/org/jnode/fs/ntfs/BootRecord.java
trunk/fs/src/fs/org/jnode/fs/ntfs/CompressedDataRun.java
trunk/fs/src/fs/org/jnode/fs/ntfs/DataRun.java
trunk/fs/src/fs/org/jnode/fs/ntfs/DataRunInterface.java
trunk/fs/src/fs/org/jnode/fs/ntfs/FileNameAttribute.java
trunk/fs/src/fs/org/jnode/fs/ntfs/FileRecord.java
trunk/fs/src/fs/org/jnode/fs/ntfs/IndexEntry.java
trunk/fs/src/fs/org/jnode/fs/ntfs/IndexEntryIterator.java
trunk/fs/src/fs/org/jnode/fs/ntfs/IndexRootAttribute.java
trunk/fs/src/fs/org/jnode/fs/ntfs/MasterFileTable.java
trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSEntry.java
trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSFile.java
trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSFileSystem.java
trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSNonResidentAttribute.java
trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSRecord.java
trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSStructure.java
trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSVolume.java
trunk/fs/src/fs/org/jnode/fs/ramfs/RAMFileSystem.java
trunk/fs/src/fs/org/jnode/fs/service/def/VirtualFS.java
trunk/fs/src/fs/org/jnode/fs/smbfs/SMBFileSystem.java
trunk/gui/gui.iml
trunk/jnode.iml
trunk/net/net.iml
trunk/shell/shell.iml
trunk/textui/textui.iml
Added Paths:
-----------
trunk/fs/src/fs/org/jnode/fs/FSFileSlackSpace.java
trunk/fs/src/fs/org/jnode/fs/FSFileStreams.java
trunk/fs/src/fs/org/jnode/fs/ntfs/UsnJournalEntry.java
Modified: trunk/JNode.ipr
===================================================================
--- trunk/JNode.ipr 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/JNode.ipr 2012-12-19 08:38:08 UTC (rev 5936)
@@ -181,7 +181,11 @@
<entry name="?*.jpeg" />
<entry name="?*.jpg" />
</wildcardResourcePatterns>
- <annotationProcessing enabled="false" useClasspath="true" />
+ <annotationProcessing>
+ <profile default="true" name="Default" enabled="false">
+ <processorPath useClasspath="true" />
+ </profile>
+ </annotationProcessing>
</component>
<component name="CopyrightManager" default="">
<module2copyright />
@@ -193,6 +197,15 @@
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
+ <component name="EclipseCodeFormatter">
+ <option name="defaultSettings" value="true" />
+ <option name="formatter" value="ECLIPSE" />
+ <option name="id" value="1355311468141" />
+ <option name="name" value="default" />
+ <option name="optimizeImports" value="false" />
+ <option name="pathToConfigFileJava" value="$PROJECT_DIR$/../../../../documentation/others/isabel_codingFormat.xml" />
+ <option name="selectedJavaProfile" value="isabel" />
+ </component>
<component name="EclipseCompilerSettings">
<option name="GENERATE_NO_WARNINGS" value="true" />
<option name="DEPRECATION" value="false" />
@@ -224,6 +237,14 @@
<item index="5" class="java.lang.String" itemvalue="ERROR" />
</list>
</component>
+ <component name="IvyIDEA.ProjectSettings">
+ <option name="artifactTypeSettings">
+ <ArtifactTypeSettings />
+ </option>
+ <option name="propertiesSettings">
+ <PropertiesSettings />
+ </option>
+ </component>
<component name="JavacSettings">
<option name="MAXIMUM_HEAP_SIZE" value="1024" />
</component>
Modified: trunk/all/all.iml
===================================================================
--- trunk/all/all.iml 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/all/all.iml 2012-12-19 08:38:08 UTC (rev 5936)
@@ -3,7 +3,6 @@
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes" />
<exclude-output />
- <exclude-exploded />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
Modified: trunk/builder/builder.iml
===================================================================
--- trunk/builder/builder.iml 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/builder/builder.iml 2012-12-19 08:38:08 UTC (rev 5936)
@@ -3,7 +3,6 @@
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes" />
<exclude-output />
- <exclude-exploded />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/builder" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/configure" isTestSource="false" />
Modified: trunk/core/core.iml
===================================================================
--- trunk/core/core.iml 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/core/core.iml 2012-12-19 08:38:08 UTC (rev 5936)
@@ -3,7 +3,6 @@
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes" />
<exclude-output />
- <exclude-exploded />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/classlib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/classpath/ext" isTestSource="false" />
Modified: trunk/distr/distr.iml
===================================================================
--- trunk/distr/distr.iml 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/distr/distr.iml 2012-12-19 08:38:08 UTC (rev 5936)
@@ -3,7 +3,6 @@
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes" />
<exclude-output />
- <exclude-exploded />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/apps" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/emu" isTestSource="false" />
Modified: trunk/fs/fs.iml
===================================================================
--- trunk/fs/fs.iml 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/fs/fs.iml 2012-12-19 08:38:08 UTC (rev 5936)
@@ -6,7 +6,6 @@
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes" />
<exclude-output />
- <exclude-exploded />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/driver" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/fs" isTestSource="false" />
Added: trunk/fs/src/fs/org/jnode/fs/FSFileSlackSpace.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/FSFileSlackSpace.java (rev 0)
+++ trunk/fs/src/fs/org/jnode/fs/FSFileSlackSpace.java 2012-12-19 08:38:08 UTC (rev 5936)
@@ -0,0 +1,21 @@
+package org.jnode.fs;
+
+import java.io.IOException;
+
+/**
+ * <p>
+ * Interface for {@link FSFile} implementation that support reading "slack space" at the end of the file data.
+ * </p>
+ * <p>
+ * For example if a filesystem has a block size of 512 bytes and a file is only using 500 bytes then there will be 12
+ * bytes of unallocated space at the end of the block that may contain data from a previous file.
+ * </p>
+ */
+public interface FSFileSlackSpace {
+ /**
+ * Gets the file slack space.
+ * @return the slack space.
+ * @throws IOException if an error occurs reading the file.
+ */
+ byte[] getSlackSpace() throws IOException;
+}
Added: trunk/fs/src/fs/org/jnode/fs/FSFileStreams.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/FSFileStreams.java (rev 0)
+++ trunk/fs/src/fs/org/jnode/fs/FSFileStreams.java 2012-12-19 08:38:08 UTC (rev 5936)
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2012 JNode.org
+ *
+ * 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 org.jnode.fs;
+
+import java.util.Map;
+
+/**
+ * A FSFileStreams is a representation of a file system file that can have alternative data streams.
+ * @author Luke Quinane
+ */
+public interface FSFileStreams extends FSFile {
+ /**
+ * Gets the map of alternate stream names to their file interface.
+ * @return the mapping.
+ */
+ Map<String, FSFile> getStreams();
+}
Modified: trunk/fs/src/fs/org/jnode/fs/FileSystem.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/FileSystem.java 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/fs/src/fs/org/jnode/fs/FileSystem.java 2012-12-19 08:38:08 UTC (rev 5936)
@@ -17,95 +17,83 @@
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
+
package org.jnode.fs;
import java.io.IOException;
-
import org.jnode.driver.Device;
/**
* The <tt>FileSystem<tt> interface provide methods common to file system implementations.
- * *
+ * *
* @param <T> {@link FSEntry} sub-type
- *
- * @author epr
+ * @author epr
*/
public interface FileSystem<T extends FSEntry> {
- /**
- * Return type of the file system.
- *
- * @return {@link FileSystemType} corresponding to this file system
- */
- public FileSystemType<? extends FileSystem<T>> getType();
+ /**
+ * Return type of the file system.
+ * @return {@link FileSystemType} corresponding to this file system
+ */
+ public FileSystemType<? extends FileSystem<T>> getType();
- /**
- * Gets the device this FS driver operates on.
- *
- * @return {@link Device} contains this file system.
- */
- public Device getDevice();
+ /**
+ * Gets the device this FS driver operates on.
+ * @return {@link Device} contains this file system.
+ */
+ public Device getDevice();
- /**
- * Gets the root entry of this filesystem. This is usually a directory, but
- * this is not required.
- *
- * @return {@link FSEntry} corresponding to root entry.
- *
- * @throws IOException if an I/O error occurs
- */
- public T getRootEntry() throws IOException;
+ /**
+ * Gets the root entry of this filesystem. This is usually a directory, but this is not required.
+ * @return {@link FSEntry} corresponding to root entry.
+ * @throws IOException if an I/O error occurs
+ */
+ public T getRootEntry() throws IOException;
- /**
- * Returns <tt>true</tt> if the file system is mounted in read-only mode.
- *
- * @return <tt>true</tt> if it's a read-only file system.
- */
- public boolean isReadOnly();
+ /**
+ * Returns <tt>true</tt> if the file system is mounted in read-only mode.
+ * @return <tt>true</tt> if it's a read-only file system.
+ */
+ public boolean isReadOnly();
- /**
- * Close this file system. After a close, all invocations of method of this
- * file system or objects created by this file system will throw an
- * IOException.
- *
- *
- *
- * @throws IOException if an I/O error occurs
- */
- public void close() throws IOException;
+ /**
+ * Close this file system. After a close, all invocations of method of this file system or objects created by this
+ * file system will throw an IOException.
+ * @throws IOException if an I/O error occurs
+ */
+ public void close() throws IOException;
- /**
- * Returns <tt>true</tt> if this file system is close.
- *
- * @return <tt>true</tt> if file system is closed.
- */
- public boolean isClosed();
+ /**
+ * Returns <tt>true</tt> if this file system is close.
+ * @return <tt>true</tt> if file system is closed.
+ */
+ public boolean isClosed();
- /**
- * Return The total size in bytes of this file system.
- *
- * @return total size in bytes or -1 if this feature is unsupported.
- *
- * @throws IOException if an I/O error occurs
- */
- public long getTotalSpace() throws IOException;
+ /**
+ * Return The total size in bytes of this file system.
+ * @return total size in bytes or -1 if this feature is unsupported.
+ * @throws IOException if an I/O error occurs
+ */
+ public long getTotalSpace() throws IOException;
- /**
- * The total free space in bytes of this file system.
- *
- * @return total free space in bytes or -1 if this feature is unsupported
- *
- * @throws IOException if an I/O error occurs
- */
- public long getFreeSpace() throws IOException;
+ /**
+ * The total free space in bytes of this file system.
+ * @return total free space in bytes or -1 if this feature is unsupported
+ * @throws IOException if an I/O error occurs
+ */
+ public long getFreeSpace() throws IOException;
- /**
- * The usable space of this file system.
- *
- * @return usable space in bytes or -1 if this feature is unsupported
- *
- * @throws IOException if an I/O error occurs
- */
- public long getUsableSpace() throws IOException;
+ /**
+ * The usable space of this file system.
+ * @return usable space in bytes or -1 if this feature is unsupported
+ * @throws IOException if an I/O error occurs
+ */
+ public long getUsableSpace() throws IOException;
+
+ /**
+ * Gets the volume name for this file system.
+ * @return the volume name.
+ * @throws IOException if an error occurs reading the volume name.
+ */
+ public String getVolumeName() throws IOException;
}
Modified: trunk/fs/src/fs/org/jnode/fs/ext2/Ext2File.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/ext2/Ext2File.java 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/fs/src/fs/org/jnode/fs/ext2/Ext2File.java 2012-12-19 08:38:08 UTC (rev 5936)
@@ -17,13 +17,14 @@
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
+
package org.jnode.fs.ext2;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
+import org.jnode.fs.FSFileSlackSpace;
import org.jnode.fs.FileSystemException;
import org.jnode.fs.ReadOnlyFileSystemException;
import org.jnode.fs.spi.AbstractFSFile;
@@ -32,314 +33,330 @@
/**
* @author Andras Nagy
*/
-public class Ext2File extends AbstractFSFile {
+public class Ext2File extends AbstractFSFile implements FSFileSlackSpace {
- Ext2Entry entry;
- INode iNode;
+ Ext2Entry entry;
+ INode iNode;
- private final Logger log = Logger.getLogger(getClass());
+ private final Logger log = Logger.getLogger(getClass());
- public Ext2File(Ext2Entry entry) {
- super(entry.getINode().getExt2FileSystem());
- this.iNode = entry.getINode();
- this.entry = entry;
- log.setLevel(Level.DEBUG);
- }
+ public Ext2File(Ext2Entry entry) {
+ super(entry.getINode().getExt2FileSystem());
+ this.iNode = entry.getINode();
+ this.entry = entry;
+ log.setLevel(Level.DEBUG);
+ }
- @Override
- public long getLength() {
- //log.debug("getLength(): "+iNode.getSize());
- return iNode.getSize();
- }
+ @Override
+ public long getLength() {
+ // log.debug("getLength(): "+iNode.getSize());
+ return iNode.getSize();
+ }
- @Override
- public void setLength(long length) throws IOException {
- if (!canWrite())
- throw new ReadOnlyFileSystemException("FileSystem or File is readonly");
+ @Override
+ public void setLength(long length) throws IOException {
+ if (!canWrite()) throw new ReadOnlyFileSystemException("FileSystem or File is readonly");
- long blockSize = iNode.getExt2FileSystem().getBlockSize();
+ long blockSize = iNode.getExt2FileSystem().getBlockSize();
- //synchronize to the inode cache to make sure that the inode does not
- // get
- //flushed between reading it and locking it
- synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {
- //reread the inode before synchronizing to it to make sure
- //all threads use the same instance
- rereadInode();
+ // synchronize to the inode cache to make sure that the inode does not
+ // get
+ // flushed between reading it and locking it
+ synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {
+ // reread the inode before synchronizing to it to make sure
+ // all threads use the same instance
+ rereadInode();
- //lock the inode into the cache so it is not flushed before
- // synchronizing to it
- //(otherwise a new instance of INode referring to the same inode
- // could be put
- //in the cache resulting in the possibility of two threads
- // manipulating the same
- //inode at the same time because they would synchronize to
- // different INode instances)
- iNode.incLocked();
- }
- //a single inode may be represented by more than one Ext2Directory
- // instances,
- //but each will use the same instance of the underlying inode (see
- // Ext2FileSystem.getINode()),
- //so synchronize to the inode
- synchronized (iNode) {
- try {
- //if length<getLength(), then the file is truncated
- if (length < getLength()) {
- long blockNr = length / blockSize;
- long blockOffset = length % blockSize;
- long nextBlock;
- if (blockOffset == 0)
- nextBlock = blockNr;
- else
- nextBlock = blockNr + 1;
+ // lock the inode into the cache so it is not flushed before
+ // synchronizing to it
+ // (otherwise a new instance of INode referring to the same inode
+ // could be put
+ // in the cache resulting in the possibility of two threads
+ // manipulating the same
+ // inode at the same time because they would synchronize to
+ // different INode instances)
+ iNode.incLocked();
+ }
+ // a single inode may be represented by more than one Ext2Directory
+ // instances,
+ // but each will use the same instance of the underlying inode (see
+ // Ext2FileSystem.getINode()),
+ // so synchronize to the inode
+ synchronized (iNode) {
+ try {
+ // if length<getLength(), then the file is truncated
+ if (length < getLength()) {
+ long blockNr = length / blockSize;
+ long blockOffset = length % blockSize;
+ long nextBlock;
+ if (blockOffset == 0) nextBlock = blockNr;
+ else nextBlock = blockNr + 1;
- for (long i = iNode.getAllocatedBlockCount() - 1; i >= nextBlock; i--) {
- log.debug("setLength(): freeing up block " + i + " of inode");
- iNode.freeDataBlock(i);
- }
- iNode.setSize(length);
+ for(long i = iNode.getAllocatedBlockCount() - 1; i >= nextBlock; i--) {
+ log.debug("setLength(): freeing up block " + i + " of inode");
+ iNode.freeDataBlock(i);
+ }
+ iNode.setSize(length);
- iNode.setMtime(System.currentTimeMillis() / 1000);
+ iNode.setMtime(System.currentTimeMillis() / 1000);
- return;
- }
+ return;
+ }
- //if length>getLength(), then new blocks are allocated for the
- // file
- //The content of the new blocks is undefined (see the
- // setLength(long i)
- //method of java.io.RandomAccessFile
- if (length > getLength()) {
- long len = length - getLength();
- long blocksAllocated = getLengthInBlocks();
- long bytesAllocated = getLength();
- long bytesCovered = 0;
- while (bytesCovered < len) {
- long blockIndex = (bytesAllocated + bytesCovered) / blockSize;
- long blockOffset = (bytesAllocated + bytesCovered) % blockSize;
- long newSection = Math.min(len - bytesCovered, blockSize - blockOffset);
+ // if length>getLength(), then new blocks are allocated for the
+ // file
+ // The content of the new blocks is undefined (see the
+ // setLength(long i)
+ // method of java.io.RandomAccessFile
+ if (length > getLength()) {
+ long len = length - getLength();
+ long blocksAllocated = getLengthInBlocks();
+ long bytesAllocated = getLength();
+ long bytesCovered = 0;
+ while (bytesCovered < len) {
+ long blockIndex = (bytesAllocated + bytesCovered) / blockSize;
+ long blockOffset = (bytesAllocated + bytesCovered) % blockSize;
+ long newSection = Math.min(len - bytesCovered, blockSize - blockOffset);
- //allocate a new block if needed
- if (blockIndex >= blocksAllocated) {
- iNode.allocateDataBlock(blockIndex);
- blocksAllocated++;
- }
+ // allocate a new block if needed
+ if (blockIndex >= blocksAllocated) {
+ iNode.allocateDataBlock(blockIndex);
+ blocksAllocated++;
+ }
- bytesCovered += newSection;
- }
- iNode.setSize(length);
+ bytesCovered += newSection;
+ }
+ iNode.setSize(length);
- iNode.setMtime(System.currentTimeMillis() / 1000);
+ iNode.setMtime(System.currentTimeMillis() / 1000);
- return;
- }
- } catch (Throwable ex) {
- final IOException ioe = new IOException();
- ioe.initCause(ex);
- throw ioe;
- } finally {
- //setLength done, unlock the inode from the cache
- iNode.decLocked();
- }
- } // synchronized(inode)
- }
+ return;
+ }
+ } catch (Throwable ex) {
+ final IOException ioe = new IOException();
+ ioe.initCause(ex);
+ throw ioe;
+ } finally {
+ // setLength done, unlock the inode from the cache
+ iNode.decLocked();
+ }
+ } // synchronized(inode)
+ }
+ @Override
+ public void read(long fileOffset, ByteBuffer destBuf) throws IOException {
+ if (fileOffset + destBuf.remaining() > getLength()) throw new IOException("Can't read past the file!");
+ readImpl(fileOffset, destBuf);
+ }
- @Override
- public void read(long fileOffset, ByteBuffer destBuf) throws IOException {
- final int len = destBuf.remaining();
- final int off = 0;
- //TODO optimize it also to use ByteBuffer at lower level
- final ByteBufferUtils.ByteArray destBA = ByteBufferUtils.toByteArray(destBuf);
- final byte[] dest = destBA.toArray();
+ /**
+ * A read implementation that doesn't check the file length.
+ * @param fileOffset the offset to read from.
+ * @param destBuf the destination buffer.
+ * @throws IOException if an error occurs reading.
+ */
+ public void readImpl(long fileOffset, ByteBuffer destBuf) throws IOException {
+ final int len = destBuf.remaining();
+ final int off = 0;
+ // TODO optimize it also to use ByteBuffer at lower level
+ final ByteBufferUtils.ByteArray destBA = ByteBufferUtils.toByteArray(destBuf);
+ final byte[] dest = destBA.toArray();
- //synchronize to the inode cache to make sure that the inode does not
- // get flushed between reading it and locking it
- synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {
- //reread the inode before synchronizing to it to make sure
- //all threads use the same instance
- rereadInode();
+ // synchronize to the inode cache to make sure that the inode does not
+ // get flushed between reading it and locking it
+ synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {
+ // reread the inode before synchronizing to it to make sure
+ // all threads use the same instance
+ rereadInode();
- //lock the inode into the cache so it is not flushed before
- // synchronizing to it
- //(otherwise a new instance of INode referring to the same inode
- // could be put
- //in the cache resulting in the possibility of two threads
- // manipulating the same
- //inode at the same time because they would synchronize to
- // different INode instances)
- iNode.incLocked();
- }
+ // lock the inode into the cache so it is not flushed before
+ // synchronizing to it
+ // (otherwise a new instance of INode referring to the same inode
+ // could be put
+ // in the cache resulting in the possibility of two threads
+ // manipulating the same
+ // inode at the same time because they would synchronize to
+ // different INode instances)
+ iNode.incLocked();
+ }
- if (log.isDebugEnabled()) {
- log.debug("File:" + entry.getName() + " size:" + getLength() + " read offset: " + fileOffset + " len: " +
- dest.length);
- }
+ if (log.isDebugEnabled()) {
+ log.debug("File:" + entry.getName() + " size:" + getLength() + " read offset: " + fileOffset + " len: "
+ + dest.length);
+ }
- //a single inode may be represented by more than one Ext2Directory
- // instances,
- //but each will use the same instance of the underlying inode (see
- // Ext2FileSystem.getINode()),
- //so synchronize to the inode
- synchronized (iNode) {
- try {
- if (len + off > getLength())
- throw new IOException("Can't read past the file!");
+ // a single inode may be represented by more than one Ext2Directory
+ // instances,
+ // but each will use the same instance of the underlying inode (see
+ // Ext2FileSystem.getINode()),
+ // so synchronize to the inode
+ synchronized (iNode) {
+ try {
+ if ((iNode.getMode() & Ext2Constants.EXT2_S_IFLNK) == Ext2Constants.EXT2_S_IFLNK) {
+ // Sym-links are a special case: the data seems to be stored inline in the iNode
+ System.arraycopy(iNode.getINodeBlockData(), 0, dest, 0, Math.min(64, dest.length));
+ } else {
+ long blockSize = iNode.getExt2FileSystem().getBlockSize();
+ long bytesRead = 0;
+ while (bytesRead < len) {
+ long blockNr = (fileOffset + bytesRead) / blockSize;
+ long blockOffset = (fileOffset + bytesRead) % blockSize;
+ long copyLength = Math.min(len - bytesRead, blockSize - blockOffset);
- if ((iNode.getMode() & Ext2Constants.EXT2_S_IFLNK) == Ext2Constants.EXT2_S_IFLNK) {
- // Sym-links are a special case: the data seems to be stored inline in the iNode
- System.arraycopy(iNode.getINodeBlockData(), 0, dest, 0, Math.min(64, dest.length));
- }
- else {
- long blockSize = iNode.getExt2FileSystem().getBlockSize();
- long bytesRead = 0;
- while (bytesRead < len) {
- long blockNr = (fileOffset + bytesRead) / blockSize;
- long blockOffset = (fileOffset + bytesRead) % blockSize;
- long copyLength = Math.min(len - bytesRead, blockSize - blockOffset);
+ log.debug("blockNr: " + blockNr + ", blockOffset: " + blockOffset + ", copyLength: "
+ + copyLength + ", bytesRead: " + bytesRead);
- log.debug("blockNr: " + blockNr + ", blockOffset: " + blockOffset + ", copyLength: " + copyLength +
- ", bytesRead: " + bytesRead);
+ System.arraycopy(iNode.getDataBlock(blockNr), (int) blockOffset, dest, off + (int) bytesRead,
+ (int) copyLength);
- System.arraycopy(iNode.getDataBlock(blockNr), (int) blockOffset, dest, off + (int) bytesRead,
- (int) copyLength);
+ bytesRead += copyLength;
+ }
+ }
+ } catch (Throwable ex) {
+ final IOException ioe = new IOException();
+ ioe.initCause(ex);
+ throw ioe;
+ } finally {
+ // read done, unlock the inode from the cache
+ iNode.decLocked();
+ }
+ }
- bytesRead += copyLength;
- }
- }
- } catch (Throwable ex) {
- final IOException ioe = new IOException();
- ioe.initCause(ex);
- throw ioe;
- } finally {
- //read done, unlock the inode from the cache
- iNode.decLocked();
- }
- }
+ destBA.refreshByteBuffer();
+ }
- destBA.refreshByteBuffer();
- }
+ @Override
+ public void write(long fileOffset, ByteBuffer srcBuf) throws IOException {
+ final int len = srcBuf.remaining();
+ final int off = 0;
+ // TODO optimize it also to use ByteBuffer at lower level
+ final byte[] src = ByteBufferUtils.toArray(srcBuf);
- @Override
- public void write(long fileOffset, ByteBuffer srcBuf) throws IOException {
- final int len = srcBuf.remaining();
- final int off = 0;
- //TODO optimize it also to use ByteBuffer at lower level
- final byte[] src = ByteBufferUtils.toArray(srcBuf);
+ if (getFileSystem().isReadOnly()) {
+ throw new ReadOnlyFileSystemException("write in readonly filesystem");
+ }
- if (getFileSystem().isReadOnly()) {
- throw new ReadOnlyFileSystemException("write in readonly filesystem");
- }
+ // synchronize to the inode cache to make sure that the inode does not
+ // get
+ // flushed between reading it and locking it
+ synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {
+ // reread the inode before synchronizing to it to make sure
+ // all threads use the same instance
+ rereadInode();
- //synchronize to the inode cache to make sure that the inode does not
- // get
- //flushed between reading it and locking it
- synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {
- //reread the inode before synchronizing to it to make sure
- //all threads use the same instance
- rereadInode();
+ // lock the inode into the cache so it is not flushed before
+ // synchronizing to it
+ // (otherwise a new instance of INode referring to the same inode
+ // could be put
+ // in the cache resulting in the possibility of two threads
+ // manipulating the same
+ // inode at the same time because they would synchronize to
+ // different INode instances)
+ iNode.incLocked();
+ }
+ try {
+ // a single inode may be represented by more than one Ext2File
+ // instances,
+ // but each will use the same instance of the underlying inode (see
+ // Ext2FileSystem.getINode()),
+ // so synchronize to the inode
+ synchronized (iNode) {
+ if (fileOffset > getLength()) throw new IOException(
+ "Can't write beyond the end of the file! (fileOffset: " + fileOffset + ", getLength()"
+ + getLength());
+ if (off + len > src.length) throw new IOException("src is shorter than what you want to write");
- //lock the inode into the cache so it is not flushed before
- // synchronizing to it
- //(otherwise a new instance of INode referring to the same inode
- // could be put
- //in the cache resulting in the possibility of two threads
- // manipulating the same
- //inode at the same time because they would synchronize to
- // different INode instances)
- iNode.incLocked();
- }
- try {
- //a single inode may be represented by more than one Ext2File
- // instances,
- //but each will use the same instance of the underlying inode (see
- // Ext2FileSystem.getINode()),
- //so synchronize to the inode
- synchronized (iNode) {
- if (fileOffset > getLength())
- throw new IOException("Can't write beyond the end of the file! (fileOffset: " + fileOffset +
- ", getLength()" + getLength());
- if (off + len > src.length)
- throw new IOException("src is shorter than what you want to write");
+ log.debug("write(fileOffset=" + fileOffset + ", src, off, len=" + len + ")");
- log.debug("write(fileOffset=" + fileOffset + ", src, off, len=" + len + ")");
+ final long blockSize = iNode.getExt2FileSystem().getBlockSize();
+ long blocksAllocated = iNode.getAllocatedBlockCount();
+ long bytesWritten = 0;
+ while (bytesWritten < len) {
+ long blockIndex = (fileOffset + bytesWritten) / blockSize;
+ long blockOffset = (fileOffset + bytesWritten) % blockSize;
+ long copyLength = Math.min(len - bytesWritten, blockSize - blockOffset);
- final long blockSize = iNode.getExt2FileSystem().getBlockSize();
- long blocksAllocated = iNode.getAllocatedBlockCount();
- long bytesWritten = 0;
- while (bytesWritten < len) {
- long blockIndex = (fileOffset + bytesWritten) / blockSize;
- long blockOffset = (fileOffset + bytesWritten) % blockSize;
- long copyLength = Math.min(len - bytesWritten, blockSize - blockOffset);
+ // If only a part of the block is written, then read the
+ // block and update its contents with the data in src. If the
+ // whole block is overwritten, then skip reading it.
+ byte[] dest;
+ if (!((blockOffset == 0) && (copyLength == blockSize)) && (blockIndex < blocksAllocated)) dest = iNode.getDataBlock(blockIndex);
+ else dest = new byte[(int) blockSize];
- //If only a part of the block is written, then read the
- //block and update its contents with the data in src. If the
- //whole block is overwritten, then skip reading it.
- byte[] dest;
- if (!((blockOffset == 0) && (copyLength == blockSize)) && (blockIndex < blocksAllocated))
- dest = iNode.getDataBlock(blockIndex);
- else
- dest = new byte[(int) blockSize];
+ System.arraycopy(src, (int) (off + bytesWritten), dest, (int) blockOffset, (int) copyLength);
- System.arraycopy(src, (int) (off + bytesWritten), dest, (int) blockOffset, (int) copyLength);
+ // allocate a new block if needed
+ if (blockIndex >= blocksAllocated) {
+ try {
+ iNode.allocateDataBlock(blockIndex);
+ } catch (FileSystemException ex) {
+ final IOException ioe = new IOException("Internal filesystem exception");
+ ioe.initCause(ex);
+ throw ioe;
+ }
+ blocksAllocated++;
+ }
- //allocate a new block if needed
- if (blockIndex >= blocksAllocated) {
- try {
- iNode.allocateDataBlock(blockIndex);
- } catch (FileSystemException ex) {
- final IOException ioe = new IOException("Internal filesystem exception");
- ioe.initCause(ex);
- throw ioe;
- }
- blocksAllocated++;
- }
+ // write the block
+ iNode.writeDataBlock(blockIndex, dest);
- //write the block
- iNode.writeDataBlock(blockIndex, dest);
+ bytesWritten += copyLength;
+ }
+ iNode.setSize(fileOffset + len);
- bytesWritten += copyLength;
- }
- iNode.setSize(fileOffset + len);
+ iNode.setMtime(System.currentTimeMillis() / 1000);
+ }
+ } catch (IOException ex) {
+ // ... this avoids wrapping an IOException inside another one.
+ throw ex;
+ } catch (Throwable ex) {
+ final IOException ioe = new IOException();
+ ioe.initCause(ex);
+ throw ioe;
+ } finally {
+ // write done, unlock the inode from the cache
+ iNode.decLocked();
+ }
+ }
- iNode.setMtime(System.currentTimeMillis() / 1000);
- }
- } catch (IOException ex) {
- // ... this avoids wrapping an IOException inside another one.
- throw ex;
- } catch (Throwable ex) {
- final IOException ioe = new IOException();
- ioe.initCause(ex);
- throw ioe;
- } finally {
- //write done, unlock the inode from the cache
- iNode.decLocked();
- }
- }
+ @Override
+ public void flush() throws IOException {
+ log.debug("Ext2File.flush()");
+ iNode.update();
+ // update the group descriptors and superblock: needed if blocks have
+ // been allocated or deallocated
+ iNode.getExt2FileSystem().updateFS();
+ }
- @Override
- public void flush() throws IOException {
- log.debug("Ext2File.flush()");
- iNode.update();
- //update the group descriptors and superblock: needed if blocks have
- //been allocated or deallocated
- iNode.getExt2FileSystem().updateFS();
- }
+ private long getLengthInBlocks() {
+ return iNode.getSizeInBlocks();
+ }
- private long getLengthInBlocks() {
- return iNode.getSizeInBlocks();
- }
+ private void rereadInode() throws IOException {
+ int iNodeNr = iNode.getINodeNr();
+ try {
+ iNode = ((Ext2FileSystem) getFileSystem()).getINode(iNodeNr);
+ } catch (FileSystemException ex) {
+ final IOException ioe = new IOException();
+ ioe.initCause(ex);
+ throw ioe;
+ }
+ }
- private void rereadInode() throws IOException {
- int iNodeNr = iNode.getINodeNr();
- try {
- iNode = ((Ext2FileSystem) getFileSystem()).getINode(iNodeNr);
- } catch (FileSystemException ex) {
- final IOException ioe = new IOException();
- ioe.initCause(ex);
- throw ioe;
- }
- }
+ @Override
+ public byte[] getSlackSpace() throws IOException {
+ int blockSize = ((Ext2FileSystem) getFileSystem()).getBlockSize();
+
+ int slackSpaceSize = blockSize - (int) (getLength() % blockSize);
+
+ if (slackSpaceSize == blockSize) {
+ slackSpaceSize = 0;
+ }
+
+ byte[] slackSpace = new byte[slackSpaceSize];
+ readImpl(getLength(), ByteBuffer.wrap(slackSpace));
+
+ return slackSpace;
+ }
}
Modified: trunk/fs/src/fs/org/jnode/fs/ext2/Ext2FileSystem.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/ext2/Ext2FileSystem.java 2012-10-24 07:04:00 UTC (rev 5935)
+++ trunk/fs/src/fs/org/jnode/fs/ext2/Ext2FileSystem.java 2012-12-19 08:38:08 UTC (rev 5936)
@@ -17,7 +17,7 @@
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
+
package org.jnode.fs.ext2;
import java.io.IOException;
@@ -39,940 +39,868 @@
/**
* @author Andras Nagy
- *
*/
public class Ext2FileSystem extends AbstractFileSystem<Ext2Entry> {
- private Superblock superblock;
+ private Superblock superblock;
- private GroupDescriptor groupDescriptors[];
+ private GroupDescriptor groupDescriptors[];
- private INodeTable iNodeTables[];
+ private INodeTable iNodeTables[];
- private int groupCount;
+ private int groupCount;
- private BlockCache blockCache;
+ private BlockCache blockCache;
- private INodeCache inodeCache;
+ private INodeCache inodeCache;
- private final Logger log = Logger.getLogger(getClass());
+ private final Logger log = Logger.getLogger(getClass());
- // private Object groupDescriptorLock;
- // private Object superblockLock;
+ // private Object groupDescriptorLock;
+ // private Object superblockLock;
- // private final boolean DEBUG=true;
+ // private final boolean DEBUG=true;
- // TODO: SYNC_WRITE should be made a parameter
- /** if true, writeBlock() does not return until the block is written to disk */
- private boolean SYNC_WRITE = true;
+ // TODO: SYNC_WRITE should be made a parameter
+ /** if true, writeBlock() does not return until the block is written to disk */
+ private boolean SYNC_WRITE = true;
- /**
- * Constructor for Ext2FileSystem in specified readOnly mode
- *
- * @throws FileSystemException
- */
- public Ext2FileSystem(Device device, boolean readOnly, Ext2FileSystemType type) throws FileSystemException {
- super(device, readOnly, type);
- log.setLevel(Level.DEBUG);
+ /**
+ * Constructor for Ext2FileSystem in specified readOnly mode
+ * @throws FileSystemException
+ */
+ public Ext2FileSystem(Device device, boolean readOnly, Ext2FileSystemType type) throws FileSystemException {
+ super(device, readOnly, type);
+ log.setLevel(Level.DEBUG);
- blockCache = new BlockCache(50, (float) 0.75);
- inodeCache = new INodeCache(50, (float) 0.75);
+ blockCache = new BlockCache(50, (float) 0.75);
+ inodeCache = new INodeCache(50, (float) 0.75);
- // groupDescriptorLock = new Object();
- // superblockLock = new Object();
- }
+ // groupDescriptorLock = new Object();
+ // superblockLock = new Object();
+ }
- public void read() throws FileSystemException {
- ByteBuffer data;
+ public void read() throws FileSystemException {
+ ByteBuffer data;
- try {
- data = ByteBuffer.allocate(Superblock.SUPERBLOCK_LENGTH);
+ try {
+ data = ByteBuffer.allocate(Superblock.SUPERBLOCK_LENGTH);
- // skip the first 1024 bytes (bootsector) and read the superblock
- // TODO: the superblock should read itself
- getApi().read(1024, data);
- // superblock = new SuperBlock(data, this);
- superblock = new Superblock();
- superblock.read(data.array(), this);
+ // skip the first 1024 bytes (bootsector) and read the superblock
+ // TODO: the superblock should read itself
+ getApi().read(1024, data);
+ // superblock = new SuperBlock(data, this);
+ superblock = new Superblock();
+ superblock.read(data.array(), this);
- // read the group descriptors
- groupCount = (int) Ext2Utils.ceilDiv(superblock.getBlocksCount(), superblock.getBlocksPerGroup());
- groupDescriptors = new GroupDescriptor[groupCount];
- iNodeTables = new INodeTable[groupCount];
+ // read the group descriptors
+ groupCount = (int) Ext2Utils.ceilDiv(superblock.getBlocksCount(), superblock.getBlocksPerGroup());
+ groupDescriptors = new GroupDescriptor[groupCount];
+ iNodeTables = new INodeTable[groupCount];
- for (int i = 0; i < groupCount; i++) {
- // groupDescriptors[i]=new GroupDescriptor(i, this);
- groupDescriptors[i] = new GroupDescriptor();
- groupDescriptors[i].read(i, this);
+ for(int i = 0; i < groupCount; i++) {
+ // groupDescriptors[i]=new GroupDescriptor(i, this);
+ groupDescriptors[i] = new GroupDescriptor();
+ groupDescriptors[i].read(i, this);
- iNodeTables[i] = new INodeTable(this, (int) groupDescriptors[i].getInodeTable());
- }
+ iNodeTables[i] = new INodeTable(this, (int) groupDescriptors[i].getInodeTable());
+ }
- } catch (FileSystemException e) {
- throw e;
- } catch (Exception e) {
- throw new FileSystemException(e);
- }
+ } catch (FileSystemException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new FileSystemException(e);
+ }
- // check for unsupported filesystem options
- // (an unsupported INCOMPAT feature means that the fs may not be mounted
- // at all)
- if (hasIncompatFeature(Ext2Constants.EXT2_FEATURE_INCOMPAT_COMPRESSION))
- throw new FileSystemException(getDevice().getId() +
- " Unsupported filesystem feature (COMPRESSION) disallows mounting");
- if (hasIncompatFeature(Ext2Constants.EXT2_FEATURE_INCOMPAT_META_BG))
- throw new FileSystemException(getDevice().getId() +
- " Unsupported filesystem feature (META_BG) disallows mounting");
- if (hasIncompatFeature(Ext2Constants.EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
- throw new FileSystemException(getDevice().getId() +
- " Unsupported filesystem feature (JOURNAL_DEV) disallows mounting");
-// if (hasIncompatFeature(Ext2Constants.EXT3_FEATURE_INCOMPAT_RECOVER))
-// throw new FileSystemException(getDevice().getId() +
-// " Unsupported filesystem feature (RECOVER) disallows mounting");
-// if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_EXTENTS))
-// throw new FileSystemException(getDevice().getId() +
-// " Unsupported filesystem feature (EXTENTS) disallows mounting");
- if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_64BIT))
- throw new FileSystemException(getDevice().getId() +
- " Unsupported filesystem feature (64BIT) disallows mounting");
- if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_MMP))
- throw new FileSystemException(getDevice().getId() +
- " Unsupported filesystem feature (MMP) disallows mounting");
- if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_FLEX_BG))
- throw new FileSystemException(getDevice().getId() +
- " Unsupported filesystem feature (FLEX_BG) disallows mounting");
+ // check for unsupported filesystem options
+ // (an unsupported INCOMPAT feature means that the fs may not be mounted
+ // at all)
+ if (hasIncompatFeature(Ext2Constants.EXT2_FEATURE_INCOMPAT_COMPRESSION)) throw new FileSystemException(
+ getDevice().getId() + " Unsupported filesystem feature (COMPRESSION) disallows mounting");
+ if (hasIncompatFeature(Ext2Constants.EXT2_FEATURE_INCOMPAT_META_BG)) throw new FileSystemException(
+ getDevice().getId() + " Unsupported filesystem feature (META_BG) disallows mounting");
+ if (hasIncompatFeature(Ext2Constants.EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) throw new FileSystemException(
+ getDevice().getId() + " Unsupported filesystem feature (JOURNAL_DEV) disallows mounting");
+ // if (hasIncompatFeature(Ext2Constants.EXT3_FEATURE_INCOMPAT_RECOVER))
+ // throw new FileSystemException(getDevice().getId() +
+ // " Unsupported filesystem feature (RECOVER) disallows mounting");
+ // if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_EXTENTS))
+ // throw new FileSystemException(getDevice().getId() +
+ // " Unsupported filesystem feature (EXTENTS) disallows mounting");
+ if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_64BIT)) throw new FileSystemException(
+ getDevice().getId() + " Unsupported filesystem feature (64BIT) disallows mounting");
+ if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_MMP)) throw new FileSystemException(
+ getDevice().getId() + " Unsupported filesystem feature (MMP) disallows mounting");
+ if (hasIncompatFeature(Ext2Constants.EXT4_FEATURE_INCOMPAT_FLEX_BG)) throw new FileSystemException(
+ getDevice().getId() + " Unsupported filesystem feature (FLEX_BG) disallows mounting");
- // an unsupported RO_COMPAT feature means that the filesystem can only
- // be mounted readonly
- if (hasROFeature(Ext2Constants.EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
- log.info(getDevice().getId() + " Unsupported filesystem feature (LARGE_FILE) forces readonly mode");
- setReadOnly(true);
- }
- if (hasROFeature(Ext2Constants.EXT2_FEATURE_RO_COMPAT_BTREE_DIR)) {
- log.info(getDevice().getId() + " Unsupported filesystem feature (BTREE_DIR) forces readonly mode");
- setReadOnly(true);
- }
- if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
- log.info(getDevice().getId() + " Unsupported filesystem feature (HUGE_FILE) forces readonly mode");
- setReadOnly(true);
- }
- if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
- log.info(getDevice().getId() + " Unsupported filesystem feature (GDT_CSUM) forces readonly mode");
- setReadOnly(true);
- }
- if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_DIR_NLINK)) {
- log.info(getDevice().getId() + " Unsupported filesystem feature (DIR_NLINK) forces readonly mode");
- setReadOnly(true);
- }
- if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) {
- log.info(getDevice().getId() + " Unsupported filesystem feature (EXTRA_ISIZE) forces readonly mode");
- setReadOnly(true);
- }
+ // an unsupported RO_COMPAT feature means that the filesystem can only
+ // be mounted readonly
+ if (hasROFeature(Ext2Constants.EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
+ log.info(getDevice().getId() + " Unsupported filesystem feature (LARGE_FILE) forces readonly mode");
+ setReadOnly(true);
+ }
+ if (hasROFeature(Ext2Constants.EXT2_FEATURE_RO_COMPAT_BTREE_DIR)) {
+ log.info(getDevice().getId() + " Unsupported filesystem feature (BTREE_DIR) forces readonly mode");
+ setReadOnly(true);
+ }
+ if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
+ log.info(getDevice().getId() + " Unsupported filesystem feature (HUGE_FILE) forces readonly mode");
+ setReadOnly(true);
+ }
+ if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ log.info(getDevice().getId() + " Unsupported filesystem feature (GDT_CSUM) forces readonly mode");
+ setReadOnly(true);
+ }
+ if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_DIR_NLINK)) {
+ log.info(getDevice().getId() + " Unsupported filesystem feature (DIR_NLINK) forces readonly mode");
+ setReadOnly(true);
+ }
+ if (hasROFeature(Ext2Constants.EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) {
+ log.info(getDevice().getId() + " Unsupported filesystem feature (EXTRA_ISIZE) forces readonly mode");
+ setReadOnly(true);
+ }
- // if the filesystem has not been cleanly unmounted, mount it readonly
- if (superblock.getState() == Ext2Constants.EXT2_ERROR_FS) {
- log.info(getDevice().getId() + " Filesystem has not been cleanly unmounted, mounting it readonly");
- setReadOnly(true);
- }
+ // if the filesystem has not been cleanly unmounted, mount it readonly
+ if (superblock.getState() == Ext2Constants.EXT2_ERROR_FS) {
+ log.info(getDevice().getId() + " Filesystem has not been cleanly unmounted, mounting it readonly");
+ setReadOnly(true);
+ }
- // if the filesystem has been mounted R/W, set it to "unclean"
- if (!isReadOnly()) {
- log.info(getDevice().getId() + " mounting fs r/w");
- superblock.setState(Ext2Constants.EXT2_ERROR_FS);
- }
- // Mount successfull, update some superblock informations.
- superblock.setMntCount(superblock.getMntCount() + 1);
- superblock.setMTime(Ext2Utils.encodeDate(new Date()));
- superblock.setWTime(Ext2Utils.encodeDate(new Date()));
- SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy");
- log.debug(" superblock: " + "\n" +
- " #Mount: " + superblock.getMntCount() + "\n" +
- " #MaxMount: " + superblock.getMaxMntCount() + "\n" + " Last mount time: " +
- sdf.format(Ext2Utils.decodeDate(superblock.getMTime()).getTime()) + "\n" +
- " Last write time: " +
- sdf.format(Ext2Utils.decodeDate(superblock.getWTime()).getTime()) + "\n" +
- " #blocks: " + superblock.getBlocksCount() + "\n" +
- " #blocks/group: " + superblock.getBlocksPerGroup() + "\n" +
- " #block groups: " + groupCount + "\n" +
- " block size: " + superblock.getBlockSize() + "\n" +
- " #inodes: " + superblock.getINodesCount() + "\n" +
- " #inodes/group: " + superblock.getINodesPerGroup());
- }
+ // if the filesystem has been mounted R/W, set it to "unclean"
+ if (!isReadOnly()) {
+ log.info(getDevice().getId() + " mounting fs r/w");
+ superblock.setState(Ext2Constants.EXT2_ERROR_FS);
+ }
+ // Mount successfull, update some superblock informations.
+ superblock.setMntCount(superblock.getMntCount() + 1);
+ superblock.setMTime(Ext2Utils.encodeDate(new Date()));
+ superblock.setWTime(Ext2Utils.encodeDate(new Date()));
+ SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy");
+ log.debug(" superblock: " + "\n" + " #Mount: " + superblock.getMntCount() + "\n" + " #MaxMount: "
+ + superblock.getMaxMntCount() + "\n" + " Last mount time: "
+ + sdf.format(Ext2Utils.decodeDate(superblock.getMTime()).getTime()) + "\n" + " Last write time: "
+ + sdf.format(Ext2Utils.decodeDate(superblock.getWTime()).getTime()) + "\n" + " #blocks: "
+ + superblock.getBlocksCount() + "\n" + " #blocks/group: " + superblock.getBlocksPerGroup() + "\n"
+ + " #block groups: " + groupCount + "\n" + " block size: " + superblock.getBlockSize() + "\n"
+ + " #inodes: " + superblock.getINodesCount() + "\n" + " #inodes/group: "
+ + superblock.getINodesPerGroup());
+ }
- public void create(BlockSize blockSize) throws FileSystemException {
- try {
- // create the superblock
- superblock = new Superblock();
- superblock.create(blockSize, this);
+ public void create(BlockSize blockSize) throws FileSystemException {
+ try {
+ // create the superblock
+ superblock = new Superblock();
+ superblock.create(blockSize, this);
- // create the group descriptors
- groupCount = (int) Ext2Utils.ceilDiv(superblock.getBlocksCount(), superblock.getBlocksPerGroup());
- groupDescriptors = new GroupDescriptor[groupCount];
+ // create the group descriptors
+ groupCount = (int) Ext2Utils.ceilDiv(superblock.getBlocksCount(), superblock.getBlocksPerGroup());
+ groupDescriptors = new GroupDescriptor[groupCount];
- iNodeTables = new INodeTable[groupCount];
+ iNodeTables = new INodeTable[groupCount];
- for (int i = 0; i < groupCount; i++) {
- groupDescriptors[i] = new GroupDescriptor();
- groupDescriptors[i].create(i, this);
- }
+ for(int i = 0; i < groupCount; i++) {
+ groupDescriptors[i] = new GroupDescriptor();
+ groupDescriptors[i].create(i, this);
+ }
- // create each block group:
- // create the block bitmap
- // create the inode bitmap
- // fill the inode table with zeroes
- for (int i = 0; i < groupCount; i++) {
- log.debug("creating group " + i);
+ // create each block group:
+ // create the block bitmap
+ // create the inode bitmap
+ // fill the inode table with zeroes
+ for(int i = 0; i < groupCount; i++) {
+ log.debug("creating group " + i);
- byte[] blockBitmap = new byte[blockSize.getSize()];
- byte[] inodeBitmap = new byte[blockSize.getSize()];
+ byte[] blockBitmap = new byte[blockSize.getSize()];
+ byte[] inodeBitmap = new byte[blockSize.getSize()];
- // update the block bitmap: mark the metadata blocks allocated
- long iNodeTableBlock = groupDescriptors[i].getInodeTable();
- long firstNonMetadataBlock = iNodeTableBlock + INodeTable.getSizeInBlocks(this);
- int metadataLength =
- (int) (firstNonMetadataBlock - (superblock.getFirstDataBlock() + i *
- superblock.getBlocksPerGroup()));
- for (int j = 0; j < metadataLength; j++)
- BlockBitmap.setBit(blockBitmap, j);
+ // update the block bitmap: mark the metadata blocks allocated
+ long iNodeTableBlock = groupDescriptors[i].getInodeTable();
+ long firstNonMetadataBlock = iNodeTableBlock + INodeTable.getSizeInBlocks(this);
+ int metadataLength = (int) (firstNonMetadataBlock - (superblock.getFirstDataBlock() + i
+ * superblock.getBlocksPerGroup()));
+ for(int j = 0; j < metadataLength; j++)
+ BlockBitmap.setBit(blockBitmap, j);
- // set the padding at the end of the last block group
- if (i == groupCount - 1) {
- for (long k = superblock.getBlocksCount(); k < groupCount * superblock.getBlocksPerGroup(); k++)
- BlockBitmap.setBit(blockBitmap, (int) (k % superblock.getBlocksPerGroup()));
- }
+ // set the padding at the end of the last block group
+ if (i == groupCount - 1) {
+ for(long k = superblock.getBlocksCount(); k < groupCount * superblock.getBlocksPerGroup(); k++)
+ BlockBitmap.setBit(blockBitmap, (int) (k % superblock.getBlocksPerGroup()));
+ }
- // update the inode bitmap: mark the special inodes allocated in
- // the first block group
- if (i == 0)
- for (int j = 0; j < superblock.getFirstInode() - 1; j++)
- INodeBitmap.setBit(inodeBitmap, j);
+ // update the inode bitmap: mark the special inodes allocated in
+ // the first block group
+ if (i == 0) for(int j = 0; j < superblock.getFirstInode() - 1; j++)
+ INodeBitmap.setBit(inodeBitmap, j);
- // create an empty inode table
- byte[] emptyBlock = new byte[blockSize.getSize()];
- for (long j = iNodeTableBlock; j < firstNonMetadataBlock; j++)
- writeBlock(j, emptyBlock, false);
+ // create an empty inode table
+ byte[] emptyBlock = new byte[blockSize.getSize()];
+ for(long j = iNodeTableBlock; j < firstNonMetadataBlock; j++)
+ writeBlock(j, emptyBlock, false);
- iNodeTables[i] = new INodeTable(this, (int) iNodeTableBlock);
+ iNodeTables[i] = new INodeTable(this, (int) iNodeTableBlock);
- writeBlock(groupDescriptors[i].getBlockBitmap(), blockBitmap, false);
- writeBlock(groupDescriptors[i].getInodeBitmap(), inodeBitmap, false);
- }
+ writeBlock(groupDescriptors[i].getBlockBitmap(), blockBitmap, false);
+ writeBlock(groupDescriptors[i].getInodeBitmap(), inodeBitmap, false);
+ }
- log.info("superblock.getBlockSize(): " + superblock.getBlockSize());
+ log.info("superblock.getBlockSize(): " ...
[truncated message content] |