1package layer // import "github.com/docker/docker/layer"
2
3import (
4	"fmt"
5	"io"
6
7	"github.com/docker/distribution"
8	"github.com/opencontainers/go-digest"
9)
10
11type roLayer struct {
12	chainID    ChainID
13	diffID     DiffID
14	parent     *roLayer
15	cacheID    string
16	size       int64
17	layerStore *layerStore
18	descriptor distribution.Descriptor
19
20	referenceCount int
21	references     map[Layer]struct{}
22}
23
24// TarStream for roLayer guarantees that the data that is produced is the exact
25// data that the layer was registered with.
26func (rl *roLayer) TarStream() (io.ReadCloser, error) {
27	rc, err := rl.layerStore.getTarStream(rl)
28	if err != nil {
29		return nil, err
30	}
31
32	vrc, err := newVerifiedReadCloser(rc, digest.Digest(rl.diffID))
33	if err != nil {
34		return nil, err
35	}
36	return vrc, nil
37}
38
39// TarStreamFrom does not make any guarantees to the correctness of the produced
40// data. As such it should not be used when the layer content must be verified
41// to be an exact match to the registered layer.
42func (rl *roLayer) TarStreamFrom(parent ChainID) (io.ReadCloser, error) {
43	var parentCacheID string
44	for pl := rl.parent; pl != nil; pl = pl.parent {
45		if pl.chainID == parent {
46			parentCacheID = pl.cacheID
47			break
48		}
49	}
50
51	if parent != ChainID("") && parentCacheID == "" {
52		return nil, fmt.Errorf("layer ID '%s' is not a parent of the specified layer: cannot provide diff to non-parent", parent)
53	}
54	return rl.layerStore.driver.Diff(rl.cacheID, parentCacheID)
55}
56
57func (rl *roLayer) CacheID() string {
58	return rl.cacheID
59}
60
61func (rl *roLayer) ChainID() ChainID {
62	return rl.chainID
63}
64
65func (rl *roLayer) DiffID() DiffID {
66	return rl.diffID
67}
68
69func (rl *roLayer) Parent() Layer {
70	if rl.parent == nil {
71		return nil
72	}
73	return rl.parent
74}
75
76func (rl *roLayer) Size() (size int64, err error) {
77	if rl.parent != nil {
78		size, err = rl.parent.Size()
79		if err != nil {
80			return
81		}
82	}
83
84	return size + rl.size, nil
85}
86
87func (rl *roLayer) DiffSize() (size int64, err error) {
88	return rl.size, nil
89}
90
91func (rl *roLayer) Metadata() (map[string]string, error) {
92	return rl.layerStore.driver.GetMetadata(rl.cacheID)
93}
94
95type referencedCacheLayer struct {
96	*roLayer
97}
98
99func (rl *roLayer) getReference() Layer {
100	ref := &referencedCacheLayer{
101		roLayer: rl,
102	}
103	rl.references[ref] = struct{}{}
104
105	return ref
106}
107
108func (rl *roLayer) hasReference(ref Layer) bool {
109	_, ok := rl.references[ref]
110	return ok
111}
112
113func (rl *roLayer) hasReferences() bool {
114	return len(rl.references) > 0
115}
116
117func (rl *roLayer) deleteReference(ref Layer) {
118	delete(rl.references, ref)
119}
120
121func (rl *roLayer) depth() int {
122	if rl.parent == nil {
123		return 1
124	}
125	return rl.parent.depth() + 1
126}
127
128func storeLayer(tx *fileMetadataTransaction, layer *roLayer) error {
129	if err := tx.SetDiffID(layer.diffID); err != nil {
130		return err
131	}
132	if err := tx.SetSize(layer.size); err != nil {
133		return err
134	}
135	if err := tx.SetCacheID(layer.cacheID); err != nil {
136		return err
137	}
138	// Do not store empty descriptors
139	if layer.descriptor.Digest != "" {
140		if err := tx.SetDescriptor(layer.descriptor); err != nil {
141			return err
142		}
143	}
144	if layer.parent != nil {
145		if err := tx.SetParent(layer.parent.chainID); err != nil {
146			return err
147		}
148	}
149	return tx.setOS(layer.layerStore.os)
150}
151
152func newVerifiedReadCloser(rc io.ReadCloser, dgst digest.Digest) (io.ReadCloser, error) {
153	return &verifiedReadCloser{
154		rc:       rc,
155		dgst:     dgst,
156		verifier: dgst.Verifier(),
157	}, nil
158}
159
160type verifiedReadCloser struct {
161	rc       io.ReadCloser
162	dgst     digest.Digest
163	verifier digest.Verifier
164}
165
166func (vrc *verifiedReadCloser) Read(p []byte) (n int, err error) {
167	n, err = vrc.rc.Read(p)
168	if n > 0 {
169		if n, err := vrc.verifier.Write(p[:n]); err != nil {
170			return n, err
171		}
172	}
173	if err == io.EOF {
174		if !vrc.verifier.Verified() {
175			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)
176		}
177	}
178	return
179}
180func (vrc *verifiedReadCloser) Close() error {
181	return vrc.rc.Close()
182}
183