summaryrefslogtreecommitdiff
path: root/src/main/java/de/waldheinz/fs/fat/FsInfoSector.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/waldheinz/fs/fat/FsInfoSector.java')
-rw-r--r--src/main/java/de/waldheinz/fs/fat/FsInfoSector.java187
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 &lt;waldheinz at gmail.com&gt;
+ * @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
+ }
+
+}