Skip to content

Commit

Permalink
lib/fs: Try to remove read only Windows files (fixes #3744) (#8650)
Browse files Browse the repository at this point in the history
This happens when folders contain a custom icon.

Co-authored-by: Alexandre Alves <alexandrealvesdb.contact@gmail.com>
  • Loading branch information
calmh and AlexandreAlvesDB committed Nov 7, 2022
1 parent 5e384c9 commit a296057
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 8 deletions.
8 changes: 0 additions & 8 deletions lib/fs/basicfs.go
Expand Up @@ -178,14 +178,6 @@ func (f *BasicFilesystem) Lstat(name string) (FileInfo, error) {
return basicFileInfo{fi}, err
}

func (f *BasicFilesystem) Remove(name string) error {
name, err := f.rooted(name)
if err != nil {
return err
}
return os.Remove(name)
}

func (f *BasicFilesystem) RemoveAll(name string) error {
name, err := f.rooted(name)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions lib/fs/basicfs_unix.go
Expand Up @@ -74,6 +74,14 @@ func (f *BasicFilesystem) Lchown(name, uid, gid string) error {
return os.Lchown(name, nuid, ngid)
}

func (f *BasicFilesystem) Remove(name string) error {
name, err := f.rooted(name)
if err != nil {
return err
}
return os.Remove(name)
}

// unrootedChecked returns the path relative to the folder root (same as
// unrooted) or an error if the given path is not a subpath and handles the
// special case when the given path is the folder root without a trailing
Expand Down
15 changes: 15 additions & 0 deletions lib/fs/basicfs_windows.go
Expand Up @@ -190,6 +190,21 @@ func (f *BasicFilesystem) Lchown(name, uid, gid string) error {
return windows.SetSecurityInfo(hdl, windows.SE_FILE_OBJECT, si, (*windows.SID)(ownerSID), (*windows.SID)(groupSID), nil, nil)
}

func (f *BasicFilesystem) Remove(name string) error {
name, err := f.rooted(name)
if err != nil {
return err
}
err = os.Remove(name)
if os.IsPermission(err) {
// Try to remove the read-only attribute and try again
if os.Chmod(name, 0600) == nil {
err = os.Remove(name)
}
}
return err
}

// unrootedChecked returns the path relative to the folder root (same as
// unrooted) or an error if the given path is not a subpath and handles the
// special case when the given path is the folder root without a trailing
Expand Down
23 changes: 23 additions & 0 deletions lib/fs/basicfs_windows_test.go
Expand Up @@ -13,6 +13,7 @@ import (
"os"
"path/filepath"
"strings"
"syscall"
"testing"
)

Expand Down Expand Up @@ -192,3 +193,25 @@ func TestGetFinalPath(t *testing.T) {
}
}
}

func TestRemoveWindowsDirIcon(t *testing.T) {
//Try to delete a folder with a custom icon with os.Remove (simulated by the readonly file attribute)

fs, dir := setup(t)
relativePath := "folder_with_icon"
path := filepath.Join(dir, relativePath)

if err := os.Mkdir(path, os.ModeDir); err != nil {
t.Fatal(err)
}
ptr, err := syscall.UTF16PtrFromString(path)
if err != nil {
t.Fatal(err)
}
if err := syscall.SetFileAttributes(ptr, uint32(syscall.FILE_ATTRIBUTE_DIRECTORY+syscall.FILE_ATTRIBUTE_READONLY)); err != nil {
t.Fatal(err)
}
if err := fs.Remove(relativePath); err != nil {
t.Fatal(err)
}
}

0 comments on commit a296057

Please sign in to comment.