Skip to content

Commit 306fcab

Browse files
committed
Use an xz library instead of shelling out to xz for decompression
When decompressing layers compressed with xz, use a library rather than shelling out to the xz CLI. Signed-off-by: Nalin Dahyabhai <[email protected]>
1 parent 29dc210 commit 306fcab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+7549
-96
lines changed

contrib/cirrus/setup.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ case "$OS_RELEASE_ID" in
1616
bash "$SCRIPT_BASE/add_second_partition.sh"
1717
[[ -z "$RPMS_CONFLICTING" ]] || \
1818
$SHORT_DNFY erase $RPMS_CONFLICTING
19+
$SHORT_DNFY install zstd
1920
;;
2021
ubuntu)
2122
[[ -z "$DEBS_CONFLICTING" ]] || \
2223
$SHORT_APTGET -q remove $DEBS_CONFLICTING
24+
$SHORT_APTGET -q update
25+
$SHORT_APTGET -q install zstd
2326
;;
2427
*)
2528
bad_os_id_ver

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ require (
2323
github.com/stretchr/testify v1.7.0
2424
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
2525
github.com/tchap/go-patricia v2.3.0+incompatible
26+
github.com/ulikunitz/xz v0.5.10
2627
github.com/vbatts/tar-split v0.11.1
2728
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
2829
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmD
476476
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
477477
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
478478
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
479+
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
480+
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
479481
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
480482
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
481483
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=

pkg/archive/archive.go

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"io"
1010
"io/ioutil"
1111
"os"
12-
"os/exec"
1312
"path/filepath"
1413
"runtime"
1514
"strings"
@@ -18,14 +17,14 @@ import (
1817

1918
"github.com/containers/storage/pkg/fileutils"
2019
"github.com/containers/storage/pkg/idtools"
21-
"github.com/containers/storage/pkg/ioutils"
2220
"github.com/containers/storage/pkg/pools"
2321
"github.com/containers/storage/pkg/promise"
2422
"github.com/containers/storage/pkg/system"
2523
gzip "github.com/klauspost/pgzip"
2624
rsystem "github.com/opencontainers/runc/libcontainer/system"
2725
"github.com/pkg/errors"
2826
"github.com/sirupsen/logrus"
27+
"github.com/ulikunitz/xz"
2928
)
3029

3130
type (
@@ -173,12 +172,6 @@ func DetectCompression(source []byte) Compression {
173172
return Uncompressed
174173
}
175174

176-
func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) {
177-
args := []string{"xz", "-d", "-c", "-q"}
178-
179-
return cmdStream(exec.Command(args[0], args[1:]...), archive)
180-
}
181-
182175
// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
183176
func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
184177
p := pools.BufioReader32KPool
@@ -211,15 +204,12 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
211204
readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader)
212205
return readBufWrapper, nil
213206
case Xz:
214-
xzReader, chdone, err := xzDecompress(buf)
207+
xzReader, err := xz.NewReader(buf)
215208
if err != nil {
216209
return nil, err
217210
}
218211
readBufWrapper := p.NewReadCloserWrapper(buf, xzReader)
219-
return ioutils.NewReadCloserWrapper(readBufWrapper, func() error {
220-
<-chdone
221-
return readBufWrapper.Close()
222-
}), nil
212+
return readBufWrapper, nil
223213
case Zstd:
224214
return zstdReader(buf)
225215
default:
@@ -1319,35 +1309,6 @@ func remapIDs(readIDMappings, writeIDMappings *idtools.IDMappings, chownOpts *id
13191309
return nil
13201310
}
13211311

1322-
// cmdStream executes a command, and returns its stdout as a stream.
1323-
// If the command fails to run or doesn't complete successfully, an error
1324-
// will be returned, including anything written on stderr.
1325-
func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) {
1326-
chdone := make(chan struct{})
1327-
cmd.Stdin = input
1328-
pipeR, pipeW := io.Pipe()
1329-
cmd.Stdout = pipeW
1330-
var errBuf bytes.Buffer
1331-
cmd.Stderr = &errBuf
1332-
1333-
// Run the command and return the pipe
1334-
if err := cmd.Start(); err != nil {
1335-
return nil, nil, err
1336-
}
1337-
1338-
// Copy stdout to the returned pipe
1339-
go func() {
1340-
if err := cmd.Wait(); err != nil {
1341-
pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String()))
1342-
} else {
1343-
pipeW.Close()
1344-
}
1345-
close(chdone)
1346-
}()
1347-
1348-
return pipeR, chdone, nil
1349-
}
1350-
13511312
// NewTempArchive reads the content of src into a temporary file, and returns the contents
13521313
// of that file as an archive. The archive can only be read once - as soon as reading completes,
13531314
// the file will be deleted.

