diff --git a/cmd/skopeo/inspect.go b/cmd/skopeo/inspect.go index e969caa4..4ca03ac1 100644 --- a/cmd/skopeo/inspect.go +++ b/cmd/skopeo/inspect.go @@ -106,8 +106,9 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error) } }() + unparsedInstance := image.UnparsedInstance(src, nil) if err := retry.IfNecessary(ctx, func() error { - rawManifest, _, err = src.GetManifest(ctx, nil) + rawManifest, _, err = unparsedInstance.Manifest(ctx) return err }, opts.retryOpts); err != nil { return fmt.Errorf("Error retrieving manifest for image: %w", err) @@ -122,7 +123,7 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error) return nil } - img, err := image.FromUnparsedImage(ctx, sys, image.UnparsedInstance(src, nil)) + img, err := image.FromUnparsedImage(ctx, sys, unparsedInstance) if err != nil { return fmt.Errorf("Error parsing manifest for image: %w", err) } diff --git a/cmd/skopeo/layers.go b/cmd/skopeo/layers.go index 9bcf2f55..f310a033 100644 --- a/cmd/skopeo/layers.go +++ b/cmd/skopeo/layers.go @@ -151,12 +151,22 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) { }, opts.retryOpts); err != nil { return err } - if _, err := dest.PutBlob(ctx, r, types.BlobInfo{Digest: bd.digest, Size: blobSize}, cache, bd.isConfig); err != nil { - if closeErr := r.Close(); closeErr != nil { - return fmt.Errorf("%w (close error: %v)", err, closeErr) + defer func() { + if err := r.Close(); err != nil { + retErr = noteCloseFailure(retErr, fmt.Sprintf("closing blob %q", bd.digest.String()), err) } + }() + verifier := bd.digest.Verifier() + tr := io.TeeReader(r, verifier) + if _, err := dest.PutBlob(ctx, tr, types.BlobInfo{Digest: bd.digest, Size: blobSize}, cache, bd.isConfig); err != nil { return err } + if _, err := io.Copy(io.Discard, tr); err != nil { // Ensure we process all of tr, so that we can validate the digest. + return err + } + if !verifier.Verified() { + return fmt.Errorf("corrupt blob %q", bd.digest.String()) + } } var manifest []byte