Skip to content

Commit

Permalink
Merge pull request #158 from rust-embedded-community/move-make-dir-code
Browse files Browse the repository at this point in the history
Move FAT-specific code in make_dir_in_dir (and fix .. entries)
  • Loading branch information
thejpster authored Nov 3, 2024
2 parents 2c08eac + f497cc2 commit 8a8d52c
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 66 deletions.
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.

0 comments on commit 8a8d52c

Please sign in to comment.