From 8e474f5d2055191280f3050d4d7d5eb044e393eb Mon Sep 17 00:00:00 2001 From: Jochen Hilgers Date: Tue, 3 May 2022 16:06:13 +0200 Subject: [PATCH] Return os consistent error in ReadOnlyFs filter fixes #350: Use `os.ErrPermission` instead of `syscall.EPerm` to make sure that the error is consistent over different operating systems and can be checked with `os.isPermission(err)` --- README.md | 2 +- readonlyfs.go | 23 +++++++++++------------ readonlyfs_test.go | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 readonlyfs_test.go diff --git a/README.md b/README.md index cab257f..3f65995 100644 --- a/README.md +++ b/README.md @@ -290,7 +290,7 @@ A thin wrapper around the source Fs providing a read only view. ```go fs := afero.NewReadOnlyFs(afero.NewOsFs()) _, err := fs.Create("/file.txt") -// err = syscall.EPERM +// err = os.ErrPermission ``` # RegexpFs diff --git a/readonlyfs.go b/readonlyfs.go index bd8f926..859c853 100644 --- a/readonlyfs.go +++ b/readonlyfs.go @@ -2,7 +2,6 @@ package afero import ( "os" - "syscall" "time" ) @@ -21,15 +20,15 @@ func (r *ReadOnlyFs) ReadDir(name string) ([]os.FileInfo, error) { } func (r *ReadOnlyFs) Chtimes(n string, a, m time.Time) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) Chown(n string, uid, gid int) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) Name() string { @@ -61,20 +60,20 @@ func (r *ReadOnlyFs) ReadlinkIfPossible(name string) (string, error) { } func (r *ReadOnlyFs) Rename(o, n string) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) RemoveAll(p string) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) Remove(n string) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) { - if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { - return nil, syscall.EPERM + if flag&(os.O_WRONLY|os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 { + return nil, os.ErrPermission } return r.source.OpenFile(name, flag, perm) } @@ -84,13 +83,13 @@ func (r *ReadOnlyFs) Open(n string) (File, error) { } func (r *ReadOnlyFs) Mkdir(n string, p os.FileMode) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) MkdirAll(n string, p os.FileMode) error { - return syscall.EPERM + return os.ErrPermission } func (r *ReadOnlyFs) Create(n string) (File, error) { - return nil, syscall.EPERM + return nil, os.ErrPermission } diff --git a/readonlyfs_test.go b/readonlyfs_test.go new file mode 100644 index 0000000..3b6860e --- /dev/null +++ b/readonlyfs_test.go @@ -0,0 +1,34 @@ +package afero + +import ( + "os" + "testing" + "time" +) + +func checkForErrPermission(t *testing.T, err error) { + t.Helper() + if err == nil || !os.IsPermission(err) { + t.Errorf("Expected err !=nil && err == ErrPermission, got %[1]T (%[1]v)", err) + } +} + +// Make sure that the ReadOnlyFs filter returns errors that can be +// checked with os.IsPermission +func TestReadOnlyFsErrPermission(t *testing.T) { + fs := NewReadOnlyFs(NewMemMapFs()) + + _, err := fs.Create("test") + checkForErrPermission(t, err) + checkForErrPermission(t, fs.Chtimes("test", time.Now(), time.Now())) + checkForErrPermission(t, fs.Chmod("test", os.ModePerm)) + checkForErrPermission(t, fs.Chown("test", 0, 0)) + checkForErrPermission(t, fs.Mkdir("test", os.ModePerm)) + checkForErrPermission(t, fs.MkdirAll("test", os.ModePerm)) + _, err = fs.OpenFile("test", os.O_CREATE, os.ModePerm) + checkForErrPermission(t, err) + checkForErrPermission(t, fs.Remove("test")) + checkForErrPermission(t, fs.RemoveAll("test")) + checkForErrPermission(t, fs.Rename("test", "test")) + +}