regexpfs.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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) Name() string {
  55. return "RegexpFs"
  56. }
  57. func (r *RegexpFs) Stat(name string) (os.FileInfo, error) {
  58. if err := r.dirOrMatches(name); err != nil {
  59. return nil, err
  60. }
  61. return r.source.Stat(name)
  62. }
  63. func (r *RegexpFs) Rename(oldname, newname string) error {
  64. dir, err := IsDir(r.source, oldname)
  65. if err != nil {
  66. return err
  67. }
  68. if dir {
  69. return nil
  70. }
  71. if err := r.matchesName(oldname); err != nil {
  72. return err
  73. }
  74. if err := r.matchesName(newname); err != nil {
  75. return err
  76. }
  77. return r.source.Rename(oldname, newname)
  78. }
  79. func (r *RegexpFs) RemoveAll(p string) error {
  80. dir, err := IsDir(r.source, p)
  81. if err != nil {
  82. return err
  83. }
  84. if !dir {
  85. if err := r.matchesName(p); err != nil {
  86. return err
  87. }
  88. }
  89. return r.source.RemoveAll(p)
  90. }
  91. func (r *RegexpFs) Remove(name string) error {
  92. if err := r.dirOrMatches(name); err != nil {
  93. return err
  94. }
  95. return r.source.Remove(name)
  96. }
  97. func (r *RegexpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
  98. if err := r.dirOrMatches(name); err != nil {
  99. return nil, err
  100. }
  101. return r.source.OpenFile(name, flag, perm)
  102. }
  103. func (r *RegexpFs) Open(name string) (File, error) {
  104. dir, err := IsDir(r.source, name)
  105. if err != nil {
  106. return nil, err
  107. }
  108. if !dir {
  109. if err := r.matchesName(name); err != nil {
  110. return nil, err
  111. }
  112. }
  113. f, err := r.source.Open(name)
  114. return &RegexpFile{f: f, re: r.re}, nil
  115. }
  116. func (r *RegexpFs) Mkdir(n string, p os.FileMode) error {
  117. return r.source.Mkdir(n, p)
  118. }
  119. func (r *RegexpFs) MkdirAll(n string, p os.FileMode) error {
  120. return r.source.MkdirAll(n, p)
  121. }
  122. func (r *RegexpFs) Create(name string) (File, error) {
  123. if err := r.matchesName(name); err != nil {
  124. return nil, err
  125. }
  126. return r.source.Create(name)
  127. }
  128. func (f *RegexpFile) Close() error {
  129. return f.f.Close()
  130. }
  131. func (f *RegexpFile) Read(s []byte) (int, error) {
  132. return f.f.Read(s)
  133. }
  134. func (f *RegexpFile) ReadAt(s []byte, o int64) (int, error) {
  135. return f.f.ReadAt(s, o)
  136. }
  137. func (f *RegexpFile) Seek(o int64, w int) (int64, error) {
  138. return f.f.Seek(o, w)
  139. }
  140. func (f *RegexpFile) Write(s []byte) (int, error) {
  141. return f.f.Write(s)
  142. }
  143. func (f *RegexpFile) WriteAt(s []byte, o int64) (int, error) {
  144. return f.f.WriteAt(s, o)
  145. }
  146. func (f *RegexpFile) Name() string {
  147. return f.f.Name()
  148. }
  149. func (f *RegexpFile) Readdir(c int) (fi []os.FileInfo, err error) {
  150. var rfi []os.FileInfo
  151. rfi, err = f.f.Readdir(c)
  152. if err != nil {
  153. return nil, err
  154. }
  155. for _, i := range rfi {
  156. if i.IsDir() || f.re.MatchString(i.Name()) {
  157. fi = append(fi, i)
  158. }
  159. }
  160. return fi, nil
  161. }
  162. func (f *RegexpFile) Readdirnames(c int) (n []string, err error) {
  163. fi, err := f.Readdir(c)
  164. if err != nil {
  165. return nil, err
  166. }
  167. for _, s := range fi {
  168. n = append(n, s.Name())
  169. }
  170. return n, nil
  171. }
  172. func (f *RegexpFile) Stat() (os.FileInfo, error) {
  173. return f.f.Stat()
  174. }
  175. func (f *RegexpFile) Sync() error {
  176. return f.f.Sync()
  177. }
  178. func (f *RegexpFile) Truncate(s int64) error {
  179. return f.f.Truncate(s)
  180. }
  181. func (f *RegexpFile) WriteString(s string) (int, error) {
  182. return f.f.WriteString(s)
  183. }