Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move FAT-specific code in make_dir_in_dir (and fix .. entries) #158

Merged
merged 4 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/fat/volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,87 @@ impl FatVolume {
block_cache.write_back().map_err(Error::DeviceError)?;
Ok(())
}

/// Create a new directory.
///
/// 1) Creates the directory entry in the parent
/// 2) Allocates a new cluster to hold the new directory
/// 3) Writes out the `.` and `..` entries in the new directory
pub(crate) fn make_dir<D, T>(
&mut self,
block_cache: &mut BlockCache<D>,
time_source: &T,
parent: ClusterId,
sfn: ShortFileName,
att: Attributes,
) -> Result<(), Error<D::Error>>
where
D: BlockDevice,
T: TimeSource,
{
let mut new_dir_entry_in_parent =
self.write_new_directory_entry(block_cache, time_source, parent, sfn, att)?;
if new_dir_entry_in_parent.cluster == ClusterId::EMPTY {
new_dir_entry_in_parent.cluster = self.alloc_cluster(block_cache, None, false)?;
// update the parent dir with the cluster of the new dir
self.write_entry_to_disk(block_cache, &new_dir_entry_in_parent)?;
}
let new_dir_start_block = self.cluster_to_block(new_dir_entry_in_parent.cluster);
debug!("Made new dir entry {:?}", new_dir_entry_in_parent);
let now = time_source.get_timestamp();
let fat_type = self.get_fat_type();
// A blank block
let block = block_cache.blank_mut(new_dir_start_block);
// make the "." entry
let dot_entry_in_child = DirEntry {
name: crate::ShortFileName::this_dir(),
mtime: now,
ctime: now,
attributes: att,
// point at ourselves
cluster: new_dir_entry_in_parent.cluster,
size: 0,
entry_block: new_dir_start_block,
entry_offset: 0,
};
debug!("New dir has {:?}", dot_entry_in_child);
let mut offset = 0;
block[offset..offset + OnDiskDirEntry::LEN]
.copy_from_slice(&dot_entry_in_child.serialize(fat_type)[..]);
offset += OnDiskDirEntry::LEN;
// make the ".." entry
let dot_dot_entry_in_child = DirEntry {
name: crate::ShortFileName::parent_dir(),
mtime: now,
ctime: now,
attributes: att,
// point at our parent
cluster: if parent == ClusterId::ROOT_DIR {
// indicate parent is root using Cluster(0)
ClusterId::EMPTY
} else {
parent
},
size: 0,
entry_block: new_dir_start_block,
entry_offset: OnDiskDirEntry::LEN_U32,
};
debug!("New dir has {:?}", dot_dot_entry_in_child);
block[offset..offset + OnDiskDirEntry::LEN]
.copy_from_slice(&dot_dot_entry_in_child.serialize(fat_type)[..]);

block_cache.write_back()?;

for block_idx in new_dir_start_block
.range(BlockCount(u32::from(self.blocks_per_cluster)))
.skip(1)
{
let _block = block_cache.blank_mut(block_idx);
block_cache.write_back()?;
}

Ok(())
}
}

/// Load the boot parameter block from the start of the given partition and
Expand Down
67 changes: 1 addition & 66 deletions src/volume_mgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,79 +1070,14 @@ where
// Need mutable access for this
match &mut data.open_volumes[volume_idx].volume_type {
VolumeType::Fat(fat) => {
// TODO: Move this into the FAT volume code
debug!("Making dir entry");
let mut new_dir_entry_in_parent = fat.write_new_directory_entry(
fat.make_dir(
&mut data.block_cache,
&self.time_source,
parent_directory_info.cluster,
sfn,
att,
)?;
if new_dir_entry_in_parent.cluster == ClusterId::EMPTY {
new_dir_entry_in_parent.cluster =
fat.alloc_cluster(&mut data.block_cache, None, false)?;
// update the parent dir with the cluster of the new dir
fat.write_entry_to_disk(&mut data.block_cache, &new_dir_entry_in_parent)?;
}
let new_dir_start_block = fat.cluster_to_block(new_dir_entry_in_parent.cluster);
debug!("Made new dir entry {:?}", new_dir_entry_in_parent);
let now = self.time_source.get_timestamp();
let fat_type = fat.get_fat_type();
// A blank block
let block = data.block_cache.blank_mut(new_dir_start_block);
// make the "." entry
let dot_entry_in_child = DirEntry {
name: crate::ShortFileName::this_dir(),
mtime: now,
ctime: now,
attributes: att,
// point at ourselves
cluster: new_dir_entry_in_parent.cluster,
size: 0,
entry_block: new_dir_start_block,
entry_offset: 0,
};
debug!("New dir has {:?}", dot_entry_in_child);
let mut offset = 0;
block[offset..offset + fat::OnDiskDirEntry::LEN]
.copy_from_slice(&dot_entry_in_child.serialize(fat_type)[..]);
offset += fat::OnDiskDirEntry::LEN;
// make the ".." entry
let dot_dot_entry_in_child = DirEntry {
name: crate::ShortFileName::parent_dir(),
mtime: now,
ctime: now,
attributes: att,
// point at our parent
cluster: match fat_type {
fat::FatType::Fat16 => {
// On FAT16, indicate parent is root using Cluster(0)
if parent_directory_info.cluster == ClusterId::ROOT_DIR {
ClusterId::EMPTY
} else {
parent_directory_info.cluster
}
}
fat::FatType::Fat32 => parent_directory_info.cluster,
},
size: 0,
entry_block: new_dir_start_block,
entry_offset: fat::OnDiskDirEntry::LEN_U32,
};
debug!("New dir has {:?}", dot_dot_entry_in_child);
block[offset..offset + fat::OnDiskDirEntry::LEN]
.copy_from_slice(&dot_dot_entry_in_child.serialize(fat_type)[..]);

data.block_cache.write_back()?;

for block_idx in new_dir_start_block
.range(BlockCount(u32::from(fat.blocks_per_cluster)))
.skip(1)
{
let _block = data.block_cache.blank_mut(block_idx);
data.block_cache.write_back()?;
}
}
};

Expand Down
20 changes: 20 additions & 0 deletions tests/directories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ fn fat16_root_directory_listing() {
},
Some(String::from(".fseventsd")),
),
(
ExpectedDirEntry {
name: String::from("P-FAT16"),
mtime: String::from("2024-10-30 18:43:12"),
ctime: String::from("2024-10-30 18:43:12"),
size: 0,
is_dir: false,
},
None,
),
];

let mut listing = Vec::new();
Expand Down Expand Up @@ -266,6 +276,16 @@ fn fat32_root_directory_listing() {
},
Some(String::from(".fseventsd")),
),
(
ExpectedDirEntry {
name: String::from("P-FAT32"),
mtime: String::from("2024-10-30 18:43:16"),
ctime: String::from("2024-10-30 18:43:16"),
size: 0,
is_dir: false,
},
None,
),
(
ExpectedDirEntry {
name: String::from("THISIS~9"),
Expand Down
Binary file modified tests/disk.img.gz
Binary file not shown.