This page hosts a formal specification of vfat using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#![allow(unused_imports)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(irrefutable_let_patterns)]
#![allow(unused_comparisons)]
extern crate kaitai;
use kaitai::*;
use std::convert::{TryFrom, TryInto};
use std::cell::{Ref, Cell, RefCell};
use std::rc::{Rc, Weak};
use super::dos_datetime::DosDatetime;
/**
* \sa https://download.microsoft.com/download/0/8/4/084c452b-b772-4fe5-89bb-a0cbf082286a/fatgen103.doc Source
*/
#[derive(Default, Debug, Clone)]
pub struct Vfat {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat>,
pub _self: SharedType<Self>,
boot_sector: RefCell<OptRc<Vfat_BootSector>>,
_io: RefCell<BytesReader>,
root_dir_raw: RefCell<Vec<u8>>,
f_fats: Cell<bool>,
fats: RefCell<Vec<Vec<u8>>>,
f_root_dir: Cell<bool>,
root_dir: RefCell<OptRc<Vfat_RootDirectory>>,
}
impl KStruct for Vfat {
type Root = Vfat;
type Parent = Vfat;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
let t = Self::read_into::<_, Vfat_BootSector>(&*_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
*self_rc.boot_sector.borrow_mut() = t;
Ok(())
}
}
impl Vfat {
pub fn fats(
&self
) -> KResult<Ref<'_, Vec<Vec<u8>>>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_fats.get() {
return Ok(self.fats.borrow());
}
self.f_fats.set(true);
let _pos = _io.pos();
_io.seek(*self.boot_sector().pos_fats()? as usize)?;
*self.fats.borrow_mut() = Vec::new();
let l_fats = *self.boot_sector().bpb().num_fats();
for _i in 0..l_fats {
self.fats.borrow_mut().push(_io.read_bytes(*self.boot_sector().size_fat()? as usize)?.into());
}
_io.seek(_pos)?;
Ok(self.fats.borrow())
}
pub fn root_dir(
&self
) -> KResult<Ref<'_, OptRc<Vfat_RootDirectory>>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_root_dir.get() {
return Ok(self.root_dir.borrow());
}
let _pos = _io.pos();
_io.seek(*self.boot_sector().pos_root_dir()? as usize)?;
*self.root_dir_raw.borrow_mut() = _io.read_bytes(*self.boot_sector().size_root_dir()? as usize)?.into();
let root_dir_raw = self.root_dir_raw.borrow();
let _t_root_dir_raw_io = BytesReader::from(root_dir_raw.clone());
let t = Self::read_into::<BytesReader, Vfat_RootDirectory>(&_t_root_dir_raw_io, Some(self._root.clone()), Some(self._self.clone()))?.into();
*self.root_dir.borrow_mut() = t;
_io.seek(_pos)?;
Ok(self.root_dir.borrow())
}
}
impl Vfat {
pub fn boot_sector(&self) -> Ref<'_, OptRc<Vfat_BootSector>> {
self.boot_sector.borrow()
}
}
impl Vfat {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}
impl Vfat {
pub fn root_dir_raw(&self) -> Ref<'_, Vec<u8>> {
self.root_dir_raw.borrow()
}
}
#[derive(Default, Debug, Clone)]
pub struct Vfat_BiosParamBlock {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat_BootSector>,
pub _self: SharedType<Self>,
bytes_per_ls: RefCell<u16>,
ls_per_clus: RefCell<u8>,
num_reserved_ls: RefCell<u16>,
num_fats: RefCell<u8>,
max_root_dir_rec: RefCell<u16>,
total_ls_2: RefCell<u16>,
media_code: RefCell<u8>,
ls_per_fat: RefCell<u16>,
ps_per_track: RefCell<u16>,
num_heads: RefCell<u16>,
num_hidden_sectors: RefCell<u32>,
total_ls_4: RefCell<u32>,
_io: RefCell<BytesReader>,
}
impl KStruct for Vfat_BiosParamBlock {
type Root = Vfat;
type Parent = Vfat_BootSector;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
*self_rc.bytes_per_ls.borrow_mut() = _io.read_u2le()?.into();
*self_rc.ls_per_clus.borrow_mut() = _io.read_u1()?.into();
*self_rc.num_reserved_ls.borrow_mut() = _io.read_u2le()?.into();
*self_rc.num_fats.borrow_mut() = _io.read_u1()?.into();
*self_rc.max_root_dir_rec.borrow_mut() = _io.read_u2le()?.into();
*self_rc.total_ls_2.borrow_mut() = _io.read_u2le()?.into();
*self_rc.media_code.borrow_mut() = _io.read_u1()?.into();
*self_rc.ls_per_fat.borrow_mut() = _io.read_u2le()?.into();
*self_rc.ps_per_track.borrow_mut() = _io.read_u2le()?.into();
*self_rc.num_heads.borrow_mut() = _io.read_u2le()?.into();
*self_rc.num_hidden_sectors.borrow_mut() = _io.read_u4le()?.into();
*self_rc.total_ls_4.borrow_mut() = _io.read_u4le()?.into();
Ok(())
}
}
impl Vfat_BiosParamBlock {
}
/**
* Bytes per logical sector
*/
impl Vfat_BiosParamBlock {
pub fn bytes_per_ls(&self) -> Ref<'_, u16> {
self.bytes_per_ls.borrow()
}
}
/**
* Logical sectors per cluster
*/
impl Vfat_BiosParamBlock {
pub fn ls_per_clus(&self) -> Ref<'_, u8> {
self.ls_per_clus.borrow()
}
}
/**
* Count of reserved logical sectors. The number of logical
* sectors before the first FAT in the file system image.
*/
impl Vfat_BiosParamBlock {
pub fn num_reserved_ls(&self) -> Ref<'_, u16> {
self.num_reserved_ls.borrow()
}
}
/**
* Number of File Allocation Tables
*/
impl Vfat_BiosParamBlock {
pub fn num_fats(&self) -> Ref<'_, u8> {
self.num_fats.borrow()
}
}
/**
* Maximum number of FAT12 or FAT16 root directory entries. 0
* for FAT32, where the root directory is stored in ordinary
* data clusters.
*/
impl Vfat_BiosParamBlock {
pub fn max_root_dir_rec(&self) -> Ref<'_, u16> {
self.max_root_dir_rec.borrow()
}
}
/**
* Total logical sectors (if zero, use total_ls_4)
*/
impl Vfat_BiosParamBlock {
pub fn total_ls_2(&self) -> Ref<'_, u16> {
self.total_ls_2.borrow()
}
}
/**
* Media descriptor
*/
impl Vfat_BiosParamBlock {
pub fn media_code(&self) -> Ref<'_, u8> {
self.media_code.borrow()
}
}
/**
* Logical sectors per File Allocation Table for
* FAT12/FAT16. FAT32 sets this to 0 and uses the 32-bit value
* at offset 0x024 instead.
*/
impl Vfat_BiosParamBlock {
pub fn ls_per_fat(&self) -> Ref<'_, u16> {
self.ls_per_fat.borrow()
}
}
/**
* Physical sectors per track for disks with INT 13h CHS
* geometry, e.g., 15 for a "1.20 MB" (1200 KB) floppy. A zero
* entry indicates that this entry is reserved, but not used.
*/
impl Vfat_BiosParamBlock {
pub fn ps_per_track(&self) -> Ref<'_, u16> {
self.ps_per_track.borrow()
}
}
/**
* Number of heads for disks with INT 13h CHS geometry,[9]
* e.g., 2 for a double sided floppy.
*/
impl Vfat_BiosParamBlock {
pub fn num_heads(&self) -> Ref<'_, u16> {
self.num_heads.borrow()
}
}
/**
* Number of hidden sectors preceding the partition that
* contains this FAT volume. This field should always be zero
* on media that are not partitioned. This DOS 3.0 entry is
* incompatible with a similar entry at offset 0x01C in BPBs
* since DOS 3.31. It must not be used if the logical sectors
* entry at offset 0x013 is zero.
*/
impl Vfat_BiosParamBlock {
pub fn num_hidden_sectors(&self) -> Ref<'_, u32> {
self.num_hidden_sectors.borrow()
}
}
/**
* Total logical sectors including hidden sectors. This DOS 3.2
* entry is incompatible with a similar entry at offset 0x020
* in BPBs since DOS 3.31. It must not be used if the logical
* sectors entry at offset 0x013 is zero.
*/
impl Vfat_BiosParamBlock {
pub fn total_ls_4(&self) -> Ref<'_, u32> {
self.total_ls_4.borrow()
}
}
impl Vfat_BiosParamBlock {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}
#[derive(Default, Debug, Clone)]
pub struct Vfat_BootSector {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat>,
pub _self: SharedType<Self>,
jmp_instruction: RefCell<Vec<u8>>,
oem_name: RefCell<String>,
bpb: RefCell<OptRc<Vfat_BiosParamBlock>>,
ebpb_fat16: RefCell<OptRc<Vfat_ExtBiosParamBlockFat16>>,
ebpb_fat32: RefCell<OptRc<Vfat_ExtBiosParamBlockFat32>>,
_io: RefCell<BytesReader>,
f_is_fat32: Cell<bool>,
is_fat32: RefCell<bool>,
f_ls_per_fat: Cell<bool>,
ls_per_fat: RefCell<u32>,
f_ls_per_root_dir: Cell<bool>,
ls_per_root_dir: RefCell<i32>,
f_pos_fats: Cell<bool>,
pos_fats: RefCell<i32>,
f_pos_root_dir: Cell<bool>,
pos_root_dir: RefCell<i32>,
f_size_fat: Cell<bool>,
size_fat: RefCell<i32>,
f_size_root_dir: Cell<bool>,
size_root_dir: RefCell<i32>,
}
impl KStruct for Vfat_BootSector {
type Root = Vfat;
type Parent = Vfat;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
*self_rc.jmp_instruction.borrow_mut() = _io.read_bytes(3 as usize)?.into();
*self_rc.oem_name.borrow_mut() = bytes_to_str(&bytes_strip_right(&_io.read_bytes(8 as usize)?.into(), 32).into(), "ASCII")?;
let t = Self::read_into::<_, Vfat_BiosParamBlock>(&*_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
*self_rc.bpb.borrow_mut() = t;
if !(*self_rc.is_fat32()?) {
let t = Self::read_into::<_, Vfat_ExtBiosParamBlockFat16>(&*_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
*self_rc.ebpb_fat16.borrow_mut() = t;
}
if *self_rc.is_fat32()? {
let t = Self::read_into::<_, Vfat_ExtBiosParamBlockFat32>(&*_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
*self_rc.ebpb_fat32.borrow_mut() = t;
}
Ok(())
}
}
impl Vfat_BootSector {
/**
* Determines if filesystem is FAT32 (true) or FAT12/16 (false)
* by analyzing some preliminary conditions in BPB. Used to
* determine whether we should parse post-BPB data as
* `ext_bios_param_block_fat16` or `ext_bios_param_block_fat32`.
*/
pub fn is_fat32(
&self
) -> KResult<Ref<'_, bool>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_is_fat32.get() {
return Ok(self.is_fat32.borrow());
}
self.f_is_fat32.set(true);
*self.is_fat32.borrow_mut() = (((*self.bpb().max_root_dir_rec() as u16) == (0 as u16))) as bool;
Ok(self.is_fat32.borrow())
}
pub fn ls_per_fat(
&self
) -> KResult<Ref<'_, u32>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_ls_per_fat.get() {
return Ok(self.ls_per_fat.borrow());
}
self.f_ls_per_fat.set(true);
*self.ls_per_fat.borrow_mut() = (if *self.is_fat32()? { *self.ebpb_fat32().ls_per_fat() } else { *self.bpb().ls_per_fat() }) as u32;
Ok(self.ls_per_fat.borrow())
}
/**
* Size of root directory in logical sectors
* \sa FAT: General Overview of On-Disk Format, section "FAT Data Structure"
*/
pub fn ls_per_root_dir(
&self
) -> KResult<Ref<'_, i32>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_ls_per_root_dir.get() {
return Ok(self.ls_per_root_dir.borrow());
}
self.f_ls_per_root_dir.set(true);
*self.ls_per_root_dir.borrow_mut() = (((((((((*self.bpb().max_root_dir_rec() as u16) * (32 as u16)) as i32) + (*self.bpb().bytes_per_ls() as i32)) as i32) - (1 as i32)) as i32) / (*self.bpb().bytes_per_ls() as i32))) as i32;
Ok(self.ls_per_root_dir.borrow())
}
/**
* Offset of FATs in bytes from start of filesystem
*/
pub fn pos_fats(
&self
) -> KResult<Ref<'_, i32>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_pos_fats.get() {
return Ok(self.pos_fats.borrow());
}
self.f_pos_fats.set(true);
*self.pos_fats.borrow_mut() = (((*self.bpb().bytes_per_ls() as u16) * (*self.bpb().num_reserved_ls() as u16))) as i32;
Ok(self.pos_fats.borrow())
}
/**
* Offset of root directory in bytes from start of filesystem
*/
pub fn pos_root_dir(
&self
) -> KResult<Ref<'_, i32>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_pos_root_dir.get() {
return Ok(self.pos_root_dir.borrow());
}
self.f_pos_root_dir.set(true);
*self.pos_root_dir.borrow_mut() = (((*self.bpb().bytes_per_ls() as i32) * (((*self.bpb().num_reserved_ls() as i32) + (((*self.ls_per_fat()? as u32) * (*self.bpb().num_fats() as u32)) as i32)) as i32))) as i32;
Ok(self.pos_root_dir.borrow())
}
/**
* Size of one FAT in bytes
*/
pub fn size_fat(
&self
) -> KResult<Ref<'_, i32>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_size_fat.get() {
return Ok(self.size_fat.borrow());
}
self.f_size_fat.set(true);
*self.size_fat.borrow_mut() = (((*self.bpb().bytes_per_ls() as u32) * (*self.ls_per_fat()? as u32))) as i32;
Ok(self.size_fat.borrow())
}
/**
* Size of root directory in bytes
*/
pub fn size_root_dir(
&self
) -> KResult<Ref<'_, i32>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_size_root_dir.get() {
return Ok(self.size_root_dir.borrow());
}
self.f_size_root_dir.set(true);
*self.size_root_dir.borrow_mut() = (((*self.ls_per_root_dir()? as i32) * (*self.bpb().bytes_per_ls() as i32))) as i32;
Ok(self.size_root_dir.borrow())
}
}
impl Vfat_BootSector {
pub fn jmp_instruction(&self) -> Ref<'_, Vec<u8>> {
self.jmp_instruction.borrow()
}
}
impl Vfat_BootSector {
pub fn oem_name(&self) -> Ref<'_, String> {
self.oem_name.borrow()
}
}
/**
* Basic BIOS parameter block, present in all versions of FAT
*/
impl Vfat_BootSector {
pub fn bpb(&self) -> Ref<'_, OptRc<Vfat_BiosParamBlock>> {
self.bpb.borrow()
}
}
/**
* FAT12/16-specific extended BIOS parameter block
*/
impl Vfat_BootSector {
pub fn ebpb_fat16(&self) -> Ref<'_, OptRc<Vfat_ExtBiosParamBlockFat16>> {
self.ebpb_fat16.borrow()
}
}
/**
* FAT32-specific extended BIOS parameter block
*/
impl Vfat_BootSector {
pub fn ebpb_fat32(&self) -> Ref<'_, OptRc<Vfat_ExtBiosParamBlockFat32>> {
self.ebpb_fat32.borrow()
}
}
impl Vfat_BootSector {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}
/**
* Extended BIOS Parameter Block (DOS 4.0+, OS/2 1.0+). Used only
* for FAT12 and FAT16.
*/
#[derive(Default, Debug, Clone)]
pub struct Vfat_ExtBiosParamBlockFat16 {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat_BootSector>,
pub _self: SharedType<Self>,
phys_drive_num: RefCell<u8>,
reserved1: RefCell<u8>,
ext_boot_sign: RefCell<u8>,
volume_id: RefCell<Vec<u8>>,
partition_volume_label: RefCell<String>,
fs_type_str: RefCell<String>,
_io: RefCell<BytesReader>,
}
impl KStruct for Vfat_ExtBiosParamBlockFat16 {
type Root = Vfat;
type Parent = Vfat_BootSector;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
*self_rc.phys_drive_num.borrow_mut() = _io.read_u1()?.into();
*self_rc.reserved1.borrow_mut() = _io.read_u1()?.into();
*self_rc.ext_boot_sign.borrow_mut() = _io.read_u1()?.into();
*self_rc.volume_id.borrow_mut() = _io.read_bytes(4 as usize)?.into();
*self_rc.partition_volume_label.borrow_mut() = bytes_to_str(&bytes_strip_right(&_io.read_bytes(11 as usize)?.into(), 32).into(), "ASCII")?;
*self_rc.fs_type_str.borrow_mut() = bytes_to_str(&bytes_strip_right(&_io.read_bytes(8 as usize)?.into(), 32).into(), "ASCII")?;
Ok(())
}
}
impl Vfat_ExtBiosParamBlockFat16 {
}
/**
* Physical drive number (0x00 for (first) removable media,
* 0x80 for (first) fixed disk as per INT 13h).
*/
impl Vfat_ExtBiosParamBlockFat16 {
pub fn phys_drive_num(&self) -> Ref<'_, u8> {
self.phys_drive_num.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat16 {
pub fn reserved1(&self) -> Ref<'_, u8> {
self.reserved1.borrow()
}
}
/**
* Should be 0x29 to indicate that an EBPB with the following 3
* entries exists.
*/
impl Vfat_ExtBiosParamBlockFat16 {
pub fn ext_boot_sign(&self) -> Ref<'_, u8> {
self.ext_boot_sign.borrow()
}
}
/**
* Volume ID (serial number).
*
* Typically the serial number "xxxx-xxxx" is created by a
* 16-bit addition of both DX values returned by INT 21h/AH=2Ah
* (get system date) and INT 21h/AH=2Ch (get system time) for
* the high word and another 16-bit addition of both CX values
* for the low word of the serial number. Alternatively, some
* DR-DOS disk utilities provide a /# option to generate a
* human-readable time stamp "mmdd-hhmm" build from BCD-encoded
* 8-bit values for the month, day, hour and minute instead of
* a serial number.
*/
impl Vfat_ExtBiosParamBlockFat16 {
pub fn volume_id(&self) -> Ref<'_, Vec<u8>> {
self.volume_id.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat16 {
pub fn partition_volume_label(&self) -> Ref<'_, String> {
self.partition_volume_label.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat16 {
pub fn fs_type_str(&self) -> Ref<'_, String> {
self.fs_type_str.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat16 {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}
/**
* Extended BIOS Parameter Block for FAT32
*/
#[derive(Default, Debug, Clone)]
pub struct Vfat_ExtBiosParamBlockFat32 {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat_BootSector>,
pub _self: SharedType<Self>,
ls_per_fat: RefCell<u32>,
has_active_fat: RefCell<bool>,
reserved1: RefCell<u64>,
active_fat_id: RefCell<u64>,
reserved2: RefCell<Vec<u8>>,
fat_version: RefCell<u16>,
root_dir_start_clus: RefCell<u32>,
ls_fs_info: RefCell<u16>,
boot_sectors_copy_start_ls: RefCell<u16>,
reserved3: RefCell<Vec<u8>>,
phys_drive_num: RefCell<u8>,
reserved4: RefCell<u8>,
ext_boot_sign: RefCell<u8>,
volume_id: RefCell<Vec<u8>>,
partition_volume_label: RefCell<String>,
fs_type_str: RefCell<String>,
_io: RefCell<BytesReader>,
}
impl KStruct for Vfat_ExtBiosParamBlockFat32 {
type Root = Vfat;
type Parent = Vfat_BootSector;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
*self_rc.ls_per_fat.borrow_mut() = _io.read_u4le()?.into();
*self_rc.has_active_fat.borrow_mut() = _io.read_bits_int_le(1)? != 0;
*self_rc.reserved1.borrow_mut() = _io.read_bits_int_le(3)?;
*self_rc.active_fat_id.borrow_mut() = _io.read_bits_int_le(4)?;
_io.align_to_byte()?;
*self_rc.reserved2.borrow_mut() = _io.read_bytes(1 as usize)?.into();
if !(*self_rc.reserved2() == vec![0x0u8]) {
return Err(KError::ValidationFailed(ValidationFailedError { kind: ValidationKind::NotEqual, src_path: "/types/ext_bios_param_block_fat32/seq/4".to_string() }));
}
*self_rc.fat_version.borrow_mut() = _io.read_u2le()?.into();
*self_rc.root_dir_start_clus.borrow_mut() = _io.read_u4le()?.into();
*self_rc.ls_fs_info.borrow_mut() = _io.read_u2le()?.into();
*self_rc.boot_sectors_copy_start_ls.borrow_mut() = _io.read_u2le()?.into();
*self_rc.reserved3.borrow_mut() = _io.read_bytes(12 as usize)?.into();
*self_rc.phys_drive_num.borrow_mut() = _io.read_u1()?.into();
*self_rc.reserved4.borrow_mut() = _io.read_u1()?.into();
*self_rc.ext_boot_sign.borrow_mut() = _io.read_u1()?.into();
*self_rc.volume_id.borrow_mut() = _io.read_bytes(4 as usize)?.into();
*self_rc.partition_volume_label.borrow_mut() = bytes_to_str(&bytes_strip_right(&_io.read_bytes(11 as usize)?.into(), 32).into(), "ASCII")?;
*self_rc.fs_type_str.borrow_mut() = bytes_to_str(&bytes_strip_right(&_io.read_bytes(8 as usize)?.into(), 32).into(), "ASCII")?;
Ok(())
}
}
impl Vfat_ExtBiosParamBlockFat32 {
}
/**
* Logical sectors per file allocation table (corresponds with
* the old entry `ls_per_fat` in the DOS 2.0 BPB).
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn ls_per_fat(&self) -> Ref<'_, u32> {
self.ls_per_fat.borrow()
}
}
/**
* If true, then there is "active" FAT, which is designated in
* `active_fat` attribute. If false, all FATs are mirrored as
* usual.
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn has_active_fat(&self) -> Ref<'_, bool> {
self.has_active_fat.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn reserved1(&self) -> Ref<'_, u64> {
self.reserved1.borrow()
}
}
/**
* Zero-based number of active FAT, if `has_active_fat`
* attribute is true.
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn active_fat_id(&self) -> Ref<'_, u64> {
self.active_fat_id.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn reserved2(&self) -> Ref<'_, Vec<u8>> {
self.reserved2.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn fat_version(&self) -> Ref<'_, u16> {
self.fat_version.borrow()
}
}
/**
* Cluster number of root directory start, typically 2 if it
* contains no bad sector. (Microsoft's FAT32 implementation
* imposes an artificial limit of 65,535 entries per directory,
* whilst many third-party implementations do not.)
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn root_dir_start_clus(&self) -> Ref<'_, u32> {
self.root_dir_start_clus.borrow()
}
}
/**
* Logical sector number of FS Information Sector, typically 1,
* i.e., the second of the three FAT32 boot sectors. Values
* like 0 and 0xFFFF are used by some FAT32 implementations to
* designate abscence of FS Information Sector.
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn ls_fs_info(&self) -> Ref<'_, u16> {
self.ls_fs_info.borrow()
}
}
/**
* First logical sector number of a copy of the three FAT32
* boot sectors, typically 6.
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn boot_sectors_copy_start_ls(&self) -> Ref<'_, u16> {
self.boot_sectors_copy_start_ls.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn reserved3(&self) -> Ref<'_, Vec<u8>> {
self.reserved3.borrow()
}
}
/**
* Physical drive number (0x00 for (first) removable media,
* 0x80 for (first) fixed disk as per INT 13h).
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn phys_drive_num(&self) -> Ref<'_, u8> {
self.phys_drive_num.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn reserved4(&self) -> Ref<'_, u8> {
self.reserved4.borrow()
}
}
/**
* Should be 0x29 to indicate that an EBPB with the following 3
* entries exists.
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn ext_boot_sign(&self) -> Ref<'_, u8> {
self.ext_boot_sign.borrow()
}
}
/**
* Volume ID (serial number).
*
* Typically the serial number "xxxx-xxxx" is created by a
* 16-bit addition of both DX values returned by INT 21h/AH=2Ah
* (get system date) and INT 21h/AH=2Ch (get system time) for
* the high word and another 16-bit addition of both CX values
* for the low word of the serial number. Alternatively, some
* DR-DOS disk utilities provide a /# option to generate a
* human-readable time stamp "mmdd-hhmm" build from BCD-encoded
* 8-bit values for the month, day, hour and minute instead of
* a serial number.
*/
impl Vfat_ExtBiosParamBlockFat32 {
pub fn volume_id(&self) -> Ref<'_, Vec<u8>> {
self.volume_id.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn partition_volume_label(&self) -> Ref<'_, String> {
self.partition_volume_label.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn fs_type_str(&self) -> Ref<'_, String> {
self.fs_type_str.borrow()
}
}
impl Vfat_ExtBiosParamBlockFat32 {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}
#[derive(Default, Debug, Clone)]
pub struct Vfat_RootDirectory {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat>,
pub _self: SharedType<Self>,
records: RefCell<Vec<OptRc<Vfat_RootDirectoryRec>>>,
_io: RefCell<BytesReader>,
}
impl KStruct for Vfat_RootDirectory {
type Root = Vfat;
type Parent = Vfat;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
*self_rc.records.borrow_mut() = Vec::new();
let l_records = *_r.boot_sector().bpb().max_root_dir_rec();
for _i in 0..l_records {
let t = Self::read_into::<_, Vfat_RootDirectoryRec>(&*_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
self_rc.records.borrow_mut().push(t);
}
Ok(())
}
}
impl Vfat_RootDirectory {
}
impl Vfat_RootDirectory {
pub fn records(&self) -> Ref<'_, Vec<OptRc<Vfat_RootDirectoryRec>>> {
self.records.borrow()
}
}
impl Vfat_RootDirectory {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}
#[derive(Default, Debug, Clone)]
pub struct Vfat_RootDirectoryRec {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat_RootDirectory>,
pub _self: SharedType<Self>,
file_name: RefCell<Vec<u8>>,
attrs: RefCell<OptRc<Vfat_RootDirectoryRec_AttrFlags>>,
reserved: RefCell<Vec<u8>>,
last_write_time: RefCell<OptRc<DosDatetime>>,
start_clus: RefCell<u16>,
file_size: RefCell<u32>,
_io: RefCell<BytesReader>,
attrs_raw: RefCell<Vec<u8>>,
last_write_time_raw: RefCell<Vec<u8>>,
}
impl KStruct for Vfat_RootDirectoryRec {
type Root = Vfat;
type Parent = Vfat_RootDirectory;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
*self_rc.file_name.borrow_mut() = _io.read_bytes(11 as usize)?.into();
*self_rc.attrs_raw.borrow_mut() = _io.read_bytes(1 as usize)?.into();
let attrs_raw = self_rc.attrs_raw.borrow();
let _t_attrs_raw_io = BytesReader::from(attrs_raw.clone());
let t = Self::read_into::<BytesReader, Vfat_RootDirectoryRec_AttrFlags>(&_t_attrs_raw_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
*self_rc.attrs.borrow_mut() = t;
*self_rc.reserved.borrow_mut() = _io.read_bytes(10 as usize)?.into();
*self_rc.last_write_time_raw.borrow_mut() = _io.read_bytes(4 as usize)?.into();
let last_write_time_raw = self_rc.last_write_time_raw.borrow();
let _t_last_write_time_raw_io = BytesReader::from(last_write_time_raw.clone());
let t = Self::read_into::<BytesReader, DosDatetime>(&_t_last_write_time_raw_io, None, None)?.into();
*self_rc.last_write_time.borrow_mut() = t;
*self_rc.start_clus.borrow_mut() = _io.read_u2le()?.into();
*self_rc.file_size.borrow_mut() = _io.read_u4le()?.into();
Ok(())
}
}
impl Vfat_RootDirectoryRec {
}
impl Vfat_RootDirectoryRec {
pub fn file_name(&self) -> Ref<'_, Vec<u8>> {
self.file_name.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn attrs(&self) -> Ref<'_, OptRc<Vfat_RootDirectoryRec_AttrFlags>> {
self.attrs.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn reserved(&self) -> Ref<'_, Vec<u8>> {
self.reserved.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn last_write_time(&self) -> Ref<'_, OptRc<DosDatetime>> {
self.last_write_time.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn start_clus(&self) -> Ref<'_, u16> {
self.start_clus.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn file_size(&self) -> Ref<'_, u32> {
self.file_size.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn attrs_raw(&self) -> Ref<'_, Vec<u8>> {
self.attrs_raw.borrow()
}
}
impl Vfat_RootDirectoryRec {
pub fn last_write_time_raw(&self) -> Ref<'_, Vec<u8>> {
self.last_write_time_raw.borrow()
}
}
#[derive(Default, Debug, Clone)]
pub struct Vfat_RootDirectoryRec_AttrFlags {
pub _root: SharedType<Vfat>,
pub _parent: SharedType<Vfat_RootDirectoryRec>,
pub _self: SharedType<Self>,
read_only: RefCell<bool>,
hidden: RefCell<bool>,
system: RefCell<bool>,
volume_id: RefCell<bool>,
is_directory: RefCell<bool>,
archive: RefCell<bool>,
reserved: RefCell<u64>,
_io: RefCell<BytesReader>,
f_long_name: Cell<bool>,
long_name: RefCell<bool>,
}
impl KStruct for Vfat_RootDirectoryRec_AttrFlags {
type Root = Vfat;
type Parent = Vfat_RootDirectoryRec;
fn read<S: KStream>(
self_rc: &OptRc<Self>,
_io: &S,
_root: SharedType<Self::Root>,
_parent: SharedType<Self::Parent>,
) -> KResult<()> {
*self_rc._io.borrow_mut() = _io.clone();
self_rc._root.set(_root.get());
self_rc._parent.set(_parent.get());
self_rc._self.set(Ok(self_rc.clone()));
let _rrc = self_rc._root.get_value().borrow().upgrade();
let _prc = self_rc._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
*self_rc.read_only.borrow_mut() = _io.read_bits_int_le(1)? != 0;
*self_rc.hidden.borrow_mut() = _io.read_bits_int_le(1)? != 0;
*self_rc.system.borrow_mut() = _io.read_bits_int_le(1)? != 0;
*self_rc.volume_id.borrow_mut() = _io.read_bits_int_le(1)? != 0;
*self_rc.is_directory.borrow_mut() = _io.read_bits_int_le(1)? != 0;
*self_rc.archive.borrow_mut() = _io.read_bits_int_le(1)? != 0;
*self_rc.reserved.borrow_mut() = _io.read_bits_int_le(2)?;
Ok(())
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn long_name(
&self
) -> KResult<Ref<'_, bool>> {
let _io = self._io.borrow();
let _rrc = self._root.get_value().borrow().upgrade();
let _prc = self._parent.get_value().borrow().upgrade();
let _r = _rrc.as_ref().unwrap();
if self.f_long_name.get() {
return Ok(self.long_name.borrow());
}
self.f_long_name.set(true);
*self.long_name.borrow_mut() = ( ((*self.read_only()) && (*self.hidden()) && (*self.system()) && (*self.volume_id())) ) as bool;
Ok(self.long_name.borrow())
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn read_only(&self) -> Ref<'_, bool> {
self.read_only.borrow()
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn hidden(&self) -> Ref<'_, bool> {
self.hidden.borrow()
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn system(&self) -> Ref<'_, bool> {
self.system.borrow()
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn volume_id(&self) -> Ref<'_, bool> {
self.volume_id.borrow()
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn is_directory(&self) -> Ref<'_, bool> {
self.is_directory.borrow()
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn archive(&self) -> Ref<'_, bool> {
self.archive.borrow()
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn reserved(&self) -> Ref<'_, u64> {
self.reserved.borrow()
}
}
impl Vfat_RootDirectoryRec_AttrFlags {
pub fn _io(&self) -> Ref<'_, BytesReader> {
self._io.borrow()
}
}