Home | History | Annotate | Download | only in fat
      1 /*
      2  * Copyright (C) 2009,2010 Matthias Treydte <mt (at) waldheinz.de>
      3  *
      4  * This library is free software; you can redistribute it and/or modify it
      5  * under the terms of the GNU Lesser General Public License as published
      6  * by the Free Software Foundation; either version 2.1 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
     12  * License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public License
     15  * along with this library; If not, write to the Free Software Foundation, Inc.,
     16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     17  */
     18 
     19 package de.waldheinz.fs.fat;
     20 
     21 import de.waldheinz.fs.BlockDevice;
     22 import java.io.IOException;
     23 
     24 /**
     25  * Contains the FAT32 specific parts of the boot sector.
     26  *
     27  * @author Matthias Treydte &lt;matthias.treydte at meetwise.com&gt;
     28  */
     29 final class Fat32BootSector extends BootSector {
     30 
     31     /**
     32      * The offset to the entry specifying the first cluster of the FAT32
     33      * root directory.
     34      */
     35     public final static int ROOT_DIR_FIRST_CLUSTER_OFFSET = 0x2c;
     36 
     37     /**
     38      * The offset to the 4 bytes specifying the sectors per FAT value.
     39      */
     40     public static final int SECTORS_PER_FAT_OFFSET = 0x24;
     41 
     42     /**
     43      * Offset to the file system type label.
     44      */
     45     public static final int FILE_SYSTEM_TYPE_OFFSET = 0x52;
     46 
     47     public static final int VERSION_OFFSET = 0x2a;
     48     public static final int VERSION = 0;
     49 
     50     public static final int FS_INFO_SECTOR_OFFSET = 0x30;
     51     public static final int BOOT_SECTOR_COPY_OFFSET = 0x32;
     52     public static final int EXTENDED_BOOT_SIGNATURE_OFFSET = 0x42;
     53 
     54     /*
     55      * TODO: make this constructor private
     56      */
     57     public Fat32BootSector(BlockDevice device) throws IOException {
     58         super(device);
     59     }
     60 
     61     @Override
     62     public void init() throws IOException {
     63         super.init();
     64 
     65         set16(VERSION_OFFSET, VERSION);
     66 
     67         setBootSectorCopySector(6); /* as suggested by M$ */
     68     }
     69 
     70     /**
     71      * Returns the first cluster in the FAT that contains the root directory.
     72      *
     73      * @return the root directory's first cluster
     74      */
     75     public long getRootDirFirstCluster() {
     76         return get32(ROOT_DIR_FIRST_CLUSTER_OFFSET);
     77     }
     78 
     79     /**
     80      * Sets the first cluster of the root directory.
     81      *
     82      * @param value the root directory's first cluster
     83      */
     84     public void setRootDirFirstCluster(long value) {
     85         if (getRootDirFirstCluster() == value) return;
     86 
     87         set32(ROOT_DIR_FIRST_CLUSTER_OFFSET, value);
     88     }
     89 
     90     /**
     91      * Sets the sectur number that contains a copy of the boot sector.
     92      *
     93      * @param sectNr the sector that contains a boot sector copy
     94      */
     95     public void setBootSectorCopySector(int sectNr) {
     96         if (getBootSectorCopySector() == sectNr) return;
     97         if (sectNr < 0) throw new IllegalArgumentException(
     98                 "boot sector copy sector must be >= 0");
     99 
    100         set16(BOOT_SECTOR_COPY_OFFSET, sectNr);
    101     }
    102 
    103     /**
    104      * Returns the sector that contains a copy of the boot sector, or 0 if
    105      * there is no copy.
    106      *
    107      * @return the sector number of the boot sector copy
    108      */
    109     public int getBootSectorCopySector() {
    110         return get16(BOOT_SECTOR_COPY_OFFSET);
    111     }
    112 
    113     /**
    114      * Sets the 11-byte volume label stored at offset 0x47.
    115      *
    116      * @param label the new volume label, may be {@code null}
    117      */
    118     public void setVolumeLabel(String label) {
    119         for (int i=0; i < 11; i++) {
    120             final byte c =
    121                     (label == null) ? 0 :
    122                     (label.length() > i) ? (byte) label.charAt(i) : 0x20;
    123 
    124             set8(0x47 + i, c);
    125         }
    126     }
    127 
    128     public int getFsInfoSectorNr() {
    129         return get16(FS_INFO_SECTOR_OFFSET);
    130     }
    131 
    132     public void setFsInfoSectorNr(int offset) {
    133         if (getFsInfoSectorNr() == offset) return;
    134 
    135         set16(FS_INFO_SECTOR_OFFSET, offset);
    136     }
    137 
    138     @Override
    139     public void setSectorsPerFat(long v) {
    140         if (getSectorsPerFat() == v) return;
    141 
    142         set32(SECTORS_PER_FAT_OFFSET, v);
    143     }
    144 
    145     @Override
    146     public long getSectorsPerFat() {
    147         return get32(SECTORS_PER_FAT_OFFSET);
    148     }
    149 
    150     @Override
    151     public FatType getFatType() {
    152         return FatType.FAT32;
    153     }
    154 
    155     @Override
    156     public void setSectorCount(long count) {
    157         super.setNrTotalSectors(count);
    158     }
    159 
    160     @Override
    161     public long getSectorCount() {
    162         return super.getNrTotalSectors();
    163     }
    164 
    165     /**
    166      * This is always 0 for FAT32.
    167      *
    168      * @return always 0
    169      */
    170     @Override
    171     public int getRootDirEntryCount() {
    172         return 0;
    173     }
    174 
    175     public void setFileSystemId(int id) {
    176         super.set32(0x43, id);
    177     }
    178 
    179     public int getFileSystemId() {
    180         return (int) super.get32(0x43);
    181     }
    182 
    183     /**
    184      * Writes a copy of this boot sector to the specified device, if a copy
    185      * is requested.
    186      *
    187      * @param device the device to write the boot sector copy to
    188      * @throws IOException on write error
    189      * @see #getBootSectorCopySector()
    190      */
    191     public void writeCopy(BlockDevice device) throws IOException {
    192         if (getBootSectorCopySector() > 0) {
    193             final long offset = getBootSectorCopySector() * SIZE;
    194             buffer.rewind();
    195             buffer.limit(buffer.capacity());
    196             device.write(offset, buffer);
    197         }
    198     }
    199 
    200     @Override
    201     public int getFileSystemTypeLabelOffset() {
    202         return FILE_SYSTEM_TYPE_OFFSET;
    203     }
    204 
    205     @Override
    206     public int getExtendedBootSignatureOffset() {
    207         return EXTENDED_BOOT_SIGNATURE_OFFSET;
    208     }
    209 }
    210