Skip to content

Commit 55c77ce

Browse files
authored
Merge pull request #121 from peterkrull/flush-written-file
Adds flush API
2 parents ba27644 + 3cdb6cb commit 55c77ce

File tree

3 files changed

+92
-28
lines changed

3 files changed

+92
-28
lines changed

src/filesystem/files.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
filesystem::{ClusterId, DirEntry, SearchId},
3-
RawVolume, VolumeManager,
3+
Error, RawVolume, VolumeManager,
44
};
55

66
/// Represents an open file on disk.
@@ -123,6 +123,11 @@ where
123123
core::mem::forget(self);
124124
f
125125
}
126+
127+
/// Flush any written data by updating the directory entry.
128+
pub fn flush(&mut self) -> Result<(), Error<D::Error>> {
129+
self.volume_mgr.flush_file(self.raw_file)
130+
}
126131
}
127132

128133
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop

src/volume_mgr.rs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -773,38 +773,18 @@ where
773773
Ok(())
774774
}
775775

776-
/// Close a file with the given full path.
776+
/// Close a file with the given raw file handle.
777777
pub fn close_file(&mut self, file: RawFile) -> Result<(), Error<D::Error>> {
778-
let mut found_idx = None;
779-
for (idx, info) in self.open_files.iter().enumerate() {
780-
if file == info.file_id {
781-
found_idx = Some((info, idx));
782-
break;
783-
}
784-
}
785-
786-
let (file_info, file_idx) = found_idx.ok_or(Error::BadHandle)?;
787-
788-
if file_info.dirty {
789-
let volume_idx = self.get_volume_by_id(file_info.volume_id)?;
790-
match self.open_volumes[volume_idx].volume_type {
791-
VolumeType::Fat(ref mut fat) => {
792-
debug!("Updating FAT info sector");
793-
fat.update_info_sector(&self.block_device)?;
794-
debug!("Updating dir entry {:?}", file_info.entry);
795-
if file_info.entry.size != 0 {
796-
// If you have a length, you must have a cluster
797-
assert!(file_info.entry.cluster.0 != 0);
798-
}
799-
fat.write_entry_to_disk(&self.block_device, &file_info.entry)?;
800-
}
801-
};
802-
}
803-
778+
let file_idx = self.flush_file_get_index(file)?;
804779
self.open_files.swap_remove(file_idx);
805780
Ok(())
806781
}
807782

783+
/// Flush (update the entry) for a file with the given raw file handle.
784+
pub fn flush_file(&mut self, file: RawFile) -> Result<(), Error<D::Error>> {
785+
self.flush_file_get_index(file).map(|_| ())
786+
}
787+
808788
/// Check if any files or folders are open.
809789
pub fn has_open_handles(&self) -> bool {
810790
!(self.open_dirs.is_empty() || self.open_files.is_empty())
@@ -1074,6 +1054,38 @@ where
10741054
let available = Block::LEN - block_offset;
10751055
Ok((block_idx, block_offset, available))
10761056
}
1057+
1058+
/// Flush (update the entry) for a file with the given raw file handle and
1059+
/// get its index.
1060+
fn flush_file_get_index(&mut self, file: RawFile) -> Result<usize, Error<D::Error>> {
1061+
let mut found_idx = None;
1062+
for (idx, info) in self.open_files.iter().enumerate() {
1063+
if file == info.file_id {
1064+
found_idx = Some((info, idx));
1065+
break;
1066+
}
1067+
}
1068+
1069+
let (file_info, file_idx) = found_idx.ok_or(Error::BadHandle)?;
1070+
1071+
if file_info.dirty {
1072+
let volume_idx = self.get_volume_by_id(file_info.volume_id)?;
1073+
match self.open_volumes[volume_idx].volume_type {
1074+
VolumeType::Fat(ref mut fat) => {
1075+
debug!("Updating FAT info sector");
1076+
fat.update_info_sector(&self.block_device)?;
1077+
debug!("Updating dir entry {:?}", file_info.entry);
1078+
if file_info.entry.size != 0 {
1079+
// If you have a length, you must have a cluster
1080+
assert!(file_info.entry.cluster.0 != 0);
1081+
}
1082+
fat.write_entry_to_disk(&self.block_device, &file_info.entry)?;
1083+
}
1084+
};
1085+
}
1086+
1087+
Ok(file_idx)
1088+
}
10771089
}
10781090

10791091
/// Transform mode variants (ReadWriteCreate_Or_Append) to simple modes ReadWriteAppend or

tests/write_file.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,53 @@ fn append_file() {
5555
volume_mgr.close_volume(volume).expect("close volume");
5656
}
5757

58+
#[test]
59+
fn flush_file() {
60+
let time_source = utils::make_time_source();
61+
let disk = utils::make_block_device(utils::DISK_SOURCE).unwrap();
62+
let mut volume_mgr: VolumeManager<utils::RamDisk<Vec<u8>>, utils::TestTimeSource, 4, 2, 1> =
63+
VolumeManager::new_with_limits(disk, time_source, 0xAA00_0000);
64+
let volume = volume_mgr
65+
.open_raw_volume(VolumeIdx(0))
66+
.expect("open volume");
67+
let root_dir = volume_mgr.open_root_dir(volume).expect("open root dir");
68+
69+
// Open with string
70+
let f = volume_mgr
71+
.open_file_in_dir(root_dir, "README.TXT", Mode::ReadWriteTruncate)
72+
.expect("open file");
73+
74+
// Write some data to the file
75+
let test_data = vec![0xCC; 64];
76+
volume_mgr.write(f, &test_data).expect("file write");
77+
78+
// Check that the file length is zero in the directory entry, as we haven't
79+
// flushed yet
80+
let entry = volume_mgr
81+
.find_directory_entry(root_dir, "README.TXT")
82+
.expect("find entry");
83+
assert_eq!(entry.size, 0);
84+
85+
volume_mgr.flush_file(f).expect("flush");
86+
87+
// Now check the file length again after flushing
88+
let entry = volume_mgr
89+
.find_directory_entry(root_dir, "README.TXT")
90+
.expect("find entry");
91+
assert_eq!(entry.size, 64);
92+
93+
// Flush more writes
94+
volume_mgr.write(f, &test_data).expect("file write");
95+
volume_mgr.write(f, &test_data).expect("file write");
96+
volume_mgr.flush_file(f).expect("flush");
97+
98+
// Now check the file length again, again
99+
let entry = volume_mgr
100+
.find_directory_entry(root_dir, "README.TXT")
101+
.expect("find entry");
102+
assert_eq!(entry.size, 64 * 3);
103+
}
104+
58105
// ****************************************************************************
59106
//
60107
// End Of File

0 commit comments

Comments
 (0)