summaryrefslogtreecommitdiff
path: root/src/main/java/de/waldheinz/fs/fat/Fat16BootSector.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/waldheinz/fs/fat/Fat16BootSector.java')
-rw-r--r--src/main/java/de/waldheinz/fs/fat/Fat16BootSector.java233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/main/java/de/waldheinz/fs/fat/Fat16BootSector.java b/src/main/java/de/waldheinz/fs/fat/Fat16BootSector.java
new file mode 100644
index 0000000..38bdc2e
--- /dev/null
+++ b/src/main/java/de/waldheinz/fs/fat/Fat16BootSector.java
@@ -0,0 +1,233 @@
+/*
+ * 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 boot sector layout as used by the FAT12 / FAT16 variants.
+ *
+ * @author Matthias Treydte &lt;matthias.treydte at meetwise.com&gt;
+ */
+final class Fat16BootSector extends BootSector {
+
+ /**
+ * The default number of entries for the root directory.
+ *
+ * @see #getRootDirEntryCount()
+ * @see #setRootDirEntryCount(int)
+ */
+ public static final int DEFAULT_ROOT_DIR_ENTRY_COUNT = 512;
+
+ /**
+ * The default volume label.
+ */
+ public static final String DEFAULT_VOLUME_LABEL = "NO NAME"; //NOI18N
+
+ /**
+ * The maximum number of clusters for a FAT12 file system. This is actually
+ * the number of clusters where mkdosfs stop complaining about a FAT16
+ * partition having not enough sectors, so it would be misinterpreted
+ * as FAT12 without special handling.
+ *
+ * @see #getNrLogicalSectors()
+ */
+ public static final int MAX_FAT12_CLUSTERS = 4084;
+
+ public static final int MAX_FAT16_CLUSTERS = 65524;
+
+ /**
+ * The offset to the sectors per FAT value.
+ */
+ public static final int SECTORS_PER_FAT_OFFSET = 0x16;
+
+ /**
+ * The offset to the root directory entry count value.
+ *
+ * @see #getRootDirEntryCount()
+ * @see #setRootDirEntryCount(int)
+ */
+ public static final int ROOT_DIR_ENTRIES_OFFSET = 0x11;
+
+ /**
+ * The offset to the first byte of the volume label.
+ */
+ public static final int VOLUME_LABEL_OFFSET = 0x2b;
+
+ /**
+ * Offset to the FAT file system type string.
+ *
+ * @see #getFileSystemType()
+ */
+ public static final int FILE_SYSTEM_TYPE_OFFSET = 0x36;
+
+ /**
+ * The maximum length of the volume label.
+ */
+ public static final int MAX_VOLUME_LABEL_LENGTH = 11;
+
+ public static final int EXTENDED_BOOT_SIGNATURE_OFFSET = 0x26;
+
+ /**
+ * Creates a new {@code Fat16BootSector} for the specified device.
+ *
+ * @param device the {@code BlockDevice} holding the boot sector
+ */
+ public Fat16BootSector(BlockDevice device) {
+ super(device);
+ }
+
+ /**
+ * Returns the volume label that is stored in this boot sector.
+ *
+ * @return the volume label
+ */
+ public String getVolumeLabel() {
+ final StringBuilder sb = new StringBuilder();
+
+ for (int i=0; i < MAX_VOLUME_LABEL_LENGTH; i++) {
+ final char c = (char) get8(VOLUME_LABEL_OFFSET + i);
+
+ if (c != 0) {
+ sb.append(c);
+ } else {
+ break;
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Sets the volume label that is stored in this boot sector.
+ *
+ * @param label the new volume label
+ * @throws IllegalArgumentException if the specified label is longer
+ * than {@link #MAX_VOLUME_LABEL_LENGTH}
+ */
+ public void setVolumeLabel(String label) throws IllegalArgumentException {
+ if (label.length() > MAX_VOLUME_LABEL_LENGTH)
+ throw new IllegalArgumentException("volume label too long");
+
+ for (int i = 0; i < MAX_VOLUME_LABEL_LENGTH; i++) {
+ set8(VOLUME_LABEL_OFFSET + i,
+ i < label.length() ? label.charAt(i) : 0);
+ }
+ }
+
+ /**
+ * Gets the number of sectors/fat for FAT 12/16.
+ *
+ * @return int
+ */
+ @Override
+ public long getSectorsPerFat() {
+ return get16(SECTORS_PER_FAT_OFFSET);
+ }
+
+ /**
+ * Sets the number of sectors/fat
+ *
+ * @param v the new number of sectors per fat
+ */
+ @Override
+ public void setSectorsPerFat(long v) {
+ if (v == getSectorsPerFat()) return;
+ if (v > 0x7FFF) throw new IllegalArgumentException(
+ "too many sectors for a FAT12/16");
+
+ set16(SECTORS_PER_FAT_OFFSET, (int)v);
+ }
+
+ @Override
+ public FatType getFatType() {
+ final long rootDirSectors = ((getRootDirEntryCount() * 32) +
+ (getBytesPerSector() - 1)) / getBytesPerSector();
+ final long dataSectors = getSectorCount() -
+ (getNrReservedSectors() + (getNrFats() * getSectorsPerFat()) +
+ rootDirSectors);
+ final long clusterCount = dataSectors / getSectorsPerCluster();
+
+ if (clusterCount > MAX_FAT16_CLUSTERS) throw new IllegalStateException(
+ "too many clusters for FAT12/16: " + clusterCount);
+
+ return clusterCount > MAX_FAT12_CLUSTERS ?
+ FatType.FAT16 : FatType.FAT12;
+ }
+
+ @Override
+ public void setSectorCount(long count) {
+ if (count > 65535) {
+ setNrLogicalSectors(0);
+ setNrTotalSectors(count);
+ } else {
+ setNrLogicalSectors((int) count);
+ setNrTotalSectors(count);
+ }
+ }
+
+ @Override
+ public long getSectorCount() {
+ if (getNrLogicalSectors() == 0) return getNrTotalSectors();
+ else return getNrLogicalSectors();
+ }
+
+ /**
+ * Gets the number of entries in the root directory.
+ *
+ * @return int the root directory entry count
+ */
+ @Override
+ public int getRootDirEntryCount() {
+ return get16(ROOT_DIR_ENTRIES_OFFSET);
+ }
+
+ /**
+ * Sets the number of entries in the root directory
+ *
+ * @param v the new number of entries in the root directory
+ * @throws IllegalArgumentException for negative values
+ */
+ public void setRootDirEntryCount(int v) throws IllegalArgumentException {
+ if (v < 0) throw new IllegalArgumentException();
+ if (v == getRootDirEntryCount()) return;
+
+ set16(ROOT_DIR_ENTRIES_OFFSET, v);
+ }
+
+ @Override
+ public void init() throws IOException {
+ super.init();
+
+ setRootDirEntryCount(DEFAULT_ROOT_DIR_ENTRY_COUNT);
+ setVolumeLabel(DEFAULT_VOLUME_LABEL);
+ }
+
+ @Override
+ public int getFileSystemTypeLabelOffset() {
+ return FILE_SYSTEM_TYPE_OFFSET;
+ }
+
+ @Override
+ public int getExtendedBootSignatureOffset() {
+ return EXTENDED_BOOT_SIGNATURE_OFFSET;
+ }
+
+}