From da94e1f134f6d43707dff0a602989c77637523f0 Mon Sep 17 00:00:00 2001 From: Lang Martin Date: Thu, 8 Aug 2019 17:54:09 -0400 Subject: [PATCH 1/3] client add Umask to the client config, use it to Chmod files --- client.go | 26 ++++++-- copy_dir.go | 29 +++------ decompress.go | 3 +- decompress_bzip2.go | 14 +--- decompress_gzip.go | 14 +--- decompress_tar.go | 26 +++----- decompress_tar_test.go | 64 +++++++++++++++++++ decompress_tbz2.go | 6 +- decompress_testing.go | 2 +- decompress_tgz.go | 6 +- decompress_txz.go | 6 +- decompress_xz.go | 14 +--- decompress_zip.go | 24 ++----- decompress_zip_test.go | 33 ++++++++++ get_file_copy.go | 46 +++++++++++++ get_file_unix.go | 24 ++----- get_file_windows.go | 4 +- get_http.go | 8 +-- get_s3.go | 4 +- test-fixtures/decompress-tar/permissions.tar | Bin 0 -> 3584 bytes test-fixtures/decompress-zip/permissions.zip | Bin 0 -> 808 bytes 21 files changed, 224 insertions(+), 129 deletions(-) create mode 100644 test-fixtures/decompress-tar/permissions.tar create mode 100644 test-fixtures/decompress-zip/permissions.zip diff --git a/client.go b/client.go index 007a78ba7..78a96bf0b 100644 --- a/client.go +++ b/client.go @@ -19,7 +19,7 @@ import ( // Using a client directly allows more fine-grained control over how downloading // is done, as well as customizing the protocols supported. type Client struct { - // Ctx for cancellation + // Ctx for cancellation Ctx context.Context // Src is the source URL to get. @@ -39,6 +39,10 @@ type Client struct { // for documentation. Mode ClientMode + // Umask is used to mask file permissions when storing local files or decompressing + // an archive + Umask os.FileMode + // Detectors is the list of detectors that are tried on the source. // If this is nil, then the default Detectors will be used. Detectors []Detector @@ -66,6 +70,20 @@ type Client struct { Options []ClientOption } +// umask returns the effective umask for the Client, defaulting to the process umask +func (c *Client) umask() os.FileMode { + if c == nil { + return 0 + } + return c.Umask +} + +// mode returns file mode umasked by the Client umask +func (c *Client) mode(mode os.FileMode) os.FileMode { + m := mode & ^c.umask() + return m +} + // Get downloads the configured source to the destination. func (c *Client) Get() error { if err := c.Configure(c.Options...); err != nil { @@ -233,7 +251,7 @@ func (c *Client) Get() error { if decompressor != nil { // We have a decompressor, so decompress the current destination // into the final destination with the proper mode. - err := decompressor.Decompress(decompressDst, dst, decompressDir) + err := decompressor.Decompress(decompressDst, dst, decompressDir, c.umask()) if err != nil { return err } @@ -281,7 +299,7 @@ func (c *Client) Get() error { if err := os.RemoveAll(realDst); err != nil { return err } - if err := os.MkdirAll(realDst, 0755); err != nil { + if err := os.MkdirAll(realDst, c.mode(0755)); err != nil { return err } @@ -291,7 +309,7 @@ func (c *Client) Get() error { return err } - return copyDir(c.Ctx, realDst, subDir, false) + return copyDir(c.Ctx, realDst, subDir, false, c.umask()) } return nil diff --git a/copy_dir.go b/copy_dir.go index 641fe6d0f..a629306b7 100644 --- a/copy_dir.go +++ b/copy_dir.go @@ -7,11 +7,16 @@ import ( "strings" ) +// mode returns the file mode masked by the umask +func mode(mode, umask os.FileMode) os.FileMode { + return mode & ^umask +} + // copyDir copies the src directory contents into dst. Both directories // should already exist. // // If ignoreDot is set to true, then dot-prefixed files/folders are ignored. -func copyDir(ctx context.Context, dst string, src string, ignoreDot bool) error { +func copyDir(ctx context.Context, dst string, src string, ignoreDot bool, umask os.FileMode) error { src, err := filepath.EvalSymlinks(src) if err != nil { return err @@ -46,7 +51,7 @@ func copyDir(ctx context.Context, dst string, src string, ignoreDot bool) error return nil } - if err := os.MkdirAll(dstPath, 0755); err != nil { + if err := os.MkdirAll(dstPath, mode(0755, umask)); err != nil { return err } @@ -54,24 +59,8 @@ func copyDir(ctx context.Context, dst string, src string, ignoreDot bool) error } // If we have a file, copy the contents. - srcF, err := os.Open(path) - if err != nil { - return err - } - defer srcF.Close() - - dstF, err := os.Create(dstPath) - if err != nil { - return err - } - defer dstF.Close() - - if _, err := Copy(ctx, dstF, srcF); err != nil { - return err - } - - // Chmod it - return os.Chmod(dstPath, info.Mode()) + _, err = copyFile(ctx, dstPath, path, info.Mode(), umask) + return err } return filepath.Walk(src, walkFn) diff --git a/decompress.go b/decompress.go index 198bb0edd..62ca1060f 100644 --- a/decompress.go +++ b/decompress.go @@ -1,6 +1,7 @@ package getter import ( + "os" "strings" ) @@ -14,7 +15,7 @@ type Decompressor interface { // Decompress should decompress src to dst. dir specifies whether dst // is a directory or single file. src is guaranteed to be a single file // that exists. dst is not guaranteed to exist already. - Decompress(dst, src string, dir bool) error + Decompress(dst, src string, dir bool, umask os.FileMode) error } // Decompressors is the mapping of extension to the Decompressor implementation diff --git a/decompress_bzip2.go b/decompress_bzip2.go index 339f4cf7a..a5373e4e1 100644 --- a/decompress_bzip2.go +++ b/decompress_bzip2.go @@ -3,7 +3,6 @@ package getter import ( "compress/bzip2" "fmt" - "io" "os" "path/filepath" ) @@ -12,14 +11,14 @@ import ( // decompress bz2 files. type Bzip2Decompressor struct{} -func (d *Bzip2Decompressor) Decompress(dst, src string, dir bool) error { +func (d *Bzip2Decompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // Directory isn't supported at all if dir { return fmt.Errorf("bzip2-compressed files can only unarchive to a single file") } // If we're going into a directory we should make that first - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), mode(0755, umask)); err != nil { return err } @@ -34,12 +33,5 @@ func (d *Bzip2Decompressor) Decompress(dst, src string, dir bool) error { bzipR := bzip2.NewReader(f) // Copy it out - dstF, err := os.Create(dst) - if err != nil { - return err - } - defer dstF.Close() - - _, err = io.Copy(dstF, bzipR) - return err + return copyReader(dst, bzipR, 0622, umask) } diff --git a/decompress_gzip.go b/decompress_gzip.go index 5ebf709b4..669e5eafd 100644 --- a/decompress_gzip.go +++ b/decompress_gzip.go @@ -3,7 +3,6 @@ package getter import ( "compress/gzip" "fmt" - "io" "os" "path/filepath" ) @@ -12,14 +11,14 @@ import ( // decompress gzip files. type GzipDecompressor struct{} -func (d *GzipDecompressor) Decompress(dst, src string, dir bool) error { +func (d *GzipDecompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // Directory isn't supported at all if dir { return fmt.Errorf("gzip-compressed files can only unarchive to a single file") } // If we're going into a directory we should make that first - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), mode(0755, umask)); err != nil { return err } @@ -38,12 +37,5 @@ func (d *GzipDecompressor) Decompress(dst, src string, dir bool) error { defer gzipR.Close() // Copy it out - dstF, err := os.Create(dst) - if err != nil { - return err - } - defer dstF.Close() - - _, err = io.Copy(dstF, gzipR) - return err + return copyReader(dst, gzipR, 0622, umask) } diff --git a/decompress_tar.go b/decompress_tar.go index b6986a25a..4b58b036a 100644 --- a/decompress_tar.go +++ b/decompress_tar.go @@ -11,7 +11,7 @@ import ( // untar is a shared helper for untarring an archive. The reader should provide // an uncompressed view of the tar archive. -func untar(input io.Reader, dst, src string, dir bool) error { +func untar(input io.Reader, dst, src string, dir bool, umask os.FileMode) error { tarR := tar.NewReader(input) done := false dirHdrs := []*tar.Header{} @@ -51,7 +51,7 @@ func untar(input io.Reader, dst, src string, dir bool) error { } // A directory, just make the directory and continue unarchiving... - if err := os.MkdirAll(path, 0755); err != nil { + if err := os.MkdirAll(path, mode(0755, umask)); err != nil { return err } @@ -67,7 +67,7 @@ func untar(input io.Reader, dst, src string, dir bool) error { // Check that the directory exists, otherwise create it if _, err := os.Stat(dstPath); os.IsNotExist(err) { - if err := os.MkdirAll(dstPath, 0755); err != nil { + if err := os.MkdirAll(dstPath, mode(0755, umask)); err != nil { return err } } @@ -82,20 +82,10 @@ func untar(input io.Reader, dst, src string, dir bool) error { done = true // Open the file for writing - dstF, err := os.Create(path) + err = copyReader(path, tarR, hdr.FileInfo().Mode(), umask) if err != nil { return err } - _, err = io.Copy(dstF, tarR) - dstF.Close() - if err != nil { - return err - } - - // Chmod the file - if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil { - return err - } // Set the access and modification time if valid, otherwise default to current time aTime := now @@ -115,7 +105,7 @@ func untar(input io.Reader, dst, src string, dir bool) error { for _, dirHdr := range dirHdrs { path := filepath.Join(dst, dirHdr.Name) // Chmod the directory since they might be created before we know the mode flags - if err := os.Chmod(path, dirHdr.FileInfo().Mode()); err != nil { + if err := os.Chmod(path, mode(dirHdr.FileInfo().Mode(), umask)); err != nil { return err } // Set the mtime/atime attributes since they would have been changed during extraction @@ -139,13 +129,13 @@ func untar(input io.Reader, dst, src string, dir bool) error { // unpack tar files. type tarDecompressor struct{} -func (d *tarDecompressor) Decompress(dst, src string, dir bool) error { +func (d *tarDecompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // If we're going into a directory we should make that first mkdir := dst if !dir { mkdir = filepath.Dir(dst) } - if err := os.MkdirAll(mkdir, 0755); err != nil { + if err := os.MkdirAll(mkdir, mode(0755, umask)); err != nil { return err } @@ -156,5 +146,5 @@ func (d *tarDecompressor) Decompress(dst, src string, dir bool) error { } defer f.Close() - return untar(f, dst, src, dir) + return untar(f, dst, src, dir, umask) } diff --git a/decompress_tar_test.go b/decompress_tar_test.go index b8f4b8cc4..38ba38383 100644 --- a/decompress_tar_test.go +++ b/decompress_tar_test.go @@ -1,7 +1,10 @@ package getter import ( + "io/ioutil" + "os" "path/filepath" + "runtime" "testing" "time" ) @@ -41,3 +44,64 @@ func TestTar(t *testing.T) { TestDecompressor(t, new(tarDecompressor), cases) } + +// testDecompressPermissions decompresses a directory and checks the permissions of the expanded files +func testDecompressorPermissions(t *testing.T, d Decompressor, input string, expected map[string]int, umask os.FileMode) { + td, err := ioutil.TempDir("", "getter") + if err != nil { + t.Fatalf("err: %s", err) + } + + // Destination is always joining result so that we have a new path + dst := filepath.Join(td, "subdir", "result") + + err = d.Decompress(dst, input, true, umask) + if err != nil { + t.Fatalf("err: %s", err) + } + + defer os.RemoveAll(dst) + + for name, mode := range expected { + fi, err := os.Stat(filepath.Join(dst, name)) + if err != nil { + t.Fatalf("err: %s", err) + } + + real := fi.Mode() + if real != os.FileMode(mode) { + t.Fatalf("err: %s expected mode %o got %o", name, mode, real) + } + } +} + +func TestDecompressTarPermissions(t *testing.T) { + d := new(tarDecompressor) + input := "./test-fixtures/decompress-tar/permissions.tar" + + var expected map[string]int + var masked int + + if runtime.GOOS == "windows" { + expected = map[string]int{ + "directory/public": 0666, + "directory/private": 0666, + "directory/exec": 0666, + "directory/setuid": 0666, + } + masked = 0666 + } else { + expected = map[string]int{ + "directory/public": 0666, + "directory/private": 0600, + "directory/exec": 0755, + "directory/setuid": 040000755, + } + masked = 0755 + } + + testDecompressorPermissions(t, d, input, expected, os.FileMode(0)) + + expected["directory/setuid"] = masked + testDecompressorPermissions(t, d, input, expected, os.FileMode(060000000)) +} diff --git a/decompress_tbz2.go b/decompress_tbz2.go index 5391b5c8c..e2e5458c9 100644 --- a/decompress_tbz2.go +++ b/decompress_tbz2.go @@ -10,13 +10,13 @@ import ( // decompress tar.bz2 files. type TarBzip2Decompressor struct{} -func (d *TarBzip2Decompressor) Decompress(dst, src string, dir bool) error { +func (d *TarBzip2Decompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // If we're going into a directory we should make that first mkdir := dst if !dir { mkdir = filepath.Dir(dst) } - if err := os.MkdirAll(mkdir, 0755); err != nil { + if err := os.MkdirAll(mkdir, mode(0755, umask)); err != nil { return err } @@ -29,5 +29,5 @@ func (d *TarBzip2Decompressor) Decompress(dst, src string, dir bool) error { // Bzip2 compression is second bzipR := bzip2.NewReader(f) - return untar(bzipR, dst, src, dir) + return untar(bzipR, dst, src, dir, umask) } diff --git a/decompress_testing.go b/decompress_testing.go index b2f662a89..b18bd6cb6 100644 --- a/decompress_testing.go +++ b/decompress_testing.go @@ -47,7 +47,7 @@ func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) { defer os.RemoveAll(td) // Decompress - err := d.Decompress(dst, tc.Input, tc.Dir) + err := d.Decompress(dst, tc.Input, tc.Dir, 0022) if (err != nil) != tc.Err { t.Fatalf("err %s: %s", tc.Input, err) } diff --git a/decompress_tgz.go b/decompress_tgz.go index 65eb70dd2..84c4aa33d 100644 --- a/decompress_tgz.go +++ b/decompress_tgz.go @@ -11,13 +11,13 @@ import ( // decompress tar.gzip files. type TarGzipDecompressor struct{} -func (d *TarGzipDecompressor) Decompress(dst, src string, dir bool) error { +func (d *TarGzipDecompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // If we're going into a directory we should make that first mkdir := dst if !dir { mkdir = filepath.Dir(dst) } - if err := os.MkdirAll(mkdir, 0755); err != nil { + if err := os.MkdirAll(mkdir, mode(0755, umask)); err != nil { return err } @@ -35,5 +35,5 @@ func (d *TarGzipDecompressor) Decompress(dst, src string, dir bool) error { } defer gzipR.Close() - return untar(gzipR, dst, src, dir) + return untar(gzipR, dst, src, dir, umask) } diff --git a/decompress_txz.go b/decompress_txz.go index 5e151c127..24686f454 100644 --- a/decompress_txz.go +++ b/decompress_txz.go @@ -12,13 +12,13 @@ import ( // decompress tar.xz files. type TarXzDecompressor struct{} -func (d *TarXzDecompressor) Decompress(dst, src string, dir bool) error { +func (d *TarXzDecompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // If we're going into a directory we should make that first mkdir := dst if !dir { mkdir = filepath.Dir(dst) } - if err := os.MkdirAll(mkdir, 0755); err != nil { + if err := os.MkdirAll(mkdir, mode(0755, umask)); err != nil { return err } @@ -35,5 +35,5 @@ func (d *TarXzDecompressor) Decompress(dst, src string, dir bool) error { return fmt.Errorf("Error opening an xz reader for %s: %s", src, err) } - return untar(txzR, dst, src, dir) + return untar(txzR, dst, src, dir, umask) } diff --git a/decompress_xz.go b/decompress_xz.go index 4e37abab1..de5d6ce2b 100644 --- a/decompress_xz.go +++ b/decompress_xz.go @@ -2,7 +2,6 @@ package getter import ( "fmt" - "io" "os" "path/filepath" @@ -13,14 +12,14 @@ import ( // decompress xz files. type XzDecompressor struct{} -func (d *XzDecompressor) Decompress(dst, src string, dir bool) error { +func (d *XzDecompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // Directory isn't supported at all if dir { return fmt.Errorf("xz-compressed files can only unarchive to a single file") } // If we're going into a directory we should make that first - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), mode(0755, umask)); err != nil { return err } @@ -38,12 +37,5 @@ func (d *XzDecompressor) Decompress(dst, src string, dir bool) error { } // Copy it out - dstF, err := os.Create(dst) - if err != nil { - return err - } - defer dstF.Close() - - _, err = io.Copy(dstF, xzR) - return err + return copyReader(dst, xzR, 0622, umask) } diff --git a/decompress_zip.go b/decompress_zip.go index 0830f7914..4876a3374 100644 --- a/decompress_zip.go +++ b/decompress_zip.go @@ -3,7 +3,6 @@ package getter import ( "archive/zip" "fmt" - "io" "os" "path/filepath" ) @@ -12,13 +11,13 @@ import ( // decompress zip files. type ZipDecompressor struct{} -func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error { +func (d *ZipDecompressor) Decompress(dst, src string, dir bool, umask os.FileMode) error { // If we're going into a directory we should make that first mkdir := dst if !dir { mkdir = filepath.Dir(dst) } - if err := os.MkdirAll(mkdir, 0755); err != nil { + if err := os.MkdirAll(mkdir, mode(0755, umask)); err != nil { return err } @@ -56,7 +55,7 @@ func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error { } // A directory, just make the directory and continue unarchiving... - if err := os.MkdirAll(path, 0755); err != nil { + if err := os.MkdirAll(path, mode(0755, umask)); err != nil { return err } @@ -67,34 +66,23 @@ func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error { // required to contain entries for just the directories so this // can happen. if dir { - if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(path), mode(0755, umask)); err != nil { return err } } // Open the file for reading srcF, err := f.Open() - if err != nil { - return err - } - - // Open the file for writing - dstF, err := os.Create(path) if err != nil { srcF.Close() return err } - _, err = io.Copy(dstF, srcF) + + err = copyReader(path, srcF, f.Mode(), umask) srcF.Close() - dstF.Close() if err != nil { return err } - - // Chmod the file - if err := os.Chmod(path, f.Mode()); err != nil { - return err - } } return nil diff --git a/decompress_zip_test.go b/decompress_zip_test.go index d22ea109c..d898da158 100644 --- a/decompress_zip_test.go +++ b/decompress_zip_test.go @@ -1,7 +1,9 @@ package getter import ( + "os" "path/filepath" + "runtime" "testing" ) @@ -96,3 +98,34 @@ func TestZipDecompressor(t *testing.T) { TestDecompressor(t, new(ZipDecompressor), cases) } + +func TestDecompressZipPermissions(t *testing.T) { + d := new(ZipDecompressor) + input := "./test-fixtures/decompress-zip/permissions.zip" + + var expected map[string]int + var masked int + + if runtime.GOOS == "windows" { + expected = map[string]int{ + "directory/public": 0666, + "directory/private": 0666, + "directory/exec": 0666, + "directory/setuid": 0666, + } + masked = 0666 + } else { + expected = map[string]int{ + "directory/public": 0666, + "directory/private": 0600, + "directory/exec": 0755, + "directory/setuid": 040000755, + } + masked = 0755 + } + + testDecompressorPermissions(t, d, input, expected, os.FileMode(0)) + + expected["directory/setuid"] = masked + testDecompressorPermissions(t, d, input, expected, os.FileMode(060000000)) +} diff --git a/get_file_copy.go b/get_file_copy.go index d70fb4951..29abbd1aa 100644 --- a/get_file_copy.go +++ b/get_file_copy.go @@ -3,6 +3,7 @@ package getter import ( "context" "io" + "os" ) // readerFunc is syntactic sugar for read interface. @@ -27,3 +28,48 @@ func Copy(ctx context.Context, dst io.Writer, src io.Reader) (int64, error) { } })) } + +// copyReader copies from an io.Reader into a file, using umask to create the dst file +func copyReader(dst string, src io.Reader, fmode, umask os.FileMode) error { + dstF, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fmode) + if err != nil { + return err + } + defer dstF.Close() + + _, err = io.Copy(dstF, src) + if err != nil { + return err + } + + // Explicitly chmod; the process umask is unconditionally applied otherwise. + // We'll mask the mode with our own umask, but that may be different than + // the process umask + return os.Chmod(dst, mode(fmode, umask)) +} + +// copyFile copies a file in chunks from src path to dst path, using umask to create the dst file +func copyFile(ctx context.Context, dst, src string, fmode, umask os.FileMode) (int64, error) { + srcF, err := os.Open(src) + if err != nil { + return 0, err + } + defer srcF.Close() + + dstF, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fmode) + if err != nil { + return 0, err + } + defer dstF.Close() + + count, err := Copy(ctx, dstF, srcF) + if err != nil { + return 0, err + } + + // Explicitly chmod; the process umask is unconditionally applied otherwise. + // We'll mask the mode with our own umask, but that may be different than + // the process umask + err = os.Chmod(dst, mode(fmode, umask)) + return count, err +} diff --git a/get_file_unix.go b/get_file_unix.go index c3b28ae51..40ebc5af2 100644 --- a/get_file_unix.go +++ b/get_file_unix.go @@ -41,7 +41,7 @@ func (g *FileGetter) Get(dst string, u *url.URL) error { } // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } @@ -56,13 +56,15 @@ func (g *FileGetter) GetFile(dst string, u *url.URL) error { } // The source path must exist and be a file to be usable. - if fi, err := os.Stat(path); err != nil { + var fi os.FileInfo + var err error + if fi, err = os.Stat(path); err != nil { return fmt.Errorf("source path error: %s", err) } else if fi.IsDir() { return fmt.Errorf("source path must be a file") } - _, err := os.Lstat(dst) + _, err = os.Lstat(dst) if err != nil && !os.IsNotExist(err) { return err } @@ -76,7 +78,7 @@ func (g *FileGetter) GetFile(dst string, u *url.URL) error { } // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err = os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } @@ -86,18 +88,6 @@ func (g *FileGetter) GetFile(dst string, u *url.URL) error { } // Copy - srcF, err := os.Open(path) - if err != nil { - return err - } - defer srcF.Close() - - dstF, err := os.Create(dst) - if err != nil { - return err - } - defer dstF.Close() - - _, err = Copy(ctx, dstF, srcF) + _, err = copyFile(ctx, dst, path, fi.Mode(), g.client.umask()) return err } diff --git a/get_file_windows.go b/get_file_windows.go index 24f1acb17..86819ff3f 100644 --- a/get_file_windows.go +++ b/get_file_windows.go @@ -45,7 +45,7 @@ func (g *FileGetter) Get(dst string, u *url.URL) error { } // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } @@ -88,7 +88,7 @@ func (g *FileGetter) GetFile(dst string, u *url.URL) error { } // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } diff --git a/get_http.go b/get_http.go index 7c4541c6e..66fcecedc 100644 --- a/get_http.go +++ b/get_http.go @@ -138,11 +138,11 @@ func (g *HttpGetter) GetFile(dst string, src *url.URL) error { } // Create all the parent directories if needed - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } - f, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE, os.FileMode(0666)) + f, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE, g.client.mode(0666)) if err != nil { return err } @@ -253,11 +253,11 @@ func (g *HttpGetter) getSubdir(ctx context.Context, dst, source, subDir string) } // Make the final destination - if err := os.MkdirAll(dst, 0755); err != nil { + if err := os.MkdirAll(dst, g.client.mode(0755)); err != nil { return err } - return copyDir(ctx, dst, sourcePath, false) + return copyDir(ctx, dst, sourcePath, false, g.client.umask()) } // parseMeta looks for the first meta tag in the given reader that diff --git a/get_s3.go b/get_s3.go index 93eeb0b81..ad54fa653 100644 --- a/get_s3.go +++ b/get_s3.go @@ -84,7 +84,7 @@ func (g *S3Getter) Get(dst string, u *url.URL) error { } // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } @@ -165,7 +165,7 @@ func (g *S3Getter) getObject(ctx context.Context, client *s3.S3, dst, bucket, ke } // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } diff --git a/test-fixtures/decompress-tar/permissions.tar b/test-fixtures/decompress-tar/permissions.tar new file mode 100644 index 0000000000000000000000000000000000000000..0c594eaa7e7ab851852532cb04543cc19bda8001 GIT binary patch literal 3584 zcmeH|-425w4269Z-e9#*cpf)#Au*frXW8C<#hGa|nO;D$3wl$iq$%gi!P2$%(%;+H zDT@{WV2DKKv({qA0n58B++Pt0&Z4~!sBlkn^Kl`7^c>aLN|GVr$9GLlcwjW#> iqUX8?fI9a7_wT>X$M@f0^8Z@Lv`-2o1(E_G6?g+DMSD#E literal 0 HcmV?d00001 diff --git a/test-fixtures/decompress-zip/permissions.zip b/test-fixtures/decompress-zip/permissions.zip new file mode 100644 index 0000000000000000000000000000000000000000..40db777325da7ac539eacef2854999d3c10a0227 GIT binary patch literal 808 zcmWIWW@h1H00F@Wet$3nN^mjAFr;J_r6!l;7gg$qhHx@4Pbv Date: Thu, 15 Aug 2019 16:19:34 -0400 Subject: [PATCH 2/3] .travis.yml run for release branches --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4fe9176aa..5becde59d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,3 +22,4 @@ before_script: branches: only: - master + - /^release-.*/ From f5101da0117392c6e7960c934f05a2fd689a5b5f Mon Sep 17 00:00:00 2001 From: Lang Martin Date: Thu, 22 Aug 2019 15:45:07 -0400 Subject: [PATCH 3/3] missing umask/mode and copy util calls --- get_file_windows.go | 14 +------------- get_gcs.go | 13 +++---------- get_s3.go | 9 +-------- 3 files changed, 5 insertions(+), 31 deletions(-) diff --git a/get_file_windows.go b/get_file_windows.go index 86819ff3f..909d5b006 100644 --- a/get_file_windows.go +++ b/get_file_windows.go @@ -112,19 +112,7 @@ func (g *FileGetter) GetFile(dst string, u *url.URL) error { } // Copy - srcF, err := os.Open(path) - if err != nil { - return err - } - defer srcF.Close() - - dstF, err := os.Create(dst) - if err != nil { - return err - } - defer dstF.Close() - - _, err = Copy(ctx, dstF, srcF) + _, err = copyFile(ctx, dst, path, 0666, g.client.umask()) return err } diff --git a/get_gcs.go b/get_gcs.go index 6faa70f4f..4b895877b 100644 --- a/get_gcs.go +++ b/get_gcs.go @@ -77,7 +77,7 @@ func (g *GCSGetter) Get(dst string, u *url.URL) error { } // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } @@ -138,18 +138,11 @@ func (g *GCSGetter) getObject(ctx context.Context, client *storage.Client, dst, defer rc.Close() // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), g.client.mode(0755)); err != nil { return err } - f, err := os.Create(dst) - if err != nil { - return err - } - defer f.Close() - - _, err = Copy(ctx, f, rc) - return err + return copyReader(dst, rc, 0666, g.client.umask()) } func (g *GCSGetter) parseURL(u *url.URL) (bucket, path string, err error) { diff --git a/get_s3.go b/get_s3.go index ad54fa653..c98c52e2e 100644 --- a/get_s3.go +++ b/get_s3.go @@ -169,14 +169,7 @@ func (g *S3Getter) getObject(ctx context.Context, client *s3.S3, dst, bucket, ke return err } - f, err := os.Create(dst) - if err != nil { - return err - } - defer f.Close() - - _, err = Copy(ctx, f, resp.Body) - return err + return copyReader(dst, resp.Body, 0666, g.client.umask()) } func (g *S3Getter) getAWSConfig(region string, url *url.URL, creds *credentials.Credentials) *aws.Config {