From 8bf5bd15dddc1468ad5d18499ee6c7043f9e6ba1 Mon Sep 17 00:00:00 2001
From: Klemens Nanni <klemens@posteo.de>
Date: Tue, 27 Dec 2022 17:55:33 +0400
Subject: [PATCH] Honour --ignore-permission-errors for all path elements

This option only effects the last path element, i.e. in `/first/second`
`/first` is expected to be accessible and only `/first/second` may be
skipped.

Consider this test data:
```
	# ls -nd {user,root}dir/
	drwxr-xr-x  2 1000  1000  512 Dec 27 18:02 userdir/
	drwx------  2 0     0     512 Dec 27 18:02 rootdir/
```

`bupstash put --ignore-permission-errors ./rootdir/ ./userdir/` will
succeed and backup user data.

`bupstash put --ignore-permission-errors ./userdir/ ./rootdir/rootfile`
will fail and not backup anything:
```
bupstash put: unable to stat ".../rootdir/rootfile": Permission denied (os error 13)
```

Make the indexer honour the command line option such that inaccessible
files are skipped regardless of their depth.
---
 src/indexer.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/indexer.rs b/src/indexer.rs
index 2df08d7..e010848 100644
--- a/src/indexer.rs
+++ b/src/indexer.rs
@@ -121,7 +121,13 @@ impl FsWalker {
         for p in filler_dirs.drain().chain(root_paths.drain(..)) {
             let stat = match p.symlink_metadata() {
                 Ok(stat) => stat,
-                Err(err) => anyhow::bail!("unable to stat {:?}: {}", p, err),
+                Err(err) => {
+                    if opts.ignore_permission_errors
+                        && err.kind() == std::io::ErrorKind::PermissionDenied {
+                        continue;
+                    }
+                    anyhow::bail!("unable to stat {:?}: {}", p, err);
+                },
             };
 
             let parent = if let Some(parent) = p.parent() {
