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  }