Skip to content

Commit

Permalink
refactor(error): improve error messages and file handling
Browse files Browse the repository at this point in the history
- Update error messages for file operations in the `LocalBackendErrorKind` enum.
- Refactor the `ReadBackend` and `WriteBackend` implementations in the `LocalBackend` module to handle file opening errors more accurately.
- Add error variants `OpeningFileForPartialReadingFailed` and `OpeningFileForWritingFailed` to provide specific information about file opening failures.
- Create parent directory if it does not exist before opening the file for writing.

Fixes #rustic-rs/rustic#1315

Signed-off-by: simonsan <[email protected]>
  • Loading branch information
simonsan committed Oct 14, 2024
1 parent 2b32031 commit ac73cc1
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 9 deletions.
16 changes: 14 additions & 2 deletions crates/backend/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,20 @@ pub enum LocalBackendErrorKind {
FromWalkdirError(#[from] walkdir::Error),
/// removing file failed: `{0:?}`
FileRemovalFailed(std::io::Error),
/// opening file failed: `{0:?}`
OpeningFileFailed(std::io::Error),
/// Writing to file failed: `{path}` : `{source}`
OpeningFileForPartialReadingFailed {
/// Path to file
path: std::path::PathBuf,
/// Source of the error
source: std::io::Error,
},
/// Writing to file failed: `{path}` : `{source}`
OpeningFileForWritingFailed {
/// Path to file
path: std::path::PathBuf,
/// Source of the error
source: std::io::Error,
},
/// setting file length failed: `{0:?}`
SettingFileLengthFailed(std::io::Error),
/// can't jump to position in file: `{0:?}`
Expand Down
29 changes: 22 additions & 7 deletions crates/backend/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,12 @@ impl ReadBackend for LocalBackend {
///
/// # Errors
///
/// * [`LocalBackendErrorKind::OpeningFileFailed`] - If the file could not be opened.
/// * [`LocalBackendErrorKind::OpeningFileForPartialReadingFailed`] - If the file could not be opened for partial reading.
/// * [`LocalBackendErrorKind::CouldNotSeekToPositionInFile`] - If the file could not be seeked to the given position.
/// * [`LocalBackendErrorKind::FromTryIntError`] - If the length of the file could not be converted to u32.
/// * [`LocalBackendErrorKind::ReadingExactLengthOfFileFailed`] - If the length of the file could not be read.
///
/// [`LocalBackendErrorKind::OpeningFileFailed`]: LocalBackendErrorKind::OpeningFileFailed
/// [`LocalBackendErrorKind::OpeningFileForPartialReadingFailed`]: LocalBackendErrorKind::OpeningFileForPartialReadingFailed
/// [`LocalBackendErrorKind::CouldNotSeekToPositionInFile`]: LocalBackendErrorKind::CouldNotSeekToPositionInFile
/// [`LocalBackendErrorKind::FromTryIntError`]: LocalBackendErrorKind::FromTryIntError
/// [`LocalBackendErrorKind::ReadingExactLengthOfFileFailed`]: LocalBackendErrorKind::ReadingExactLengthOfFileFailed
Expand All @@ -277,8 +277,13 @@ impl ReadBackend for LocalBackend {
length: u32,
) -> Result<Bytes> {
trace!("reading tpe: {tpe:?}, id: {id}, offset: {offset}, length: {length}");
let mut file =
File::open(self.path(tpe, id)).map_err(LocalBackendErrorKind::OpeningFileFailed)?;
let filename = self.path(tpe, id);
let mut file = File::open(&filename).map_err(|err| {
LocalBackendErrorKind::OpeningFileForPartialReadingFailed {
path: filename,
source: err,
}
})?;
_ = file
.seek(SeekFrom::Start(offset.into()))
.map_err(LocalBackendErrorKind::CouldNotSeekToPositionInFile)?;
Expand Down Expand Up @@ -328,26 +333,36 @@ impl WriteBackend for LocalBackend {
///
/// # Errors
///
/// * [`LocalBackendErrorKind::OpeningFileFailed`] - If the file could not be opened.
/// * [`LocalBackendErrorKind::OpeningFileForWritingFailed`] - If the file could not be opened for writing.
/// * [`LocalBackendErrorKind::FromTryIntError`] - If the length of the bytes could not be converted to u64.
/// * [`LocalBackendErrorKind::SettingFileLengthFailed`] - If the length of the file could not be set.
/// * [`LocalBackendErrorKind::CouldNotWriteToBuffer`] - If the bytes could not be written to the file.
/// * [`LocalBackendErrorKind::SyncingOfOsMetadataFailed`] - If the metadata of the file could not be synced.
///
/// [`LocalBackendErrorKind::OpeningFileFailed`]: LocalBackendErrorKind::OpeningFileFailed
/// [`LocalBackendErrorKind::OpeningFileForWritingFailed`]: LocalBackendErrorKind::OpeningFileForWritingFailed
/// [`LocalBackendErrorKind::FromTryIntError`]: LocalBackendErrorKind::FromTryIntError
/// [`LocalBackendErrorKind::SettingFileLengthFailed`]: LocalBackendErrorKind::SettingFileLengthFailed
/// [`LocalBackendErrorKind::CouldNotWriteToBuffer`]: LocalBackendErrorKind::CouldNotWriteToBuffer
/// [`LocalBackendErrorKind::SyncingOfOsMetadataFailed`]: LocalBackendErrorKind::SyncingOfOsMetadataFailed
fn write_bytes(&self, tpe: FileType, id: &Id, _cacheable: bool, buf: Bytes) -> Result<()> {
trace!("writing tpe: {:?}, id: {}", &tpe, &id);
let filename = self.path(tpe, id);

// create parent directory if it does not exist
if let Some(parent) = filename.parent() {
fs::create_dir_all(parent).map_err(LocalBackendErrorKind::DirectoryCreationFailed)?;
}

let mut file = fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&filename)
.map_err(LocalBackendErrorKind::OpeningFileFailed)?;
.map_err(|err| LocalBackendErrorKind::OpeningFileForWritingFailed {
path: filename.clone(),
source: err,
})?;

file.set_len(
buf.len()
.try_into()
Expand Down

0 comments on commit ac73cc1

Please sign in to comment.