vendor go-getter

This commit is contained in:
Alex Dadgar 2018-04-09 13:34:38 -07:00
parent d3bd8fb96e
commit 0733ef47e6
10 changed files with 110 additions and 29 deletions

View file

@ -285,7 +285,7 @@ be used automatically.
* `aws_access_key_id` (required) - Minio access key. * `aws_access_key_id` (required) - Minio access key.
* `aws_access_key_secret` (required) - Minio access key secret. * `aws_access_key_secret` (required) - Minio access key secret.
* `region` (optional - defaults to us-east-1) - Region identifier to use. * `region` (optional - defaults to us-east-1) - Region identifier to use.
* `version` (optional - fefaults to Minio default) - Configuration file format. * `version` (optional - defaults to Minio default) - Configuration file format.
#### S3 Bucket Examples #### S3 Bucket Examples

View file

@ -17,6 +17,7 @@ import (
"strings" "strings"
urlhelper "github.com/hashicorp/go-getter/helper/url" urlhelper "github.com/hashicorp/go-getter/helper/url"
"github.com/hashicorp/go-safetemp"
) )
// Client is a client for downloading things. // Client is a client for downloading things.
@ -100,17 +101,14 @@ func (c *Client) Get() error {
dst := c.Dst dst := c.Dst
src, subDir := SourceDirSubdir(src) src, subDir := SourceDirSubdir(src)
if subDir != "" { if subDir != "" {
tmpDir, err := ioutil.TempDir("", "tf") td, tdcloser, err := safetemp.Dir("", "getter")
if err != nil { if err != nil {
return err return err
} }
if err := os.RemoveAll(tmpDir); err != nil { defer tdcloser.Close()
return err
}
defer os.RemoveAll(tmpDir)
realDst = dst realDst = dst
dst = tmpDir dst = td
} }
u, err := urlhelper.Parse(src) u, err := urlhelper.Parse(src)

View file

@ -1,7 +1,15 @@
package getter package getter
import (
"strings"
)
// Decompressor defines the interface that must be implemented to add // Decompressor defines the interface that must be implemented to add
// support for decompressing a type. // support for decompressing a type.
//
// Important: if you're implementing a decompressor, please use the
// containsDotDot helper in this file to ensure that files can't be
// decompressed outside of the specified directory.
type Decompressor interface { type Decompressor interface {
// Decompress should decompress src to dst. dir specifies whether dst // Decompress should decompress src to dst. dir specifies whether dst
// is a directory or single file. src is guaranteed to be a single file // is a directory or single file. src is guaranteed to be a single file
@ -31,3 +39,20 @@ func init() {
"zip": new(ZipDecompressor), "zip": new(ZipDecompressor),
} }
} }
// containsDotDot checks if the filepath value v contains a ".." entry.
// This will check filepath components by splitting along / or \. This
// function is copied directly from the Go net/http implementation.
func containsDotDot(v string) bool {
if !strings.Contains(v, "..") {
return false
}
for _, ent := range strings.FieldsFunc(v, isSlashRune) {
if ent == ".." {
return true
}
}
return false
}
func isSlashRune(r rune) bool { return r == '/' || r == '\\' }

View file

