2016-06-28 15:24:25 +08:00
|
|
|
|
package directory
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2017-07-29 04:47:24 +08:00
|
|
|
|
"context"
|
2022-07-06 01:34:12 +08:00
|
|
|
|
"fmt"
|
2016-06-28 15:24:25 +08:00
|
|
|
|
"io"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
|
2022-07-02 08:46:57 +08:00
|
|
|
|
"github.com/containers/image/v5/internal/imagesource/impl"
|
2022-07-02 08:06:00 +08:00
|
|
|
|
"github.com/containers/image/v5/internal/imagesource/stubs"
|
2023-02-07 16:51:24 +08:00
|
|
|
|
"github.com/containers/image/v5/internal/manifest"
|
2022-07-02 08:06:00 +08:00
|
|
|
|
"github.com/containers/image/v5/internal/private"
|
2022-07-06 01:34:12 +08:00
|
|
|
|
"github.com/containers/image/v5/internal/signature"
|
2019-10-26 04:27:45 +08:00
|
|
|
|
"github.com/containers/image/v5/types"
|
2017-01-09 18:10:30 +08:00
|
|
|
|
"github.com/opencontainers/go-digest"
|
2016-06-28 15:24:25 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type dirImageSource struct {
|
2022-07-06 01:34:12 +08:00
|
|
|
|
impl.Compat
|
2022-07-02 08:46:57 +08:00
|
|
|
|
impl.PropertyMethodsInitialize
|
2022-07-02 08:56:06 +08:00
|
|
|
|
impl.DoesNotAffectLayerInfosForCopy
|
2022-07-02 08:06:00 +08:00
|
|
|
|
stubs.NoGetBlobAtInitialize
|
|
|
|
|
|
|
2016-07-14 09:37:11 +08:00
|
|
|
|
ref dirReference
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-07-14 09:37:11 +08:00
|
|
|
|
// newImageSource returns an ImageSource reading from an existing directory.
|
2016-08-27 05:24:39 +08:00
|
|
|
|
// The caller must call .Close() on the returned ImageSource.
|
2022-07-02 08:06:00 +08:00
|
|
|
|
func newImageSource(ref dirReference) private.ImageSource {
|
2022-07-06 01:34:12 +08:00
|
|
|
|
s := &dirImageSource{
|
2022-07-02 08:46:57 +08:00
|
|
|
|
PropertyMethodsInitialize: impl.PropertyMethods(impl.Properties{
|
|
|
|
|
|
HasThreadSafeGetBlob: false,
|
|
|
|
|
|
}),
|
2022-07-02 08:06:00 +08:00
|
|
|
|
NoGetBlobAtInitialize: stubs.NoGetBlobAt(ref),
|
|
|
|
|
|
|
|
|
|
|
|
ref: ref,
|
|
|
|
|
|
}
|
2022-07-06 01:34:12 +08:00
|
|
|
|
s.Compat = impl.AddCompat(s)
|
|
|
|
|
|
return s
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-07-14 03:50:04 +08:00
|
|
|
|
// Reference returns the reference used to set up this source, _as specified by the user_
|
|
|
|
|
|
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
|
|
|
|
|
|
func (s *dirImageSource) Reference() types.ImageReference {
|
|
|
|
|
|
return s.ref
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-08-27 05:24:39 +08:00
|
|
|
|
// Close removes resources associated with an initialized ImageSource, if any.
|
2017-02-06 15:13:00 +08:00
|
|
|
|
func (s *dirImageSource) Close() error {
|
|
|
|
|
|
return nil
|
2016-08-27 05:24:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-02 01:20:36 +08:00
|
|
|
|
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
|
|
|
|
|
|
// It may use a remote (= slow) service.
|
2017-09-16 05:42:07 +08:00
|
|
|
|
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
|
|
|
|
|
|
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
|
2018-02-23 17:45:56 +08:00
|
|
|
|
func (s *dirImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
|
2024-04-18 04:26:46 +08:00
|
|
|
|
path, err := s.ref.manifestPath(instanceDigest)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, "", err
|
|
|
|
|
|
}
|
|
|
|
|
|
m, err := os.ReadFile(path)
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, "", err
|
|
|
|
|
|
}
|
2016-10-29 00:07:29 +08:00
|
|
|
|
return m, manifest.GuessMIMEType(m), err
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-08-27 09:13:00 +08:00
|
|
|
|
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
2018-08-25 11:48:44 +08:00
|
|
|
|
// The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided.
|
|
|
|
|
|
// May update BlobInfoCache, preferably after it knows for certain that a blob truly exists at a specific location.
|
|
|
|
|
|
func (s *dirImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {
|
2024-04-18 04:26:46 +08:00
|
|
|
|
path, err := s.ref.layerPath(info.Digest)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, -1, err
|
|
|
|
|
|
}
|
|
|
|
|
|
r, err := os.Open(path)
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
2018-02-20 01:06:10 +08:00
|
|
|
|
return nil, -1, err
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
2016-07-14 00:59:27 +08:00
|
|
|
|
fi, err := r.Stat()
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
2018-02-20 01:06:10 +08:00
|
|
|
|
return nil, -1, err
|
2016-06-28 15:24:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
return r, fi.Size(), nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-06 01:34:12 +08:00
|
|
|
|
// GetSignaturesWithFormat returns the image's signatures. It may use a remote (= slow) service.
|
2017-09-16 06:43:30 +08:00
|
|
|
|
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
|
|
|
|
|
|
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
|
|
|
|
|
// (e.g. if the source never returns manifest lists).
|
2022-07-06 01:34:12 +08:00
|
|
|
|
func (s *dirImageSource) GetSignaturesWithFormat(ctx context.Context, instanceDigest *digest.Digest) ([]signature.Signature, error) {
|
|
|
|
|
|
signatures := []signature.Signature{}
|
2016-06-28 15:24:25 +08:00
|
|
|
|
for i := 0; ; i++ {
|
2024-04-18 04:26:46 +08:00
|
|
|
|
path, err := s.ref.signaturePath(i, instanceDigest)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
2022-07-06 01:34:12 +08:00
|
|
|
|
sigBlob, err := os.ReadFile(path)
|
2016-06-28 15:24:25 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
2022-07-06 01:34:12 +08:00
|
|
|
|
signature, err := signature.FromBlob(sigBlob)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, fmt.Errorf("parsing signature %q: %w", path, err)
|
|
|
|
|
|
}
|
2016-06-28 15:24:25 +08:00
|
|
|
|
signatures = append(signatures, signature)
|
|
|
|
|
|
}
|
|
|
|
|
|
return signatures, nil
|
|
|
|
|
|
}
|