memmap.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. // Copyright © 2014 Steve Francia <spf@spf13.com>.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package afero
  14. import (
  15. "fmt"
  16. "log"
  17. "os"
  18. "path/filepath"
  19. "strings"
  20. "sync"
  21. "time"
  22. "github.com/spf13/afero/mem"
  23. )
  24. const chmodBits = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky // Only a subset of bits are allowed to be changed. Documented under os.Chmod()
  25. type MemMapFs struct {
  26. mu sync.RWMutex
  27. data map[string]*mem.FileData
  28. init sync.Once
  29. }
  30. func NewMemMapFs() Fs {
  31. return &MemMapFs{}
  32. }
  33. func (m *MemMapFs) getData() map[string]*mem.FileData {
  34. m.init.Do(func() {
  35. m.data = make(map[string]*mem.FileData)
  36. // Root should always exist, right?
  37. // TODO: what about windows?
  38. root := mem.CreateDir(FilePathSeparator)
  39. mem.SetMode(root, os.ModeDir|0755)
  40. m.data[FilePathSeparator] = root
  41. })
  42. return m.data
  43. }
  44. func (*MemMapFs) Name() string { return "MemMapFS" }
  45. func (m *MemMapFs) Create(name string) (File, error) {
  46. name = normalizePath(name)
  47. m.mu.Lock()
  48. file := mem.CreateFile(name)
  49. m.getData()[name] = file
  50. m.registerWithParent(file, 0)
  51. m.mu.Unlock()
  52. return mem.NewFileHandle(file), nil
  53. }
  54. func (m *MemMapFs) unRegisterWithParent(fileName string) error {
  55. f, err := m.lockfreeOpen(fileName)
  56. if err != nil {
  57. return err
  58. }
  59. parent := m.findParent(f)
  60. if parent == nil {
  61. log.Panic("parent of ", f.Name(), " is nil")
  62. }
  63. parent.Lock()
  64. mem.RemoveFromMemDir(parent, f)
  65. parent.Unlock()
  66. return nil
  67. }
  68. func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData {
  69. pdir, _ := filepath.Split(f.Name())
  70. pdir = filepath.Clean(pdir)
  71. pfile, err := m.lockfreeOpen(pdir)
  72. if err != nil {
  73. return nil
  74. }
  75. return pfile
  76. }
  77. func (m *MemMapFs) registerWithParent(f *mem.FileData, perm os.FileMode) {
  78. if f == nil {
  79. return
  80. }
  81. parent := m.findParent(f)
  82. if parent == nil {
  83. pdir := filepath.Dir(filepath.Clean(f.Name()))
  84. err := m.lockfreeMkdir(pdir, perm)
  85. if err != nil {
  86. //log.Println("Mkdir error:", err)
  87. return
  88. }
  89. parent, err = m.lockfreeOpen(pdir)
  90. if err != nil {
  91. //log.Println("Open after Mkdir error:", err)
  92. return
  93. }
  94. }
  95. parent.Lock()
  96. mem.InitializeDir(parent)
  97. mem.AddToMemDir(parent, f)
  98. parent.Unlock()
  99. }
  100. func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
  101. name = normalizePath(name)
  102. x, ok := m.getData()[name]
  103. if ok {
  104. // Only return ErrFileExists if it's a file, not a directory.
  105. i := mem.FileInfo{FileData: x}
  106. if !i.IsDir() {
  107. return ErrFileExists
  108. }
  109. } else {
  110. item := mem.CreateDir(name)
  111. mem.SetMode(item, os.ModeDir|perm)
  112. m.getData()[name] = item
  113. m.registerWithParent(item, perm)
  114. }
  115. return nil
  116. }
  117. func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
  118. perm &= chmodBits
  119. name = normalizePath(name)
  120. m.mu.RLock()
  121. _, ok := m.getData()[name]
  122. m.mu.RUnlock()
  123. if ok {
  124. return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
  125. }
  126. m.mu.Lock()
  127. // Dobule check that it doesn't exist.
  128. if _, ok := m.getData()[name]; ok {
  129. m.mu.Unlock()
  130. return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
  131. }
  132. item := mem.CreateDir(name)
  133. mem.SetMode(item, os.ModeDir|perm)
  134. m.getData()[name] = item
  135. m.registerWithParent(item, perm)
  136. m.mu.Unlock()
  137. return m.setFileMode(name, perm|os.ModeDir)
  138. }
  139. func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
  140. err := m.Mkdir(path, perm)
  141. if err != nil {
  142. if err.(*os.PathError).Err == ErrFileExists {
  143. return nil
  144. }
  145. return err
  146. }
  147. return nil
  148. }
  149. // Handle some relative paths
  150. func normalizePath(path string) string {
  151. path = filepath.Clean(path)
  152. switch path {
  153. case ".":
  154. return FilePathSeparator
  155. case "..":
  156. return FilePathSeparator
  157. default:
  158. return path
  159. }
  160. }
  161. func (m *MemMapFs) Open(name string) (File, error) {
  162. f, err := m.open(name)
  163. if f != nil {
  164. return mem.NewReadOnlyFileHandle(f), err
  165. }
  166. return nil, err
  167. }
  168. func (m *MemMapFs) openWrite(name string) (File, error) {
  169. f, err := m.open(name)
  170. if f != nil {
  171. return mem.NewFileHandle(f), err
  172. }
  173. return nil, err
  174. }
  175. func (m *MemMapFs) open(name string) (*mem.FileData, error) {
  176. name = normalizePath(name)
  177. m.mu.RLock()
  178. f, ok := m.getData()[name]
  179. m.mu.RUnlock()
  180. if !ok {
  181. return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
  182. }
  183. return f, nil
  184. }
  185. func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
  186. name = normalizePath(name)
  187. f, ok := m.getData()[name]
  188. if ok {
  189. return f, nil
  190. } else {
  191. return nil, ErrFileNotFound
  192. }
  193. }
  194. func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
  195. perm &= chmodBits
  196. chmod := false
  197. file, err := m.openWrite(name)
  198. if err == nil && (flag&os.O_EXCL > 0) {
  199. return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileExists}
  200. }
  201. if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
  202. file, err = m.Create(name)
  203. chmod = true
  204. }
  205. if err != nil {
  206. return nil, err
  207. }
  208. if flag == os.O_RDONLY {
  209. file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
  210. }
  211. if flag&os.O_APPEND > 0 {
  212. _, err = file.Seek(0, os.SEEK_END)
  213. if err != nil {
  214. file.Close()
  215. return nil, err
  216. }
  217. }
  218. if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 {
  219. err = file.Truncate(0)
  220. if err != nil {
  221. file.Close()
  222. return nil, err
  223. }
  224. }
  225. if chmod {
  226. return file, m.setFileMode(name, perm)
  227. }
  228. return file, nil
  229. }
  230. func (m *MemMapFs) Remove(name string) error {
  231. name = normalizePath(name)
  232. m.mu.Lock()
  233. defer m.mu.Unlock()
  234. if _, ok := m.getData()[name]; ok {
  235. err := m.unRegisterWithParent(name)
  236. if err != nil {
  237. return &os.PathError{Op: "remove", Path: name, Err: err}
  238. }
  239. delete(m.getData(), name)
  240. } else {
  241. return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
  242. }
  243. return nil
  244. }
  245. func (m *MemMapFs) RemoveAll(path string) error {
  246. path = normalizePath(path)
  247. m.mu.Lock()
  248. m.unRegisterWithParent(path)
  249. m.mu.Unlock()
  250. m.mu.RLock()
  251. defer m.mu.RUnlock()
  252. for p := range m.getData() {
  253. if p == path || strings.HasPrefix(p, path+FilePathSeparator) {
  254. m.mu.RUnlock()
  255. m.mu.Lock()
  256. delete(m.getData(), p)
  257. m.mu.Unlock()
  258. m.mu.RLock()
  259. }
  260. }
  261. return nil
  262. }
  263. func (m *MemMapFs) Rename(oldname, newname string) error {
  264. oldname = normalizePath(oldname)
  265. newname = normalizePath(newname)
  266. if oldname == newname {
  267. return nil
  268. }
  269. m.mu.RLock()
  270. defer m.mu.RUnlock()
  271. if _, ok := m.getData()[oldname]; ok {
  272. m.mu.RUnlock()
  273. m.mu.Lock()
  274. m.unRegisterWithParent(oldname)
  275. fileData := m.getData()[oldname]
  276. delete(m.getData(), oldname)
  277. mem.ChangeFileName(fileData, newname)
  278. m.getData()[newname] = fileData
  279. m.registerWithParent(fileData, 0)
  280. m.mu.Unlock()
  281. m.mu.RLock()
  282. } else {
  283. return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
  284. }
  285. return nil
  286. }
  287. func (m *MemMapFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
  288. fileInfo, err := m.Stat(name)
  289. return fileInfo, false, err
  290. }
  291. func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
  292. f, err := m.Open(name)
  293. if err != nil {
  294. return nil, err
  295. }
  296. fi := mem.GetFileInfo(f.(*mem.File).Data())
  297. return fi, nil
  298. }
  299. func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
  300. mode &= chmodBits
  301. m.mu.RLock()
  302. f, ok := m.getData()[name]
  303. m.mu.RUnlock()
  304. if !ok {
  305. return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
  306. }
  307. prevOtherBits := mem.GetFileInfo(f).Mode() & ^chmodBits
  308. mode = prevOtherBits | mode
  309. return m.setFileMode(name, mode)
  310. }
  311. func (m *MemMapFs) setFileMode(name string, mode os.FileMode) error {
  312. name = normalizePath(name)
  313. m.mu.RLock()
  314. f, ok := m.getData()[name]
  315. m.mu.RUnlock()
  316. if !ok {
  317. return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
  318. }
  319. m.mu.Lock()
  320. mem.SetMode(f, mode)
  321. m.mu.Unlock()
  322. return nil
  323. }
  324. func (m *MemMapFs) Chown(name string, uid, gid int) error {
  325. name = normalizePath(name)
  326. m.mu.RLock()
  327. f, ok := m.getData()[name]
  328. m.mu.RUnlock()
  329. if !ok {
  330. return &os.PathError{Op: "chown", Path: name, Err: ErrFileNotFound}
  331. }
  332. mem.SetUID(f, uid)
  333. mem.SetGID(f, gid)
  334. return nil
  335. }
  336. func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
  337. name = normalizePath(name)
  338. m.mu.RLock()
  339. f, ok := m.getData()[name]
  340. m.mu.RUnlock()
  341. if !ok {
  342. return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
  343. }
  344. m.mu.Lock()
  345. mem.SetModTime(f, mtime)
  346. m.mu.Unlock()
  347. return nil
  348. }
  349. func (m *MemMapFs) List() {
  350. for _, x := range m.data {
  351. y := mem.FileInfo{FileData: x}
  352. fmt.Println(x.Name(), y.Size())
  353. }
  354. }