You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

65 lines
1.7 KiB

  1. // Copyright 2013 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 vfs
  5. import (
  6. "fmt"
  7. "io/ioutil"
  8. "os"
  9. pathpkg "path"
  10. "path/filepath"
  11. )
  12. // OS returns an implementation of FileSystem reading from the
  13. // tree rooted at root. Recording a root is convenient everywhere
  14. // but necessary on Windows, because the slash-separated path
  15. // passed to Open has no way to specify a drive letter. Using a root
  16. // lets code refer to OS(`c:\`), OS(`d:\`) and so on.
  17. func OS(root string) FileSystem {
  18. return osFS(root)
  19. }
  20. type osFS string
  21. func (root osFS) String() string { return "os(" + string(root) + ")" }
  22. func (root osFS) resolve(path string) string {
  23. // Clean the path so that it cannot possibly begin with ../.
  24. // If it did, the result of filepath.Join would be outside the
  25. // tree rooted at root. We probably won't ever see a path
  26. // with .. in it, but be safe anyway.
  27. path = pathpkg.Clean("/" + path)
  28. return filepath.Join(string(root), path)
  29. }
  30. func (root osFS) Open(path string) (ReadSeekCloser, error) {
  31. f, err := os.Open(root.resolve(path))
  32. if err != nil {
  33. return nil, err
  34. }
  35. fi, err := f.Stat()
  36. if err != nil {
  37. f.Close()
  38. return nil, err
  39. }
  40. if fi.IsDir() {
  41. f.Close()
  42. return nil, fmt.Errorf("Open: %s is a directory", path)
  43. }
  44. return f, nil
  45. }
  46. func (root osFS) Lstat(path string) (os.FileInfo, error) {
  47. return os.Lstat(root.resolve(path))
  48. }
  49. func (root osFS) Stat(path string) (os.FileInfo, error) {
  50. return os.Stat(root.resolve(path))
  51. }
  52. func (root osFS) ReadDir(path string) ([]os.FileInfo, error) {
  53. return ioutil.ReadDir(root.resolve(path)) // is sorted
  54. }