@@ -37,6 +37,7 @@ import (
37
37
"sync"
38
38
39
39
"github.com/containerd/stargz-snapshotter/estargz/errorutil"
40
+ "github.com/klauspost/compress/zstd"
40
41
digest "github.com/opencontainers/go-digest"
41
42
"github.com/pkg/errors"
42
43
"golang.org/x/sync/errgroup"
@@ -112,11 +113,11 @@ func (b *Blob) TOCDigest() digest.Digest {
112
113
return b .tocDigest
113
114
}
114
115
115
- // Build builds an eStargz blob which is an extended version of stargz, from tar blob passed
116
- // through the argument. If there are some prioritized files are listed in the option, these
117
- // files are grouped as "prioritized" and can be used for runtime optimization (e.g. prefetch).
118
- // This function builds a blob in parallel, with dividing that blob into several (at least the
119
- // number of runtime.GOMAXPROCS(0)) sub-blobs.
116
+ // Build builds an eStargz blob which is an extended version of stargz, from a blob (gzip, zstd
117
+ // or plain tar) passed through the argument. If there are some prioritized files are listed in
118
+ // the option, these files are grouped as "prioritized" and can be used for runtime optimization
119
+ // (e.g. prefetch). This function builds a blob in parallel, with dividing that blob into several
120
+ // (at least the number of runtime.GOMAXPROCS(0)) sub-blobs.
120
121
func Build (tarBlob * io.SectionReader , opt ... Option ) (_ * Blob , rErr error ) {
121
122
var opts options
122
123
opts .compressionLevel = gzip .BestCompression // BestCompression by default
@@ -133,6 +134,10 @@ func Build(tarBlob *io.SectionReader, opt ...Option) (_ *Blob, rErr error) {
133
134
}
134
135
}
135
136
}()
137
+ tarBlob , err := decompressBlob (tarBlob , layerFiles )
138
+ if err != nil {
139
+ return nil , err
140
+ }
136
141
entries , err := sortEntries (tarBlob , opts .prioritizedFiles , opts .missedPrioritizedFiles )
137
142
if err != nil {
138
143
return nil , err
@@ -593,3 +598,42 @@ func (cr *countReader) currentPos() int64 {
593
598
594
599
return * cr .cPos
595
600
}
601
+
602
+ func decompressBlob (org * io.SectionReader , tmp * tempFiles ) (* io.SectionReader , error ) {
603
+ if org .Size () < 4 {
604
+ return org , nil
605
+ }
606
+ src := make ([]byte , 4 )
607
+ if _ , err := org .Read (src ); err != nil && err != io .EOF {
608
+ return nil , err
609
+ }
610
+ var dR io.Reader
611
+ if bytes .Equal ([]byte {0x1F , 0x8B , 0x08 }, src [:3 ]) {
612
+ // gzip
613
+ dgR , err := gzip .NewReader (io .NewSectionReader (org , 0 , org .Size ()))
614
+ if err != nil {
615
+ return nil , err
616
+ }
617
+ defer dgR .Close ()
618
+ dR = io .Reader (dgR )
619
+ } else if bytes .Equal ([]byte {0x28 , 0xb5 , 0x2f , 0xfd }, src [:4 ]) {
620
+ // zstd
621
+ dzR , err := zstd .NewReader (io .NewSectionReader (org , 0 , org .Size ()))
622
+ if err != nil {
623
+ return nil , err
624
+ }
625
+ defer dzR .Close ()
626
+ dR = io .Reader (dzR )
627
+ } else {
628
+ // uncompressed
629
+ return io .NewSectionReader (org , 0 , org .Size ()), nil
630
+ }
631
+ b , err := tmp .TempFile ("" , "uncompresseddata" )
632
+ if err != nil {
633
+ return nil , err
634
+ }
635
+ if _ , err := io .Copy (b , dR ); err != nil {
636
+ return nil , err
637
+ }
638
+ return fileSectionReader (b )
639
+ }
0 commit comments