copyOnWriteFs.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. package afero
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "syscall"
  7. "time"
  8. )
  9. var _ Lstater = (*CopyOnWriteFs)(nil)
  10. // The CopyOnWriteFs is a union filesystem: a read only base file system with
  11. // a possibly writeable layer on top. Changes to the file system will only
  12. // be made in the overlay: Changing an existing file in the base layer which
  13. // is not present in the overlay will copy the file to the overlay ("changing"
  14. // includes also calls to e.g. Chtimes(), Chmod() and Chown()).
  15. //
  16. // Reading directories is currently only supported via Open(), not OpenFile().
  17. type CopyOnWriteFs struct {
  18. base Fs
  19. layer Fs
  20. }
  21. func NewCopyOnWriteFs(base Fs, layer Fs) Fs {
  22. return &CopyOnWriteFs{base: base, layer: layer}
  23. }
  24. // Returns true if the file is not in the overlay
  25. func (u *CopyOnWriteFs) isBaseFile(name string) (bool, error) {
  26. if _, err := u.layer.Stat(name); err == nil {
  27. return false, nil
  28. }
  29. _, err := u.base.Stat(name)
  30. if err != nil {
  31. if oerr, ok := err.(*os.PathError); ok {
  32. if oerr.Err == os.ErrNotExist || oerr.Err == syscall.ENOENT || oerr.Err == syscall.ENOTDIR {
  33. return false, nil
  34. }
  35. }
  36. if err == syscall.ENOENT {
  37. return false, nil
  38. }
  39. }
  40. return true, err
  41. }
  42. func (u *CopyOnWriteFs) copyToLayer(name string) error {
  43. return copyToLayer(u.base, u.layer, name)
  44. }
  45. func (u *CopyOnWriteFs) Chtimes(name string, atime, mtime time.Time) error {
  46. b, err := u.isBaseFile(name)
  47. if err != nil {
  48. return err
  49. }
  50. if b {
  51. if err := u.copyToLayer(name); err != nil {
  52. return err
  53. }
  54. }
  55. return u.layer.Chtimes(name, atime, mtime)
  56. }
  57. func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error {
  58. b, err := u.isBaseFile(name)
  59. if err != nil {
  60. return err
  61. }
  62. if b {
  63. if err := u.copyToLayer(name); err != nil {
  64. return err
  65. }
  66. }
  67. return u.layer.Chmod(name, mode)
  68. }
  69. func (u *CopyOnWriteFs) Chown(name string, uid, gid int) error {
  70. b, err := u.isBaseFile(name)
  71. if err != nil {
  72. return err
  73. }
  74. if b {
  75. if err := u.copyToLayer(name); err != nil {
  76. return err
  77. }
  78. }
  79. return u.layer.Chown(name, uid, gid)
  80. }
  81. func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
  82. fi, err := u.layer.Stat(name)
  83. if err != nil {
  84. isNotExist := u.isNotExist(err)
  85. if isNotExist {
  86. return u.base.Stat(name)
  87. }
  88. return nil, err
  89. }
  90. return fi, nil
  91. }
  92. func (u *CopyOnWriteFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
  93. llayer, ok1 := u.layer.(Lstater)
  94. lbase, ok2 := u.base.(Lstater)
  95. if ok1 {
  96. fi, b, err := llayer.LstatIfPossible(name)
  97. if err == nil {
  98. return fi, b, nil
  99. }
  100. if !u.isNotExist(err) {
  101. return nil, b, err
  102. }
  103. }
  104. if ok2 {
  105. fi, b, err := lbase.LstatIfPossible(name)
  106. if err == nil {
  107. return fi, b, nil
  108. }
  109. if !u.isNotExist(err) {
  110. return nil, b, err
  111. }
  112. }
  113. fi, err := u.Stat(name)
  114. return fi, false, err
  115. }
  116. func (u *CopyOnWriteFs) SymlinkIfPossible(oldname, newname string) error {
  117. if slayer, ok := u.layer.(Linker); ok {
  118. return slayer.SymlinkIfPossible(oldname, newname)
  119. }
  120. return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: ErrNoSymlink}
  121. }
  122. func (u *CopyOnWriteFs) ReadlinkIfPossible(name string) (string, error) {
  123. if rlayer, ok := u.layer.(LinkReader); ok {
  124. return rlayer.ReadlinkIfPossible(name)
  125. }
  126. if rbase, ok := u.base.(LinkReader); ok {
  127. return rbase.ReadlinkIfPossible(name)
  128. }
  129. return "", &os.PathError{Op: "readlink", Path: name, Err: ErrNoReadlink}
  130. }
  131. func (u *CopyOnWriteFs) isNotExist(err error) bool {
  132. if e, ok := err.(*os.PathError); ok {
  133. err = e.Err
  134. }
  135. if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR {
  136. return true
  137. }
  138. return false
  139. }
  140. // Renaming files present only in the base layer is not permitted
  141. func (u *CopyOnWriteFs) Rename(oldname, newname string) error {
  142. b, err := u.isBaseFile(oldname)
  143. if err != nil {
  144. return err
  145. }
  146. if b {
  147. return syscall.EPERM
  148. }
  149. return u.layer.Rename(oldname, newname)
  150. }
  151. // Removing files present only in the base layer is not permitted. If
  152. // a file is present in the base layer and the overlay, only the overlay
  153. // will be removed.
  154. func (u *CopyOnWriteFs) Remove(name string) error {
  155. err := u.layer.Remove(name)
  156. switch err {
  157. case syscall.ENOENT:
  158. _, err = u.base.Stat(name)
  159. if err == nil {
  160. return syscall.EPERM
  161. }
  162. return syscall.ENOENT
  163. default:
  164. return err
  165. }
  166. }
  167. func (u *CopyOnWriteFs) RemoveAll(name string) error {
  168. err := u.layer.RemoveAll(name)
  169. switch err {
  170. case syscall.ENOENT:
  171. _, err = u.base.Stat(name)
  172. if err == nil {
  173. return syscall.EPERM
  174. }
  175. return syscall.ENOENT
  176. default:
  177. return err
  178. }
  179. }
  180. func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
  181. b, err := u.isBaseFile(name)
  182. if err != nil {
  183. return nil, err
  184. }
  185. if flag&(os.O_WRONLY|os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
  186. if b {
  187. if err = u.copyToLayer(name); err != nil {
  188. return nil, err
  189. }
  190. return u.layer.OpenFile(name, flag, perm)
  191. }
  192. dir := filepath.Dir(name)
  193. isaDir, err := IsDir(u.base, dir)
  194. if err != nil && !os.IsNotExist(err) {
  195. return nil, err
  196. }
  197. if isaDir {
  198. if err = u.layer.MkdirAll(dir, 0777); err != nil {
  199. return nil, err
  200. }
  201. return u.layer.OpenFile(name, flag, perm)
  202. }
  203. isaDir, err = IsDir(u.layer, dir)
  204. if err != nil {
  205. return nil, err
  206. }
  207. if isaDir {
  208. return u.layer.OpenFile(name, flag, perm)
  209. }
  210. return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOTDIR} // ...or os.ErrNotExist?
  211. }
  212. if b {
  213. return u.base.OpenFile(name, flag, perm)
  214. }
  215. return u.layer.OpenFile(name, flag, perm)
  216. }
  217. // This function handles the 9 different possibilities caused
  218. // by the union which are the intersection of the following...
  219. // layer: doesn't exist, exists as a file, and exists as a directory
  220. // base: doesn't exist, exists as a file, and exists as a directory
  221. func (u *CopyOnWriteFs) Open(name string) (File, error) {
  222. // Since the overlay overrides the base we check that first
  223. b, err := u.isBaseFile(name)
  224. if err != nil {
  225. return nil, err
  226. }
  227. // If overlay doesn't exist, return the base (base state irrelevant)
  228. if b {
  229. return u.base.Open(name)
  230. }
  231. // If overlay is a file, return it (base state irrelevant)
  232. dir, err := IsDir(u.layer, name)
  233. if err != nil {
  234. return nil, err
  235. }
  236. if !dir {
  237. return u.layer.Open(name)
  238. }
  239. // Overlay is a directory, base state now matters.
  240. // Base state has 3 states to check but 2 outcomes:
  241. // A. It's a file or non-readable in the base (return just the overlay)
  242. // B. It's an accessible directory in the base (return a UnionFile)
  243. // If base is file or nonreadable, return overlay
  244. dir, err = IsDir(u.base, name)
  245. if !dir || err != nil {
  246. return u.layer.Open(name)
  247. }
  248. // Both base & layer are directories
  249. // Return union file (if opens are without error)
  250. bfile, bErr := u.base.Open(name)
  251. lfile, lErr := u.layer.Open(name)
  252. // If either have errors at this point something is very wrong. Return nil and the errors
  253. if bErr != nil || lErr != nil {
  254. return nil, fmt.Errorf("BaseErr: %v\nOverlayErr: %v", bErr, lErr)
  255. }
  256. return &UnionFile{Base: bfile, Layer: lfile}, nil
  257. }
  258. func (u *CopyOnWriteFs) Mkdir(name string, perm os.FileMode) error {
  259. dir, err := IsDir(u.base, name)
  260. if err != nil {
  261. return u.layer.MkdirAll(name, perm)
  262. }
  263. if dir {
  264. return ErrFileExists
  265. }
  266. return u.layer.MkdirAll(name, perm)
  267. }
  268. func (u *CopyOnWriteFs) Name() string {
  269. return "CopyOnWriteFs"
  270. }
  271. func (u *CopyOnWriteFs) MkdirAll(name string, perm os.FileMode) error {
  272. dir, err := IsDir(u.base, name)
  273. if err != nil {
  274. return u.layer.MkdirAll(name, perm)
  275. }
  276. if dir {
  277. // This is in line with how os.MkdirAll behaves.
  278. return nil
  279. }
  280. return u.layer.MkdirAll(name, perm)
  281. }
  282. func (u *CopyOnWriteFs) Create(name string) (File, error) {
  283. return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
  284. }