github.com/maxnasonov/afero@v1.8.4/regexpfs.go (about)

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