1 /* 2 * Copyright (C) 2009,2010 Matthias Treydte <mt@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 <matthias.treydte at meetwise.com> 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 */ Fat32BootSector(BlockDevice device)57 public Fat32BootSector(BlockDevice device) throws IOException { 58 super(device); 59 } 60 61 @Override init()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 */ getRootDirFirstCluster()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 */ setRootDirFirstCluster(long value)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 */ setBootSectorCopySector(int sectNr)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 */ getBootSectorCopySector()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 */ setVolumeLabel(String label)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 getFsInfoSectorNr()128 public int getFsInfoSectorNr() { 129 return get16(FS_INFO_SECTOR_OFFSET); 130 } 131 setFsInfoSectorNr(int offset)132 public void setFsInfoSectorNr(int offset) { 133 if (getFsInfoSectorNr() == offset) return; 134 135 set16(FS_INFO_SECTOR_OFFSET, offset); 136 } 137 138 @Override setSectorsPerFat(long v)139 public void setSectorsPerFat(long v) { 140 if (getSectorsPerFat() == v) return; 141 142 set32(SECTORS_PER_FAT_OFFSET, v); 143 } 144 145 @Override getSectorsPerFat()146 public long getSectorsPerFat() { 147 return get32(SECTORS_PER_FAT_OFFSET); 148 } 149 150 @Override getFatType()151 public FatType getFatType() { 152 return FatType.FAT32; 153 } 154 155 @Override setSectorCount(long count)156 public void setSectorCount(long count) { 157 super.setNrTotalSectors(count); 158 } 159 160 @Override getSectorCount()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 getRootDirEntryCount()171 public int getRootDirEntryCount() { 172 return 0; 173 } 174 setFileSystemId(int id)175 public void setFileSystemId(int id) { 176 super.set32(0x43, id); 177 } 178 getFileSystemId()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 */ writeCopy(BlockDevice device)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 getFileSystemTypeLabelOffset()201 public int getFileSystemTypeLabelOffset() { 202 return FILE_SYSTEM_TYPE_OFFSET; 203 } 204 205 @Override getExtendedBootSignatureOffset()206 public int getExtendedBootSignatureOffset() { 207 return EXTENDED_BOOT_SIGNATURE_OFFSET; 208 } 209 } 210