regexpfs.go raw

   1  package afero
   2  
   3  import (
   4  	"os"
   5  	"regexp"
   6  	"syscall"
   7  	"time"
   8  )
   9  
  10  // The RegexpFs filters files (not directories) by regular expression. Only
  11  // files matching the given regexp will be allowed, all others get a ENOENT error (
  12  // "No such file or directory").
  13  type RegexpFs struct {
  14  	re     *regexp.Regexp
  15  	source Fs
  16  }
  17  
  18  func NewRegexpFs(source Fs, re *regexp.Regexp) Fs {
  19  	return &RegexpFs{source: source, re: re}
  20  }
  21  
  22  type RegexpFile struct {
  23  	f  File
  24  	re *regexp.Regexp
  25  }
  26  
  27  func (r *RegexpFs) matchesName(name string) error {
  28  	if r.re == nil {
  29  		return nil
  30  	}
  31  	if r.re.MatchString(name) {
  32  		return nil
  33  	}
  34  	return syscall.ENOENT
  35  }
  36  
  37  func (r *RegexpFs) dirOrMatches(name string) error {
  38  	dir, err := IsDir(r.source, name)
  39  	if err != nil {
  40  		return err
  41  	}
  42  	if dir {
  43  		return nil
  44  	}
  45  	return r.matchesName(name)
  46  }
  47  
  48  func (r *RegexpFs) Chtimes(name string, a, m time.Time) error {
  49  	if err := r.dirOrMatches(name); err != nil {
  50  		return err
  51  	}
  52  	return r.source.Chtimes(name, a, m)
  53  }
  54  
  55  func (r *RegexpFs) Chmod(name string, mode os.FileMode) error {
  56  	if err := r.dirOrMatches(name); err != nil {
  57  		return err
  58  	}
  59  	return r.source.Chmod(name, mode)
  60  }
  61  
  62  func (r *RegexpFs) Chown(name string, uid, gid int) error {
  63  	if err := r.dirOrMatches(name); err != nil {
  64  		return err
  65  	}
  66  	return r.source.Chown(name, uid, gid)
  67  }
  68  
  69  func (r *RegexpFs) Name() string {
  70  	return "RegexpFs"
  71  }
  72  
  73  func (r *RegexpFs) Stat(name string) (os.FileInfo, error) {
  74  	if err := r.dirOrMatches(name); err != nil {
  75  		return nil, err
  76  	}
  77  	return r.source.Stat(name)
  78  }
  79  
  80  func (r *RegexpFs) Rename(oldname, newname string) error {
  81  	dir, err := IsDir(r.source, oldname)
  82  	if err != nil {
  83  		return err
  84  	}
  85  	if dir {
  86  		return nil
  87  	}
  88  	if err := r.matchesName(oldname); err != nil {
  89  		return err
  90  	}
  91  	if err := r.matchesName(newname); err != nil {
  92  		return err
  93  	}
  94  	return r.source.Rename(oldname, newname)
  95  }
  96  
  97  func (r *RegexpFs) RemoveAll(p string) error {
  98  	dir, err := IsDir(r.source, p)
  99  	if err != nil {
 100  		return err
 101  	}
 102  	if !dir {
 103  		if err := r.matchesName(p); err != nil {
 104  			return err
 105  		}
 106  	}
 107  	return r.source.RemoveAll(p)
 108  }
 109  
 110  func (r *RegexpFs) Remove(name string) error {
 111  	if err := r.dirOrMatches(name); err != nil {
 112  		return err
 113  	}
 114  	return r.source.Remove(name)
 115  }
 116  
 117  func (r *RegexpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 118  	if err := r.dirOrMatches(name); err != nil {
 119  		return nil, err
 120  	}
 121  	return r.source.OpenFile(name, flag, perm)
 122  }
 123  
 124  func (r *RegexpFs) Open(name string) (File, error) {
 125  	dir, err := IsDir(r.source, name)
 126  	if err != nil {
 127  		return nil, err
 128  	}
 129  	if !dir {
 130  		if err := r.matchesName(name); err != nil {
 131  			return nil, err
 132  		}
 133  	}
 134  	f, err := r.source.Open(name)
 135  	if err != nil {
 136  		return nil, err
 137  	}
 138  	return &RegexpFile{f: f, re: r.re}, nil
 139  }
 140  
 141  func (r *RegexpFs) Mkdir(n string, p os.FileMode) error {
 142  	return r.source.Mkdir(n, p)
 143  }
 144  
 145  func (r *RegexpFs) MkdirAll(n string, p os.FileMode) error {
 146  	return r.source.MkdirAll(n, p)
 147  }
 148  
 149  func (r *RegexpFs) Create(name string) (File, error) {
 150  	if err := r.matchesName(name); err != nil {
 151  		return nil, err
 152  	}
 153  	return r.source.Create(name)
 154  }
 155  
 156  func (f *RegexpFile) Close() error {
 157  	return f.f.Close()
 158  }
 159  
 160  func (f *RegexpFile) Read(s []byte) (int, error) {
 161  	return f.f.Read(s)
 162  }
 163  
 164  func (f *RegexpFile) ReadAt(s []byte, o int64) (int, error) {
 165  	return f.f.ReadAt(s, o)
 166  }
 167  
 168  func (f *RegexpFile) Seek(o int64, w int) (int64, error) {
 169  	return f.f.Seek(o, w)
 170  }
 171  
 172  func (f *RegexpFile) Write(s []byte) (int, error) {
 173  	return f.f.Write(s)
 174  }
 175  
 176  func (f *RegexpFile) WriteAt(s []byte, o int64) (int, error) {
 177  	return f.f.WriteAt(s, o)
 178  }
 179  
 180  func (f *RegexpFile) Name() string {
 181  	return f.f.Name()
 182  }
 183  
 184  func (f *RegexpFile) Readdir(c int) (fi []os.FileInfo, err error) {
 185  	var rfi []os.FileInfo
 186  	rfi, err = f.f.Readdir(c)
 187  	if err != nil {
 188  		return nil, err
 189  	}
 190  	for _, i := range rfi {
 191  		if i.IsDir() || f.re.MatchString(i.Name()) {
 192  			fi = append(fi, i)
 193  		}
 194  	}
 195  	return fi, nil
 196  }
 197  
 198  func (f *RegexpFile) Readdirnames(c int) (n []string, err error) {
 199  	fi, err := f.Readdir(c)
 200  	if err != nil {
 201  		return nil, err
 202  	}
 203  	for _, s := range fi {
 204  		n = append(n, s.Name())
 205  	}
 206  	return n, nil
 207  }
 208  
 209  func (f *RegexpFile) Stat() (os.FileInfo, error) {
 210  	return f.f.Stat()
 211  }
 212  
 213  func (f *RegexpFile) Sync() error {
 214  	return f.f.Sync()
 215  }
 216  
 217  func (f *RegexpFile) Truncate(s int64) error {
 218  	return f.f.Truncate(s)
 219  }
 220  
 221  func (f *RegexpFile) WriteString(s string) (int, error) {
 222  	return f.f.WriteString(s)
 223  }
 224