Ask the file, not its folder, why the write was refused

The 403 probe read `oc:permissions` off the parent collection and warned
when `W` was missing. But Nextcloud reports `W` on files and `CK` on
collections, so a directory legitimately lacks `W`: the warning fired on
a healthy share and pointed at a mount that was fine.

Probe the file itself. Its permissions answer the question that matters,
and the status distinguishes the two cases the parent could not: a 404
means the sidecar does not exist and the refusal was about creating it,
while a 200 without `W` means it exists and cannot be updated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 20:38:48 +02:00
co-authored by Claude Opus 5
parent 6621c11ad6
commit 18f20170b3
+12 -9
View File
@@ -373,16 +373,18 @@ impl RemoteBackend for NextcloudBackend {
// make anything worse and it is the difference between a
// server-side fix and a client-side one.
if status == reqwest::StatusCode::FORBIDDEN {
let parent = path
.as_str()
.rsplit_once('/')
.map(|(head, _)| head)
.unwrap_or("");
// The *file*, not the folder. `W` is reported on files and
// `CK` on collections, so a directory legitimately lacks `W`
// and reading that as read-only would send someone to change a
// mount that is fine. If the file exists without `W` the
// refusal is an update it will not allow; a 404 here means it
// does not exist and the refusal was about creating it.
let target = path.as_str().to_string();
let probe = self
.client
.request(
reqwest::Method::from_bytes(b"PROPFIND").expect("valid method"),
self.url_for(&RemotePath::new(parent)),
self.url_for(path),
)
.basic_auth(&self.login, Some(&self.password))
.header("Depth", "0")
@@ -394,6 +396,7 @@ impl RemoteBackend for NextcloudBackend {
.await;
match probe {
Ok(r) => {
let status = r.status();
let text = r.text().await.unwrap_or_default();
let perms = text
.split("<oc:permissions>")
@@ -401,11 +404,11 @@ impl RemoteBackend for NextcloudBackend {
.and_then(|t| t.split('<').next())
.unwrap_or("(not reported)");
log::warn!(
" parent {parent} permissions: {perms} \
(W = write, C = create; absent means read-only)"
" target {target} -> {status} permissions: {perms} \
(on a file W = update; a 404 means it does not exist yet)"
);
}
Err(e) => log::warn!(" could not read parent permissions: {e}"),
Err(e) => log::warn!(" could not read {target} permissions: {e}"),
}
}