123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package layer // import "github.com/docker/docker/layer"
- import (
- "fmt"
- "io"
- "github.com/docker/distribution"
- "github.com/opencontainers/go-digest"
- )
- type roLayer struct {
- chainID ChainID
- diffID DiffID
- parent *roLayer
- cacheID string
- size int64
- layerStore *layerStore
- descriptor distribution.Descriptor
- referenceCount int
- references map[Layer]struct{}
- }
- // TarStream for roLayer guarantees that the data that is produced is the exact
- // data that the layer was registered with.
- func (rl *roLayer) TarStream() (io.ReadCloser, error) {
- rc, err := rl.layerStore.getTarStream(rl)
- if err != nil {
- return nil, err
- }
- vrc, err := newVerifiedReadCloser(rc, digest.Digest(rl.diffID))
- if err != nil {
- return nil, err
- }
- return vrc, nil
- }
- // TarStreamFrom does not make any guarantees to the correctness of the produced
- // data. As such it should not be used when the layer content must be verified
- // to be an exact match to the registered layer.
- func (rl *roLayer) TarStreamFrom(parent ChainID) (io.ReadCloser, error) {
- var parentCacheID string
- for pl := rl.parent; pl != nil; pl = pl.parent {
- if pl.chainID == parent {
- parentCacheID = pl.cacheID
- break
- }
- }
- if parent != ChainID("") && parentCacheID == "" {
- return nil, fmt.Errorf("layer ID '%s' is not a parent of the specified layer: cannot provide diff to non-parent", parent)
- }
- return rl.layerStore.driver.Diff(rl.cacheID, parentCacheID)
- }
- func (rl *roLayer) CacheID() string {
- return rl.cacheID
- }
- func (rl *roLayer) ChainID() ChainID {
- return rl.chainID
- }
- func (rl *roLayer) DiffID() DiffID {
- return rl.diffID
- }
- func (rl *roLayer) Parent() Layer {
- if rl.parent == nil {
- return nil
- }
- return rl.parent
- }
- func (rl *roLayer) Size() int64 {
- size := rl.size
- if rl.parent != nil {
- size += rl.parent.Size()
- }
- return size
- }
- func (rl *roLayer) DiffSize() int64 {
- return rl.size
- }
- func (rl *roLayer) Metadata() (map[string]string, error) {
- return rl.layerStore.driver.GetMetadata(rl.cacheID)
- }
- type referencedCacheLayer struct {
- *roLayer
- }
- func (rl *roLayer) getReference() Layer {
- ref := &referencedCacheLayer{
- roLayer: rl,
- }
- rl.references[ref] = struct{}{}
- return ref
- }
- func (rl *roLayer) hasReference(ref Layer) bool {
- _, ok := rl.references[ref]
- return ok
- }
- func (rl *roLayer) hasReferences() bool {
- return len(rl.references) > 0
- }
- func (rl *roLayer) deleteReference(ref Layer) {
- delete(rl.references, ref)
- }
- func (rl *roLayer) depth() int {
- if rl.parent == nil {
- return 1
- }
- return rl.parent.depth() + 1
- }
- func storeLayer(tx *fileMetadataTransaction, layer *roLayer) error {
- if err := tx.SetDiffID(layer.diffID); err != nil {
- return err
- }
- if err := tx.SetSize(layer.size); err != nil {
- return err
- }
- if err := tx.SetCacheID(layer.cacheID); err != nil {
- return err
- }
- // Do not store empty descriptors
- if layer.descriptor.Digest != "" {
- if err := tx.SetDescriptor(layer.descriptor); err != nil {
- return err
- }
- }
- if layer.parent != nil {
- if err := tx.SetParent(layer.parent.chainID); err != nil {
- return err
- }
- }
- return nil
- }
- func newVerifiedReadCloser(rc io.ReadCloser, dgst digest.Digest) (io.ReadCloser, error) {
- return &verifiedReadCloser{
- rc: rc,
- dgst: dgst,
- verifier: dgst.Verifier(),
- }, nil
- }
- type verifiedReadCloser struct {
- rc io.ReadCloser
- dgst digest.Digest
- verifier digest.Verifier
- }
- func (vrc *verifiedReadCloser) Read(p []byte) (n int, err error) {
- n, err = vrc.rc.Read(p)
- if n > 0 {
- if n, err := vrc.verifier.Write(p[:n]); err != nil {
- return n, err
- }
- }
- if err == io.EOF {
- if !vrc.verifier.Verified() {
- err = fmt.Errorf("could not verify layer data for: %s. This may be because internal files in the layer store were modified. Re-pulling or rebuilding this image may resolve the issue", vrc.dgst)
- }
- }
- return
- }
- func (vrc *verifiedReadCloser) Close() error {
- return vrc.rc.Close()
- }
|