const EOC12_MIN: u32 = 0xff8;
const EOC16_MIN: u32 = 0xfff8;
const EOC32_MIN: u32 = 0xffffff8; const EOC12_SET: u32 = 0xfff;
const EOC16_SET: u32 = 0xffff;
const EOC32_SET: u32 = 0xfffffff;
const BAD_CLUSTER12: u32 = 0xff7;
const BAD_CLUSTER16: u32 = 0xfff7;
const BAD_CLUSTER32: u32 = 0xffffff7;
const FREE_CLUSTER: u32 = 0;
pub const FIRST_DATA_CLUSTER: u32 = 2;
pub fn repair(typ: usize, working: &mut Vec<u8>, bak: &Vec<u8>, cluster_end: u32) {
for n in FIRST_DATA_CLUSTER as usize..cluster_end as usize {
let v1 = get_cluster(n,typ,working);
let v2 = get_cluster(n,typ,bak);
let dmg1 = is_damaged(n,typ,working);
let dmg2 = is_damaged(n,typ,bak);
if v1 != v2 {
log::trace!("cluster {}: working FAT has {}, backup has {}",n,v1,v2);
}
let v = match (v1 >= FIRST_DATA_CLUSTER && v1 < cluster_end && !dmg1, v2 >= FIRST_DATA_CLUSTER && v2 < cluster_end && !dmg2) {
(true,false) => v1,
(false,true) => v2,
_ => v1
};
set_cluster(n,v,typ,working);
}
}
pub fn get_cluster(n: usize,typ: usize,buf: &Vec<u8>) -> u32 {
match typ {
12 => {
let offset = n + (n/2);
let val16 = u16::from_le_bytes([buf[offset],buf[offset+1]]);
if n & 1 == 1 {
(val16 >> 4) as u32
} else {
(val16 & 0x0fff) as u32
}
},
16 => {
let offset = n*2;
u16::from_le_bytes([buf[offset],buf[offset+1]]) as u32
},
32 => {
let offset = n*4;
u32::from_le_bytes(buf[offset..offset+4].try_into().expect("bounds")) & 0x0fffffff
}
_ => panic!("unexpected FAT type {}",typ)
}
}
pub fn set_cluster(n: usize,val: u32,typ: usize,buf: &mut Vec<u8>) {
match typ {
12 => {
let offset = n + (n/2);
if n & 1 == 1 {
let val12 = (val as u16) << 4;
let low4 = 0x000f & u16::from_le_bytes(buf[offset..offset+2].try_into().expect("bounds"));
let val16 = u16::to_le_bytes(val12 | low4);
buf[offset] = val16[0];
buf[offset+1] = val16[1];
} else {
let val12 = (val as u16) & 0x0fff;
let high4 = 0xf000 & u16::from_le_bytes(buf[offset..offset+2].try_into().expect("bounds"));
let val16 = u16::to_le_bytes(val12 | high4);
buf[offset] = val16[0];
buf[offset+1] = val16[1];
}
},
16 => {
let offset = n*2;
let val16 = u16::to_le_bytes(val as u16);
buf[offset] = val16[0];
buf[offset+1] = val16[1];
},
32 => {
let offset = n*4;
let high4 = 0xf0000000 & u32::from_le_bytes(buf[offset..offset+4].try_into().expect("bounds"));
let val32 = u32::to_le_bytes(high4 | (val & 0x0fffffff));
for i in 0..4 {
buf[offset+i] = val32[i];
}
}
_ => panic!("unexpected FAT type {}",typ)
}
}
pub fn is_damaged(n: usize,typ: usize,buf: &Vec<u8>) -> bool {
match typ {
12 => BAD_CLUSTER12==get_cluster(n,typ,buf),
16 => BAD_CLUSTER16==get_cluster(n,typ,buf),
32 => BAD_CLUSTER32==get_cluster(n,typ,buf),
_ => panic!("unexpected FAT type {}",typ)
}
}
pub fn is_free(n: usize,typ: usize,buf: &Vec<u8>) -> bool {
get_cluster(n,typ,buf)==FREE_CLUSTER
}
pub fn is_last(n: usize,typ: usize,buf: &Vec<u8>) -> bool {
match typ {
12 => EOC12_MIN<=get_cluster(n,typ,buf),
16 => EOC16_MIN<=get_cluster(n,typ,buf),
32 => EOC32_MIN<=get_cluster(n,typ,buf),
_ => panic!("unexpected FAT type {}",typ)
}
}
pub fn deallocate(n: usize,typ: usize,buf: &mut Vec<u8>) {
set_cluster(n,FREE_CLUSTER,typ,buf);
}
pub fn mark_damaged(n: usize,typ: usize,buf: &mut Vec<u8>) {
match typ {
12 => set_cluster(n,BAD_CLUSTER12,typ,buf),
16 => set_cluster(n,BAD_CLUSTER16,typ,buf),
32 => set_cluster(n,BAD_CLUSTER32,typ,buf),
_ => panic!("unexpected FAT type {}",typ)
}
}
pub fn mark_last(n: usize,typ: usize,buf: &mut Vec<u8>) {
match typ {
12 => set_cluster(n,EOC12_SET,typ,buf),
16 => set_cluster(n,EOC16_SET,typ,buf),
32 => set_cluster(n,EOC32_SET,typ,buf),
_ => panic!("unexpected FAT type {}",typ)
}
}