regexpfs.go (4369B)
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 }