diff options
Diffstat (limited to 'src/main/java/de/waldheinz/fs/fat/FsInfoSector.java')
-rw-r--r-- | src/main/java/de/waldheinz/fs/fat/FsInfoSector.java | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/main/java/de/waldheinz/fs/fat/FsInfoSector.java b/src/main/java/de/waldheinz/fs/fat/FsInfoSector.java new file mode 100644 index 0000000..0399a9f --- /dev/null +++ b/src/main/java/de/waldheinz/fs/fat/FsInfoSector.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2009,2010 Matthias Treydte <mt@waldheinz.de> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package de.waldheinz.fs.fat; + +import de.waldheinz.fs.BlockDevice; +import java.io.IOException; + +/** + * The FAT32 File System Information Sector. + * + * @author Matthias Treydte <waldheinz at gmail.com> + * @see http://en.wikipedia.org/wiki/File_Allocation_Table#FS_Information_Sector + */ +final class FsInfoSector extends Sector { + + /** + * The offset to the free cluster count value in the FS info sector. + */ + public static final int FREE_CLUSTERS_OFFSET = 0x1e8; + + /** + * The offset to the "last allocated cluster" value in this sector. + */ + public static final int LAST_ALLOCATED_OFFSET = 0x1ec; + + /** + * The offset to the signature of this sector. + */ + public static final int SIGNATURE_OFFSET = 0x1fe; + + private FsInfoSector(BlockDevice device, long offset) { + super(device, offset, BootSector.SIZE); + } + + /** + * Reads a {@code FsInfoSector} as specified by the given + * {@code Fat32BootSector}. + * + * @param bs the boot sector that specifies where the FS info sector is + * stored + * @return the FS info sector that was read + * @throws IOException on read error + * @see Fat32BootSector#getFsInfoSectorNr() + */ + public static FsInfoSector read(Fat32BootSector bs) throws IOException { + final FsInfoSector result = + new FsInfoSector(bs.getDevice(), offset(bs)); + + result.read(); + result.verify(); + return result; + } + + /** + * Creates an new {@code FsInfoSector} where the specified + * {@code Fat32BootSector} indicates it should be. + * + * @param bs the boot sector specifying the FS info sector storage + * @return the FS info sector instance that was created + * @throws IOException on write error + * @see Fat32BootSector#getFsInfoSectorNr() + */ + public static FsInfoSector create(Fat32BootSector bs) throws IOException { + final int offset = offset(bs); + + if (offset == 0) throw new IOException( + "creating a FS info sector at offset 0 is strange"); + + final FsInfoSector result = + new FsInfoSector(bs.getDevice(), offset(bs)); + + result.init(); + result.write(); + return result; + } + + private static int offset(Fat32BootSector bs) { + return bs.getFsInfoSectorNr() * bs.getBytesPerSector(); + } + + /** + * Sets the number of free clusters on the file system stored at + * {@link #FREE_CLUSTERS_OFFSET}. + * + * @param value the new free cluster count + * @see Fat#getFreeClusterCount() + */ + public void setFreeClusterCount(long value) { + if (getFreeClusterCount() == value) return; + + set32(FREE_CLUSTERS_OFFSET, value); + } + + /** + * Returns the number of free clusters on the file system as sepcified by + * the 32-bit value at {@link #FREE_CLUSTERS_OFFSET}. + * + * @return the number of free clusters + * @see Fat#getFreeClusterCount() + */ + public long getFreeClusterCount() { + return get32(FREE_CLUSTERS_OFFSET); + } + + /** + * Sets the last allocated cluster that was used in the {@link Fat}. + * + * @param value the FAT's last allocated cluster number + * @see Fat#getLastAllocatedCluster() + */ + public void setLastAllocatedCluster(long value) { + if (getLastAllocatedCluster() == value) return; + + super.set32(LAST_ALLOCATED_OFFSET, value); + } + + /** + * Returns the last allocated cluster number of the {@link Fat} of the + * file system this FS info sector is part of. + * + * @return the last allocated cluster number + * @see Fat#getLastAllocatedCluster() + */ + public long getLastAllocatedCluster() { + return super.get32(LAST_ALLOCATED_OFFSET); + } + + private void init() { + buffer.position(0x00); + buffer.put((byte) 0x52); + buffer.put((byte) 0x52); + buffer.put((byte) 0x61); + buffer.put((byte) 0x41); + + /* 480 reserved bytes */ + + buffer.position(0x1e4); + buffer.put((byte) 0x72); + buffer.put((byte) 0x72); + buffer.put((byte) 0x41); + buffer.put((byte) 0x61); + + setFreeClusterCount(-1); + setLastAllocatedCluster(Fat.FIRST_CLUSTER); + + buffer.position(SIGNATURE_OFFSET); + buffer.put((byte) 0x55); + buffer.put((byte) 0xaa); + + markDirty(); + } + + private void verify() throws IOException { + if (!(get8(SIGNATURE_OFFSET) == 0x55) || + !(get8(SIGNATURE_OFFSET + 1) == 0xaa)) { + + throw new IOException("invalid FS info sector signature"); + } + } + + @Override + public String toString() { + return FsInfoSector.class.getSimpleName() + + " [freeClusterCount=" + getFreeClusterCount() + //NOI18N + ", lastAllocatedCluster=" + getLastAllocatedCluster() + //NOI18N + ", offset=" + getOffset() + //NOI18N + ", dirty=" + isDirty() + //NOI18N + "]"; //NOI18N + } + +} |