diff options
Diffstat (limited to 'src/main/java/de/waldheinz/fs/fat/ClusterChainDirectory.java')
-rw-r--r-- | src/main/java/de/waldheinz/fs/fat/ClusterChainDirectory.java | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/main/java/de/waldheinz/fs/fat/ClusterChainDirectory.java b/src/main/java/de/waldheinz/fs/fat/ClusterChainDirectory.java new file mode 100644 index 0000000..fa3e9df --- /dev/null +++ b/src/main/java/de/waldheinz/fs/fat/ClusterChainDirectory.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2003-2009 JNode.org + * 2009,2010 Matthias Treydte <mt@waldheinz.de> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package de.waldheinz.fs.fat; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * A directory that is stored in a cluster chain. + * + * @author Ewout Prangsma <epr at jnode.org> + * @author Matthias Treydte <waldheinz at gmail.com> + */ +class ClusterChainDirectory extends AbstractDirectory { + + /** + * According to the FAT specification, this is the maximum size a FAT + * directory may occupy on disk. The {@code ClusterChainDirectory} takes + * care not to grow beyond this limit. + * + * @see #changeSize(int) + */ + public final static int MAX_SIZE = 65536 * 32; + + /** + * The {@code ClusterChain} that stores this directory. Package-visible + * for testing. + */ + final ClusterChain chain; + + protected ClusterChainDirectory(ClusterChain chain, boolean isRoot) { + + super((int)(chain.getLengthOnDisk() / FatDirectoryEntry.SIZE), + chain.isReadOnly(), isRoot); + + this.chain = chain; + } + + public static ClusterChainDirectory readRoot( + ClusterChain chain) throws IOException { + + final ClusterChainDirectory result = + new ClusterChainDirectory(chain, true); + + result.read(); + return result; + } + + public static ClusterChainDirectory createRoot(Fat fat) throws IOException { + + if (fat.getFatType() != FatType.FAT32) { + throw new IllegalArgumentException( + "only FAT32 stores root directory in a cluster chain"); + } + + final Fat32BootSector bs = (Fat32BootSector) fat.getBootSector(); + final ClusterChain cc = new ClusterChain(fat, false); + cc.setChainLength(1); + + bs.setRootDirFirstCluster(cc.getStartCluster()); + + final ClusterChainDirectory result = + new ClusterChainDirectory(cc, true); + + result.flush(); + return result; + } + + @Override + protected final void read(ByteBuffer data) throws IOException { + this.chain.readData(0, data); + } + + @Override + protected final void write(ByteBuffer data) throws IOException { + final int toWrite = data.remaining(); + chain.writeData(0, data); + final long trueSize = chain.getLengthOnDisk(); + + /* TODO: check if the code below is really needed */ + if (trueSize > toWrite) { + final int rest = (int) (trueSize - toWrite); + final ByteBuffer fill = ByteBuffer.allocate(rest); + chain.writeData(toWrite, fill); + } + } + + /** + * Returns the first cluster of the chain that stores this directory for + * non-root instances or 0 if this is the root directory. + * + * @return the first storage cluster of this directory + * @see #isRoot() + */ + @Override + protected final long getStorageCluster() { + return isRoot() ? 0 : chain.getStartCluster(); + } + + public final void delete() throws IOException { + chain.setChainLength(0); + } + + @Override + protected final void changeSize(int entryCount) + throws IOException, IllegalArgumentException { + + assert (entryCount >= 0); + + final int size = entryCount * FatDirectoryEntry.SIZE; + + if (size > MAX_SIZE) throw new DirectoryFullException( + "directory would grow beyond " + MAX_SIZE + " bytes", + getCapacity(), entryCount); + + sizeChanged(chain.setSize(Math.max(size, chain.getClusterSize()))); + } + +} |