Add read_status_flags API for getting dirty and IO error volume flags.
This commit is contained in:
parent
2318bd0c5c
commit
8bb24994e0
23
src/fs.rs
23
src/fs.rs
@ -8,7 +8,7 @@ use byteorder::{LittleEndian, ReadBytesExt};
|
|||||||
use file::File;
|
use file::File;
|
||||||
use dir::{DirRawStream, Dir};
|
use dir::{DirRawStream, Dir};
|
||||||
use dir_entry::DIR_ENTRY_SIZE;
|
use dir_entry::DIR_ENTRY_SIZE;
|
||||||
use table::{ClusterIterator, alloc_cluster};
|
use table::{ClusterIterator, alloc_cluster, read_fat_flags};
|
||||||
|
|
||||||
// FAT implementation based on:
|
// FAT implementation based on:
|
||||||
// http://wiki.osdev.org/FAT
|
// http://wiki.osdev.org/FAT
|
||||||
@ -31,6 +31,11 @@ impl FatType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct FsStatusFlags {
|
||||||
|
pub dirty: bool,
|
||||||
|
pub io_error: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ReadSeek: Read + Seek {}
|
pub trait ReadSeek: Read + Seek {}
|
||||||
impl<T> ReadSeek for T where T: Read + Seek {}
|
impl<T> ReadSeek for T where T: Read + Seek {}
|
||||||
|
|
||||||
@ -137,6 +142,13 @@ impl BiosParameterBlock {
|
|||||||
fn active_fat(&self) -> u16 {
|
fn active_fat(&self) -> u16 {
|
||||||
self.extended_flags & 0x0F
|
self.extended_flags & 0x0F
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn status_flags(&self) -> FsStatusFlags {
|
||||||
|
FsStatusFlags {
|
||||||
|
dirty: self.reserved_1 & 1 != 0,
|
||||||
|
io_error: self.reserved_1 & 2 != 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -317,6 +329,15 @@ impl <'a> FileSystem<'a> {
|
|||||||
let mut disk_slice = self.fat_slice();
|
let mut disk_slice = self.fat_slice();
|
||||||
alloc_cluster(&mut disk_slice, self.fat_type, prev_cluster)
|
alloc_cluster(&mut disk_slice, self.fat_type, prev_cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_status_flags(&self) -> io::Result<FsStatusFlags> {
|
||||||
|
let bpb_status = self.bpb.status_flags();
|
||||||
|
let fat_status = read_fat_flags(&mut self.fat_slice(), self.fat_type)?;
|
||||||
|
Ok(FsStatusFlags {
|
||||||
|
dirty: bpb_status.dirty || fat_status.dirty,
|
||||||
|
io_error: bpb_status.io_error || fat_status.io_error,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
53
src/table.rs
53
src/table.rs
@ -1,7 +1,7 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use fs::{FatType, DiskSlice, ReadSeek};
|
use fs::{FatType, FsStatusFlags, DiskSlice, ReadSeek};
|
||||||
|
|
||||||
struct Fat<T> {
|
struct Fat<T> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -24,6 +24,7 @@ trait FatTrait {
|
|||||||
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue>;
|
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue>;
|
||||||
fn set(fat: &mut DiskSlice, cluster: u32, value: FatValue) -> io::Result<()>;
|
fn set(fat: &mut DiskSlice, cluster: u32, value: FatValue) -> io::Result<()>;
|
||||||
fn find_free(fat: &mut ReadSeek, hint_cluster: u32) -> io::Result<u32>;
|
fn find_free(fat: &mut ReadSeek, hint_cluster: u32) -> io::Result<u32>;
|
||||||
|
fn get_raw(fat: &mut ReadSeek, cluster: u32) -> io::Result<u32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_fat(fat: &mut ReadSeek, fat_type: FatType, cluster: u32) -> io::Result<FatValue> {
|
fn read_fat(fat: &mut ReadSeek, fat_type: FatType, cluster: u32) -> io::Result<FatValue> {
|
||||||
@ -70,15 +71,43 @@ pub(crate) fn alloc_cluster(fat: &mut DiskSlice, fat_type: FatType, prev_cluster
|
|||||||
Ok(new_cluster)
|
Ok(new_cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub(crate) fn read_fat_flags(fat: &mut DiskSlice, fat_type: FatType) -> io::Result<FsStatusFlags> {
|
||||||
|
// check MSB (except in FAT12)
|
||||||
|
let val = match fat_type {
|
||||||
|
FatType::Fat12 => 0xFFF,
|
||||||
|
FatType::Fat16 => Fat16::get_raw(fat, 1)?,
|
||||||
|
FatType::Fat32 => Fat32::get_raw(fat, 1)?,
|
||||||
|
};
|
||||||
|
let dirty = match fat_type {
|
||||||
|
FatType::Fat12 => false,
|
||||||
|
FatType::Fat16 => val & (1 << 15) == 0,
|
||||||
|
FatType::Fat32 => val & (1 << 27) == 0,
|
||||||
|
};
|
||||||
|
let io_error = match fat_type {
|
||||||
|
FatType::Fat12 => false,
|
||||||
|
FatType::Fat16 => val & (1 << 14) == 0,
|
||||||
|
FatType::Fat32 => val & (1 << 26) == 0,
|
||||||
|
};
|
||||||
|
Ok(FsStatusFlags {
|
||||||
|
dirty, io_error,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl FatTrait for Fat12 {
|
impl FatTrait for Fat12 {
|
||||||
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue> {
|
fn get_raw(fat: &mut ReadSeek, cluster: u32) -> io::Result<u32> {
|
||||||
let fat_offset = cluster + (cluster / 2);
|
let fat_offset = cluster + (cluster / 2);
|
||||||
fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
|
fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
|
||||||
let packed_val = fat.read_u16::<LittleEndian>()?;
|
let packed_val = fat.read_u16::<LittleEndian>()?;
|
||||||
let val = match cluster & 1 {
|
Ok(match cluster & 1 {
|
||||||
0 => packed_val & 0x0FFF,
|
0 => packed_val & 0x0FFF,
|
||||||
_ => packed_val >> 4,
|
_ => packed_val >> 4,
|
||||||
};
|
} as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue> {
|
||||||
|
let val = Self::get_raw(fat, cluster)?;
|
||||||
Ok(match val {
|
Ok(match val {
|
||||||
0 => FatValue::Free,
|
0 => FatValue::Free,
|
||||||
0xFF7 => FatValue::Bad,
|
0xFF7 => FatValue::Bad,
|
||||||
@ -132,9 +161,13 @@ impl FatTrait for Fat12 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FatTrait for Fat16 {
|
impl FatTrait for Fat16 {
|
||||||
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue> {
|
fn get_raw(fat: &mut ReadSeek, cluster: u32) -> io::Result<u32> {
|
||||||
fat.seek(io::SeekFrom::Start((cluster*2) as u64))?;
|
fat.seek(io::SeekFrom::Start((cluster*2) as u64))?;
|
||||||
let val = fat.read_u16::<LittleEndian>()?;
|
Ok(fat.read_u16::<LittleEndian>()? as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue> {
|
||||||
|
let val = Self::get_raw(fat, cluster)?;
|
||||||
Ok(match val {
|
Ok(match val {
|
||||||
0 => FatValue::Free,
|
0 => FatValue::Free,
|
||||||
0xFFF7 => FatValue::Bad,
|
0xFFF7 => FatValue::Bad,
|
||||||
@ -169,9 +202,13 @@ impl FatTrait for Fat16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FatTrait for Fat32 {
|
impl FatTrait for Fat32 {
|
||||||
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue> {
|
fn get_raw(fat: &mut ReadSeek, cluster: u32) -> io::Result<u32> {
|
||||||
fat.seek(io::SeekFrom::Start((cluster*4) as u64))?;
|
fat.seek(io::SeekFrom::Start((cluster*4) as u64))?;
|
||||||
let val = fat.read_u32::<LittleEndian>()? & 0x0FFFFFFF;
|
Ok(fat.read_u32::<LittleEndian>()? & 0x0FFFFFFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue> {
|
||||||
|
let val = Self::get_raw(fat, cluster)?;
|
||||||
Ok(match val {
|
Ok(match val {
|
||||||
0 => FatValue::Free,
|
0 => FatValue::Free,
|
||||||
0x0FFFFFF7 => FatValue::Bad,
|
0x0FFFFFF7 => FatValue::Bad,
|
||||||
|
@ -188,3 +188,25 @@ fn test_volume_metadata_fat16() {
|
|||||||
fn test_volume_metadata_fat32() {
|
fn test_volume_metadata_fat32() {
|
||||||
call_with_fs(&|fs| test_volume_metadata(fs, FatType::Fat32), FAT32_IMG)
|
call_with_fs(&|fs| test_volume_metadata(fs, FatType::Fat32), FAT32_IMG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_status_flags(fs: FileSystem) {
|
||||||
|
let status_flags = fs.read_status_flags().unwrap();
|
||||||
|
assert_eq!(status_flags.dirty, false);
|
||||||
|
assert_eq!(status_flags.io_error, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_status_flags_fat12() {
|
||||||
|
call_with_fs(&|fs| test_status_flags(fs), FAT12_IMG)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_status_flags_fat16() {
|
||||||
|
call_with_fs(&|fs| test_status_flags(fs), FAT16_IMG)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_status_flags_fat32() {
|
||||||
|
call_with_fs(&|fs| test_status_flags(fs), FAT32_IMG)
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user