Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Custom .tar.gz and .zip unarchive functions #1824

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ go 1.22.6

require (
github.com/google/uuid v1.6.0
github.com/mholt/archiver/v3 v3.5.1
github.com/observiq/bindplane-agent/exporter/azureblobexporter v1.59.0
github.com/observiq/bindplane-agent/exporter/chronicleexporter v1.59.0
github.com/observiq/bindplane-agent/exporter/chronicleforwarderexporter v1.59.0
Expand Down Expand Up @@ -518,7 +517,6 @@ require (
github.com/docker/docker v27.1.1+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/eapache/go-resiliency v1.6.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
github.com/eapache/queue v1.1.0 // indirect
Expand Down Expand Up @@ -603,7 +601,6 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/karrick/godirwalk v1.17.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/knadh/koanf v1.5.0 // indirect
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect
Expand Down Expand Up @@ -632,7 +629,6 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/nginxinc/nginx-prometheus-exporter v0.11.0 // indirect
github.com/nwaples/rardecode v1.1.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/googlecloudexporter v0.107.0 // indirect; indi72.0
github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/awsutil v0.107.0 // indirect; indi72.0
github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/containerinsight v0.107.0 // indirect; indi72.0
Expand Down Expand Up @@ -706,15 +702,13 @@ require (
github.com/tinylib/msgp v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/ulikunitz/xz v0.5.9 // indirect
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
github.com/vmware/govmomi v0.39.0 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
Expand Down Expand Up @@ -836,10 +830,6 @@ replace github.com/observiq/bindplane-agent/internal/measurements => ./internal/
// Relevant issue https://github.com/mattn/go-ieproxy/issues/45
replace github.com/mattn/go-ieproxy => github.com/mattn/go-ieproxy v0.0.1

// TODO(dakota): This could be removed after https://github.com/mholt/archiver/pull/396 is merged.
// This replace includes a resolution for https://github.com/advisories/GHSA-rhh4-rh7c-7r5v.
replace github.com/mholt/archiver/v3 => github.com/anchore/archiver/v3 v3.5.2

// Replaces below this are required by datadog exporter in v0.83.0 https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.83.0/exporter/datadogexporter/go.mod#L266-L275

// openshift removed all tags from their repo, use the pseudoversion from the release-3.9 branch HEAD
Expand Down
20 changes: 0 additions & 20 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -950,9 +950,6 @@ github.com/aliyun/aliyun-log-go-sdk v0.1.81 h1:OXQ78LSL0yZw60VLd+YjeevdK0XofKaHb
github.com/aliyun/aliyun-log-go-sdk v0.1.81/go.mod h1:aCY/2vkzJxMpoAVuyuMMTYFHur5otoWXSo9ofKJ67Ek=
github.com/aliyun/credentials-go v1.1.2 h1:qU1vwGIBb3UJ8BwunHDRFtAhS6jnQLnde/yk0+Ih2GY=
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58PaB6aA=
github.com/anchore/archiver/v3 v3.5.2/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
Expand Down Expand Up @@ -1170,9 +1167,6 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02 h1:tR3jsKPiO/mb6ntzk/dJlHZtm37CPfVp1C9KIo534+4=
github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02/go.mod h1:7NQ3kWOx2cZOSjtcveTa5nqupVr2s6/83sG+rTlI7uA=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
Expand Down Expand Up @@ -1404,7 +1398,6 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
Expand Down Expand Up @@ -1708,18 +1701,13 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs=
github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs=
github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM=
Expand Down Expand Up @@ -1877,8 +1865,6 @@ github.com/nginxinc/nginx-prometheus-exporter v0.11.0 h1:21xjnqNgxtni2jDgAQ90bl1
github.com/nginxinc/nginx-prometheus-exporter v0.11.0/go.mod h1:GdyHnWAb8q8OW1Pssrrqbcqra0SH0Vn6UXICMmyWkw8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk=
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
Expand Down Expand Up @@ -2301,7 +2287,6 @@ github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
Expand Down Expand Up @@ -2518,9 +2503,6 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA=
Expand All @@ -2544,8 +2526,6 @@ github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3k
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
Expand Down
151 changes: 149 additions & 2 deletions opamp/observiq/observiq_downloadable_file_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
package observiq

import (
"archive/tar"
"archive/zip"
"compress/gzip"
"crypto/sha256"
"crypto/subtle"
"errors"
Expand All @@ -24,14 +27,15 @@ import (
"net/url"
"os"
"path/filepath"
"strings"

archiver "github.com/mholt/archiver/v3"
"github.com/observiq/bindplane-agent/opamp"
"github.com/open-telemetry/opamp-go/protobufs"
"go.uber.org/zap"
)

const extractFolder = "latest"
const maxArchiveObjectByteSize = 1000000000

// Ensure interface is satisfied
var _ opamp.DownloadableFileManager = (*DownloadableFileManager)(nil)
Expand Down Expand Up @@ -75,7 +79,7 @@ func (m DownloadableFileManager) FetchAndExtractArchive(file *protobufs.Download
return fmt.Errorf("error cleaning archive extraction target path: %w", err)
}

if err := archiver.Unarchive(archiveFilePath, extractPath); err != nil {
if err := unarchive(archiveFilePath, extractPath); err != nil {
return fmt.Errorf("failed to extract file: %w", err)
}

Expand Down Expand Up @@ -171,3 +175,146 @@ func (m DownloadableFileManager) CleanupArtifacts() {
m.logger.Error("Failed to remove temporary directory", zap.Error(err))
}
}

// unarchive will unpack the package at archivePath(.tar.gz or .zip) into the directory found at extractPath
func unarchive(archivePath, extractPath string) error {
if strings.HasSuffix(archivePath, ".tar.gz") {
// Handle tar.gz files
if err := extractTarGz(archivePath, extractPath); err != nil {
return fmt.Errorf("extract tar.gz: %w", err)
}
} else if strings.HasSuffix(archivePath, ".zip") {
// Handle zip files
if err := extractZip(archivePath, extractPath); err != nil {
return fmt.Errorf("extract .zip: %w", err)
}
} else {
return fmt.Errorf("unsupported file type: %s", archivePath)
}

return nil
}

// extractTarGz will extract the .tar package at archivePath into the dir at extractPath
func extractTarGz(archivePath, extractPath string) error {
if err := os.MkdirAll(extractPath, 0750); err != nil {
return fmt.Errorf("mkdir extract path: %w", err)
}

archivePathClean := filepath.Clean(archivePath)
file, err := os.Open(archivePathClean)
if err != nil {
return fmt.Errorf("open archive package: %w", err)
}
defer file.Close()

gzipReader, err := gzip.NewReader(file)
if err != nil {
return fmt.Errorf("new gzip reader: %w", err)
}
defer gzipReader.Close()

tarReader := tar.NewReader(gzipReader)

for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("read next tarball header: %w", err)
}

outputPath, err := sanitizeArchivePath(extractPath, header.Name)
if err != nil {
return fmt.Errorf("sanitize archive path: %w", err)
}

switch header.Typeflag {
case tar.TypeDir:
if err := os.MkdirAll(outputPath, os.FileMode(header.Mode)); err != nil {
return fmt.Errorf("mkdir: %w", err)
}

case tar.TypeReg:
if err := os.MkdirAll(filepath.Dir(outputPath), 0700); err != nil {
return fmt.Errorf("create file's dir: %w", err)
}

outputPathClean := filepath.Clean(outputPath)
BinaryFissionGames marked this conversation as resolved.
Show resolved Hide resolved
outFile, err := os.OpenFile(outputPathClean, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(header.Mode))
if err != nil {
return fmt.Errorf("open output file: %w", err)
}
defer outFile.Close()

_, err = io.CopyN(outFile, tarReader, maxArchiveObjectByteSize)
if err != nil && err != io.EOF {
return fmt.Errorf("write to file: %w", err)
}
dpaasman00 marked this conversation as resolved.
Show resolved Hide resolved

default:
fmt.Printf("Unsupported type: %v in %s\n", header.Typeflag, header.Name)
}
}
return nil
}

// extractZip will extract the .zip package at archivePath into the dir at extractPath
func extractZip(archivePath, extractPath string) error {
// Ensure the output directory exists
if err := os.MkdirAll(extractPath, 0750); err != nil {
return fmt.Errorf("mkdir extract path: %w", err)
}

r, err := zip.OpenReader(archivePath)
if err != nil {
return fmt.Errorf("new zip reader: %w", err)
}
defer r.Close()

for _, f := range r.File {
outputPath, err := sanitizeArchivePath(extractPath, f.Name)
if err != nil {
return fmt.Errorf("sanitize archive path: %w", err)
}

if f.FileInfo().IsDir() {
if err := os.MkdirAll(outputPath, f.Mode()); err != nil {
return fmt.Errorf("mkdir: %w", err)
}
continue
}

if err := os.MkdirAll(filepath.Dir(outputPath), 0700); err != nil {
return fmt.Errorf("create file's dir: %w", err)
}

outputPathClean := filepath.Clean(outputPath)
outFile, err := os.OpenFile(outputPathClean, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return fmt.Errorf("open output file: %w", err)
}
defer outFile.Close()

rc, err := f.Open()
if err != nil {
return fmt.Errorf("open source file: %w", err)
}
defer rc.Close()

_, err = io.CopyN(outFile, rc, maxArchiveObjectByteSize)
if err != nil && err != io.EOF {
return fmt.Errorf("write source file to output file: %w", err)
}
}
return nil
}

func sanitizeArchivePath(dir, file string) (string, error) {
s := filepath.Join(dir, file)
if strings.HasPrefix(s, filepath.Clean(dir)) {
return s, nil
}
return "", fmt.Errorf("content filepath is tainted: %q", file)
}
Loading