Skip to content

Commit

Permalink
feat: support decompression
Browse files Browse the repository at this point in the history
  • Loading branch information
Yongsheng Xu committed Aug 23, 2021
1 parent c17c3d1 commit f78e5b6
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 3 deletions.
82 changes: 79 additions & 3 deletions apply.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package update

import (
"archive/tar"
"archive/zip"
"bytes"
"compress/gzip"
"crypto"
"crypto/x509"
"encoding/pem"
Expand Down Expand Up @@ -113,9 +116,29 @@ func Apply(update io.Reader, opts Options) error {
}
defer fp.Close()

_, err = io.Copy(fp, bytes.NewReader(newBytes))
if err != nil {
return err
if opts.IsTarGz {
uncompressedBytes, err := extractTarGz(newBytes)
if err != nil {
return err
}
_, err = io.Copy(fp, bytes.NewReader(uncompressedBytes))
if err != nil {
return err
}
} else if opts.IsZip {
uncompressedBytes, err := extractZip(newBytes)
if err != nil {
return err
}
_, err = io.Copy(fp, bytes.NewReader(uncompressedBytes))
if err != nil {
return err
}
} else {
_, err = io.Copy(fp, bytes.NewReader(newBytes))
if err != nil {
return err
}
}

// if we don't call fp.Close(), windows won't let us move the new executable
Expand Down Expand Up @@ -217,6 +240,12 @@ type Options struct {
// Used by ed25519 verifier
VerifyUseContent bool

// If true, it will be uncompressed(.tar.gz) before apply
IsTarGz bool

// If true, it will be uncompressed(.zip) before apply
IsZip bool

// Use this hash function to generate the checksum. If not set, SHA256 is used.
Hash crypto.Hash

Expand Down Expand Up @@ -328,3 +357,50 @@ func checksumFor(h crypto.Hash, payload []byte) ([]byte, error) {
hash.Write(payload) // guaranteed not to error
return hash.Sum([]byte{}), nil
}

func extractZip(content []byte) ([]byte, error) {
zipReader, err := zip.NewReader(bytes.NewReader(content), int64(len(content)))
if err != nil {
return nil, err
}

if len(zipReader.File) != 1 {
return nil, errors.New(fmt.Sprintf("extractZip: multi file is not supported, files: %d",
len(zipReader.File)))
}
f := zipReader.File[0]
rc, err := f.Open()
if err != nil {
return nil, err
}
output, err := ioutil.ReadAll(rc)
if err != nil {
return nil, err
}
rc.Close()
return output, nil
}

func extractTarGz(content []byte) ([]byte, error) {
uncompressedStream, err := gzip.NewReader(bytes.NewReader(content))
if err != nil {
return nil, err
}

tarReader := tar.NewReader(uncompressedStream)

header, err := tarReader.Next()

if err != nil {
return nil, err
}

// Only support single binary
if header.Typeflag == tar.TypeReg {
return ioutil.ReadAll(tarReader)
}
return nil, errors.New(fmt.Sprintf("extractTarGz: uknown type: %s in %s",
string(header.Typeflag),
header.Name,
))
}
17 changes: 17 additions & 0 deletions ed25519_veryfier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package update
import (
"bytes"
"crypto"
"io/ioutil"
"testing"
)

Expand Down Expand Up @@ -35,3 +36,19 @@ func TestVerifyED25519ignature(t *testing.T) {
err := Apply(bytes.NewReader(newFile), opts)
validateUpdate(fName, err, t)
}

func TestUnZip(t *testing.T) {
content, _ := ioutil.ReadFile("test/newFile.zip") // the file is inside the local directory
uncompressedBytes, _ := extractZip(content)
if !bytes.Equal(uncompressedBytes, newFile) {
t.Fatalf("Unzip Failed")
}
}

func TestUnTarGz(t *testing.T) {
content, _ := ioutil.ReadFile("test/newFile.tar.gz") // the file is inside the local directory
uncompressedBytes, _ := extractTarGz(content)
if !bytes.Equal(uncompressedBytes, newFile) {
t.Fatalf("UnTarGz Failed")
}
}
Binary file added test/newFile.tar.gz
Binary file not shown.
Binary file added test/newFile.zip
Binary file not shown.

0 comments on commit f78e5b6

Please sign in to comment.