Skip to content

Commit 710bd34

Browse files
authored
Merge pull request #123 from peterkrull/always-closing
Always closing (and more)
2 parents 55c77ce + 86c20e0 commit 710bd34

File tree

4 files changed

+76
-53
lines changed

4 files changed

+76
-53
lines changed

src/filesystem/directory.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,12 @@ impl RawDirectory {
7272

7373
/// Represents an open directory on disk.
7474
///
75-
/// If you drop a value of this type, it closes the directory automatically. However,
76-
/// it holds a mutable reference to its parent `VolumeManager`, which restricts
77-
/// which operations you can perform.
75+
/// In contrast to a `RawDirectory`, a `Directory` holds a mutable reference to
76+
/// its parent `VolumeManager`, which restricts which operations you can perform.
77+
///
78+
/// If you drop a value of this type, it closes the directory automatically, but
79+
/// any error that may occur will be ignored. To handle potential errors, use
80+
/// the [`Directory::close`] method.
7881
pub struct Directory<
7982
'a,
8083
D,
@@ -188,6 +191,16 @@ where
188191
core::mem::forget(self);
189192
d
190193
}
194+
195+
/// Consume the `Directory` handle and close it. The behavior of this is similar
196+
/// to using [`core::mem::drop`] or letting the `Directory` go out of scope,
197+
/// except this lets the user handle any errors that may occur in the process,
198+
/// whereas when using drop, any errors will be discarded silently.
199+
pub fn close(self) -> Result<(), Error<D::Error>> {
200+
let result = self.volume_mgr.close_dir(self.raw_directory);
201+
core::mem::forget(self);
202+
result
203+
}
191204
}
192205

193206
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop
@@ -197,9 +210,7 @@ where
197210
T: crate::TimeSource,
198211
{
199212
fn drop(&mut self) {
200-
self.volume_mgr
201-
.close_dir(self.raw_directory)
202-
.expect("Failed to close directory");
213+
_ = self.volume_mgr.close_dir(self.raw_directory)
203214
}
204215
}
205216

src/filesystem/files.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@ impl RawFile {
3939

4040
/// Represents an open file on disk.
4141
///
42-
/// If you drop a value of this type, it closes the file automatically. However,
43-
/// it holds a mutable reference to its parent `VolumeManager`, which restricts
44-
/// which operations you can perform.
42+
/// In contrast to a `RawFile`, a `File` holds a mutable reference to its
43+
/// parent `VolumeManager`, which restricts which operations you can perform.
44+
///
45+
/// If you drop a value of this type, it closes the file automatically, and but
46+
/// error that may occur will be ignored. To handle potential errors, use
47+
/// the [`File::close`] method.
4548
pub struct File<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
4649
where
4750
D: crate::BlockDevice,
@@ -128,6 +131,16 @@ where
128131
pub fn flush(&mut self) -> Result<(), Error<D::Error>> {
129132
self.volume_mgr.flush_file(self.raw_file)
130133
}
134+
135+
/// Consume the `File` handle and close it. The behavior of this is similar
136+
/// to using [`core::mem::drop`] or letting the `File` go out of scope,
137+
/// except this lets the user handle any errors that may occur in the process,
138+
/// whereas when using drop, any errors will be discarded silently.
139+
pub fn close(self) -> Result<(), Error<D::Error>> {
140+
let result = self.volume_mgr.close_file(self.raw_file);
141+
core::mem::forget(self);
142+
result
143+
}
131144
}
132145

133146
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop
@@ -137,9 +150,7 @@ where
137150
T: crate::TimeSource,
138151
{
139152
fn drop(&mut self) {
140-
self.volume_mgr
141-
.close_file(self.raw_file)
142-
.expect("Failed to close file");
153+
_ = self.volume_mgr.close_file(self.raw_file);
143154
}
144155
}
145156

src/lib.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,12 @@ impl RawVolume {
239239

240240
/// Represents an open volume on disk.
241241
///
242-
/// If you drop a value of this type, it closes the volume automatically. However,
243-
/// it holds a mutable reference to its parent `VolumeManager`, which restricts
244-
/// which operations you can perform.
242+
/// In contrast to a `RawVolume`, a `Volume` holds a mutable reference to its
243+
/// parent `VolumeManager`, which restricts which operations you can perform.
244+
///
245+
/// If you drop a value of this type, it closes the volume automatically, but
246+
/// any error that may occur will be ignored. To handle potential errors, use
247+
/// the [`Volume::close`] method.
245248
pub struct Volume<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
246249
where
247250
D: crate::BlockDevice,
@@ -285,6 +288,16 @@ where
285288
core::mem::forget(self);
286289
v
287290
}
291+
292+
/// Consume the `Volume` handle and close it. The behavior of this is similar
293+
/// to using [`core::mem::drop`] or letting the `Volume` go out of scope,
294+
/// except this lets the user handle any errors that may occur in the process,
295+
/// whereas when using drop, any errors will be discarded silently.
296+
pub fn close(self) -> Result<(), Error<D::Error>> {
297+
let result = self.volume_mgr.close_volume(self.raw_volume);
298+
core::mem::forget(self);
299+
result
300+
}
288301
}
289302

290303
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop
@@ -294,9 +307,7 @@ where
294307
T: crate::TimeSource,
295308
{
296309
fn drop(&mut self) {
297-
self.volume_mgr
298-
.close_volume(self.raw_volume)
299-
.expect("Failed to close volume");
310+
_ = self.volume_mgr.close_volume(self.raw_volume)
300311
}
301312
}
302313

src/volume_mgr.rs

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -775,14 +775,36 @@ where
775775

776776
/// Close a file with the given raw file handle.
777777
pub fn close_file(&mut self, file: RawFile) -> Result<(), Error<D::Error>> {
778-
let file_idx = self.flush_file_get_index(file)?;
778+
let flush_result = self.flush_file(file);
779+
let file_idx = self.get_file_by_id(file)?;
779780
self.open_files.swap_remove(file_idx);
780-
Ok(())
781+
flush_result
781782
}
782783

783784
/// Flush (update the entry) for a file with the given raw file handle.
784785
pub fn flush_file(&mut self, file: RawFile) -> Result<(), Error<D::Error>> {
785-
self.flush_file_get_index(file).map(|_| ())
786+
let file_info = self
787+
.open_files
788+
.iter()
789+
.find(|info| info.file_id == file)
790+
.ok_or(Error::BadHandle)?;
791+
792+
if file_info.dirty {
793+
let volume_idx = self.get_volume_by_id(file_info.volume_id)?;
794+
match self.open_volumes[volume_idx].volume_type {
795+
VolumeType::Fat(ref mut fat) => {
796+
debug!("Updating FAT info sector");
797+
fat.update_info_sector(&self.block_device)?;
798+
debug!("Updating dir entry {:?}", file_info.entry);
799+
if file_info.entry.size != 0 {
800+
// If you have a length, you must have a cluster
801+
assert!(file_info.entry.cluster.0 != 0);
802+
}
803+
fat.write_entry_to_disk(&self.block_device, &file_info.entry)?;
804+
}
805+
};
806+
}
807+
Ok(())
786808
}
787809

788810
/// Check if any files or folders are open.
@@ -1054,38 +1076,6 @@ where
10541076
let available = Block::LEN - block_offset;
10551077
Ok((block_idx, block_offset, available))
10561078
}
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-
}
10891079
}
10901080

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

0 commit comments

Comments
 (0)