diff --git a/cmd/artifact/install/install.go b/cmd/artifact/install/install.go index b8f49a265..60a906693 100644 --- a/cmd/artifact/install/install.go +++ b/cmd/artifact/install/install.go @@ -337,7 +337,7 @@ func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args [] return err } // Extract artifact and move it to its destination directory - _, err = utils.ExtractTarGz(f, destDir, 0) + _, err = utils.ExtractTarGz(ctx, f, destDir, 0) if err != nil { return fmt.Errorf("cannot extract %q to %q: %w", result.Filename, destDir, err) } diff --git a/go.mod b/go.mod index 484d1d81a..1ff277a4e 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21 require ( cloud.google.com/go/storage v1.33.0 github.com/blang/semver v3.5.1+incompatible + github.com/codeclysm/extract/v3 v3.1.1 github.com/distribution/distribution/v3 v3.0.0-20230608105614-4501a6e06d3b github.com/docker/cli v24.0.7+incompatible github.com/docker/docker v24.0.7+incompatible @@ -170,6 +171,7 @@ require ( github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gowebpki/jcs v1.0.1 // indirect + github.com/h2non/filetype v1.1.3 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect @@ -180,6 +182,8 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 // indirect + github.com/juju/loggo v1.0.0 // indirect github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/leodido/go-urn v1.2.4 // indirect @@ -249,6 +253,7 @@ require ( github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect github.com/transparency-dev/merkle v0.0.2 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/xanzy/go-gitlab v0.93.2 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect @@ -281,6 +286,7 @@ require ( gopkg.in/DataDog/dd-trace-go.v1 v1.56.1 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a // indirect k8s.io/api v0.28.3 // indirect diff --git a/go.sum b/go.sum index 4ff71dbb2..87f1e8569 100644 --- a/go.sum +++ b/go.sum @@ -188,6 +188,8 @@ github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTs github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/arduino/go-paths-helper v1.2.0 h1:qDW93PR5IZUN/jzO4rCtexiwF8P4OIcOmcSgAYLZfY4= +github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= @@ -271,6 +273,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= +github.com/codeclysm/extract/v3 v3.1.1 h1:iHZtdEAwSTqPrd+1n4jfhr1qBhUWtHlMTjT90+fJVXg= +github.com/codeclysm/extract/v3 v3.1.1/go.mod h1:ZJi80UG2JtfHqJI+lgJSCACttZi++dHxfWuPaMhlOfQ= github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= @@ -593,6 +597,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gowebpki/jcs v1.0.1 h1:Qjzg8EOkrOTuWP7DqQ1FbYtcpEbeTzUoTN9bptp8FOU= github.com/gowebpki/jcs v1.0.1/go.mod h1:CID1cNZ+sHp1CCpAR8mPf6QRtagFBgPJE0FCUQ6+BrI= +github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= +github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -656,6 +662,13 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 h1:rhqTjzJlm7EbkELJDKMTU7udov+Se0xZkWmugr6zGok= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v1.0.0 h1:Y6ZMQOGR9Aj3BGkiWx7HBbIx6zNwNkxhVNOHU2i1bl0= +github.com/juju/loggo v1.0.0/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= +github.com/juju/testing v0.0.0-20200510222523-6c8c298c77a0 h1:+WWUkhnTjV6RNOxkcwk79qrjeyHEHvBzlneueBsatX4= +github.com/juju/testing v0.0.0-20200510222523-6c8c298c77a0/go.mod h1:hpGvhGHPVbNBraRLZEhoQwFLMrjK8PSlO4D3nDjKYXo= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= @@ -706,6 +719,7 @@ github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 h1:WGrKdjHtWC6 github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491/go.mod h1:o158RFmdEbYyIZmXAbrvmJWesbyxlLKee6X64VPVuOc= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -715,9 +729,11 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-colorable v0.0.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -989,6 +1005,8 @@ github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4= github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= @@ -1523,6 +1541,7 @@ gopkg.in/DataDog/dd-trace-go.v1 v1.56.1 h1:AUe/ZF7xm6vYnigPe+TY54DmfWYJxhMRaw/Tf gopkg.in/DataDog/dd-trace-go.v1 v1.56.1/go.mod h1:KDLJ3CWVOSuVVwu+0ZR5KZo2rP6c7YyBV3v387dIpUU= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1537,6 +1556,8 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/internal/follower/follower.go b/internal/follower/follower.go index 398c6fcfc..36060d38d 100644 --- a/internal/follower/follower.go +++ b/internal/follower/follower.go @@ -291,7 +291,7 @@ func (f *Follower) pull(ctx context.Context) (filePaths []string, res *oci.Regis } // Extract artifact and move it to its destination directory - filePaths, err = utils.ExtractTarGz(file, f.tmpDir, 0) + filePaths, err = utils.ExtractTarGz(ctx, file, f.tmpDir, 0) if err != nil { return filePaths, res, fmt.Errorf("unable to extract %q to %q: %w", res.Filename, f.tmpDir, err) } diff --git a/internal/utils/extract.go b/internal/utils/extract.go index 27cd7120a..681d72dcf 100644 --- a/internal/utils/extract.go +++ b/internal/utils/extract.go @@ -16,99 +16,43 @@ package utils import ( - "archive/tar" - "compress/gzip" - "errors" - "fmt" "io" - "os" "path/filepath" "strings" + + "github.com/codeclysm/extract/v3" + "golang.org/x/net/context" ) // ExtractTarGz extracts a *.tar.gz compressed archive and moves its content to destDir. // Returns a slice containing the full path of the extracted files. -func ExtractTarGz(gzipStream io.Reader, destDir string, stripPathComponents int) ([]string, error) { - var files []string - - uncompressedStream, err := gzip.NewReader(gzipStream) +func ExtractTarGz(ctx context.Context, gzipStream io.Reader, destDir string, stripPathComponents int) ([]string, error) { + var ( + files []string + err error + ) + + // destDir must be absolute (otherwise the library won't extract anything) + destDir, err = filepath.Abs(destDir) if err != nil { - return nil, err - } - - tarReader := tar.NewReader(uncompressedStream) - - for { - header, err := tarReader.Next() - - if errors.Is(err, io.EOF) { - break - } - - if err != nil { - return nil, err - } - - if strings.Contains(header.Name, "..") { - return nil, fmt.Errorf("not allowed relative path in tar archive") - } - - strippedName := stripComponents(header.Name, stripPathComponents) - - switch header.Typeflag { - case tar.TypeDir: - d := filepath.Join(destDir, strippedName) - if err = os.MkdirAll(filepath.Clean(d), 0o750); err != nil { - return nil, err - } - files = append(files, d) - case tar.TypeReg: - f := filepath.Join(destDir, strippedName) - outFile, err := os.Create(filepath.Clean(f)) - if err != nil { - return nil, err - } - if written, err := io.CopyN(outFile, tarReader, header.Size); err != nil { - return nil, err - } else if written != header.Size { - return nil, io.ErrShortWrite - } - if err = outFile.Close(); err != nil { - return nil, err - } - if err = os.Chmod(filepath.Clean(f), header.FileInfo().Mode()); err != nil { - return nil, err - } - files = append(files, f) - case tar.TypeLink, tar.TypeSymlink: - strippedSrcName := stripComponents(header.Linkname, stripPathComponents) - fDst := filepath.Join(destDir, strippedName) - if header.Typeflag == tar.TypeSymlink { - err = os.Symlink(filepath.Clean(strippedSrcName), filepath.Clean(fDst)) - } else { - err = os.Link(filepath.Clean(strippedSrcName), filepath.Clean(fDst)) - } - if err != nil { - return nil, err - } - files = append(files, fDst) - default: - return nil, fmt.Errorf("extractTarGz: uknown type: %b in %s", header.Typeflag, header.Name) - } + return files, err } - return files, nil + err = extract.Gz(ctx, gzipStream, destDir, func(s string) string { + strippedName := stripComponents(s, stripPathComponents) + files = append(files, filepath.Join(destDir, strippedName)) + return strippedName + }) + return files, err } func stripComponents(headerName string, stripComponents int) string { if stripComponents == 0 { return headerName } - names := strings.FieldsFunc(headerName, func(r rune) bool { - return r == os.PathSeparator - }) + names := strings.Split(headerName, string(filepath.Separator)) if len(names) < stripComponents { return headerName } - return filepath.Clean(strings.Join(names[stripComponents:], string(os.PathSeparator))) + return filepath.Clean(strings.Join(names[stripComponents:], string(filepath.Separator))) } diff --git a/internal/utils/extract_test.go b/internal/utils/extract_test.go deleted file mode 100644 index 411df7ba9..000000000 --- a/internal/utils/extract_test.go +++ /dev/null @@ -1,203 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (C) 2024 The Falco Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package utils - -import ( - "archive/tar" - "compress/gzip" - "io" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -const ( - srcDir = "./foo" -) - -var ( - files = []string{srcDir + "/example.txt", srcDir + "/test.txt", srcDir + "/bar/baz.txt"} -) - -func createTarball(t *testing.T, tarballFilePath, srcDir string) { - file, err := os.Create(tarballFilePath) - assert.NoError(t, err) - defer file.Close() - - gzipWriter := gzip.NewWriter(file) - defer gzipWriter.Close() - - tarWriter := tar.NewWriter(gzipWriter) - defer tarWriter.Close() - - err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error { - return addToArchive(tarWriter, path, info) - }) - assert.NoError(t, err) -} - -func addToArchive(tw *tar.Writer, fullName string, info os.FileInfo) error { - // Open the file which will be written into the archive - file, err := os.Open(fullName) - if err != nil { - return err - } - defer file.Close() - - // Create a tar Header from the FileInfo data - header, err := tar.FileInfoHeader(info, info.Name()) - if err != nil { - return err - } - - // Use full path as name (FileInfoHeader only takes the basename) - // If we don't do this the directory strucuture would - // not be preserved - // https://golang.org/src/archive/tar/common.go?#L626 - header.Name = fullName - - // Write file header to the tar archive - err = tw.WriteHeader(header) - if err != nil { - return err - } - - if !info.IsDir() { - // Copy file content to tar archive - _, err = io.Copy(tw, file) - if err != nil { - return err - } - } - - return nil -} - -func TestExtractTarGz(t *testing.T) { - // Create src dir - err := os.MkdirAll(srcDir, 0o750) - assert.NoError(t, err) - t.Cleanup(func() { - _ = os.RemoveAll(srcDir) - }) - - // Generate files to be tarballed - for _, f := range files { - err := os.MkdirAll(filepath.Dir(f), 0o755) - assert.NoError(t, err) - _, err = os.Create(f) - assert.NoError(t, err) - } - - // create tarball - createTarball(t, "./test.tgz", srcDir) - t.Cleanup(func() { - _ = os.RemoveAll("./test.tgz") - }) - - // Create dest folder - destDir := "./test/" - err = os.MkdirAll(destDir, 0o750) - assert.NoError(t, err) - t.Cleanup(func() { - _ = os.RemoveAll(destDir) - }) - - // Extract tarball - f, err := os.Open("./test.tgz") - assert.NoError(t, err) - t.Cleanup(func() { - f.Close() - }) - - list, err := ExtractTarGz(f, destDir, 0) - assert.NoError(t, err) - - // Final checks - - // All extracted files are ok - for _, f := range list { - _, err := os.Stat(f) - assert.NoError(t, err) - } - - // Extracted folder contains all source files (plus folders) - for _, f := range files { - path := filepath.Join(destDir, f) - assert.Contains(t, list, path) - } -} - -func TestExtractTarGzStripComponents(t *testing.T) { - // Create src dir - srcDir := "./foo" - err := os.MkdirAll(srcDir, 0o750) - assert.NoError(t, err) - t.Cleanup(func() { - _ = os.RemoveAll(srcDir) - }) - - // Generate files to be tarballed - for _, f := range files { - err := os.MkdirAll(filepath.Dir(f), 0o755) - assert.NoError(t, err) - _, err = os.Create(f) - assert.NoError(t, err) - } - - // create tarball - createTarball(t, "./test.tgz", srcDir) - t.Cleanup(func() { - _ = os.RemoveAll("./test.tgz") - }) - - // Create dest folder - destdirStrip := "./test_strip/" - err = os.MkdirAll(destdirStrip, 0o750) - assert.NoError(t, err) - t.Cleanup(func() { - _ = os.RemoveAll(destdirStrip) - }) - - // Extract tarball - f, err := os.Open("./test.tgz") - assert.NoError(t, err) - t.Cleanup(func() { - f.Close() - }) - // NOTE that here we strip first component - list, err := ExtractTarGz(f, destdirStrip, 1) - assert.NoError(t, err) - - // Final checks - - // All extracted files are ok - for _, f := range list { - _, err := os.Stat(f) - assert.NoError(t, err) - } - - // Extracted folder contains all source files (plus folders) - for _, f := range files { - // We stripped first component (ie: srcDir) - ff := strings.TrimPrefix(f, srcDir) - path := filepath.Join(destdirStrip, ff) - assert.Contains(t, list, path) - } -} diff --git a/pkg/driver/distro/distro.go b/pkg/driver/distro/distro.go index d11f72039..2fb348c06 100644 --- a/pkg/driver/distro/distro.go +++ b/pkg/driver/distro/distro.go @@ -319,7 +319,7 @@ func downloadKernelSrc(ctx context.Context, return env, err } - _, err = utils.ExtractTarGz(resp.Body, fullKernelDir, stripComponents) + _, err = utils.ExtractTarGz(ctx, resp.Body, fullKernelDir, stripComponents) if err != nil { return env, err }