file.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package webdav
  5. import (
  6. "io"
  7. "net/http"
  8. "os"
  9. "path"
  10. "path/filepath"
  11. "strings"
  12. )
  13. // A FileSystem implements access to a collection of named files. The elements
  14. // in a file path are separated by slash ('/', U+002F) characters, regardless
  15. // of host operating system convention.
  16. //
  17. // Each method has the same semantics as the os package's function of the same
  18. // name.
  19. type FileSystem interface {
  20. Mkdir(name string, perm os.FileMode) error
  21. OpenFile(name string, flag int, perm os.FileMode) (File, error)
  22. RemoveAll(name string) error
  23. Stat(name string) (os.FileInfo, error)
  24. }
  25. // A File is returned by a FileSystem's OpenFile method and can be served by a
  26. // Handler.
  27. type File interface {
  28. http.File
  29. io.Writer
  30. }
  31. // A Dir implements FileSystem using the native file system restricted to a
  32. // specific directory tree.
  33. //
  34. // While the FileSystem.OpenFile method takes '/'-separated paths, a Dir's
  35. // string value is a filename on the native file system, not a URL, so it is
  36. // separated by filepath.Separator, which isn't necessarily '/'.
  37. //
  38. // An empty Dir is treated as ".".
  39. type Dir string
  40. func (d Dir) resolve(name string) string {
  41. // This implementation is based on Dir.Open's code in the standard net/http package.
  42. if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
  43. strings.Contains(name, "\x00") {
  44. return ""
  45. }
  46. dir := string(d)
  47. if dir == "" {
  48. dir = "."
  49. }
  50. return filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))
  51. }
  52. func (d Dir) Mkdir(name string, perm os.FileMode) error {
  53. if name = d.resolve(name); name == "" {
  54. return os.ErrNotExist
  55. }
  56. return os.Mkdir(name, perm)
  57. }
  58. func (d Dir) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
  59. if name = d.resolve(name); name == "" {
  60. return nil, os.ErrNotExist
  61. }
  62. return os.OpenFile(name, flag, perm)
  63. }
  64. func (d Dir) RemoveAll(name string) error {
  65. if name = d.resolve(name); name == "" {
  66. return os.ErrNotExist
  67. }
  68. if name == filepath.Clean(string(d)) {
  69. // Prohibit removing the virtual root directory.
  70. return os.ErrInvalid
  71. }
  72. return os.RemoveAll(name)
  73. }
  74. func (d Dir) Stat(name string) (os.FileInfo, error) {
  75. if name = d.resolve(name); name == "" {
  76. return nil, os.ErrNotExist
  77. }
  78. return os.Stat(name)
  79. }
  80. // TODO: a MemFS implementation.