@ -13,6 +13,7 @@ import (
func untar(input io.Reader, dst, src string, dir bool) error { func untar(input io.Reader, dst, src string, dir bool) error {
tarR := tar.NewReader(input) tarR := tar.NewReader(input)
done := false done := false
dirHdrs := []*tar.Header{}
for { for {
hdr, err := tarR.Next() hdr, err := tarR.Next()
if err == io.EOF { if err == io.EOF {
@ -21,7 +22,7 @@ func untar(input io.Reader, dst, src string, dir bool) error {
return fmt.Errorf("empty archive: %s", src) return fmt.Errorf("empty archive: %s", src)
} }
return nil break
} }
if err != nil { if err != nil {
return err return err
@ -34,6 +35,11 @@ func untar(input io.Reader, dst, src string, dir bool) error {
path := dst path := dst
if dir { if dir {
// Disallow parent traversal
if containsDotDot(hdr.Name) {
return fmt.Errorf("entry contains '..': %s", hdr.Name)
}
path = filepath.Join(path, hdr.Name) path = filepath.Join(path, hdr.Name)
} }
@ -47,6 +53,10 @@ func untar(input io.Reader, dst, src string, dir bool) error {
return err return err
} }
// Record the directory information so that we may set its attributes
// after all files have been extracted
dirHdrs = append(dirHdrs, hdr)
continue continue
} else { } else {
// There is no ordering guarantee that a file in a directory is // There is no ordering guarantee that a file in a directory is
@ -84,7 +94,23 @@ func untar(input io.Reader, dst, src string, dir bool) error {
if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil { if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil {
return err return err
} }
// Set the access and modification time
if err := os.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
return err
}
} }
// Adding a file or subdirectory changes the mtime of a directory
// We therefore wait until we've extracted everything and then set the mtime and atime attributes
for _, dirHdr := range dirHdrs {
path := filepath.Join(dst, dirHdr.Name)
if err := os.Chtimes(path, dirHdr.AccessTime, dirHdr.ModTime); err != nil {
return err
}
}
return nil
} }
// tarDecompressor is an implementation of Decompressor that can // tarDecompressor is an implementation of Decompressor that can

View file

@ -11,6 +11,7 @@ import (
"runtime" "runtime"
"sort" "sort"
"strings" "strings"
"time"
"github.com/mitchellh/go-testing-interface" "github.com/mitchellh/go-testing-interface"
) )
@ -22,6 +23,7 @@ type TestDecompressCase struct {
Err bool // Err is whether we expect an error or not Err bool // Err is whether we expect an error or not
DirList []string // DirList is the list of files for Dir mode DirList []string // DirList is the list of files for Dir mode
FileMD5 string // FileMD5 is the expected MD5 for a single file FileMD5 string // FileMD5 is the expected MD5 for a single file
Mtime *time.Time // Mtime is the optionally expected mtime for a single file (or all files if in Dir mode)
} }
// TestDecompressor is a helper function for testing generic decompressors. // TestDecompressor is a helper function for testing generic decompressors.
@ -68,6 +70,14 @@ func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) {
} }
} }
if tc.Mtime != nil {
actual := fi.ModTime()
expected := *tc.Mtime
if actual != expected {
t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), dst, actual.String())
}
}
return return
} }
@ -84,6 +94,21 @@ func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) {
if !reflect.DeepEqual(actual, expected) { if !reflect.DeepEqual(actual, expected) {
t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected) t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected)
} }
// Check for correct atime/mtime
for _, dir := range actual {
path := filepath.Join(dst, dir)
if tc.Mtime != nil {
fi, err := os.Stat(path)
if err != nil {
t.Fatalf("err: %s", err)
}
actual := fi.ModTime()
expected := *tc.Mtime
if actual != expected {
t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), path, actual.String())
}
}
}
}() }()
} }
} }

View file

