fatfs/
table.rs

1use crate::byteorder_ext::{ReadBytesExt, WriteBytesExt};
2use crate::core::cmp;
3use crate::io;
4use byteorder::LittleEndian;
5
6use crate::error::FatfsError;
7use crate::fs::{FatType, FsStatusFlags, ReadSeek, ReadWriteSeek};
8
9struct Fat<T> {
10    #[allow(dead_code)]
11    dummy: [T; 0],
12}
13
14type Fat12 = Fat<u8>;
15type Fat16 = Fat<u16>;
16type Fat32 = Fat<u32>;
17
18pub const RESERVED_FAT_ENTRIES: u32 = 2;
19
20#[derive(Copy, Clone, Eq, PartialEq, Debug)]
21enum FatValue {
22    Free,
23    Data(u32),
24    Bad,
25    EndOfChain,
26}
27
28trait FatTrait {
29    fn get_raw<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<u32>;
30    fn get<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<FatValue>;
31    fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_value: u32) -> io::Result<()>;
32    fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()>;
33    fn find_free<T: ReadSeek>(fat: &mut T, start_cluster: u32, end_cluster: u32)
34        -> io::Result<u32>;
35    fn count_free<T: ReadSeek>(fat: &mut T, end_cluster: u32) -> io::Result<u32>;
36}
37
38fn read_fat<T: ReadSeek>(fat: &mut T, fat_type: FatType, cluster: u32) -> io::Result<FatValue> {
39    match fat_type {
40        FatType::Fat12 => Fat12::get(fat, cluster),
41        FatType::Fat16 => Fat16::get(fat, cluster),
42        FatType::Fat32 => Fat32::get(fat, cluster),
43    }
44}
45
46fn write_fat<T: ReadWriteSeek>(
47    fat: &mut T,
48    fat_type: FatType,
49    cluster: u32,
50    value: FatValue,
51) -> io::Result<()> {
52    trace!("write FAT - cluster {} value {:?}", cluster, value);
53    match fat_type {
54        FatType::Fat12 => Fat12::set(fat, cluster, value),
55        FatType::Fat16 => Fat16::set(fat, cluster, value),
56        FatType::Fat32 => Fat32::set(fat, cluster, value),
57    }
58}
59
60fn get_next_cluster<T: ReadSeek>(
61    fat: &mut T,
62    fat_type: FatType,
63    cluster: u32,
64) -> io::Result<Option<u32>> {
65    let val = read_fat(fat, fat_type, cluster)?;
66    match val {
67        FatValue::Data(n) => Ok(Some(n)),
68        _ => Ok(None),
69    }
70}
71
72fn find_free_cluster<T: ReadSeek>(
73    fat: &mut T,
74    fat_type: FatType,
75    start_cluster: u32,
76    end_cluster: u32,
77) -> io::Result<u32> {
78    match fat_type {
79        FatType::Fat12 => Fat12::find_free(fat, start_cluster, end_cluster),
80        FatType::Fat16 => Fat16::find_free(fat, start_cluster, end_cluster),
81        FatType::Fat32 => Fat32::find_free(fat, start_cluster, end_cluster),
82    }
83}
84
85pub(crate) fn alloc_cluster<T: ReadWriteSeek>(
86    fat: &mut T,
87    fat_type: FatType,
88    prev_cluster: Option<u32>,
89    hint: Option<u32>,
90    total_clusters: u32,
91) -> io::Result<u32> {
92    let end_cluster = total_clusters + RESERVED_FAT_ENTRIES;
93    let start_cluster = match hint {
94        Some(n) if n < end_cluster => n,
95        _ => RESERVED_FAT_ENTRIES,
96    };
97    let new_cluster = match find_free_cluster(fat, fat_type, start_cluster, end_cluster) {
98        Ok(n) => n,
99        Err(_) if start_cluster > RESERVED_FAT_ENTRIES => {
100            find_free_cluster(fat, fat_type, RESERVED_FAT_ENTRIES, start_cluster)?
101        }
102        Err(e) => return Err(e),
103    };
104    write_fat(fat, fat_type, new_cluster, FatValue::EndOfChain)?;
105    if let Some(n) = prev_cluster {
106        write_fat(fat, fat_type, n, FatValue::Data(new_cluster))?;
107    }
108    trace!("allocated cluster {}", new_cluster);
109    Ok(new_cluster)
110}
111
112pub(crate) fn read_fat_flags<T: ReadSeek>(
113    fat: &mut T,
114    fat_type: FatType,
115) -> io::Result<FsStatusFlags> {
116    // check MSB (except in FAT12)
117    let val = match fat_type {
118        FatType::Fat12 => 0xFFF,
119        FatType::Fat16 => Fat16::get_raw(fat, 1)?,
120        FatType::Fat32 => Fat32::get_raw(fat, 1)?,
121    };
122    let dirty = match fat_type {
123        FatType::Fat12 => false,
124        FatType::Fat16 => val & (1 << 15) == 0,
125        FatType::Fat32 => val & (1 << 27) == 0,
126    };
127    let io_error = match fat_type {
128        FatType::Fat12 => false,
129        FatType::Fat16 => val & (1 << 14) == 0,
130        FatType::Fat32 => val & (1 << 26) == 0,
131    };
132    Ok(FsStatusFlags { dirty, io_error })
133}
134
135pub(crate) fn count_free_clusters<T: ReadSeek>(
136    fat: &mut T,
137    fat_type: FatType,
138    total_clusters: u32,
139) -> io::Result<u32> {
140    let end_cluster = total_clusters + RESERVED_FAT_ENTRIES;
141    match fat_type {
142        FatType::Fat12 => Fat12::count_free(fat, end_cluster),
143        FatType::Fat16 => Fat16::count_free(fat, end_cluster),
144        FatType::Fat32 => Fat32::count_free(fat, end_cluster),
145    }
146}
147
148pub(crate) fn format_fat<T: ReadWriteSeek>(
149    fat: &mut T,
150    fat_type: FatType,
151    media: u8,
152    bytes_per_fat: u64,
153    total_clusters: u32,
154) -> io::Result<()> {
155    // init first two reserved entries to FAT ID
156    match fat_type {
157        FatType::Fat12 => {
158            fat.write_u8(media)?;
159            fat.write_u16::<LittleEndian>(0xFFFF)?;
160        }
161        FatType::Fat16 => {
162            fat.write_u16::<LittleEndian>(media as u16 | 0xFF00)?;
163            fat.write_u16::<LittleEndian>(0xFFFF)?;
164        }
165        FatType::Fat32 => {
166            fat.write_u32::<LittleEndian>(media as u32 | 0xFFFFF00)?;
167            fat.write_u32::<LittleEndian>(0xFFFFFFFF)?;
168        }
169    };
170    // mark entries at the end of FAT as used (after FAT but before sector end)
171    const BITS_PER_BYTE: u64 = 8;
172    let start_cluster = total_clusters + RESERVED_FAT_ENTRIES;
173    let end_cluster = (bytes_per_fat * BITS_PER_BYTE / fat_type.bits_per_fat_entry() as u64) as u32;
174    for cluster in start_cluster..end_cluster {
175        write_fat(fat, fat_type, cluster, FatValue::EndOfChain)?;
176    }
177    // mark special entries 0x0FFFFFF0 - 0x0FFFFFFF as BAD if they exists on FAT32 volume
178    if end_cluster > 0x0FFFFFF0 {
179        let end_bad_cluster = cmp::min(0x0FFFFFFF + 1, end_cluster);
180        for cluster in 0x0FFFFFF0..end_bad_cluster {
181            write_fat(fat, fat_type, cluster, FatValue::Bad)?;
182        }
183    }
184    Ok(())
185}
186
187impl FatTrait for Fat12 {
188    fn get_raw<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<u32> {
189        let fat_offset = cluster + (cluster / 2);
190        fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
191        let packed_val = fat.read_u16::<LittleEndian>()?;
192        Ok(match cluster & 1 {
193            0 => packed_val & 0x0FFF,
194            _ => packed_val >> 4,
195        } as u32)
196    }
197
198    fn get<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<FatValue> {
199        let val = Self::get_raw(fat, cluster)?;
200        Ok(match val {
201            0 => FatValue::Free,
202            0xFF7 => FatValue::Bad,
203            0xFF8..=0xFFF => FatValue::EndOfChain,
204            n => FatValue::Data(n as u32),
205        })
206    }
207
208    fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()> {
209        let raw_val = match value {
210            FatValue::Free => 0,
211            FatValue::Bad => 0xFF7,
212            FatValue::EndOfChain => 0xFFF,
213            FatValue::Data(n) => n as u16,
214        };
215        Self::set_raw(fat, cluster, raw_val as u32)
216    }
217
218    fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_val: u32) -> io::Result<()> {
219        let fat_offset = cluster + (cluster / 2);
220        fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
221        let old_packed = fat.read_u16::<LittleEndian>()?;
222        fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
223        let new_packed = match cluster & 1 {
224            0 => (old_packed & 0xF000) | raw_val as u16,
225            _ => (old_packed & 0x000F) | ((raw_val as u16) << 4),
226        };
227        fat.write_u16::<LittleEndian>(new_packed)?;
228        Ok(())
229    }
230
231    fn find_free<T: ReadSeek>(
232        fat: &mut T,
233        start_cluster: u32,
234        end_cluster: u32,
235    ) -> io::Result<u32> {
236        let mut cluster = start_cluster;
237        let fat_offset = cluster + (cluster / 2);
238        fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
239        let mut packed_val = fat.read_u16::<LittleEndian>()?;
240        loop {
241            let val = match cluster & 1 {
242                0 => packed_val & 0x0FFF,
243                _ => packed_val >> 4,
244            };
245            if val == 0 {
246                return Ok(cluster);
247            }
248            cluster += 1;
249            if cluster == end_cluster {
250                return Err(io::Error::new(io::ErrorKind::Other, FatfsError::NoSpace));
251            }
252            packed_val = match cluster & 1 {
253                0 => fat.read_u16::<LittleEndian>()?,
254                _ => {
255                    let next_byte = fat.read_u8()? as u16;
256                    (packed_val >> 8) | (next_byte << 8)
257                }
258            };
259        }
260    }
261
262    fn count_free<T: ReadSeek>(fat: &mut T, end_cluster: u32) -> io::Result<u32> {
263        let mut count = 0;
264        let mut cluster = RESERVED_FAT_ENTRIES;
265        fat.seek(io::SeekFrom::Start((cluster * 3 / 2) as u64))?;
266        let mut prev_packed_val = 0u16;
267        while cluster < end_cluster {
268            let res = match cluster & 1 {
269                0 => fat.read_u16::<LittleEndian>(),
270                _ => fat.read_u8().map(|n| n as u16),
271            };
272            let packed_val = match res {
273                Err(err) => return Err(err),
274                Ok(n) => n,
275            };
276            let val = match cluster & 1 {
277                0 => packed_val & 0x0FFF,
278                _ => (packed_val << 8) | (prev_packed_val >> 12),
279            };
280            prev_packed_val = packed_val;
281            if val == 0 {
282                count += 1;
283            }
284            cluster += 1;
285        }
286        Ok(count)
287    }
288}
289
290impl FatTrait for Fat16 {
291    fn get_raw<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<u32> {
292        fat.seek(io::SeekFrom::Start((cluster * 2) as u64))?;
293        Ok(fat.read_u16::<LittleEndian>()? as u32)
294    }
295
296    fn get<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<FatValue> {
297        let val = Self::get_raw(fat, cluster)?;
298        Ok(match val {
299            0 => FatValue::Free,
300            0xFFF7 => FatValue::Bad,
301            0xFFF8..=0xFFFF => FatValue::EndOfChain,
302            n => FatValue::Data(n as u32),
303        })
304    }
305
306    fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_value: u32) -> io::Result<()> {
307        fat.seek(io::SeekFrom::Start((cluster * 2) as u64))?;
308        fat.write_u16::<LittleEndian>(raw_value as u16)?;
309        Ok(())
310    }
311
312    fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()> {
313        let raw_value = match value {
314            FatValue::Free => 0,
315            FatValue::Bad => 0xFFF7,
316            FatValue::EndOfChain => 0xFFFF,
317            FatValue::Data(n) => n as u16,
318        };
319        Self::set_raw(fat, cluster, raw_value as u32)
320    }
321
322    fn find_free<T: ReadSeek>(
323        fat: &mut T,
324        start_cluster: u32,
325        end_cluster: u32,
326    ) -> io::Result<u32> {
327        let mut cluster = start_cluster;
328        fat.seek(io::SeekFrom::Start((cluster * 2) as u64))?;
329        while cluster < end_cluster {
330            let val = fat.read_u16::<LittleEndian>()?;
331            if val == 0 {
332                return Ok(cluster);
333            }
334            cluster += 1;
335        }
336        Err(io::Error::new(io::ErrorKind::Other, FatfsError::NoSpace))
337    }
338
339    fn count_free<T: ReadSeek>(fat: &mut T, end_cluster: u32) -> io::Result<u32> {
340        let mut count = 0;
341        let mut cluster = RESERVED_FAT_ENTRIES;
342        fat.seek(io::SeekFrom::Start((cluster * 2) as u64))?;
343        while cluster < end_cluster {
344            let val = fat.read_u16::<LittleEndian>()?;
345            if val == 0 {
346                count += 1;
347            }
348            cluster += 1;
349        }
350        Ok(count)
351    }
352}
353
354impl FatTrait for Fat32 {
355    fn get_raw<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<u32> {
356        fat.seek(io::SeekFrom::Start((cluster * 4) as u64))?;
357        Ok(fat.read_u32::<LittleEndian>()?)
358    }
359
360    fn get<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<FatValue> {
361        let val = Self::get_raw(fat, cluster)? & 0x0FFFFFFF;
362        Ok(match val {
363            0 if cluster >= 0x0FFFFFF7 && cluster <= 0x0FFFFFFF => {
364                let tmp = if cluster == 0x0FFFFFF7 { "BAD_CLUSTER" } else { "end-of-chain" };
365                warn!(
366                    "cluster number {} is a special value in FAT to indicate {}; it should never be seen as free",
367                    cluster, tmp
368                );
369                FatValue::Bad // avoid accidental use or allocation into a FAT chain
370            }
371            0 => FatValue::Free,
372            0x0FFFFFF7 => FatValue::Bad,
373            0x0FFFFFF8..=0x0FFFFFFF => FatValue::EndOfChain,
374            n if cluster >= 0x0FFFFFF7 && cluster <= 0x0FFFFFFF => {
375                let tmp = if cluster == 0x0FFFFFF7 { "BAD_CLUSTER" } else { "end-of-chain" };
376                warn!("cluster number {} is a special value in FAT to indicate {}; hiding potential FAT chain value {} and instead reporting as a bad sector", cluster, tmp, n);
377                FatValue::Bad // avoid accidental use or allocation into a FAT chain
378            }
379            n => FatValue::Data(n as u32),
380        })
381    }
382
383    fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_value: u32) -> io::Result<()> {
384        fat.seek(io::SeekFrom::Start((cluster * 4) as u64))?;
385        fat.write_u32::<LittleEndian>(raw_value)?;
386        Ok(())
387    }
388
389    fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()> {
390        let old_reserved_bits = Self::get_raw(fat, cluster)? & 0xF0000000;
391
392        if value == FatValue::Free && cluster >= 0x0FFFFFF7 && cluster <= 0x0FFFFFFF {
393            // NOTE: it is technically allowed for them to store FAT chain loops,
394            //       or even have them all store value '4' as their next cluster.
395            //       Some believe only FatValue::Bad should be allowed for this edge case.
396            let tmp = if cluster == 0x0FFFFFF7 { "BAD_CLUSTER" } else { "end-of-chain" };
397            panic!(
398                "cluster number {} is a special value in FAT to indicate {}; it should never be set as free",
399                cluster, tmp
400            );
401        };
402        let raw_val = match value {
403            FatValue::Free => 0,
404            FatValue::Bad => 0x0FFFFFF7,
405            FatValue::EndOfChain => 0x0FFFFFFF,
406            FatValue::Data(n) => n,
407        };
408        let raw_val = raw_val | old_reserved_bits; // must preserve original reserved values
409        Self::set_raw(fat, cluster, raw_val)
410    }
411
412    fn find_free<T: ReadSeek>(
413        fat: &mut T,
414        start_cluster: u32,
415        end_cluster: u32,
416    ) -> io::Result<u32> {
417        let mut cluster = start_cluster;
418        fat.seek(io::SeekFrom::Start((cluster * 4) as u64))?;
419        while cluster < end_cluster {
420            let val = fat.read_u32::<LittleEndian>()? & 0x0FFFFFFF;
421            if val == 0 {
422                return Ok(cluster);
423            }
424            cluster += 1;
425        }
426        Err(io::Error::new(io::ErrorKind::Other, FatfsError::NoSpace))
427    }
428
429    fn count_free<T: ReadSeek>(fat: &mut T, end_cluster: u32) -> io::Result<u32> {
430        let mut count = 0;
431        let mut cluster = RESERVED_FAT_ENTRIES;
432        fat.seek(io::SeekFrom::Start((cluster * 4) as u64))?;
433        while cluster < end_cluster {
434            let val = fat.read_u32::<LittleEndian>()? & 0x0FFFFFFF;
435            if val == 0 {
436                count += 1;
437            }
438            cluster += 1;
439        }
440        Ok(count)
441    }
442}
443
444pub(crate) struct ClusterIterator<T: ReadWriteSeek> {
445    fat: T,
446    fat_type: FatType,
447    cluster: Option<u32>,
448    err: bool,
449}
450
451impl<T: ReadWriteSeek> ClusterIterator<T> {
452    pub(crate) fn new(fat: T, fat_type: FatType, cluster: u32) -> Self {
453        ClusterIterator { fat, fat_type, cluster: Some(cluster), err: false }
454    }
455
456    pub(crate) fn truncate(&mut self) -> io::Result<u32> {
457        match self.cluster {
458            Some(n) => {
459                // Move to the next cluster
460                self.next();
461                // Mark previous cluster as end of chain
462                write_fat(&mut self.fat, self.fat_type, n, FatValue::EndOfChain)?;
463                // Free rest of chain
464                self.free()
465            }
466            None => Ok(0),
467        }
468    }
469
470    pub(crate) fn free(&mut self) -> io::Result<u32> {
471        let mut num_free = 0;
472        while let Some(n) = self.cluster {
473            self.next();
474            write_fat(&mut self.fat, self.fat_type, n, FatValue::Free)?;
475            num_free += 1;
476        }
477        Ok(num_free)
478    }
479}
480
481impl<T: ReadWriteSeek> Iterator for ClusterIterator<T> {
482    type Item = io::Result<u32>;
483
484    fn next(&mut self) -> Option<Self::Item> {
485        if self.err {
486            return None;
487        }
488        if let Some(current_cluster) = self.cluster {
489            self.cluster = match get_next_cluster(&mut self.fat, self.fat_type, current_cluster) {
490                Ok(next_cluster) => next_cluster,
491                Err(err) => {
492                    self.err = true;
493                    return Some(Err(err));
494                }
495            }
496        }
497        self.cluster.map(Ok)
498    }
499}
500
501#[cfg(test)]
502mod tests {
503    use super::*;
504
505    fn test_fat<T: ReadWriteSeek>(fat_type: FatType, mut cur: T) {
506        // based on cluster maps from Wikipedia:
507        // https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#Cluster_map
508        assert_eq!(read_fat(&mut cur, fat_type, 1).unwrap(), FatValue::EndOfChain);
509        assert_eq!(read_fat(&mut cur, fat_type, 4).unwrap(), FatValue::Data(5));
510        assert_eq!(read_fat(&mut cur, fat_type, 5).unwrap(), FatValue::Data(6));
511        assert_eq!(read_fat(&mut cur, fat_type, 8).unwrap(), FatValue::EndOfChain);
512        assert_eq!(read_fat(&mut cur, fat_type, 9).unwrap(), FatValue::Data(0xA));
513        assert_eq!(read_fat(&mut cur, fat_type, 0xA).unwrap(), FatValue::Data(0x14));
514        assert_eq!(read_fat(&mut cur, fat_type, 0x12).unwrap(), FatValue::Free);
515        assert_eq!(read_fat(&mut cur, fat_type, 0x17).unwrap(), FatValue::Bad);
516        assert_eq!(read_fat(&mut cur, fat_type, 0x18).unwrap(), FatValue::Bad);
517        assert_eq!(read_fat(&mut cur, fat_type, 0x1B).unwrap(), FatValue::Free);
518
519        assert_eq!(find_free_cluster(&mut cur, fat_type, 2, 0x20).unwrap(), 0x12);
520        assert_eq!(find_free_cluster(&mut cur, fat_type, 0x12, 0x20).unwrap(), 0x12);
521        assert_eq!(find_free_cluster(&mut cur, fat_type, 0x13, 0x20).unwrap(), 0x1B);
522        assert!(find_free_cluster(&mut cur, fat_type, 0x13, 0x14).is_err());
523
524        assert_eq!(count_free_clusters(&mut cur, fat_type, 0x1E).unwrap(), 5);
525
526        // test allocation
527        assert_eq!(alloc_cluster(&mut cur, fat_type, None, Some(0x13), 0x1E).unwrap(), 0x1B);
528        assert_eq!(read_fat(&mut cur, fat_type, 0x1B).unwrap(), FatValue::EndOfChain);
529        assert_eq!(alloc_cluster(&mut cur, fat_type, Some(0x1B), None, 0x1E).unwrap(), 0x12);
530        assert_eq!(read_fat(&mut cur, fat_type, 0x1B).unwrap(), FatValue::Data(0x12));
531        assert_eq!(read_fat(&mut cur, fat_type, 0x12).unwrap(), FatValue::EndOfChain);
532        assert_eq!(count_free_clusters(&mut cur, fat_type, 0x1E).unwrap(), 3);
533        // test reading from iterator
534        {
535            let iter = ClusterIterator::new(&mut cur, fat_type, 0x9);
536            assert_eq!(
537                iter.map(|r| r.unwrap()).collect::<Vec<_>>(),
538                vec![0xA, 0x14, 0x15, 0x16, 0x19, 0x1A]
539            );
540        }
541        // test truncating a chain
542        {
543            let mut iter = ClusterIterator::new(&mut cur, fat_type, 0x9);
544            assert_eq!(iter.nth(3).unwrap().unwrap(), 0x16);
545            iter.truncate().unwrap();
546        }
547        assert_eq!(read_fat(&mut cur, fat_type, 0x16).unwrap(), FatValue::EndOfChain);
548        assert_eq!(read_fat(&mut cur, fat_type, 0x19).unwrap(), FatValue::Free);
549        assert_eq!(read_fat(&mut cur, fat_type, 0x1A).unwrap(), FatValue::Free);
550        // test freeing a chain
551        {
552            let mut iter = ClusterIterator::new(&mut cur, fat_type, 0x9);
553            iter.free().unwrap();
554        }
555        assert_eq!(read_fat(&mut cur, fat_type, 0x9).unwrap(), FatValue::Free);
556        assert_eq!(read_fat(&mut cur, fat_type, 0xA).unwrap(), FatValue::Free);
557        assert_eq!(read_fat(&mut cur, fat_type, 0x14).unwrap(), FatValue::Free);
558        assert_eq!(read_fat(&mut cur, fat_type, 0x15).unwrap(), FatValue::Free);
559        assert_eq!(read_fat(&mut cur, fat_type, 0x16).unwrap(), FatValue::Free);
560    }
561
562    #[test]
563    fn test_fat12() {
564        let fat: Vec<u8> = vec![
565            0xF0, 0xFF, 0xFF, 0x03, 0x40, 0x00, 0x05, 0x60, 0x00, 0x07, 0x80, 0x00, 0xFF, 0xAF,
566            0x00, 0x14, 0xC0, 0x00, 0x0D, 0xE0, 0x00, 0x0F, 0x00, 0x01, 0x11, 0xF0, 0xFF, 0x00,
567            0xF0, 0xFF, 0x15, 0x60, 0x01, 0x19, 0x70, 0xFF, 0xF7, 0xAF, 0x01, 0xFF, 0x0F, 0x00,
568            0x00, 0x70, 0xFF, 0x00, 0x00, 0x00,
569        ];
570        test_fat(FatType::Fat12, io::Cursor::new(fat));
571    }
572
573    #[test]
574    fn test_fat16() {
575        let fat: Vec<u8> = vec![
576            0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00,
577            0x08, 0x00, 0xFF, 0xFF, 0x0A, 0x00, 0x14, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00,
578            0x0F, 0x00, 0x10, 0x00, 0x11, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00,
579            0x16, 0x00, 0x19, 0x00, 0xF7, 0xFF, 0xF7, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00,
580            0x00, 0x00, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,
581        ];
582        test_fat(FatType::Fat16, io::Cursor::new(fat));
583    }
584
585    #[test]
586    fn test_fat32() {
587        let fat: Vec<u8> = vec![
588            0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0x04, 0x00,
589            0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
590            0x08, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00,
591            0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
592            0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF,
593            0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x15, 0x00, 0x00, 0x00,
594            0x16, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0x0F, 0xF7, 0xFF,
595            0xFF, 0x0F, 0x1A, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00,
596            0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597            0x00, 0x00,
598        ];
599        test_fat(FatType::Fat32, io::Cursor::new(fat));
600    }
601}