1 /*
2  * Copyright (C) 2003-2009 JNode.org
3  *               2009,2010 Matthias Treydte <mt@waldheinz.de>
4  *
5  * This library is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; either version 2.1 of the License, or
8  * (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13  * License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; If not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package de.waldheinz.fs.fat;
21 
22 /**
23  * Enumerates the different entry sizes of 12, 16 and 32 bits for the different
24  * FAT flavours.
25  *
26  * @author Ewout Prangsma &lt;epr at jnode.org&gt;
27  * @author Matthias Treydte &lt;waldheinz at gmail.com&gt;
28  */
29 public enum FatType {
30 
31     /**
32      * Represents a 12-bit file allocation table.
33      */
34     FAT12((1 << 12) - 16, 0xFFFL, 1.5f, "FAT12   ") { //NOI18N
35 
36         @Override
readEntry(byte[] data, int index)37         long readEntry(byte[] data, int index) {
38             final int idx = (int) (index * 1.5);
39             final int b1 = data[idx] & 0xFF;
40             final int b2 = data[idx + 1] & 0xFF;
41             final int v = (b2 << 8) | b1;
42 
43             if ((index % 2) == 0) {
44                 return v & 0xFFF;
45             } else {
46                 return v >> 4;
47             }
48         }
49 
50         @Override
writeEntry(byte[] data, int index, long entry)51         void writeEntry(byte[] data, int index, long entry) {
52             final int idx = (int) (index * 1.5);
53 
54             if ((index % 2) == 0) {
55                 data[idx] = (byte) (entry & 0xFF);
56                 data[idx + 1] = (byte) ((entry >> 8) & 0x0F);
57             } else {
58                 data[idx] |= (byte) ((entry & 0x0F) << 4);
59                 data[idx + 1] = (byte) ((entry >> 4) & 0xFF);
60             }
61         }
62     },
63 
64     /**
65      * Represents a 16-bit file allocation table.
66      */
67     FAT16((1 << 16) - 16, 0xFFFFL, 2.0f, "FAT16   ") { //NOI18N
68 
69         @Override
readEntry(byte[] data, int index)70         long readEntry(byte[] data, int index) {
71             final int idx = index << 1;
72             final int b1 = data[idx] & 0xFF;
73             final int b2 = data[idx + 1] & 0xFF;
74             return (b2 << 8) | b1;
75         }
76 
77         @Override
writeEntry(byte[] data, int index, long entry)78         void writeEntry(byte[] data, int index, long entry) {
79             final int idx = index << 1;
80             data[idx] = (byte) (entry & 0xFF);
81             data[idx + 1] = (byte) ((entry >> 8) & 0xFF);
82         }
83     },
84 
85     /**
86      * Represents a 32-bit file allocation table.
87      */
88     FAT32((1 << 28) - 16, 0xFFFFFFFFL, 4.0f, "FAT32   ") { //NOI18N
89 
90         @Override
readEntry(byte[] data, int index)91         long readEntry(byte[] data, int index) {
92             final int idx = index * 4;
93             final long l1 = data[idx] & 0xFF;
94             final long l2 = data[idx + 1] & 0xFF;
95             final long l3 = data[idx + 2] & 0xFF;
96             final long l4 = data[idx + 3] & 0xFF;
97             return (l4 << 24) | (l3 << 16) | (l2 << 8) | l1;
98         }
99 
100         @Override
writeEntry(byte[] data, int index, long entry)101         void writeEntry(byte[] data, int index, long entry) {
102             final int idx = index << 2;
103             data[idx] = (byte) (entry & 0xFF);
104             data[idx + 1] = (byte) ((entry >> 8) & 0xFF);
105             data[idx + 2] = (byte) ((entry >> 16) & 0xFF);
106             data[idx + 3] = (byte) ((entry >> 24) & 0xFF);
107         }
108     };
109 
110     private final long minReservedEntry;
111     private final long maxReservedEntry;
112     private final long eofCluster;
113     private final long eofMarker;
114     private final long bitMask;
115     private final int maxClusters;
116     private final String label;
117     private final float entrySize;
118 
FatType(int maxClusters, long bitMask, float entrySize, String label)119     private FatType(int maxClusters,
120             long bitMask, float entrySize, String label) {
121 
122         this.minReservedEntry = (0xFFFFFF0L & bitMask);
123         this.maxReservedEntry = (0xFFFFFF6L & bitMask);
124         this.eofCluster = (0xFFFFFF8L & bitMask);
125         this.eofMarker = (0xFFFFFFFL & bitMask);
126         this.entrySize = entrySize;
127         this.label = label;
128         this.maxClusters = maxClusters;
129         this.bitMask = bitMask;
130     }
131 
readEntry(byte[] data, int index)132     abstract long readEntry(byte[] data, int index);
133 
writeEntry(byte[] data, int index, long entry)134     abstract void writeEntry(byte[] data, int index, long entry);
135 
136     /**
137      * Returns the maximum number of clusters this file system can address.
138      *
139      * @return the maximum cluster count supported
140      */
maxClusters()141     long maxClusters() {
142         return this.maxClusters;
143     }
144 
145     /**
146      * Returns the human-readable FAT name string as written to the
147      * {@link com.meetwise.fs.BootSector}.
148      *
149      * @return the boot sector label for this FAT type
150      */
getLabel()151     String getLabel() {
152         return this.label;
153     }
154 
isReservedCluster(long entry)155     boolean isReservedCluster(long entry) {
156         return ((entry >= minReservedEntry) && (entry <= maxReservedEntry));
157     }
158 
isEofCluster(long entry)159     boolean isEofCluster(long entry) {
160         return (entry >= eofCluster);
161     }
162 
getEofMarker()163     long getEofMarker() {
164         return eofMarker;
165     }
166 
getEntrySize()167     float getEntrySize() {
168         return entrySize;
169     }
170 
getBitMask()171     long getBitMask() {
172         return bitMask;
173     }
174 }
175