mirror of
https://github.com/containers/skopeo.git
synced 2025-09-22 02:18:41 +00:00
Update non-module dependencies
Dependabot was apparently not picking these up (and several haven't had a release for a long time anyway). Also move from github.com/go-check/check to its newly declared (and go.mod-enforced) name gopkg.in/check.v1. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
12
vendor/github.com/opencontainers/image-spec/schema/config-schema.json
generated
vendored
12
vendor/github.com/opencontainers/image-spec/schema/config-schema.json
generated
vendored
@@ -14,9 +14,21 @@
|
||||
"architecture": {
|
||||
"type": "string"
|
||||
},
|
||||
"variant": {
|
||||
"type": "string"
|
||||
},
|
||||
"os": {
|
||||
"type": "string"
|
||||
},
|
||||
"os.version": {
|
||||
"type": "string"
|
||||
},
|
||||
"os.features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
19
vendor/github.com/opencontainers/image-spec/schema/error.go
generated
vendored
19
vendor/github.com/opencontainers/image-spec/schema/error.go
generated
vendored
@@ -15,10 +15,9 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"go4.org/errorutil"
|
||||
)
|
||||
|
||||
// A SyntaxError is a description of a JSON syntax error
|
||||
@@ -36,7 +35,21 @@ func (e *SyntaxError) Error() string { return e.msg }
|
||||
// If the given error is not a *json.SyntaxError it is returned unchanged.
|
||||
func WrapSyntaxError(r io.Reader, err error) error {
|
||||
if serr, ok := err.(*json.SyntaxError); ok {
|
||||
line, col, _ := errorutil.HighlightBytePosition(r, serr.Offset)
|
||||
buf := bufio.NewReader(r)
|
||||
line := 0
|
||||
col := 0
|
||||
for i := int64(0); i < serr.Offset; i++ {
|
||||
b, berr := buf.ReadByte()
|
||||
if berr != nil {
|
||||
break
|
||||
}
|
||||
if b == '\n' {
|
||||
line++
|
||||
col = 1
|
||||
} else {
|
||||
col++
|
||||
}
|
||||
}
|
||||
return &SyntaxError{serr.Error(), line, col, serr.Offset}
|
||||
}
|
||||
|
||||
|
80
vendor/github.com/opencontainers/image-spec/schema/fs.go
generated
vendored
80
vendor/github.com/opencontainers/image-spec/schema/fs.go
generated
vendored
@@ -20,6 +20,8 @@ import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -114,7 +116,24 @@ func (f *_escFile) Close() error {
|
||||
}
|
||||
|
||||
func (f *_escFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
return nil, nil
|
||||
if !f.isDir {
|
||||
return nil, fmt.Errorf(" escFile.Readdir: '%s' is not directory", f.name)
|
||||
}
|
||||
|
||||
fis, ok := _escDirs[f.local]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(" escFile.Readdir: '%s' is directory, but we have no info about content of this dir, local=%s", f.name, f.local)
|
||||
}
|
||||
limit := count
|
||||
if count <= 0 || limit > len(fis) {
|
||||
limit = len(fis)
|
||||
}
|
||||
|
||||
if len(fis) == 0 && count > 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
return fis[0:limit], nil
|
||||
}
|
||||
|
||||
func (f *_escFile) Stat() (os.FileInfo, error) {
|
||||
@@ -205,27 +224,29 @@ func _escFSMustString(useLocal bool, name string) string {
|
||||
var _escData = map[string]*_escFile{
|
||||
|
||||
"/config-schema.json": {
|
||||
name: "config-schema.json",
|
||||
local: "config-schema.json",
|
||||
size: 2771,
|
||||
modtime: 1515512099,
|
||||
size: 2969,
|
||||
modtime: 1625865937,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/+RWQY/TPBC951dE2T22m+/wnXot3JCKVAGHFarcZNLOEnvMeIKIUP87itNCkjpp6apc
|
||||
OEUaz7z35nns+EcUx0kOLmO0gmSSRZysLJglGVFogOMlmQJ38dpChgVmymfNmrJHl+1Bq6ZkL2IXafri
|
||||
yMzb6BPxLs1ZFTL/7/+0jT20dZifStwiTcmCyU5szpe12SlqtYM08/xtpdQWmlravkAmbcwyWWBBcMki
|
||||
btqJ4yRjUAL5r0Cn1AmjaeF8vCDWSpqVXAnMBTUkfu3QpiSqkj3xBFQ/m7M9CmRSMVxbQ+7azKMXgeyO
|
||||
Iz4ecMXHPzjgXmSEscPqc95+t+Qgf08sblj/yFB4A6FwT80IPKQ5FGiwGRWXamXXHnnVagzjm29jshSz
|
||||
qpNZdwkF9FDGRCNxfBghFa4toZEhNxlYNT099wj6dJMSJ2RekNqXO5A8qcJUZdlH6uJ8Dlqw1Pk/2/tH
|
||||
KisN7sb+b536e3f1ifgLmt0bvOmcv1NbKO9tyTqw8fe0ZC1k17gzqrzakqj7PV2/TCSFe831m2NRbDB3
|
||||
f/+uO+ZPdd+jBVPpsx1PSlUDuyTseDRgTRi+Vsj+P/wc8GCoLuoinjzfoxPiOmR636yAUWPbM75BwbfD
|
||||
Zbem3hGB8T5/U1ze1FlA42ZbvwKDtIazP98fAIC2Um/8RIyDbIlKUGZkPvunLDoynM9N/1n1+9nUP5dR
|
||||
MzuH6GcAAAD//0pj2wvTCgAA
|
||||
H4sIAAAAAAAC/+RWsW7bQAzd9RWCkjGJOnTymnYrkAJG2yEojLNE2Ux1xyuPMioU/vdCJzvx2SfZteEu
|
||||
XSnyvcdHSuLvJE2zElzBaAXJZJM0e7JgHsmIQgOcPpKpcJFOLRRYYaF81l1XduuKJWjVlSxF7CTPXxyZ
|
||||
+z76QLzIS1aV3L97n/exm74Oy22Jm+Q5WTDFls35sj47R60WkBeev6+U1kJXS/MXKKSPWSYLLAgum6Rd
|
||||
O2maFQxKoHwN7JQ6YTQ9nI9XxFpJ96RUAveCGjL/bN2nZKqRJfEIVJjNxRIFCmkYTq1ZKUZl5NR0cqdn
|
||||
PqyAXT/WUysqUJ34KIliVu2bdyigd/MGwNN0HZBsJhrB35mrj0dm6+NfHHAQGWR+ZfU5H39ZclB+Jha3
|
||||
X3/LUPk1gMo9dIt8k5dQocFu4V2ulZ165KdeYxzfrIZkhdYN2DfayNbGQ1Lh1hIGG9RP08BT19NzQBDS
|
||||
jUockXlEaih3T/KoCtPUdYi0i/M9asGjLv/b3r9S3WhwZ/Z/7tZfu6tvxD/QLD7gWe/5JzWH+tqWTCOD
|
||||
v6YlUyE7xYVR9cmWRD+/TCSVu+TzW2JVzbB0//5bt8kf6z6gBdPog4lntWqBXRZ3PNljzRh+Nsj+mniO
|
||||
eLCvLtlF3Hq+RCfE7WX/1L3xDA8oegEdd2vsGoqs9+FldHyodxGNs3l7AQZpDQd/vr8AAG2lnfmNGAaZ
|
||||
E9WgzMB+hm9ZsmE43JvwOHy75sL3Mul2Z538CQAA//9C38scmQsAAA==
|
||||
`,
|
||||
},
|
||||
|
||||
"/content-descriptor.json": {
|
||||
name: "content-descriptor.json",
|
||||
local: "content-descriptor.json",
|
||||
size: 1079,
|
||||
modtime: 1537191585,
|
||||
modtime: 1625865919,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/5yTsW7cMAyGdz8F4QTIkos6BB2MIEu7d2i3ooNOok5Mz5JK8RBci7x7QcvX2G2RILfZ
|
||||
xP+Rn2zqVwfQe6yOqQjl1A/QfyqYPuQklhIy6BMmgY9zKDN8LugokLMTca0tLquLOFrFo0gZjHmoOW1a
|
||||
@@ -238,9 +259,10 @@ dIbaEm+G3WzZM/44EKMqff37riz3dL0uHcC37qn7HQAA//9DKIMKNwQAAA==
|
||||
},
|
||||
|
||||
"/defs-descriptor.json": {
|
||||
name: "defs-descriptor.json",
|
||||
local: "defs-descriptor.json",
|
||||
size: 844,
|
||||
modtime: 1537191664,
|
||||
modtime: 1625865919,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/5SST2/TTBDG7/kU826jt0DiOHBAqlWKKnrnUE6t0mi6O7aneP9od6IqVPnuaG03SYtA
|
||||
cLC1+2jmefwbz9MEQBlKOnIQ9k5VoK6oZsf5liBgFNabDiOIh6+B3BfvBNlRhKuxzUe4DqS5Zo29x3ww
|
||||
@@ -254,9 +276,10 @@ TAMAAA==
|
||||
},
|
||||
|
||||
"/defs.json": {
|
||||
name: "defs.json",
|
||||
local: "defs.json",
|
||||
size: 1670,
|
||||
modtime: 1515512099,
|
||||
modtime: 1625865903,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/7STza6bMBCF9zzFyO2S9oJtbGDb7hMpy6oLSiaJq2AjY6RWEe9e8RNChFuJKneRgGc8
|
||||
3zmeMbcAgByxKa2qnTKa5EC+4klp1a8aaBs8grtY054vpnXgLgi7GvUXo12hNFo41FiqkyqLoTwceTOA
|
||||
@@ -269,9 +292,10 @@ fIvD7in0ryMEy+fK1G6UfmdTE+tvpoL+1wV/AgAA//96IpqyhgYAAA==
|
||||
},
|
||||
|
||||
"/image-index-schema.json": {
|
||||
name: "image-index-schema.json",
|
||||
local: "image-index-schema.json",
|
||||
size: 2993,
|
||||
modtime: 1515512099,
|
||||
modtime: 1625865919,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/6yWz0/jOhDH7/0rRgGJC5CnJ/QOFeLy9sJpD4v2suJg7EkybGNnx1Ogu+r/vrJN2qRJ
|
||||
C4Te2rHnO5/vxL/+zAAyg14zNULOZnPIvjZo/3dWFFlkuK1ViXBrDb7AtwY1FaRVnHoeck+9rrBWIa8S
|
||||
@@ -289,9 +313,10 @@ VmZjL8HOE24GcD9bz/4GAAD//yCnv52xCwAA
|
||||
},
|
||||
|
||||
"/image-layout-schema.json": {
|
||||
name: "image-layout-schema.json",
|
||||
local: "image-layout-schema.json",
|
||||
size: 439,
|
||||
modtime: 1515512099,
|
||||
modtime: 1625865903,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/2yPQUvEMBCF7/0VQ/Sg4DYVPOW6pwVhD4IX8VDTaTvLNonJVFik/12SaRXRU5g38+W9
|
||||
91kBqA6TjRSYvFMG1DGg23vHLTmMcJjaAeGxvfiZ4cmOOLXqLlPXSQYDamQORutT8m4nau3joLvY9rxr
|
||||
@@ -302,9 +327,10 @@ HrRoV8JRtyHJaO0DOruZpYLJtaZsrM/FWEi+BMysfzuhXbUQfcDIhEkZyG2yQyYl8TPGJLVk97fth1yA
|
||||
},
|
||||
|
||||
"/image-manifest-schema.json": {
|
||||
name: "image-manifest-schema.json",
|
||||
local: "image-manifest-schema.json",
|
||||
size: 921,
|
||||
modtime: 1515512099,
|
||||
modtime: 1625865903,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/5ySMW8iMRCF+/0VI0MJ+O501bZXUZxSJEoTpXB2x7uDWNsZmygo4r9HtnHAkCKifTvv
|
||||
zTdv/dEAiB59x+QCWSNaEHcOzT9rgiKDDOtJDQj/lSGNPsC9w440dSpNL6J97rsRJxWtYwiulXLjrVlm
|
||||
@@ -317,7 +343,21 @@ Dj+ZAwAA
|
||||
},
|
||||
|
||||
"/": {
|
||||
name: "/",
|
||||
local: `.`,
|
||||
isDir: true,
|
||||
local: "",
|
||||
},
|
||||
}
|
||||
|
||||
var _escDirs = map[string][]os.FileInfo{
|
||||
|
||||
".": {
|
||||
_escData["/config-schema.json"],
|
||||
_escData["/content-descriptor.json"],
|
||||
_escData["/defs-descriptor.json"],
|
||||
_escData["/defs.json"],
|
||||
_escData["/image-index-schema.json"],
|
||||
_escData["/image-layout-schema.json"],
|
||||
_escData["/image-manifest-schema.json"],
|
||||
},
|
||||
}
|
||||
|
31
vendor/github.com/opencontainers/image-spec/schema/validator.go
generated
vendored
31
vendor/github.com/opencontainers/image-spec/schema/validator.go
generated
vendored
@@ -23,7 +23,7 @@ import (
|
||||
"regexp"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
)
|
||||
@@ -168,6 +168,7 @@ func validateIndex(r io.Reader) error {
|
||||
}
|
||||
if manifest.Platform != nil {
|
||||
checkPlatform(manifest.Platform.OS, manifest.Platform.Architecture)
|
||||
checkArchitecture(manifest.Platform.Architecture, manifest.Platform.Variant)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -189,6 +190,7 @@ func validateConfig(r io.Reader) error {
|
||||
}
|
||||
|
||||
checkPlatform(header.OS, header.Architecture)
|
||||
checkArchitecture(header.Architecture, header.Variant)
|
||||
|
||||
envRegexp := regexp.MustCompile(`^[^=]+=.*$`)
|
||||
for _, e := range header.Config.Env {
|
||||
@@ -200,6 +202,31 @@ func validateConfig(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkArchitecture(Architecture string, Variant string) {
|
||||
validCombins := map[string][]string{
|
||||
"arm": {"", "v6", "v7", "v8"},
|
||||
"arm64": {"", "v8"},
|
||||
"386": {""},
|
||||
"amd64": {""},
|
||||
"ppc64": {""},
|
||||
"ppc64le": {""},
|
||||
"mips64": {""},
|
||||
"mips64le": {""},
|
||||
"s390x": {""},
|
||||
}
|
||||
for arch, variants := range validCombins {
|
||||
if arch == Architecture {
|
||||
for _, variant := range variants {
|
||||
if variant == Variant {
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Printf("warning: combination of architecture %q and variant %q is not valid.\n", Architecture, Variant)
|
||||
}
|
||||
}
|
||||
fmt.Printf("warning: architecture %q is not supported yet.\n", Architecture)
|
||||
}
|
||||
|
||||
func checkPlatform(OS string, Architecture string) {
|
||||
validCombins := map[string][]string{
|
||||
"android": {"arm"},
|
||||
@@ -219,7 +246,7 @@ func checkPlatform(OS string, Architecture string) {
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Printf("warning: combination of %q and %q is invalid.\n", OS, Architecture)
|
||||
fmt.Printf("warning: combination of os %q and architecture %q is invalid.\n", OS, Architecture)
|
||||
}
|
||||
}
|
||||
fmt.Printf("warning: operating system %q of the bundle is not supported yet.\n", OS)
|
||||
|
6
vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go
generated
vendored
6
vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go
generated
vendored
@@ -53,4 +53,10 @@ const (
|
||||
|
||||
// AnnotationDescription is the annotation key for the human-readable description of the software packaged in the image.
|
||||
AnnotationDescription = "org.opencontainers.image.description"
|
||||
|
||||
// AnnotationBaseImageDigest is the annotation key for the digest of the image's base image.
|
||||
AnnotationBaseImageDigest = "org.opencontainers.image.base.digest"
|
||||
|
||||
// AnnotationBaseImageName is the annotation key for the image reference of the image's base image.
|
||||
AnnotationBaseImageName = "org.opencontainers.image.base.name"
|
||||
)
|
||||
|
11
vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go
generated
vendored
11
vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go
generated
vendored
@@ -89,9 +89,20 @@ type Image struct {
|
||||
// Architecture is the CPU architecture which the binaries in this image are built to run on.
|
||||
Architecture string `json:"architecture"`
|
||||
|
||||
// Variant is the variant of the specified CPU architecture which image binaries are intended to run on.
|
||||
Variant string `json:"variant,omitempty"`
|
||||
|
||||
// OS is the name of the operating system which the image is built to run on.
|
||||
OS string `json:"os"`
|
||||
|
||||
// OSVersion is an optional field specifying the operating system
|
||||
// version, for example on Windows `10.0.14393.1066`.
|
||||
OSVersion string `json:"os.version,omitempty"`
|
||||
|
||||
// OSFeatures is an optional field specifying an array of strings,
|
||||
// each listing a required OS feature (for example on Windows `win32k`).
|
||||
OSFeatures []string `json:"os.features,omitempty"`
|
||||
|
||||
// Config defines the execution parameters which should be used as a base when running a container using the image.
|
||||
Config ImageConfig `json:"config,omitempty"`
|
||||
|
||||
|
47
vendor/github.com/opencontainers/image-tools/image/autodetect.go
generated
vendored
47
vendor/github.com/opencontainers/image-tools/image/autodetect.go
generated
vendored
@@ -15,13 +15,11 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/opencontainers/image-spec/schema"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -47,7 +45,7 @@ func Autodetect(path string) (string, error) {
|
||||
return TypeImageLayout, nil
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
f, err := os.Open(path) // nolint: errcheck, gosec
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "unable to open file") // os.Open includes the filename
|
||||
}
|
||||
@@ -65,48 +63,7 @@ func Autodetect(path string) (string, error) {
|
||||
return TypeImage, nil
|
||||
case "application/zip":
|
||||
return TypeImageZip, nil
|
||||
|
||||
case "text/plain; charset=utf-8":
|
||||
// might be a JSON file, will be handled below
|
||||
|
||||
default:
|
||||
return "", errors.New("unknown file type")
|
||||
}
|
||||
|
||||
if _, err := f.Seek(0, io.SeekStart); err != nil {
|
||||
return "", errors.Wrap(err, "unable to seek")
|
||||
}
|
||||
|
||||
header := struct {
|
||||
SchemaVersion int `json:"schemaVersion"`
|
||||
MediaType string `json:"mediaType"`
|
||||
Config interface{} `json:"config"`
|
||||
}{}
|
||||
|
||||
if err := json.NewDecoder(f).Decode(&header); err != nil {
|
||||
if _, errSeek := f.Seek(0, io.SeekStart); errSeek != nil {
|
||||
return "", errors.Wrap(err, "unable to seek")
|
||||
}
|
||||
|
||||
e := errors.Wrap(
|
||||
schema.WrapSyntaxError(f, err),
|
||||
"unable to parse JSON",
|
||||
)
|
||||
|
||||
return "", e
|
||||
}
|
||||
|
||||
switch {
|
||||
case header.MediaType == string(schema.ValidatorMediaTypeManifest):
|
||||
return TypeManifest, nil
|
||||
|
||||
case header.MediaType == string(schema.ValidatorMediaTypeImageIndex):
|
||||
return TypeImageIndex, nil
|
||||
|
||||
case header.MediaType == "" && header.SchemaVersion == 0 && header.Config != nil:
|
||||
// config files don't have mediaType/schemaVersion header
|
||||
return TypeConfig, nil
|
||||
}
|
||||
|
||||
return "", errors.New("unknown media type")
|
||||
return "", errors.New("unknown file type")
|
||||
}
|
||||
|
14
vendor/github.com/opencontainers/image-tools/image/config.go
generated
vendored
14
vendor/github.com/opencontainers/image-tools/image/config.go
generated
vendored
@@ -20,7 +20,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -31,16 +30,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type config v1.Image
|
||||
|
||||
func findConfig(w walker, d *v1.Descriptor) (*config, error) {
|
||||
var c config
|
||||
func findConfig(w walker, d *v1.Descriptor) (*v1.Image, error) {
|
||||
var c v1.Image
|
||||
cpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex())
|
||||
|
||||
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
|
||||
if info.IsDir() || filepath.Clean(path) != cpath {
|
||||
return nil
|
||||
}
|
||||
switch err := w.find(cpath, func(path string, r io.Reader) error {
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "%s: error reading config", path)
|
||||
@@ -65,7 +59,7 @@ func findConfig(w walker, d *v1.Descriptor) (*config, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) {
|
||||
func runtimeSpec(c *v1.Image, rootfs string) (*specs.Spec, error) {
|
||||
if c.OS != "linux" {
|
||||
return nil, fmt.Errorf("%s: unsupported OS", c.OS)
|
||||
}
|
||||
|
91
vendor/github.com/opencontainers/image-tools/image/descriptor.go
generated
vendored
91
vendor/github.com/opencontainers/image-tools/image/descriptor.go
generated
vendored
@@ -20,6 +20,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@@ -27,8 +28,8 @@ import (
|
||||
|
||||
const indexPath = "index.json"
|
||||
|
||||
func listReferences(w walker) (map[string]*v1.Descriptor, error) {
|
||||
refs := make(map[string]*v1.Descriptor)
|
||||
func listReferences(w walker) ([]v1.Descriptor, error) {
|
||||
var descs []v1.Descriptor
|
||||
var index v1.Index
|
||||
|
||||
if err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
|
||||
@@ -39,10 +40,54 @@ func listReferences(w walker) (map[string]*v1.Descriptor, error) {
|
||||
if err := json.NewDecoder(r).Decode(&index); err != nil {
|
||||
return err
|
||||
}
|
||||
descs = index.Manifests
|
||||
|
||||
for i := 0; i < len(index.Manifests); i++ {
|
||||
if index.Manifests[i].Annotations[v1.AnnotationRefName] != "" {
|
||||
refs[index.Manifests[i].Annotations[v1.AnnotationRefName]] = &index.Manifests[i]
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return descs, nil
|
||||
}
|
||||
|
||||
func findDescriptor(w walker, names []string) ([]v1.Descriptor, error) {
|
||||
var descs []v1.Descriptor
|
||||
var index v1.Index
|
||||
dpath := "index.json"
|
||||
|
||||
if err := w.find(dpath, func(path string, r io.Reader) error {
|
||||
if err := json.NewDecoder(r).Decode(&index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
descs = index.Manifests
|
||||
for _, name := range names {
|
||||
argsParts := strings.Split(name, "=")
|
||||
if len(argsParts) != 2 {
|
||||
return fmt.Errorf("each ref must contain two parts")
|
||||
}
|
||||
|
||||
switch argsParts[0] {
|
||||
case "name":
|
||||
for i := 0; i < len(descs); i++ {
|
||||
if descs[i].Annotations[v1.AnnotationRefName] != argsParts[1] {
|
||||
descs = append(descs[:i], descs[i+1:]...)
|
||||
}
|
||||
}
|
||||
case "platform.os":
|
||||
for i := 0; i < len(descs); i++ {
|
||||
if descs[i].Platform != nil && index.Manifests[i].Platform.OS != argsParts[1] {
|
||||
descs = append(descs[:i], descs[i+1:]...)
|
||||
}
|
||||
}
|
||||
case "digest":
|
||||
for i := 0; i < len(descs); i++ {
|
||||
if string(descs[i].Digest) != argsParts[1] {
|
||||
descs = append(descs[:i], descs[i+1:]...)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("criteria %q unimplemented", argsParts[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,38 +95,14 @@ func listReferences(w walker) (map[string]*v1.Descriptor, error) {
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
func findDescriptor(w walker, name string) (*v1.Descriptor, error) {
|
||||
var d v1.Descriptor
|
||||
var index v1.Index
|
||||
|
||||
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
|
||||
if info.IsDir() || filepath.Clean(path) != indexPath {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r).Decode(&index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(index.Manifests); i++ {
|
||||
if index.Manifests[i].Annotations[v1.AnnotationRefName] == name {
|
||||
d = index.Manifests[i]
|
||||
return errEOW
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err {
|
||||
case nil:
|
||||
return nil, fmt.Errorf("index.json: descriptor %q not found", name)
|
||||
case errEOW:
|
||||
return &d, nil
|
||||
default:
|
||||
return nil, err
|
||||
if len(descs) == 0 {
|
||||
return nil, fmt.Errorf("index.json: descriptor retrieved by refs %v is not match", names)
|
||||
} else if len(descs) > 1 {
|
||||
return nil, fmt.Errorf("index.json: descriptor retrieved by refs %v is not unique", names)
|
||||
}
|
||||
|
||||
return descs, nil
|
||||
}
|
||||
|
||||
func validateDescriptor(d *v1.Descriptor, w walker, mts []string) error {
|
||||
|
2
vendor/github.com/opencontainers/image-tools/image/doc.go
generated
vendored
2
vendor/github.com/opencontainers/image-tools/image/doc.go
generated
vendored
@@ -12,5 +12,5 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package image defines methods for validating, and unpacking OCI images.
|
||||
// Package image defines methods for validating, unpacking OCI images and creating OCI runtime bundle.
|
||||
package image
|
||||
|
125
vendor/github.com/opencontainers/image-tools/image/image.go
generated
vendored
125
vendor/github.com/opencontainers/image-tools/image/image.go
generated
vendored
@@ -41,7 +41,7 @@ func ValidateZip(src string, refs []string, out *log.Logger) error {
|
||||
|
||||
// ValidateFile opens the tar file given by the filename, then calls ValidateReader
|
||||
func ValidateFile(tarFile string, refs []string, out *log.Logger) error {
|
||||
f, err := os.Open(tarFile)
|
||||
f, err := os.Open(tarFile) // nolint: errcheck, gosec
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to open file")
|
||||
}
|
||||
@@ -65,36 +65,35 @@ var validRefMediaTypes = []string{
|
||||
}
|
||||
|
||||
func validate(w walker, refs []string, out *log.Logger) error {
|
||||
if err := layoutValidate(w); err != nil {
|
||||
return err
|
||||
}
|
||||
var descs []v1.Descriptor
|
||||
var err error
|
||||
|
||||
ds, err := listReferences(w)
|
||||
if err != nil {
|
||||
if err = layoutValidate(w); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(refs) == 0 && len(ds) == 0 {
|
||||
// TODO(runcom): ugly, we'll need a better way and library
|
||||
// to express log levels.
|
||||
// see https://github.com/opencontainers/image-spec/issues/288
|
||||
out.Print("WARNING: no descriptors found")
|
||||
}
|
||||
|
||||
if len(refs) == 0 {
|
||||
for ref := range ds {
|
||||
refs = append(refs, ref)
|
||||
out.Print("No ref specified, verify all refs")
|
||||
descs, err = listReferences(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(descs) == 0 {
|
||||
// TODO(runcom): ugly, we'll need a better way and library
|
||||
// to express log levels.
|
||||
// see https://github.com/opencontainers/image-spec/issues/288
|
||||
out.Print("WARNING: no descriptors found")
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
descs, err = findDescriptor(w, refs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, ref := range refs {
|
||||
d, ok := ds[ref]
|
||||
if !ok {
|
||||
// TODO(runcom):
|
||||
// soften this error to a warning if the user didn't ask for any specific reference
|
||||
// with --ref but she's just validating the whole image.
|
||||
return fmt.Errorf("reference %s not found", ref)
|
||||
}
|
||||
|
||||
for _, desc := range descs {
|
||||
d := &desc
|
||||
if err = validateDescriptor(d, w, validRefMediaTypes); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -105,7 +104,7 @@ func validate(w walker, refs []string, out *log.Logger) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.validate(w); err != nil {
|
||||
if err := validateManifest(m, w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -131,15 +130,15 @@ func validate(w walker, refs []string, out *log.Logger) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.validate(w); err != nil {
|
||||
if err := validateManifest(m, w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if out != nil {
|
||||
out.Printf("reference %q: OK", ref)
|
||||
}
|
||||
if out != nil && len(refs) > 0 {
|
||||
out.Printf("reference %v: OK", refs)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -148,46 +147,47 @@ func validate(w walker, refs []string, out *log.Logger) error {
|
||||
// UnpackLayout walks through the file tree given by src and, using the layers
|
||||
// specified in the manifest pointed to by the given ref, unpacks all layers in
|
||||
// the given destination directory or returns an error if the unpacking failed.
|
||||
func UnpackLayout(src, dest, ref, platform string) error {
|
||||
return unpack(newPathWalker(src), dest, ref, platform)
|
||||
func UnpackLayout(src, dest, platform string, refs []string) error {
|
||||
return unpack(newPathWalker(src), dest, platform, refs)
|
||||
}
|
||||
|
||||
// UnpackZip opens and walks through the zip file given by src and, using the layers
|
||||
// specified in the manifest pointed to by the given ref, unpacks all layers in
|
||||
// the given destination directory or returns an error if the unpacking failed.
|
||||
func UnpackZip(src, dest, ref, platform string) error {
|
||||
return unpack(newZipWalker(src), dest, ref, platform)
|
||||
func UnpackZip(src, dest, platform string, refs []string) error {
|
||||
return unpack(newZipWalker(src), dest, platform, refs)
|
||||
}
|
||||
|
||||
// UnpackFile opens the file pointed by tarFileName and calls Unpack on it.
|
||||
func UnpackFile(tarFileName, dest, ref, platform string) error {
|
||||
f, err := os.Open(tarFileName)
|
||||
func UnpackFile(tarFileName, dest, platform string, refs []string) error {
|
||||
f, err := os.Open(tarFileName) // nolint: errcheck, gosec
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to open file")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return Unpack(f, dest, ref, platform)
|
||||
return Unpack(f, dest, platform, refs)
|
||||
}
|
||||
|
||||
// Unpack walks through the tar stream and, using the layers specified in
|
||||
// the manifest pointed to by the given ref, unpacks all layers in the given
|
||||
// destination directory or returns an error if the unpacking failed.
|
||||
// The destination will be created if it does not exist.
|
||||
func Unpack(r io.ReadSeeker, dest, refName, platform string) error {
|
||||
return unpack(newTarWalker(r), dest, refName, platform)
|
||||
func Unpack(r io.ReadSeeker, dest, platform string, refs []string) error {
|
||||
return unpack(newTarWalker(r), dest, platform, refs)
|
||||
}
|
||||
|
||||
func unpack(w walker, dest, refName, platform string) error {
|
||||
func unpack(w walker, dest, platform string, refs []string) error {
|
||||
if err := layoutValidate(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ref, err := findDescriptor(w, refName)
|
||||
descs, err := findDescriptor(w, refs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ref := &descs[0]
|
||||
if err = validateDescriptor(ref, w, validRefMediaTypes); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -198,11 +198,11 @@ func unpack(w walker, dest, refName, platform string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.validate(w); err != nil {
|
||||
if err := validateManifest(m, w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.unpack(w, dest)
|
||||
return unpackManifest(m, w, dest)
|
||||
}
|
||||
|
||||
if ref.MediaType == validRefMediaTypes[1] {
|
||||
@@ -221,7 +221,7 @@ func unpack(w walker, dest, refName, platform string) error {
|
||||
}
|
||||
|
||||
for _, m := range manifests {
|
||||
return m.unpack(w, dest)
|
||||
return unpackManifest(m, w, dest)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,46 +231,47 @@ func unpack(w walker, dest, refName, platform string) error {
|
||||
// CreateRuntimeBundleLayout walks through the file tree given by src and
|
||||
// creates an OCI runtime bundle in the given destination dest
|
||||
// or returns an error if the unpacking failed.
|
||||
func CreateRuntimeBundleLayout(src, dest, ref, root, platform string) error {
|
||||
return createRuntimeBundle(newPathWalker(src), dest, ref, root, platform)
|
||||
func CreateRuntimeBundleLayout(src, dest, root, platform string, refs []string) error {
|
||||
return createRuntimeBundle(newPathWalker(src), dest, root, platform, refs)
|
||||
}
|
||||
|
||||
// CreateRuntimeBundleZip opens and walks through the zip file given by src
|
||||
// and creates an OCI runtime bundle in the given destination dest
|
||||
// or returns an error if the unpacking failed.
|
||||
func CreateRuntimeBundleZip(src, dest, ref, root, platform string) error {
|
||||
return createRuntimeBundle(newZipWalker(src), dest, ref, root, platform)
|
||||
func CreateRuntimeBundleZip(src, dest, root, platform string, refs []string) error {
|
||||
return createRuntimeBundle(newZipWalker(src), dest, root, platform, refs)
|
||||
}
|
||||
|
||||
// CreateRuntimeBundleFile opens the file pointed by tarFile and calls
|
||||
// CreateRuntimeBundle.
|
||||
func CreateRuntimeBundleFile(tarFile, dest, ref, root, platform string) error {
|
||||
f, err := os.Open(tarFile)
|
||||
func CreateRuntimeBundleFile(tarFile, dest, root, platform string, refs []string) error {
|
||||
f, err := os.Open(tarFile) // nolint: errcheck, gosec
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to open file")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return createRuntimeBundle(newTarWalker(f), dest, ref, root, platform)
|
||||
return createRuntimeBundle(newTarWalker(f), dest, root, platform, refs)
|
||||
}
|
||||
|
||||
// CreateRuntimeBundle walks through the given tar stream and
|
||||
// creates an OCI runtime bundle in the given destination dest
|
||||
// or returns an error if the unpacking failed.
|
||||
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root, platform string) error {
|
||||
return createRuntimeBundle(newTarWalker(r), dest, ref, root, platform)
|
||||
func CreateRuntimeBundle(r io.ReadSeeker, dest, root, platform string, refs []string) error {
|
||||
return createRuntimeBundle(newTarWalker(r), dest, root, platform, refs)
|
||||
}
|
||||
|
||||
func createRuntimeBundle(w walker, dest, refName, rootfs, platform string) error {
|
||||
func createRuntimeBundle(w walker, dest, rootfs, platform string, refs []string) error {
|
||||
if err := layoutValidate(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ref, err := findDescriptor(w, refName)
|
||||
descs, err := findDescriptor(w, refs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ref := &descs[0]
|
||||
if err = validateDescriptor(ref, w, validRefMediaTypes); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -281,7 +282,7 @@ func createRuntimeBundle(w walker, dest, refName, rootfs, platform string) error
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.validate(w); err != nil {
|
||||
if err := validateManifest(m, w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -311,7 +312,7 @@ func createRuntimeBundle(w walker, dest, refName, rootfs, platform string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func createBundle(w walker, m *manifest, dest, rootfs string) (retErr error) {
|
||||
func createBundle(w walker, m *v1.Manifest, dest, rootfs string) (retErr error) {
|
||||
c, err := findConfig(w, &m.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -319,7 +320,7 @@ func createBundle(w walker, m *manifest, dest, rootfs string) (retErr error) {
|
||||
|
||||
if _, err = os.Stat(dest); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err2 := os.MkdirAll(dest, 0755); err2 != nil {
|
||||
if err2 := os.MkdirAll(dest, 0750); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
defer func() {
|
||||
@@ -334,11 +335,11 @@ func createBundle(w walker, m *manifest, dest, rootfs string) (retErr error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = m.unpack(w, filepath.Join(dest, rootfs)); err != nil {
|
||||
if err = unpackManifest(m, w, filepath.Join(dest, rootfs)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spec, err := c.runtimeSpec(rootfs)
|
||||
spec, err := runtimeSpec(c, rootfs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -353,8 +354,8 @@ func createBundle(w walker, m *manifest, dest, rootfs string) (retErr error) {
|
||||
}
|
||||
|
||||
// filertManifest returns a filtered list of manifests
|
||||
func filterManifest(w walker, Manifests []v1.Descriptor, platform string) ([]*manifest, error) {
|
||||
var manifests []*manifest
|
||||
func filterManifest(w walker, Manifests []v1.Descriptor, platform string) ([]*v1.Manifest, error) {
|
||||
var manifests []*v1.Manifest
|
||||
|
||||
argsParts := strings.Split(platform, ":")
|
||||
if len(argsParts) != 2 {
|
||||
@@ -372,7 +373,7 @@ func filterManifest(w walker, Manifests []v1.Descriptor, platform string) ([]*ma
|
||||
return manifests, err
|
||||
}
|
||||
|
||||
if err := m.validate(w); err != nil {
|
||||
if err := validateManifest(m, w); err != nil {
|
||||
return manifests, err
|
||||
}
|
||||
if strings.EqualFold(manifest.Platform.OS, argsParts[0]) && strings.EqualFold(manifest.Platform.Architecture, argsParts[1]) {
|
||||
@@ -381,7 +382,7 @@ func filterManifest(w walker, Manifests []v1.Descriptor, platform string) ([]*ma
|
||||
}
|
||||
|
||||
if len(manifests) == 0 {
|
||||
return manifests, fmt.Errorf("There is no matching manifest")
|
||||
return manifests, fmt.Errorf("there is no matching manifest")
|
||||
}
|
||||
|
||||
return manifests, nil
|
||||
|
7
vendor/github.com/opencontainers/image-tools/image/layout.go
generated
vendored
7
vendor/github.com/opencontainers/image-tools/image/layout.go
generated
vendored
@@ -48,14 +48,13 @@ func layoutValidate(w walker) error {
|
||||
return fmt.Errorf("index.json is a directory")
|
||||
}
|
||||
|
||||
var index v1.Index
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error reading index.json")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(buf, &index); err != nil {
|
||||
return errors.Wrap(err, "index.json format mismatch")
|
||||
if err := schema.ValidatorMediaTypeImageIndex.Validate(bytes.NewReader(buf)); err != nil {
|
||||
return errors.Wrap(err, "index.json validation failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -74,7 +73,7 @@ func layoutValidate(w walker) error {
|
||||
}
|
||||
|
||||
if err := schema.ValidatorMediaTypeLayoutHeader.Validate(bytes.NewReader(buf)); err != nil {
|
||||
return errors.Wrap(err, "oci-layout: imageLayout validation failed")
|
||||
return errors.Wrap(err, "oci-layout validation failed")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(buf, &imageLayout); err != nil {
|
||||
|
212
vendor/github.com/opencontainers/image-tools/image/manifest.go
generated
vendored
212
vendor/github.com/opencontainers/image-tools/image/manifest.go
generated
vendored
@@ -29,26 +29,17 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/opencontainers/image-spec/schema"
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type manifest struct {
|
||||
Config v1.Descriptor `json:"config"`
|
||||
Layers []v1.Descriptor `json:"layers"`
|
||||
}
|
||||
|
||||
func findManifest(w walker, d *v1.Descriptor) (*manifest, error) {
|
||||
var m manifest
|
||||
func findManifest(w walker, d *v1.Descriptor) (*v1.Manifest, error) {
|
||||
var m v1.Manifest
|
||||
mpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex())
|
||||
|
||||
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
|
||||
if info.IsDir() || filepath.Clean(path) != mpath {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch err := w.find(mpath, func(path string, r io.Reader) error {
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "%s: error reading manifest", path)
|
||||
@@ -73,7 +64,7 @@ func findManifest(w walker, d *v1.Descriptor) (*manifest, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *manifest) validate(w walker) error {
|
||||
func validateManifest(m *v1.Manifest, w walker) error {
|
||||
if err := validateDescriptor(&m.Config, w, []string{v1.MediaTypeImageConfig}); err != nil {
|
||||
return errors.Wrap(err, "config validation failed")
|
||||
}
|
||||
@@ -94,7 +85,7 @@ func (m *manifest) validate(w walker) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *manifest) unpack(w walker, dest string) (retErr error) {
|
||||
func unpackManifest(m *v1.Manifest, w walker, dest string) (retErr error) {
|
||||
// error out if the dest directory is not empty
|
||||
s, err := ioutil.ReadDir(dest)
|
||||
if err != nil && !os.IsNotExist(err) { // We'll create the dir later
|
||||
@@ -113,18 +104,10 @@ func (m *manifest) unpack(w walker, dest string) (retErr error) {
|
||||
}
|
||||
}()
|
||||
for _, d := range m.Layers {
|
||||
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
dd, err := filepath.Rel(filepath.Join("blobs", string(d.Digest.Algorithm())), filepath.Clean(path))
|
||||
if err != nil || d.Digest.Hex() != dd {
|
||||
return nil
|
||||
}
|
||||
|
||||
lpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex())
|
||||
switch err := w.find(lpath, func(path string, r io.Reader) error {
|
||||
if err := unpackLayer(d.MediaType, path, dest, r); err != nil {
|
||||
return errors.Wrap(err, "error unpack: extracting layer")
|
||||
return errors.Wrap(err, "unpack: error extracting layer")
|
||||
}
|
||||
|
||||
return errEOW
|
||||
@@ -218,85 +201,15 @@ loop:
|
||||
return errors.Wrapf(err, "error advancing tar stream")
|
||||
}
|
||||
|
||||
hdr.Name = filepath.Clean(hdr.Name)
|
||||
if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) {
|
||||
// Not the root directory, ensure that the parent directory exists
|
||||
parent := filepath.Dir(hdr.Name)
|
||||
parentPath := filepath.Join(dest, parent)
|
||||
if _, err2 := os.Lstat(parentPath); err2 != nil && os.IsNotExist(err2) {
|
||||
if err3 := os.MkdirAll(parentPath, 0755); err3 != nil {
|
||||
return err3
|
||||
}
|
||||
}
|
||||
}
|
||||
path := filepath.Join(dest, hdr.Name)
|
||||
if entries[path] {
|
||||
return fmt.Errorf("duplicate entry for %s", path)
|
||||
}
|
||||
entries[path] = true
|
||||
rel, err := filepath.Rel(dest, path)
|
||||
var whiteout bool
|
||||
whiteout, err = unpackLayerEntry(dest, hdr, tr, &entries)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info := hdr.FileInfo()
|
||||
if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
|
||||
return fmt.Errorf("%q is outside of %q", hdr.Name, dest)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(info.Name(), ".wh.") {
|
||||
path = strings.Replace(path, ".wh.", "", 1)
|
||||
|
||||
if err := os.RemoveAll(path); err != nil {
|
||||
return errors.Wrap(err, "unable to delete whiteout path")
|
||||
}
|
||||
|
||||
if whiteout {
|
||||
continue loop
|
||||
}
|
||||
|
||||
switch hdr.Typeflag {
|
||||
case tar.TypeDir:
|
||||
if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
|
||||
if err2 := os.MkdirAll(path, info.Mode()); err2 != nil {
|
||||
return errors.Wrap(err2, "error creating directory")
|
||||
}
|
||||
}
|
||||
|
||||
case tar.TypeReg, tar.TypeRegA:
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, info.Mode())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to open file")
|
||||
}
|
||||
|
||||
if _, err := io.Copy(f, tr); err != nil {
|
||||
f.Close()
|
||||
return errors.Wrap(err, "unable to copy")
|
||||
}
|
||||
f.Close()
|
||||
|
||||
case tar.TypeLink:
|
||||
target := filepath.Join(dest, hdr.Linkname)
|
||||
|
||||
if !strings.HasPrefix(target, dest) {
|
||||
return fmt.Errorf("invalid hardlink %q -> %q", target, hdr.Linkname)
|
||||
}
|
||||
|
||||
if err := os.Link(target, path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case tar.TypeSymlink:
|
||||
target := filepath.Join(filepath.Dir(path), hdr.Linkname)
|
||||
|
||||
if !strings.HasPrefix(target, dest) {
|
||||
return fmt.Errorf("invalid symlink %q -> %q", path, hdr.Linkname)
|
||||
}
|
||||
|
||||
if err := os.Symlink(hdr.Linkname, path); err != nil {
|
||||
return err
|
||||
}
|
||||
case tar.TypeXGlobalHeader:
|
||||
return nil
|
||||
}
|
||||
// Directory mtimes must be handled at the end to avoid further
|
||||
// file creation in them to modify the directory mtime
|
||||
if hdr.Typeflag == tar.TypeDir {
|
||||
@@ -315,3 +228,104 @@ loop:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// unpackLayerEntry unpacks a single entry from a layer.
|
||||
func unpackLayerEntry(dest string, header *tar.Header, reader io.Reader, entries *map[string]bool) (whiteout bool, err error) {
|
||||
header.Name = filepath.Clean(header.Name)
|
||||
if !strings.HasSuffix(header.Name, string(os.PathSeparator)) {
|
||||
// Not the root directory, ensure that the parent directory exists
|
||||
parent := filepath.Dir(header.Name)
|
||||
parentPath := filepath.Join(dest, parent)
|
||||
if _, err2 := os.Lstat(parentPath); err2 != nil && os.IsNotExist(err2) {
|
||||
if err3 := os.MkdirAll(parentPath, 0750); err3 != nil {
|
||||
return false, err3
|
||||
}
|
||||
}
|
||||
}
|
||||
path := filepath.Join(dest, header.Name)
|
||||
if (*entries)[path] {
|
||||
return false, fmt.Errorf("duplicate entry for %s", path)
|
||||
}
|
||||
(*entries)[path] = true
|
||||
rel, err := filepath.Rel(dest, path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
info := header.FileInfo()
|
||||
if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
|
||||
return false, fmt.Errorf("%q is outside of %q", header.Name, dest)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(info.Name(), ".wh.") {
|
||||
path = strings.Replace(path, ".wh.", "", 1)
|
||||
|
||||
if err = os.RemoveAll(path); err != nil {
|
||||
return true, errors.Wrap(err, "unable to delete whiteout path")
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if header.Typeflag != tar.TypeDir {
|
||||
err = os.RemoveAll(path)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
fi, err := os.Lstat(path)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
if os.IsNotExist(err) || !fi.IsDir() {
|
||||
err = os.RemoveAll(path)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
err = os.MkdirAll(path, info.Mode())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
case tar.TypeReg, tar.TypeRegA:
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, info.Mode())
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "unable to open file")
|
||||
}
|
||||
|
||||
if _, err := io.Copy(f, reader); err != nil {
|
||||
defer f.Close()
|
||||
return false, errors.Wrap(err, "unable to copy")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
case tar.TypeLink:
|
||||
target := filepath.Join(dest, header.Linkname)
|
||||
|
||||
if !strings.HasPrefix(target, dest) {
|
||||
return false, fmt.Errorf("invalid hardlink %q -> %q", target, header.Linkname)
|
||||
}
|
||||
|
||||
if err := os.Link(target, path); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
case tar.TypeSymlink:
|
||||
target := filepath.Join(filepath.Dir(path), header.Linkname)
|
||||
|
||||
if !strings.HasPrefix(target, dest) {
|
||||
return false, fmt.Errorf("invalid symlink %q -> %q", path, header.Linkname)
|
||||
}
|
||||
|
||||
if err := os.Symlink(header.Linkname, path); err != nil {
|
||||
return false, err
|
||||
}
|
||||
case tar.TypeXGlobalHeader:
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
86
vendor/github.com/opencontainers/image-tools/image/walker.go
generated
vendored
86
vendor/github.com/opencontainers/image-tools/image/walker.go
generated
vendored
@@ -34,6 +34,8 @@ var (
|
||||
// walkFunc is a function type that gets called for each file or directory visited by the Walker.
|
||||
type walkFunc func(path string, _ os.FileInfo, _ io.Reader) error
|
||||
|
||||
type findFunc func(path string, r io.Reader) error
|
||||
|
||||
// walker is the interface that defines how to access a given archival format
|
||||
type walker interface {
|
||||
|
||||
@@ -43,6 +45,9 @@ type walker interface {
|
||||
// get will copy an arbitrary blob, defined by desc, in to dst. returns
|
||||
// the number of bytes copied on success.
|
||||
get(desc v1.Descriptor, dst io.Writer) (int64, error)
|
||||
|
||||
// find calls findFunc for handling content of path
|
||||
find(path string, ff findFunc) error
|
||||
}
|
||||
|
||||
// tarWalker exposes access to image layouts in a tar file.
|
||||
@@ -120,6 +125,34 @@ func (w *tarWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
func (w *tarWalker) find(path string, ff findFunc) error {
|
||||
done := false
|
||||
|
||||
f := func(relpath string, info os.FileInfo, rdr io.Reader) error {
|
||||
var err error
|
||||
if done {
|
||||
return nil
|
||||
}
|
||||
|
||||
if filepath.Clean(relpath) == path && !info.IsDir() {
|
||||
if err = ff(relpath, rdr); err != nil {
|
||||
return err
|
||||
}
|
||||
done = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := w.walk(f); err != nil {
|
||||
return errors.Wrapf(err, "find failed: unable to walk")
|
||||
}
|
||||
if !done {
|
||||
return os.ErrNotExist
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type eofReader struct{}
|
||||
|
||||
func (eofReader) Read(_ []byte) (int, error) {
|
||||
@@ -153,7 +186,7 @@ func (w *pathWalker) walk(f walkFunc) error {
|
||||
return f(rel, info, eofReader{})
|
||||
}
|
||||
|
||||
file, err := os.Open(path)
|
||||
file, err := os.Open(path) // nolint: errcheck, gosec
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to open file") // os.Open includes the path
|
||||
}
|
||||
@@ -175,7 +208,7 @@ func (w *pathWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
|
||||
return 0, fmt.Errorf("object is dir")
|
||||
}
|
||||
|
||||
fp, err := os.Open(name)
|
||||
fp, err := os.Open(name) // nolint: errcheck, gosec
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "get failed")
|
||||
}
|
||||
@@ -188,6 +221,27 @@ func (w *pathWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
|
||||
return nbytes, nil
|
||||
}
|
||||
|
||||
func (w *pathWalker) find(path string, ff findFunc) error {
|
||||
name := filepath.Join(w.root, path)
|
||||
|
||||
info, err := os.Stat(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return fmt.Errorf("object is dir")
|
||||
}
|
||||
|
||||
file, err := os.Open(name) // nolint: errcheck, gosec
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to open file") // os.Open includes the path
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
return ff(name, file)
|
||||
}
|
||||
|
||||
type zipWalker struct {
|
||||
fileName string
|
||||
}
|
||||
@@ -249,3 +303,31 @@ func (w *zipWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
|
||||
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
func (w *zipWalker) find(path string, ff findFunc) error {
|
||||
done := false
|
||||
|
||||
f := func(relpath string, info os.FileInfo, rdr io.Reader) error {
|
||||
var err error
|
||||
if done {
|
||||
return nil
|
||||
}
|
||||
|
||||
if filepath.Clean(relpath) == path && !info.IsDir() {
|
||||
if err = ff(relpath, rdr); err != nil {
|
||||
return err
|
||||
}
|
||||
done = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := w.walk(f); err != nil {
|
||||
return errors.Wrapf(err, "find failed: unable to walk")
|
||||
}
|
||||
if !done {
|
||||
return os.ErrNotExist
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user