mirror of
https://github.com/rclone/rclone.git
synced 2025-11-23 21:44:49 +02:00
Before this change, Rmdir (and other commands that rely on Rmdir) would fail with "Access is denied" on Windows, if the directory had FILE_ATTRIBUTE_READONLY. This could happen if, for example, an empty folder had a custom icon added via Windows Explorer's interface (Properties => Customize => Change Icon...). However, Microsoft docs indicate that "This attribute is not honored on directories." https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants#file_attribute_readonly Accordingly, this created an odd situation where such directories were removable (by their owner) via File Explorer and the rd command, but not via rclone. An upstream issue has been open since 2018, but has not yet resulted in a fix. https://github.com/golang/go/issues/26295 This change gets around the issue by doing os.Chmod on the dir and then retrying os.Remove. If the dir is not empty, this will still fail with "The directory is not empty." A bisync user confirmed that it fixed their issue in https://forum.rclone.org/t/bisync-leaving-empty-directories-on-unc-path-1-or-local-filesystem-path-2-on-directory-renames/52456/4?u=nielash It is likely also a fix for #8019, although @ncw is correct that Purge would be a more efficient solution in that particular scenario.
41 lines
1.1 KiB
Go
41 lines
1.1 KiB
Go
//go:build windows
|
|
|
|
package local
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"runtime"
|
|
"syscall"
|
|
"testing"
|
|
|
|
"github.com/rclone/rclone/fs/operations"
|
|
"github.com/rclone/rclone/fstest"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestRmdirWindows tests that FILE_ATTRIBUTE_READONLY does not block Rmdir on windows.
|
|
// Microsoft docs indicate that "This attribute is not honored on directories."
|
|
// See https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants#file_attribute_readonly
|
|
// and https://github.com/golang/go/issues/26295
|
|
func TestRmdirWindows(t *testing.T) {
|
|
if runtime.GOOS != "windows" {
|
|
t.Skipf("windows only")
|
|
}
|
|
r := fstest.NewRun(t)
|
|
defer r.Finalise()
|
|
|
|
err := operations.Mkdir(context.Background(), r.Flocal, "testdir")
|
|
require.NoError(t, err)
|
|
|
|
ptr, err := syscall.UTF16PtrFromString(filepath.Join(r.Flocal.Root(), "testdir"))
|
|
require.NoError(t, err)
|
|
|
|
err = syscall.SetFileAttributes(ptr, uint32(syscall.FILE_ATTRIBUTE_DIRECTORY+syscall.FILE_ATTRIBUTE_READONLY))
|
|
require.NoError(t, err)
|
|
|
|
err = operations.Rmdir(context.Background(), r.Flocal, "testdir")
|
|
assert.NoError(t, err)
|
|
}
|