From 989b50a633ad285b86c3549ea9ac6f62c0a13273 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Fri, 12 Mar 2021 12:31:49 +0200 Subject: feat: handle files in directories that can be read but not executed --- obnam.md | 19 +++++++++++++++++++ src/error.rs | 3 +-- src/fsiter.rs | 12 ++++++------ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/obnam.md b/obnam.md index cffd83a..15cddb2 100644 --- a/obnam.md +++ b/obnam.md @@ -1449,6 +1449,25 @@ then file live/unreadable is restored to rest then file live/unreadable/data.dat is not restored to rest ~~~ +## Unexecutable directory + +This scenario verifies that Obnam will skip a file in a directory it +can't read. Obnam should warn about that, but not give an error. + +~~~scenario +given an installed obnam +and a running chunk server +and a client config based on smoke.yaml +and a file live/dir/data.dat containing some random data +and file live/dir has mode 600 +when I run obnam --config smoke.yaml backup +then stdout contains "live/dir" +then backup generation is GEN +when I invoke obnam --config smoke.yaml restore rest +then file live/dir is restored to rest +then file live/dir/data.dat is not restored to rest +~~~ + ## Restore latest generation This scenario verifies that the latest backup generation can be diff --git a/src/error.rs b/src/error.rs index 73d4a66..a905458 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,11 +5,10 @@ use crate::generation::{LocalGenerationError, NascentError}; use crate::genlist::GenerationListError; use std::time::SystemTimeError; use tempfile::PersistError; -use thiserror::Error; /// Define all the kinds of errors that functions corresponding to /// subcommands of the main program can return. -#[derive(Debug, Error)] +#[derive(Debug, thiserror::Error)] pub enum ObnamError { #[error(transparent)] GenerationListError(#[from] GenerationListError), diff --git a/src/fsiter.rs b/src/fsiter.rs index 57b6fd5..b778cf3 100644 --- a/src/fsiter.rs +++ b/src/fsiter.rs @@ -1,6 +1,6 @@ use crate::fsentry::{FilesystemEntry, FsEntryError}; -use log::{debug, error}; -use std::path::Path; +use log::{debug, warn}; +use std::path::{Path, PathBuf}; use walkdir::{DirEntry, IntoIter, WalkDir}; /// Iterator over file system entries in a directory tree. @@ -13,8 +13,8 @@ pub enum FsIterError { #[error(transparent)] WalkError(#[from] walkdir::Error), - #[error(transparent)] - IoError(#[from] std::io::Error), + #[error("I/O error on {0}: {1}")] + IoError(PathBuf, #[source] std::io::Error), #[error(transparent)] FsEntryError(#[from] FsEntryError), @@ -50,8 +50,8 @@ fn new_entry(e: &DirEntry) -> FsIterResult { let meta = match meta { Ok(meta) => meta, Err(err) => { - error!("failed to get metadata: {}", err); - return Err(err.into()); + warn!("failed to get metadata for {}: {}", path.display(), err); + return Err(FsIterError::IoError(path.to_path_buf(), err)); } }; let entry = FilesystemEntry::from_metadata(path, &meta)?; -- cgit v1.2.1