spf13 / afero

A FileSystem Abstraction System for Go
Apache License 2.0
5.8k stars 498 forks source link

Inconsistent error reporting when using ReadOnlyFs and Windows #350

Open jochil opened 2 years ago

jochil commented 2 years ago

When using the ReadOnlyFs filter, the error returned when trying to write to the FS is different on Windows than on Linux or MacOSX

How to reproduce:

package afero_win

import (
    "errors"
    "os"
    "testing"

    pkgErrors "github.com/pkg/errors"
    "github.com/spf13/afero"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
)

func TestAferoPerm(t *testing.T) {
    fs := &afero.Afero{Fs: afero.NewReadOnlyFs(afero.NewMemMapFs())}

    err := fs.WriteFile("test.txt", []byte("foobar"), 0644);
    require.Error(t, err)

    assert.True(t, errors.Is(err, os.ErrPermission))
    assert.True(t, os.IsPermission(pkgErrors.Cause(err)))
    assert.True(t, pkgErrors.Is(err, os.ErrPermission))
}

while the test is running fine on Linux, on Windows it results in:

 --- FAIL: TestAferoPerm (0.00s)
    perm_test.go:22: 
            Error Trace:    perm_test.go:22
            Error:          Should be true
            Test:           TestAferoPerm
    perm_test.go:23: 
            Error Trace:    perm_test.go:23
            Error:          Should be true
            Test:           TestAferoPerm
    perm_test.go:24: 
            Error Trace:    perm_test.go:24
            Error:          Should be true
            Test:           TestAferoPerm

Expected behavior

Under windows it already returns an error operation not permitted but it is not matching with os.ErrPermission I think it would be more consistent if this behaves identical on different operating systems

jochil commented 2 years ago

I created the linked PR, where the returned error is changed from syscall.EPERM to os.ErrPermission. I think this is more idiomatic to the std package This code creates a permission error under windows... this might helpful to verify

  os.Chmod(file, 0400)
  err := os.WriteFile(file, []byte("test"), 0400)
  assert.True(t, errors.Is(err, os.ErrPermission))