forked from mirror/afero
port RO & Regexp from filter to filesystem
This commit is contained in:
parent
da00b1fb7c
commit
84018f2b47
|
@ -1,80 +0,0 @@
|
|||
package afero
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ReadOnlyFilter struct {
|
||||
source Fs
|
||||
}
|
||||
|
||||
func NewReadonlyFilter() FilterFs {
|
||||
return &ReadOnlyFilter{}
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) SetSource(fs Fs) {
|
||||
r.source = fs
|
||||
}
|
||||
|
||||
// prepend a filter in the filter chain
|
||||
func (r *ReadOnlyFilter) AddFilter(fs FilterFs) {
|
||||
fs.SetSource(r.source)
|
||||
r.source = fs
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) ReadDir(name string) ([]os.FileInfo, error) {
|
||||
return ReadDir(r.source, name)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Chtimes(n string, a, m time.Time) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Chmod(n string, m os.FileMode) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Name() string {
|
||||
return "ReadOnlyFilter"
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Stat(name string) (os.FileInfo, error) {
|
||||
return r.source.Stat(name)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Rename(o, n string) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) RemoveAll(p string) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Remove(n string) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) 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
|
||||
}
|
||||
return r.source.OpenFile(name, flag, perm)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Open(n string) (File, error) {
|
||||
return r.source.Open(n)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Mkdir(n string, p os.FileMode) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) MkdirAll(n string, p os.FileMode) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFilter) Create(n string) (File, error) {
|
||||
return nil, syscall.EPERM
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package afero
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ReadOnlyFs struct {
|
||||
source Fs
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) ReadDir(name string) ([]os.FileInfo, error) {
|
||||
return ReadDir(r.source, name)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Chtimes(n string, a, m time.Time) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Name() string {
|
||||
return "ReadOnlyFilter"
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Stat(name string) (os.FileInfo, error) {
|
||||
return r.source.Stat(name)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Rename(o, n string) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) RemoveAll(p string) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Remove(n string) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
return r.source.OpenFile(name, flag, perm)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Open(n string) (File, error) {
|
||||
return r.source.Open(n)
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Mkdir(n string, p os.FileMode) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) MkdirAll(n string, p os.FileMode) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Create(n string) (File, error) {
|
||||
return nil, syscall.EPERM
|
||||
}
|
|
@ -7,11 +7,11 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// The RegexpFilter filters files (not directories) by regular expression. Only
|
||||
// The RegexpFs filters files (not directories) by regular expression. Only
|
||||
// files matching the given regexp will be allowed, all others get a ENOENT error (
|
||||
// "No such file or directory").
|
||||
//
|
||||
type RegexpFilter struct {
|
||||
type RegexpFs struct {
|
||||
re *regexp.Regexp
|
||||
source Fs
|
||||
}
|
||||
|
@ -21,21 +21,7 @@ type RegexpFile struct {
|
|||
re *regexp.Regexp
|
||||
}
|
||||
|
||||
func NewRegexpFilter(re *regexp.Regexp) FilterFs {
|
||||
return &RegexpFilter{re: re}
|
||||
}
|
||||
|
||||
// prepend a filter in the filter chain
|
||||
func (r *RegexpFilter) AddFilter(fs FilterFs) {
|
||||
fs.SetSource(r.source)
|
||||
r.source = fs
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) SetSource(fs Fs) {
|
||||
r.source = fs
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) matchesName(name string) error {
|
||||
func (r *RegexpFs) matchesName(name string) error {
|
||||
if r.re == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -45,7 +31,7 @@ func (r *RegexpFilter) matchesName(name string) error {
|
|||
return syscall.ENOENT
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) dirOrMatches(name string) error {
|
||||
func (r *RegexpFs) dirOrMatches(name string) error {
|
||||
dir, err := IsDir(r.source, name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -56,32 +42,32 @@ func (r *RegexpFilter) dirOrMatches(name string) error {
|
|||
return r.matchesName(name)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Chtimes(name string, a, m time.Time) error {
|
||||
func (r *RegexpFs) Chtimes(name string, a, m time.Time) error {
|
||||
if err := r.dirOrMatches(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.source.Chtimes(name, a, m)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Chmod(name string, mode os.FileMode) error {
|
||||
func (r *RegexpFs) Chmod(name string, mode os.FileMode) error {
|
||||
if err := r.dirOrMatches(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.source.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Name() string {
|
||||
return "RegexpFilter"
|
||||
func (r *RegexpFs) Name() string {
|
||||
return "RegexpFs"
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Stat(name string) (os.FileInfo, error) {
|
||||
func (r *RegexpFs) Stat(name string) (os.FileInfo, error) {
|
||||
if err := r.dirOrMatches(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.source.Stat(name)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Rename(oldname, newname string) error {
|
||||
func (r *RegexpFs) Rename(oldname, newname string) error {
|
||||
dir, err := IsDir(r.source, oldname)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -98,7 +84,7 @@ func (r *RegexpFilter) Rename(oldname, newname string) error {
|
|||
return r.source.Rename(oldname, newname)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) RemoveAll(p string) error {
|
||||
func (r *RegexpFs) RemoveAll(p string) error {
|
||||
dir, err := IsDir(r.source, p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -111,21 +97,21 @@ func (r *RegexpFilter) RemoveAll(p string) error {
|
|||
return r.source.RemoveAll(p)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Remove(name string) error {
|
||||
func (r *RegexpFs) Remove(name string) error {
|
||||
if err := r.dirOrMatches(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.source.Remove(name)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
|
||||
func (r *RegexpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
|
||||
if err := r.dirOrMatches(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.source.OpenFile(name, flag, perm)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Open(name string) (File, error) {
|
||||
func (r *RegexpFs) Open(name string) (File, error) {
|
||||
dir, err := IsDir(r.source, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -139,15 +125,15 @@ func (r *RegexpFilter) Open(name string) (File, error) {
|
|||
return &RegexpFile{f: f, re: r.re}, nil
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Mkdir(n string, p os.FileMode) error {
|
||||
func (r *RegexpFs) Mkdir(n string, p os.FileMode) error {
|
||||
return r.source.Mkdir(n, p)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) MkdirAll(n string, p os.FileMode) error {
|
||||
func (r *RegexpFs) MkdirAll(n string, p os.FileMode) error {
|
||||
return r.source.MkdirAll(n, p)
|
||||
}
|
||||
|
||||
func (r *RegexpFilter) Create(name string) (File, error) {
|
||||
func (r *RegexpFs) Create(name string) (File, error) {
|
||||
if err := r.matchesName(name); err != nil {
|
||||
return nil, err
|
||||
}
|
|
@ -6,9 +6,7 @@ import (
|
|||
)
|
||||
|
||||
func TestFilterReadOnly(t *testing.T) {
|
||||
mfs := &MemMapFs{}
|
||||
fs := NewFilter(mfs)
|
||||
fs.AddFilter(NewReadonlyFilter())
|
||||
fs := &ReadOnlyFs{source: &MemMapFs{}}
|
||||
_, err := fs.Create("/file.txt")
|
||||
if err == nil {
|
||||
t.Errorf("Did not fail to create file")
|
||||
|
@ -22,8 +20,7 @@ func TestFilterReadonlyRemoveAndRead(t *testing.T) {
|
|||
fh.Write([]byte("content here"))
|
||||
fh.Close()
|
||||
|
||||
fs := NewFilter(mfs)
|
||||
fs.AddFilter(NewReadonlyFilter())
|
||||
fs := &ReadOnlyFs{source: mfs}
|
||||
err = fs.Remove("/file.txt")
|
||||
if err == nil {
|
||||
t.Errorf("Did not fail to remove file")
|
||||
|
@ -54,9 +51,7 @@ func TestFilterReadonlyRemoveAndRead(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFilterRegexp(t *testing.T) {
|
||||
mfs := &MemMapFs{}
|
||||
fs := NewFilter(mfs)
|
||||
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`\.txt$`)))
|
||||
fs := &RegexpFs{re: regexp.MustCompile(`\.txt$`), source: &MemMapFs{}}
|
||||
_, err := fs.Create("/file.html")
|
||||
if err == nil {
|
||||
|
||||
|
@ -66,10 +61,8 @@ func TestFilterRegexp(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFilterRORegexpChain(t *testing.T) {
|
||||
mfs := &MemMapFs{}
|
||||
fs := NewFilter(mfs)
|
||||
fs.AddFilter(NewReadonlyFilter())
|
||||
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`\.txt$`)))
|
||||
rofs := &ReadOnlyFs{source: &MemMapFs{}}
|
||||
fs := &RegexpFs{re: regexp.MustCompile(`\.txt$`), source: rofs}
|
||||
_, err := fs.Create("/file.txt")
|
||||
if err == nil {
|
||||
t.Errorf("Did not fail to create file")
|
||||
|
@ -79,9 +72,8 @@ func TestFilterRORegexpChain(t *testing.T) {
|
|||
|
||||
func TestFilterRegexReadDir(t *testing.T) {
|
||||
mfs := &MemMapFs{}
|
||||
fs := NewFilter(mfs)
|
||||
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`\.txt$`)))
|
||||
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`^a`)))
|
||||
fs1 := &RegexpFs{re: regexp.MustCompile(`\.txt$`), source: mfs}
|
||||
fs := &RegexpFs{re: regexp.MustCompile(`^a`), source: fs1}
|
||||
|
||||
mfs.MkdirAll("/dir/sub", 0777)
|
||||
for _, name := range []string{"afile.txt", "afile.html", "bfile.txt"} {
|
|
@ -9,8 +9,7 @@ import (
|
|||
|
||||
func TestUnionCreateExisting(t *testing.T) {
|
||||
base := &MemMapFs{}
|
||||
roBase := NewFilter(base)
|
||||
roBase.AddFilter(NewReadonlyFilter())
|
||||
roBase := &ReadOnlyFs{source: base}
|
||||
|
||||
ufs := NewUnionFs(roBase, &MemMapFs{}, NewCoWUnionFs())
|
||||
|
||||
|
@ -60,8 +59,7 @@ func TestUnionCreateExisting(t *testing.T) {
|
|||
|
||||
func TestUnionMergeReaddir(t *testing.T) {
|
||||
base := &MemMapFs{}
|
||||
roBase := NewFilter(base)
|
||||
roBase.AddFilter(NewReadonlyFilter())
|
||||
roBase := &ReadOnlyFs{source: base}
|
||||
|
||||
ufs := NewUnionFs(roBase, &MemMapFs{}, NewCoWUnionFs())
|
||||
|
||||
|
|
Loading…
Reference in New Issue