From 7f3e3b77cea69ac3edf92c865b24d3f60dfb4912 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Sat, 15 Nov 2025 20:59:14 -0500 Subject: [PATCH] backend/local: fix "operation not supported" when unlocking If the repo is on a mounted folder that doesn't support chmod (like SMB), it was causing an "operation not supported" error when trying to chmod 666 a file before deleting it. But it isn't generally needed before deleting a file (the folder permissions matter there, not the file permissions). So, just drop it. --- changelog/unreleased/issue-5595 | 8 ++++++++ internal/backend/local/local.go | 8 +------- internal/backend/local/local_unix.go | 4 ++++ internal/backend/local/local_windows.go | 13 +++++++++++++ 4 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 changelog/unreleased/issue-5595 diff --git a/changelog/unreleased/issue-5595 b/changelog/unreleased/issue-5595 new file mode 100644 index 000000000..a5b6706f0 --- /dev/null +++ b/changelog/unreleased/issue-5595 @@ -0,0 +1,8 @@ +Bugfix: Fix "chmod not supported" errors when unlocking + +Restic 0.18.0 introduced a bug that caused "chmod xxx: operation not supported" +errors to appear when unlocking with a stale lock, on a local file repository +that did not support chmod (like CIFS or WebDAV mounted via FUSE). Restic now +just doesn't bother calling chmod in that case on Unix, as it is unnecessary. + +https://github.com/restic/restic/issues/5595 diff --git a/internal/backend/local/local.go b/internal/backend/local/local.go index 1c1a13470..25ea4f47c 100644 --- a/internal/backend/local/local.go +++ b/internal/backend/local/local.go @@ -255,13 +255,7 @@ func (b *Local) Stat(_ context.Context, h backend.Handle) (backend.FileInfo, err func (b *Local) Remove(_ context.Context, h backend.Handle) error { fn := b.Filename(h) - // reset read-only flag - err := os.Chmod(fn, 0666) - if err != nil && !os.IsPermission(err) { - return errors.WithStack(err) - } - - return os.Remove(fn) + return removeFile(fn) } // List runs fn for each file in the backend which has the type t. When an diff --git a/internal/backend/local/local_unix.go b/internal/backend/local/local_unix.go index b885ae1a3..164785c49 100644 --- a/internal/backend/local/local_unix.go +++ b/internal/backend/local/local_unix.go @@ -52,3 +52,7 @@ func setFileReadonly(f string, mode os.FileMode) error { return err } + +func removeFile(f string) error { + return os.Remove(f) +} diff --git a/internal/backend/local/local_windows.go b/internal/backend/local/local_windows.go index dd372941d..fa21d8240 100644 --- a/internal/backend/local/local_windows.go +++ b/internal/backend/local/local_windows.go @@ -2,6 +2,8 @@ package local import ( "os" + + "github.com/restic/restic/internal/errors" ) // Can't explicitly flush directory changes on Windows. @@ -16,3 +18,14 @@ func isMacENOTTY(_ error) bool { return false } func setFileReadonly(_ string, _ os.FileMode) error { return nil } + +func removeFile(f string) error { + // Reset read-only flag, + // as Windows won't let you delete a read-only file + err := os.Chmod(f, 0666) + if err != nil && !os.IsPermission(err) { + return errors.WithStack(err) + } + + return os.Remove(f) +}