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