pkg/archive/archive_test.go

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"runtime"
1313
"strings"
1414
"testing"
15-
"time"
1615

1716
"github.com/containers/storage/pkg/idtools"
1817
"github.com/stretchr/testify/assert"
@@ -209,59 +208,6 @@ func TestExtensionXz(t *testing.T) {
209208
}
210209
}
211210

212-
func TestCmdStreamLargeStderr(t *testing.T) {
213-
cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello")
214-
out, _, err := cmdStream(cmd, nil)
215-
if err != nil {
216-
t.Fatalf("Failed to start command: %s", err)
217-
}
218-
errCh := make(chan error)
219-
go func() {
220-
_, err := io.Copy(ioutil.Discard, out)
221-
errCh <- err
222-
}()
223-
select {
224-
case err := <-errCh:
225-
if err != nil {
226-
t.Fatalf("Command should not have failed (err=%.100s...)", err)
227-
}
228-
case <-time.After(5 * time.Second):
229-
t.Fatalf("Command did not complete in 5 seconds; probable deadlock")
230-
}
231-
}
232-
233-
func TestCmdStreamBad(t *testing.T) {
234-
// TODO Windows: Figure out why this is failing in CI but not locally
235-
if runtime.GOOS == windows {
236-
t.Skip("Failing on Windows CI machines")
237-
}
238-
badCmd := exec.Command("sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1")
239-
out, _, err := cmdStream(badCmd, nil)
240-
if err != nil {
241-
t.Fatalf("Failed to start command: %s", err)
242-
}
243-
if output, err := ioutil.ReadAll(out); err == nil {
244-
t.Fatalf("Command should have failed")
245-
} else if err.Error() != "exit status 1: error couldn't reverse the phase pulser\n" {
246-
t.Fatalf("Wrong error value (%s)", err)
247-
} else if s := string(output); s != "hello\n" {
248-
t.Fatalf("Command output should be '%s', not '%s'", "hello\\n", output)
249-
}
250-
}
251-
252-
func TestCmdStreamGood(t *testing.T) {
253-
cmd := exec.Command("sh", "-c", "echo hello; exit 0")
254-
out, _, err := cmdStream(cmd, nil)
255-
if err != nil {
256-
t.Fatal(err)
257-
}
258-
if output, err := ioutil.ReadAll(out); err != nil {
259-
t.Fatalf("Command should not have failed (err=%s)", err)
260-
} else if s := string(output); s != "hello\n" {
261-
t.Fatalf("Command output should be '%s', not '%s'", "hello\\n", output)
262-
}
263-
}
264-
265211
func TestUntarPathWithInvalidDest(t *testing.T) {
266212
tempFolder, err := ioutil.TempDir("", "storage-archive-test")
267213
require.NoError(t, err)

tests/apply-junk.bats

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bats
2+
3+
load helpers
4+
5+
@test "applyjunk" {
6+
# Create and try to populate layers with... garbage. It should be
7+
# rejected cleanly.
8+
for compressed in cat gzip bzip2 xz zstd ; do
9+
storage create-layer --id layer-${compressed}
10+
11+
echo [[${compressed} /etc/os-release]]
12+
${compressed} < /etc/os-release > junkfile
13+
run storage apply-diff --file junkfile layer-${compressed}
14+
echo "$output"
15+
[[ "$status" -ne 0 ]]
16+
[[ "$output" =~ "invalid tar header" ]] || [[ "$output" =~ "unexpected EOF" ]]
17+
18+
echo [[${compressed}]]
19+
echo "sorry, not even enough info for a tar header here" | ${compressed} > junkfile
20+
run storage apply-diff --file junkfile layer-${compressed}
21+
echo "$output"
22+
[[ "$status" -ne 0 ]]
23+
[[ "$output" =~ "unexpected EOF" ]]
24+
done
25+
}

vendor/github.com/ulikunitz/xz/.gitignore

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/ulikunitz/xz/LICENSE

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/ulikunitz/xz/README.md

Lines changed: 73 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/ulikunitz/xz/SECURITY.md

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)