regexpfs.go 4.3 KB

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