github.com/gozelle/afero@v0.0.0-20230510083704-09e2ff18f19e/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  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  }