@ -42,6 +42,11 @@ func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error {
for _, f := range zipR.File { for _, f := range zipR.File {
path := dst path := dst
if dir { if dir {
// Disallow parent traversal
if containsDotDot(f.Name) {
return fmt.Errorf("entry contains '..': %s", f.Name)
}
path = filepath.Join(path, f.Name) path = filepath.Join(path, f.Name)
} }

View file

@ -11,6 +11,7 @@ import (
"strings" "strings"
urlhelper "github.com/hashicorp/go-getter/helper/url" urlhelper "github.com/hashicorp/go-getter/helper/url"
"github.com/hashicorp/go-safetemp"
"github.com/hashicorp/go-version" "github.com/hashicorp/go-version"
) )
@ -105,13 +106,11 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
// GetFile for Git doesn't support updating at this time. It will download // GetFile for Git doesn't support updating at this time. It will download
// the file every time. // the file every time.
func (g *GitGetter) GetFile(dst string, u *url.URL) error { func (g *GitGetter) GetFile(dst string, u *url.URL) error {
td, err := ioutil.TempDir("", "getter-git") td, tdcloser, err := safetemp.Dir("", "getter")
if err != nil { if err != nil {
return err return err
} }
if err := os.RemoveAll(td); err != nil { defer tdcloser.Close()
return err
}
// Get the filename, and strip the filename from the URL so we can // Get the filename, and strip the filename from the URL so we can
// just get the repository directly. // just get the repository directly.

View file

@ -2,7 +2,6 @@ package getter
import ( import (
"fmt" "fmt"
"io/ioutil"
"net/url" "net/url"
"os" "os"
"os/exec" "os/exec"
@ -10,6 +9,7 @@ import (
"runtime" "runtime"
urlhelper "github.com/hashicorp/go-getter/helper/url" urlhelper "github.com/hashicorp/go-getter/helper/url"
"github.com/hashicorp/go-safetemp"
) )
// HgGetter is a Getter implementation that will download a module from // HgGetter is a Getter implementation that will download a module from
@ -64,13 +64,13 @@ func (g *HgGetter) Get(dst string, u *url.URL) error {
// GetFile for Hg doesn't support updating at this time. It will download // GetFile for Hg doesn't support updating at this time. It will download
// the file every time. // the file every time.
func (g *HgGetter) GetFile(dst string, u *url.URL) error { func (g *HgGetter) GetFile(dst string, u *url.URL) error {
td, err := ioutil.TempDir("", "getter-hg") // Create a temporary directory to store the full source. This has to be
// a non-existent directory.
td, tdcloser, err := safetemp.Dir("", "getter")
if err != nil { if err != nil {
return err return err
} }
if err := os.RemoveAll(td); err != nil { defer tdcloser.Close()
return err
}
// Get the filename, and strip the filename from the URL so we can // Get the filename, and strip the filename from the URL so we can
// just get the repository directly. // just get the repository directly.

View file

@ -4,12 +4,13 @@ import (
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/hashicorp/go-safetemp"
) )
// HttpGetter is a Getter implementation that will download from an HTTP // HttpGetter is a Getter implementation that will download from an HTTP
@ -135,25 +136,27 @@ func (g *HttpGetter) GetFile(dst string, u *url.URL) error {
if err != nil { if err != nil {
return err return err
} }
defer f.Close()
_, err = io.Copy(f, resp.Body) n, err := io.Copy(f, resp.Body)
if err == nil && n < resp.ContentLength {
err = io.ErrShortWrite
}
if err1 := f.Close(); err == nil {
err = err1
}
return err return err
} }
// getSubdir downloads the source into the destination, but with // getSubdir downloads the source into the destination, but with
// the proper subdir. // the proper subdir.
func (g *HttpGetter) getSubdir(dst, source, subDir string) error { func (g *HttpGetter) getSubdir(dst, source, subDir string) error {
// Create a temporary directory to store the full source // Create a temporary directory to store the full source. This has to be
td, err := ioutil.TempDir("", "tf") // a non-existent directory.
td, tdcloser, err := safetemp.Dir("", "getter")
if err != nil { if err != nil {
return err return err
} }
defer os.RemoveAll(td) defer tdcloser.Close()
// We have to create a subdirectory that doesn't exist for the file
// getter to work.
td = filepath.Join(td, "data")
// Download that into the given directory // Download that into the given directory
if err := Get(td, source); err != nil { if err := Get(td, source); err != nil {

4
vendor/vendor.json vendored
View file

@ -135,8 +135,8 @@
{"path":"github.com/hashicorp/go-checkpoint","checksumSHA1":"D267IUMW2rcb+vNe3QU+xhfSrgY=","revision":"1545e56e46dec3bba264e41fde2c1e2aa65b5dd4","revisionTime":"2017-10-09T17:35:28Z"}, {"path":"github.com/hashicorp/go-checkpoint","checksumSHA1":"D267IUMW2rcb+vNe3QU+xhfSrgY=","revision":"1545e56e46dec3bba264e41fde2c1e2aa65b5dd4","revisionTime":"2017-10-09T17:35:28Z"},
{"path":"github.com/hashicorp/go-cleanhttp","checksumSHA1":"6ihdHMkDfFx/rJ1A36com2F6bQk=","revision":"a45970658e51fea2c41445ff0f7e07106d007617","revisionTime":"2017-02-11T00:33:01Z"}, {"path":"github.com/hashicorp/go-cleanhttp","checksumSHA1":"6ihdHMkDfFx/rJ1A36com2F6bQk=","revision":"a45970658e51fea2c41445ff0f7e07106d007617","revisionTime":"2017-02-11T00:33:01Z"},
{"path":"github.com/hashicorp/go-envparse","checksumSHA1":"FKmqR4DC3nCXtnT9pe02z5CLNWo=","revision":"310ca1881b22af3522e3a8638c0b426629886196","revisionTime":"2018-01-19T21:58:41Z"}, {"path":"github.com/hashicorp/go-envparse","checksumSHA1":"FKmqR4DC3nCXtnT9pe02z5CLNWo=","revision":"310ca1881b22af3522e3a8638c0b426629886196","revisionTime":"2018-01-19T21:58:41Z"},
{"path":"github.com/hashicorp/go-getter","checksumSHA1":"wCKbbnwvVEoKAE5TWunloLhErm4=","revision":"994f50a6f071b07cfbea9eca9618c9674091ca51","revisionTime":"2017-12-04T19:28:26Z"}, {"path":"github.com/hashicorp/go-getter","checksumSHA1":"fvjFEz5PBN1m9ALWf9UuLgTFWLg=","revision":"90bb99a48d86cf1d327cee9968f7428f90ba13c1","revisionTime":"2018-03-27T01:01:14Z"},
{"path":"github.com/hashicorp/go-getter/helper/url","checksumSHA1":"9J+kDr29yDrwsdu2ULzewmqGjpA=","revision":"994f50a6f071b07cfbea9eca9618c9674091ca51","revisionTime":"2017-12-04T19:28:26Z"}, {"path":"github.com/hashicorp/go-getter/helper/url","checksumSHA1":"9J+kDr29yDrwsdu2ULzewmqGjpA=","revision":"90bb99a48d86cf1d327cee9968f7428f90ba13c1","revisionTime":"2018-03-27T01:01:14Z"},
{"path":"github.com/hashicorp/go-hclog","checksumSHA1":"miVF4/7JP0lRwZvFJGKwZWk7aAQ=","revision":"b4e5765d1e5f00a0550911084f45f8214b5b83b9","revisionTime":"2017-07-16T17:45:23Z"}, {"path":"github.com/hashicorp/go-hclog","checksumSHA1":"miVF4/7JP0lRwZvFJGKwZWk7aAQ=","revision":"b4e5765d1e5f00a0550911084f45f8214b5b83b9","revisionTime":"2017-07-16T17:45:23Z"},
{"path":"github.com/hashicorp/go-immutable-radix","checksumSHA1":"Cas2nprG6pWzf05A2F/OlnjUu2Y=","revision":"8aac2701530899b64bdea735a1de8da899815220","revisionTime":"2017-07-25T22:12:15Z"}, {"path":"github.com/hashicorp/go-immutable-radix","checksumSHA1":"Cas2nprG6pWzf05A2F/OlnjUu2Y=","revision":"8aac2701530899b64bdea735a1de8da899815220","revisionTime":"2017-07-25T22:12:15Z"},
{"path":"github.com/hashicorp/go-memdb","checksumSHA1":"FMAvwDar2bQyYAW4XMFhAt0J5xA=","revision":"20ff6434c1cc49b80963d45bf5c6aa89c78d8d57","revisionTime":"2017-08-31T20:15:40Z"}, {"path":"github.com/hashicorp/go-memdb","checksumSHA1":"FMAvwDar2bQyYAW4XMFhAt0J5xA=","revision":"20ff6434c1cc49b80963d45bf5c6aa89c78d8d57","revisionTime":"2017-08-31T20:15:40Z"},