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] |