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