Lots of breaking crap.. this is more of a backup than a commit.

This commit is contained in:
Bas Wiel, van de 2024-04-25 19:01:02 +02:00
parent d5a1ae328e
commit 1f63d61aad
7 changed files with 196 additions and 121 deletions

12
Cargo.lock generated
View File

@ -895,9 +895,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
version = "0.38.32"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
@ -1097,18 +1097,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.58"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
dependencies = [
"proc-macro2",
"quote",

View File

@ -19,13 +19,18 @@ impl Analyzer {
Ok(Analyzer { disk, filesystem })
}
pub fn print_metadata(&self) {
pub fn print_metadata(&mut self) {
println!("Disk metadata according to VHD footer\n-------------------------------------\n");
println!("{}", self.disk.get_metadata());
println!("Partition table according to the MBR\n------------------------------------\n");
println!("{}", self.disk.partition_table);
println!("Filesystem information\n-----------------------------------------------\n");
println!("{}", self.filesystem);
println!("Root directory information\n----------------------------------\n");
println!("{}", self.filesystem.root_directory);
for child in self.filesystem.root_directory.get_children() {
println!("{}", child);
}
}
fn get_boot_partition(disk: &Disk) -> Option<Partition> {

View File

@ -70,11 +70,10 @@ impl DiskBuilder {
)
.unwrap()
.to_vec();
filesystem.write_file(
iosys.as_slice(),
"ibmbio.com",
filesystem.mkfile(
None,
Some(DirEntryType::SysFile),
"ibmbio.com",
iosys.as_slice(),
&root_partition,
&mut disk,
)?;
@ -104,11 +103,11 @@ impl DiskBuilder {
&mut disk,
)?;
}
filesystem.mkdir(None,"DOS")?;
filesystem.mkdir(None,"GAME")?;
filesystem.mkdir(None, "DOS")?;
//filesystem.mkdir(None,"GAME")?;
// Last action: write the allocation table copies to the disk
filesystem.write_allocation_tables(&root_partition, &mut disk)?;
filesystem.write_dirs(None,&root_partition, &mut disk)?;
filesystem.write_dirs(None, &root_partition, &mut disk)?;
disk.commit_storage()?;
Ok(())
}

View File

@ -441,12 +441,8 @@ impl Partition {
let mut end_sector_bytes = [0u8; 3];
end_sector_bytes.copy_from_slice(&bytes[5..8]);
println!(
"End sector bytes {:08b}, {:08b}, {:08b}",
end_sector_bytes[0], end_sector_bytes[1], end_sector_bytes[2]
);
let end_sector = CHS::from_bytes(end_sector_bytes);
println!("End sector CHS: {}", end_sector);
let start_sector_lba = u32::from_le_bytes(bytes[8..12].try_into().map_err(|_| {
std::io::Error::new(

View File

@ -172,7 +172,14 @@ impl Fat {
allocation_table: AllocationTable::new(
sector_count as u32 / sectors_per_cluster as u32,
),
root_directory: DirEntry::new("ROOTDIR", DirEntryType::RootDirectory, None, 0, 0)?,
root_directory: DirEntry::new(
"ROOTDIR",
DirEntryType::RootDirectory,
None,
0,
0,
None,
)?,
oem_name: String::from("IBM 2.0"),
bytes_per_sector: SECTOR_SIZE,
sectors_per_cluster,
@ -256,7 +263,14 @@ impl Fat {
sector_count as u32 / sectors_per_cluster as u32,
),
oem_name: Self::oem_name_from_bytes(&vbr_bytes),
root_directory: DirEntry::new("ROOTDIR", DirEntryType::RootDirectory, None, 0, 0)?,
root_directory: DirEntry::new(
"ROOTDIR",
DirEntryType::RootDirectory,
None,
0,
0,
None,
)?,
bytes_per_sector: 512,
sectors_per_cluster,
reserved_sector_count: u16::from_le_bytes([vbr_bytes[0x00e], vbr_bytes[0x00f]]),
@ -316,17 +330,108 @@ impl Fat {
bootsector
}
/// Create a new file, give the data as a byte slice.
pub fn mkfile(
&mut self,
parent: Option<&mut DirEntry>,
filename: &str,
data: &[u8],
partition: &Partition,
disk: &mut Disk,
) -> Result<(), std::io::Error> {
// 1. Allocate the required number of clusters on the allocation table
let clusters = self.allocate_clusters(data)?;
let bytes_per_cluster = self.sectors_per_cluster as usize * 512;
let mut remaining_data = data;
// 2. Create a directory entry for the new file.
let file_entry = DirEntry::new(
filename,
DirEntryType::File,
None,
clusters[0],
data.len() as u32,
Some(data),
)?;
// 3. Place the entry into the correct directory entry inside the file system
match parent {
Some(subdir) => subdir.add_child(file_entry),
None => self.root_directory.add_child(file_entry),
}
// 4. Write the file's bytes to the clusters
for i in 0..clusters.len() {
let mut data: Vec<u8> = Vec::with_capacity(bytes_per_cluster);
let cluster_number = clusters[i];
let bytes_to_write = std::cmp::min(bytes_per_cluster, remaining_data.len());
// Copy data to write into the buffer
data.extend_from_slice(&remaining_data[..bytes_to_write]);
remaining_data = &remaining_data[bytes_to_write..];
// Write data to cluster
self.write_cluster(&mut data, cluster_number as u16, partition, disk)?;
// Update cluster allocation table
if let Some(value) = clusters.get(i + 1).cloned() {
self.allocation_table
.allocate_cluster(cluster_number, value)?;
} else {
// No next cluster, mark end of chain.
self.allocation_table.mark_end_of_chain(cluster_number)?;
break;
}
}
Ok(())
}
/// Equivalent of the MS-DOS "MKDIR" command. Provide a name, the system will do the rest.
pub fn mkdir(
&mut self,
parent: Option<&DirEntry>,
parent: Option<&mut DirEntry>,
dir_name: &str,
) -> Result<(), std::io::Error> {
// Set the parent to the root dir if none is given
let parent_entry = match parent {
None => &self.root_directory,
Some(_) => parent.unwrap(),
};
let new_start_cluster = self.allocate_cluster()?;
self.allocation_table.mark_end_of_chain(new_start_cluster)?;
let parent_entry = parent.unwrap_or(&mut self.root_directory);
// Instantiate the new entry.
let mut new_entry = DirEntry::new(
dir_name,
DirEntryType::Directory,
None,
new_start_cluster,
0,
None,
)?;
// Create the "." entry as a child.
new_entry.add_child(DirEntry::new(
".",
DirEntryType::Directory,
None,
new_entry.get_start_cluster(),
0,
None,
)?);
// Create the ".." entry as a child.
new_entry.add_child(DirEntry::new(
"..",
DirEntryType::Directory,
None,
parent_entry.get_start_cluster(),
0,
None,
)?);
// Add the complete new entry to its parent
parent_entry.add_child(new_entry);
Ok(())
}
@ -367,6 +472,7 @@ impl Fat {
let mut sector_address = (cluster_address as usize * self.sectors_per_cluster as usize
+ first_data_sector as usize)
- 2 * self.sectors_per_cluster as usize;
for chunk in data.chunks_exact(512) {
let mut chunk_array = [0u8; 512];
chunk_array.copy_from_slice(chunk);
@ -442,17 +548,6 @@ impl Fat {
Some(directory) => directory.clone(),
};
// Collect the raw sectors in a Vec
let mut sectors: Vec<[u8; 512]> = Vec::new();
// Figure out at which sector we need start writing this entry
let data_sector = self.sectors_per_cluster as u32 * directory.start_cluster;
// Take into account the offset caused by FAT's own data structures
let sector_offset = self.reserved_sector_count as u32
+ (self.fat_copies as u32 * self.sectors_per_fat as u32) as u32
+ data_sector;
// Collect all the bytes in a Vec
let mut bytes: Vec<u8> = Vec::new();
@ -460,7 +555,7 @@ impl Fat {
for child in &directory.children {
bytes.extend_from_slice(&child.as_bytes()?);
// Do this again for all subdirs
// Do this again for all subdirs except for recursive system dirs
if child.get_type() == DirEntryType::Directory {
if child.directory_name() != "." && child.directory_name() != ".." {
self.write_dirs(Some(child), partition, disk)?;
@ -468,33 +563,12 @@ impl Fat {
}
}
// Initialize chunk and index to known zero values
let mut current_chunk: [u8; 512] = [0; 512];
let mut current_index = 0;
// Loop over the bytes to put them into sectors
for &byte in bytes.iter() {
current_chunk[current_index] = byte;
current_index += 1;
// If the current sector is full, push it to the sectors vector and reset
if current_index == 512 {
sectors.push(current_chunk);
current_chunk = [0; 512];
current_index = 0;
}
}
// If there are remaining bytes in the last chunk, fill the rest with zeros and push it
if current_index > 0 {
sectors.push(current_chunk);
}
// Finally write the sectors out to storage and exit.
for (index, sector) in sectors.iter().enumerate() {
partition.write_sector(disk, sector_offset as u32 + index as u32, *sector)?;
}
//self.write_cluster(&mut bytes, directory.get_start_cluster() as u16, partition, disk)?;
self.write_cluster(
&mut bytes.to_vec(),
directory.get_start_cluster() as u16,
partition,
disk,
)?;
Ok(())
}
@ -519,6 +593,7 @@ impl Fat {
None,
cluster_numbers[0],
file.len() as u32,
Some(file),
)?,
Some(entry_type) => DirEntry::new(
filename,
@ -526,6 +601,7 @@ impl Fat {
None,
cluster_numbers[0],
file.len() as u32,
Some(file),
)?,
};

View File

@ -1,5 +1,5 @@
use std::cmp::min;
use super::{attributes::Attributes, filename::FileName, timedate::TimeDate};
use std::{cmp::min, fmt};
#[derive(Clone, Debug, PartialEq)]
pub struct DirEntry {
@ -10,6 +10,7 @@ pub struct DirEntry {
pub file_size: u32,
pub entry_type: DirEntryType,
pub children: Vec<DirEntry>,
data: Vec<u8>,
}
/// Enum to differentiate between different types of DirEntry. These types streamline
@ -22,6 +23,32 @@ pub enum DirEntryType {
RootDirectory,
}
impl fmt::Display for DirEntryType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DirEntryType::Directory => write!(f, "Subdirectory"),
DirEntryType::File => write!(f, "Regular file"),
DirEntryType::RootDirectory => write!(f, "Root Directory"),
DirEntryType::SysFile => write!(f, "System file"),
}
}
}
impl fmt::Display for DirEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"File name : {}\n\
Start cluster : {}\n\
Entry type : {}\n\
",
self.filename.base_as_string(),
self.start_cluster,
self.entry_type
)
}
}
impl DirEntry {
/// Public entry point for creating new DirEntry instances. The function itself branches out
/// depending on the type of entry desired.
@ -31,20 +58,23 @@ impl DirEntry {
create_timedate: Option<TimeDate>,
start_cluster: u32,
file_size: u32,
data: Option<&[u8]>,
) -> Result<Self, std::io::Error> {
match entry_type {
DirEntryType::File => {
Self::create_file(filename, create_timedate, start_cluster, file_size)
}
DirEntryType::File => Self::create_file(
filename,
create_timedate,
start_cluster,
file_size,
data.unwrap().to_vec(),
),
DirEntryType::SysFile => {
Self::create_sysfile(filename, create_timedate, start_cluster, file_size)
}
DirEntryType::Directory => {
Self::create_directory(filename, create_timedate, start_cluster)
}
DirEntryType::RootDirectory => {
Self::create_rootdir()
}
DirEntryType::RootDirectory => Self::create_rootdir(),
}
}
@ -67,6 +97,7 @@ impl DirEntry {
file_size,
entry_type: DirEntryType::SysFile,
children: Vec::new(),
data: Vec::new(),
}),
_ => Ok(DirEntry {
filename: FileName::new(filename)?,
@ -76,6 +107,7 @@ impl DirEntry {
file_size,
entry_type: DirEntryType::SysFile,
children: Vec::new(),
data: Vec::new(),
}),
}
}
@ -87,6 +119,7 @@ impl DirEntry {
create_timedate: Option<TimeDate>,
start_cluster: u32,
file_size: u32,
data: Vec<u8>,
) -> Result<Self, std::io::Error> {
// Set of attributes appropriate to a regular file
let attributes = Attributes::new(true, false, false, false, false, false, false);
@ -99,6 +132,7 @@ impl DirEntry {
file_size,
entry_type: DirEntryType::File,
children: Vec::new(),
data,
}),
_ => Ok(DirEntry {
filename: FileName::new(filename)?,
@ -108,6 +142,7 @@ impl DirEntry {
file_size,
entry_type: DirEntryType::File,
children: Vec::new(),
data,
}),
}
}
@ -115,12 +150,13 @@ impl DirEntry {
fn create_rootdir() -> Result<Self, std::io::Error> {
Ok(DirEntry {
filename: FileName::new("ROOTDIR")?,
attributes: Attributes::new(true, false, false, false, false, true, false),
attributes: Attributes::new(false, false, false, false, false, true, false),
create_timedate: TimeDate::now(),
start_cluster: 0,
file_size: 0,
entry_type: DirEntryType::RootDirectory,
children: Vec::new(),
data: Vec::new(),
})
}
@ -130,9 +166,9 @@ impl DirEntry {
start_cluster: u32,
) -> Result<Self, std::io::Error> {
// Set of attributes appropriate to a directory
let attributes = Attributes::new(true, false, false, false, false, true, false);
let attributes = Attributes::new(false, false, false, false, false, true, false);
// This is the acual directory we're making
let mut new_entry = match create_timedate {
let new_entry = match create_timedate {
None => DirEntry {
filename: FileName::new(filename)?,
attributes: attributes.clone(),
@ -141,6 +177,7 @@ impl DirEntry {
file_size: 0,
entry_type: DirEntryType::Directory,
children: Vec::new(),
data: Vec::new(),
},
_ => DirEntry {
filename: FileName::new(filename)?,
@ -150,53 +187,9 @@ impl DirEntry {
file_size: 0,
entry_type: DirEntryType::Directory,
children: Vec::new(),
data: Vec::new(),
},
};
// Every directory in DOS needs a "." sub-entry to refer to itself.
let self_entry = match create_timedate {
None => DirEntry {
filename: FileName::new(".")?,
attributes: attributes,
create_timedate: TimeDate::now(),
start_cluster: new_entry.get_start_cluster(),
file_size: 0,
entry_type: DirEntryType::Directory,
children: Vec::new(),
},
Some(_) => DirEntry {
filename: FileName::new(".")?,
attributes,
create_timedate: create_timedate.unwrap(),
start_cluster: new_entry.get_start_cluster(),
file_size: 0,
entry_type: DirEntryType::Directory,
children: Vec::new(),
},
};
// Every entry in DOS needs a ".." sub-entry to refer one level up.
// [TODO] This has the wrong start cluster! Figure out how to get this value!
let parent_entry = match create_timedate {
None => DirEntry {
filename: FileName::new("..")?,
attributes,
create_timedate: TimeDate::now(),
start_cluster: 0,
file_size: 0,
entry_type: DirEntryType::Directory,
children: Vec::new(),
},
_ => DirEntry {
filename: FileName::new("..")?,
attributes,
create_timedate: create_timedate.unwrap(),
start_cluster: 0,
file_size: 0,
entry_type: DirEntryType::Directory,
children: Vec::new(),
},
};
new_entry.add_child(self_entry);
new_entry.add_child(parent_entry);
Ok(new_entry)
}
@ -241,6 +234,7 @@ impl DirEntry {
file_size: 0,
entry_type: DirEntryType::File, // This is just as wrong as the rest of this function.
children: Vec::new(),
data: Vec::new(),
};
Ok(new_direntry)
}
@ -347,6 +341,10 @@ impl DirEntry {
self.children.push(child);
}
pub fn count_children(&self) -> usize {
self.children.len()
}
pub fn get_start_cluster(&self) -> u32 {
self.start_cluster
}
@ -386,6 +384,7 @@ mod tests {
file_size: 4608,
entry_type: DirEntryType::File, // Dummy placeholder
children: Vec::new(),
data: Vec::new(),
};
// Semi-representative entry that reflects IBMBIO.COM on April 4 1983.
let reference: [u8; 32] = [

View File

@ -45,7 +45,7 @@ fn main() {
}
Commands::Analyze { name } => {
print_header();
let analyzer = Analyzer::load(name.as_str()).unwrap();
let mut analyzer = Analyzer::load(name.as_str()).unwrap();
analyzer.print_metadata();
}
}