mirror of
https://github.com/containers/podman.git
synced 2025-09-26 16:25:00 +08:00
Update containers/storage to pick up overlay driver fix
New pinned commit is ff8a6d2bf496daf46ab1a153f783a0f6b8762a54 This includes a fix to error reporting with overlayfs, and will produce more verbose errors when initializing overlayfs fails. Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #546 Approved by: baude
This commit is contained in:
@ -3,7 +3,7 @@ github.com/sirupsen/logrus v1.0.0
|
|||||||
github.com/containers/image b327f751c16e4a189fdcde4ea36be67cc964c605
|
github.com/containers/image b327f751c16e4a189fdcde4ea36be67cc964c605
|
||||||
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
|
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
|
||||||
github.com/ostreedev/ostree-go master
|
github.com/ostreedev/ostree-go master
|
||||||
github.com/containers/storage 1e5ce40cdb84ab66e26186435b1273e04b879fef
|
github.com/containers/storage ff8a6d2bf496daf46ab1a153f783a0f6b8762a54
|
||||||
github.com/containernetworking/cni v0.4.0
|
github.com/containernetworking/cni v0.4.0
|
||||||
google.golang.org/grpc v1.0.4 https://github.com/grpc/grpc-go
|
google.golang.org/grpc v1.0.4 https://github.com/grpc/grpc-go
|
||||||
github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
|
github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
|
||||||
|
23
vendor/github.com/containers/storage/containers.go
generated
vendored
23
vendor/github.com/containers/storage/containers.go
generated
vendored
@ -106,10 +106,25 @@ type containerStore struct {
|
|||||||
byname map[string]*Container
|
byname map[string]*Container
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyContainer(c *Container) *Container {
|
||||||
|
return &Container{
|
||||||
|
ID: c.ID,
|
||||||
|
Names: copyStringSlice(c.Names),
|
||||||
|
ImageID: c.ImageID,
|
||||||
|
LayerID: c.LayerID,
|
||||||
|
Metadata: c.Metadata,
|
||||||
|
BigDataNames: copyStringSlice(c.BigDataNames),
|
||||||
|
BigDataSizes: copyStringInt64Map(c.BigDataSizes),
|
||||||
|
BigDataDigests: copyStringDigestMap(c.BigDataDigests),
|
||||||
|
Created: c.Created,
|
||||||
|
Flags: copyStringInterfaceMap(c.Flags),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *containerStore) Containers() ([]Container, error) {
|
func (r *containerStore) Containers() ([]Container, error) {
|
||||||
containers := make([]Container, len(r.containers))
|
containers := make([]Container, len(r.containers))
|
||||||
for i := range r.containers {
|
for i := range r.containers {
|
||||||
containers[i] = *(r.containers[i])
|
containers[i] = *copyContainer(r.containers[i])
|
||||||
}
|
}
|
||||||
return containers, nil
|
return containers, nil
|
||||||
}
|
}
|
||||||
@ -277,7 +292,7 @@ func (r *containerStore) Create(id string, names []string, image, layer, metadat
|
|||||||
}
|
}
|
||||||
err = r.Save()
|
err = r.Save()
|
||||||
}
|
}
|
||||||
return container, err
|
return copyContainer(container), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *containerStore) Metadata(id string) (string, error) {
|
func (r *containerStore) Metadata(id string) (string, error) {
|
||||||
@ -355,7 +370,7 @@ func (r *containerStore) Delete(id string) error {
|
|||||||
|
|
||||||
func (r *containerStore) Get(id string) (*Container, error) {
|
func (r *containerStore) Get(id string) (*Container, error) {
|
||||||
if container, ok := r.lookup(id); ok {
|
if container, ok := r.lookup(id); ok {
|
||||||
return container, nil
|
return copyContainer(container), nil
|
||||||
}
|
}
|
||||||
return nil, ErrContainerUnknown
|
return nil, ErrContainerUnknown
|
||||||
}
|
}
|
||||||
@ -444,7 +459,7 @@ func (r *containerStore) BigDataNames(id string) ([]string, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrContainerUnknown
|
return nil, ErrContainerUnknown
|
||||||
}
|
}
|
||||||
return c.BigDataNames, nil
|
return copyStringSlice(c.BigDataNames), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *containerStore) SetBigData(id, key string, data []byte) error {
|
func (r *containerStore) SetBigData(id, key string, data []byte) error {
|
||||||
|
2
vendor/github.com/containers/storage/containers_ffjson.go
generated
vendored
2
vendor/github.com/containers/storage/containers_ffjson.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
||||||
// source: containers.go
|
// source: ./containers.go
|
||||||
|
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
|
12
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
@ -114,8 +114,8 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init returns the a native diff driver for overlay filesystem.
|
// Init returns the a native diff driver for overlay filesystem.
|
||||||
// If overlay filesystem is not supported on the host, graphdriver.ErrNotSupported is returned as error.
|
// If overlay filesystem is not supported on the host, a wrapped graphdriver.ErrNotSupported is returned as error.
|
||||||
// If an overlay filesystem is not supported over an existing filesystem then error graphdriver.ErrIncompatibleFS is returned.
|
// If an overlay filesystem is not supported over an existing filesystem then a wrapped graphdriver.ErrIncompatibleFS is returned.
|
||||||
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
|
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
|
||||||
opts, err := parseOptions(options)
|
opts, err := parseOptions(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -151,7 +151,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
os.Remove(filepath.Join(home, linkDir))
|
os.Remove(filepath.Join(home, linkDir))
|
||||||
os.Remove(home)
|
os.Remove(home)
|
||||||
return nil, errors.Wrap(graphdriver.ErrNotSupported, "kernel does not support overlay fs")
|
return nil, errors.Wrap(err, "kernel does not support overlay fs")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mount.MakePrivate(home); err != nil {
|
if err := mount.MakePrivate(home); err != nil {
|
||||||
@ -740,6 +740,11 @@ func (d *Driver) Diff(id, parent, mountLabel string) (io.ReadCloser, error) {
|
|||||||
return d.naiveDiff.Diff(id, parent, mountLabel)
|
return d.naiveDiff.Diff(id, parent, mountLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lowerDirs, err := d.getLowerDirs(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
diffPath := d.getDiffPath(id)
|
diffPath := d.getDiffPath(id)
|
||||||
logrus.Debugf("Tar with options on %s", diffPath)
|
logrus.Debugf("Tar with options on %s", diffPath)
|
||||||
return archive.TarWithOptions(diffPath, &archive.TarOptions{
|
return archive.TarWithOptions(diffPath, &archive.TarOptions{
|
||||||
@ -747,6 +752,7 @@ func (d *Driver) Diff(id, parent, mountLabel string) (io.ReadCloser, error) {
|
|||||||
UIDMaps: d.uidMaps,
|
UIDMaps: d.uidMaps,
|
||||||
GIDMaps: d.gidMaps,
|
GIDMaps: d.gidMaps,
|
||||||
WhiteoutFormat: archive.OverlayWhiteoutFormat,
|
WhiteoutFormat: archive.OverlayWhiteoutFormat,
|
||||||
|
WhiteoutData: lowerDirs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go
generated
vendored
6
vendor/github.com/containers/storage/drivers/overlayutils/overlayutils.go
generated
vendored
@ -3,8 +3,10 @@
|
|||||||
package overlayutils
|
package overlayutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containers/storage/drivers"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type.
|
// ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type.
|
||||||
@ -14,5 +16,5 @@ func ErrDTypeNotSupported(driver, backingFs string) error {
|
|||||||
msg += " Reformat the filesystem with ftype=1 to enable d_type support."
|
msg += " Reformat the filesystem with ftype=1 to enable d_type support."
|
||||||
}
|
}
|
||||||
msg += " Running without d_type is not supported."
|
msg += " Running without d_type is not supported."
|
||||||
return errors.New(msg)
|
return errors.Wrap(graphdriver.ErrNotSupported, msg)
|
||||||
}
|
}
|
||||||
|
23
vendor/github.com/containers/storage/images.go
generated
vendored
23
vendor/github.com/containers/storage/images.go
generated
vendored
@ -124,10 +124,25 @@ type imageStore struct {
|
|||||||
bydigest map[digest.Digest][]*Image
|
bydigest map[digest.Digest][]*Image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyImage(i *Image) *Image {
|
||||||
|
return &Image{
|
||||||
|
ID: i.ID,
|
||||||
|
Digest: i.Digest,
|
||||||
|
Names: copyStringSlice(i.Names),
|
||||||
|
TopLayer: i.TopLayer,
|
||||||
|
Metadata: i.Metadata,
|
||||||
|
BigDataNames: copyStringSlice(i.BigDataNames),
|
||||||
|
BigDataSizes: copyStringInt64Map(i.BigDataSizes),
|
||||||
|
BigDataDigests: copyStringDigestMap(i.BigDataDigests),
|
||||||
|
Created: i.Created,
|
||||||
|
Flags: copyStringInterfaceMap(i.Flags),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *imageStore) Images() ([]Image, error) {
|
func (r *imageStore) Images() ([]Image, error) {
|
||||||
images := make([]Image, len(r.images))
|
images := make([]Image, len(r.images))
|
||||||
for i := range r.images {
|
for i := range r.images {
|
||||||
images[i] = *(r.images[i])
|
images[i] = *copyImage(r.images[i])
|
||||||
}
|
}
|
||||||
return images, nil
|
return images, nil
|
||||||
}
|
}
|
||||||
@ -343,7 +358,7 @@ func (r *imageStore) Create(id string, names []string, layer, metadata string, c
|
|||||||
}
|
}
|
||||||
err = r.Save()
|
err = r.Save()
|
||||||
}
|
}
|
||||||
return image, err
|
return copyImage(image), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *imageStore) Metadata(id string) (string, error) {
|
func (r *imageStore) Metadata(id string) (string, error) {
|
||||||
@ -450,7 +465,7 @@ func (r *imageStore) Delete(id string) error {
|
|||||||
|
|
||||||
func (r *imageStore) Get(id string) (*Image, error) {
|
func (r *imageStore) Get(id string) (*Image, error) {
|
||||||
if image, ok := r.lookup(id); ok {
|
if image, ok := r.lookup(id); ok {
|
||||||
return image, nil
|
return copyImage(image), nil
|
||||||
}
|
}
|
||||||
return nil, ErrImageUnknown
|
return nil, ErrImageUnknown
|
||||||
}
|
}
|
||||||
@ -546,7 +561,7 @@ func (r *imageStore) BigDataNames(id string) ([]string, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrImageUnknown
|
return nil, ErrImageUnknown
|
||||||
}
|
}
|
||||||
return image.BigDataNames, nil
|
return copyStringSlice(image.BigDataNames), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageSliceWithoutValue(slice []*Image, value *Image) []*Image {
|
func imageSliceWithoutValue(slice []*Image, value *Image) []*Image {
|
||||||
|
2
vendor/github.com/containers/storage/images_ffjson.go
generated
vendored
2
vendor/github.com/containers/storage/images_ffjson.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
||||||
// source: images.go
|
// source: ./images.go
|
||||||
|
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
|
27
vendor/github.com/containers/storage/layers.go
generated
vendored
27
vendor/github.com/containers/storage/layers.go
generated
vendored
@ -223,10 +223,29 @@ type layerStore struct {
|
|||||||
byuncompressedsum map[digest.Digest][]string
|
byuncompressedsum map[digest.Digest][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyLayer(l *Layer) *Layer {
|
||||||
|
return &Layer{
|
||||||
|
ID: l.ID,
|
||||||
|
Names: copyStringSlice(l.Names),
|
||||||
|
Parent: l.Parent,
|
||||||
|
Metadata: l.Metadata,
|
||||||
|
MountLabel: l.MountLabel,
|
||||||
|
MountPoint: l.MountPoint,
|
||||||
|
MountCount: l.MountCount,
|
||||||
|
Created: l.Created,
|
||||||
|
CompressedDigest: l.CompressedDigest,
|
||||||
|
CompressedSize: l.CompressedSize,
|
||||||
|
UncompressedDigest: l.UncompressedDigest,
|
||||||
|
UncompressedSize: l.UncompressedSize,
|
||||||
|
CompressionType: l.CompressionType,
|
||||||
|
Flags: copyStringInterfaceMap(l.Flags),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *layerStore) Layers() ([]Layer, error) {
|
func (r *layerStore) Layers() ([]Layer, error) {
|
||||||
layers := make([]Layer, len(r.layers))
|
layers := make([]Layer, len(r.layers))
|
||||||
for i := range r.layers {
|
for i := range r.layers {
|
||||||
layers[i] = *(r.layers[i])
|
layers[i] = *copyLayer(r.layers[i])
|
||||||
}
|
}
|
||||||
return layers, nil
|
return layers, nil
|
||||||
}
|
}
|
||||||
@ -558,7 +577,7 @@ func (r *layerStore) Put(id, parent string, names []string, mountLabel string, o
|
|||||||
return nil, -1, err
|
return nil, -1, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return layer, size, err
|
return copyLayer(layer), size, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *layerStore) CreateWithFlags(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}) (layer *Layer, err error) {
|
func (r *layerStore) CreateWithFlags(id, parent string, names []string, mountLabel string, options map[string]string, writeable bool, flags map[string]interface{}) (layer *Layer, err error) {
|
||||||
@ -731,7 +750,7 @@ func (r *layerStore) Exists(id string) bool {
|
|||||||
|
|
||||||
func (r *layerStore) Get(id string) (*Layer, error) {
|
func (r *layerStore) Get(id string) (*Layer, error) {
|
||||||
if layer, ok := r.lookup(id); ok {
|
if layer, ok := r.lookup(id); ok {
|
||||||
return layer, nil
|
return copyLayer(layer), nil
|
||||||
}
|
}
|
||||||
return nil, ErrLayerUnknown
|
return nil, ErrLayerUnknown
|
||||||
}
|
}
|
||||||
@ -1003,7 +1022,7 @@ func (r *layerStore) layersByDigestMap(m map[digest.Digest][]string, d digest.Di
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrLayerUnknown
|
return nil, ErrLayerUnknown
|
||||||
}
|
}
|
||||||
layers = append(layers, *layer)
|
layers = append(layers, *copyLayer(layer))
|
||||||
}
|
}
|
||||||
return layers, nil
|
return layers, nil
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/containers/storage/layers_ffjson.go
generated
vendored
2
vendor/github.com/containers/storage/layers_ffjson.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
|
||||||
// source: layers.go. Hack to make this work on github.com
|
// source: ./layers.go
|
||||||
|
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
|
8
vendor/github.com/containers/storage/pkg/archive/archive.go
generated
vendored
8
vendor/github.com/containers/storage/pkg/archive/archive.go
generated
vendored
@ -45,6 +45,10 @@ type (
|
|||||||
// This format will be converted to the standard format on pack
|
// This format will be converted to the standard format on pack
|
||||||
// and from the standard format on unpack.
|
// and from the standard format on unpack.
|
||||||
WhiteoutFormat WhiteoutFormat
|
WhiteoutFormat WhiteoutFormat
|
||||||
|
// This is additional data to be used by the converter. It will
|
||||||
|
// not survive a round trip through JSON, so it's primarily
|
||||||
|
// intended for generating archives (i.e., converting writes).
|
||||||
|
WhiteoutData interface{}
|
||||||
// When unpacking, specifies whether overwriting a directory with a
|
// When unpacking, specifies whether overwriting a directory with a
|
||||||
// non-directory is allowed and vice versa.
|
// non-directory is allowed and vice versa.
|
||||||
NoOverwriteDirNonDir bool
|
NoOverwriteDirNonDir bool
|
||||||
@ -702,7 +706,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
|||||||
compressWriter,
|
compressWriter,
|
||||||
options.ChownOpts,
|
options.ChownOpts,
|
||||||
)
|
)
|
||||||
ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat)
|
ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat, options.WhiteoutData)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
// Make sure to check the error on Close.
|
// Make sure to check the error on Close.
|
||||||
@ -860,7 +864,7 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err
|
|||||||
var dirs []*tar.Header
|
var dirs []*tar.Header
|
||||||
idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
|
idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
|
||||||
rootIDs := idMappings.RootPair()
|
rootIDs := idMappings.RootPair()
|
||||||
whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat)
|
whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat, options.WhiteoutData)
|
||||||
|
|
||||||
// Iterate through the files in the archive.
|
// Iterate through the files in the archive.
|
||||||
loop:
|
loop:
|
||||||
|
62
vendor/github.com/containers/storage/pkg/archive/archive_linux.go
generated
vendored
62
vendor/github.com/containers/storage/pkg/archive/archive_linux.go
generated
vendored
@ -5,21 +5,27 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/containers/storage/pkg/system"
|
"github.com/containers/storage/pkg/system"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
|
func getWhiteoutConverter(format WhiteoutFormat, data interface{}) tarWhiteoutConverter {
|
||||||
if format == OverlayWhiteoutFormat {
|
if format == OverlayWhiteoutFormat {
|
||||||
return overlayWhiteoutConverter{}
|
if rolayers, ok := data.([]string); ok && len(rolayers) > 0 {
|
||||||
|
return overlayWhiteoutConverter{rolayers: rolayers}
|
||||||
|
}
|
||||||
|
return overlayWhiteoutConverter{rolayers: nil}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type overlayWhiteoutConverter struct{}
|
type overlayWhiteoutConverter struct {
|
||||||
|
rolayers []string
|
||||||
|
}
|
||||||
|
|
||||||
func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) (wo *tar.Header, err error) {
|
func (o overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) (wo *tar.Header, err error) {
|
||||||
// convert whiteouts to AUFS format
|
// convert whiteouts to AUFS format
|
||||||
if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 {
|
if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 {
|
||||||
// we just rename the file and make it normal
|
// we just rename the file and make it normal
|
||||||
@ -31,7 +37,7 @@ func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os
|
|||||||
}
|
}
|
||||||
|
|
||||||
if fi.Mode()&os.ModeDir != 0 {
|
if fi.Mode()&os.ModeDir != 0 {
|
||||||
// convert opaque dirs to AUFS format by writing an empty file with the prefix
|
// convert opaque dirs to AUFS format by writing an empty file with the whiteout prefix
|
||||||
opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque")
|
opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -40,7 +46,29 @@ func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os
|
|||||||
if hdr.Xattrs != nil {
|
if hdr.Xattrs != nil {
|
||||||
delete(hdr.Xattrs, "trusted.overlay.opaque")
|
delete(hdr.Xattrs, "trusted.overlay.opaque")
|
||||||
}
|
}
|
||||||
|
// If there are no lower layers, then it can't have been deleted in this layer.
|
||||||
|
if len(o.rolayers) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
// At this point, we have a directory that's opaque. If it appears in one of the lower
|
||||||
|
// layers, then it was newly-created here, so it wasn't also deleted here.
|
||||||
|
for _, rolayer := range o.rolayers {
|
||||||
|
stat, statErr := os.Stat(filepath.Join(rolayer, hdr.Name))
|
||||||
|
if statErr != nil && !os.IsNotExist(statErr) && !isENOTDIR(statErr) {
|
||||||
|
// Not sure what happened here.
|
||||||
|
return nil, statErr
|
||||||
|
}
|
||||||
|
if statErr == nil {
|
||||||
|
if stat.Mode()&os.ModeCharDevice != 0 {
|
||||||
|
// It's a whiteout for this directory, so it can't have been
|
||||||
|
// both deleted and recreated in the layer we're diffing.
|
||||||
|
s := stat.Sys().(*syscall.Stat_t)
|
||||||
|
if major(s.Rdev) == 0 && minor(s.Rdev) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// It's not whiteout, so it was there in the older layer, so we need to
|
||||||
|
// add a whiteout for this item in this layer.
|
||||||
// create a header for the whiteout file
|
// create a header for the whiteout file
|
||||||
// it should inherit some properties from the parent, but be a regular file
|
// it should inherit some properties from the parent, but be a regular file
|
||||||
wo = &tar.Header{
|
wo = &tar.Header{
|
||||||
@ -55,6 +83,28 @@ func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os
|
|||||||
AccessTime: hdr.AccessTime,
|
AccessTime: hdr.AccessTime,
|
||||||
ChangeTime: hdr.ChangeTime,
|
ChangeTime: hdr.ChangeTime,
|
||||||
}
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for dir := filepath.Dir(hdr.Name); dir != "" && dir != "." && dir != string(os.PathSeparator); dir = filepath.Dir(dir) {
|
||||||
|
// Check for whiteout for a parent directory in a parent layer.
|
||||||
|
stat, statErr := os.Stat(filepath.Join(rolayer, dir))
|
||||||
|
if statErr != nil && !os.IsNotExist(statErr) && !isENOTDIR(statErr) {
|
||||||
|
// Not sure what happened here.
|
||||||
|
return nil, statErr
|
||||||
|
}
|
||||||
|
if statErr == nil {
|
||||||
|
if stat.Mode()&os.ModeCharDevice != 0 {
|
||||||
|
// If it's whiteout for a parent directory, then the
|
||||||
|
// original directory wasn't inherited into this layer,
|
||||||
|
// so we don't need to emit whiteout for it.
|
||||||
|
s := stat.Sys().(*syscall.Stat_t)
|
||||||
|
if major(s.Rdev) == 0 && minor(s.Rdev) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/containers/storage/pkg/archive/archive_other.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/archive/archive_other.go
generated
vendored
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
package archive
|
package archive
|
||||||
|
|
||||||
func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
|
func getWhiteoutConverter(format WhiteoutFormat, data interface{}) tarWhiteoutConverter {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
57
vendor/github.com/containers/storage/pkg/archive/changes.go
generated
vendored
57
vendor/github.com/containers/storage/pkg/archive/changes.go
generated
vendored
@ -81,7 +81,7 @@ func sameFsTimeSpec(a, b syscall.Timespec) bool {
|
|||||||
// Changes walks the path rw and determines changes for the files in the path,
|
// Changes walks the path rw and determines changes for the files in the path,
|
||||||
// with respect to the parent layers
|
// with respect to the parent layers
|
||||||
func Changes(layers []string, rw string) ([]Change, error) {
|
func Changes(layers []string, rw string) ([]Change, error) {
|
||||||
return changes(layers, rw, aufsDeletedFile, aufsMetadataSkip)
|
return changes(layers, rw, aufsDeletedFile, aufsMetadataSkip, aufsWhiteoutPresent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func aufsMetadataSkip(path string) (skip bool, err error) {
|
func aufsMetadataSkip(path string) (skip bool, err error) {
|
||||||
@ -104,10 +104,35 @@ func aufsDeletedFile(root, path string, fi os.FileInfo) (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func aufsWhiteoutPresent(root, path string) (bool, error) {
|
||||||
|
f := filepath.Join(filepath.Dir(path), WhiteoutPrefix+filepath.Base(path))
|
||||||
|
_, err := os.Stat(filepath.Join(root, f))
|
||||||
|
if err == nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) || isENOTDIR(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func isENOTDIR(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if perror, ok := err.(*os.PathError); ok {
|
||||||
|
if errno, ok := perror.Err.(syscall.Errno); ok {
|
||||||
|
return errno == syscall.ENOTDIR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type skipChange func(string) (bool, error)
|
type skipChange func(string) (bool, error)
|
||||||
type deleteChange func(string, string, os.FileInfo) (string, error)
|
type deleteChange func(string, string, os.FileInfo) (string, error)
|
||||||
|
type whiteoutChange func(string, string) (bool, error)
|
||||||
|
|
||||||
func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Change, error) {
|
func changes(layers []string, rw string, dc deleteChange, sc skipChange, wc whiteoutChange) ([]Change, error) {
|
||||||
var (
|
var (
|
||||||
changes []Change
|
changes []Change
|
||||||
changedDirs = make(map[string]struct{})
|
changedDirs = make(map[string]struct{})
|
||||||
@ -156,7 +181,28 @@ func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Chan
|
|||||||
change.Kind = ChangeAdd
|
change.Kind = ChangeAdd
|
||||||
|
|
||||||
// ...Unless it already existed in a top layer, in which case, it's a modification
|
// ...Unless it already existed in a top layer, in which case, it's a modification
|
||||||
|
layerScan:
|
||||||
for _, layer := range layers {
|
for _, layer := range layers {
|
||||||
|
if wc != nil {
|
||||||
|
// ...Unless a lower layer also had whiteout for this directory or one of its parents,
|
||||||
|
// in which case, it's new
|
||||||
|
ignore, err := wc(layer, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ignore {
|
||||||
|
break layerScan
|
||||||
|
}
|
||||||
|
for dir := filepath.Dir(path); dir != "" && dir != string(os.PathSeparator); dir = filepath.Dir(dir) {
|
||||||
|
ignore, err = wc(layer, dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ignore {
|
||||||
|
break layerScan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
stat, err := os.Stat(filepath.Join(layer, path))
|
stat, err := os.Stat(filepath.Join(layer, path))
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
@ -187,10 +233,15 @@ func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Chan
|
|||||||
}
|
}
|
||||||
if change.Kind == ChangeAdd || change.Kind == ChangeDelete {
|
if change.Kind == ChangeAdd || change.Kind == ChangeDelete {
|
||||||
parent := filepath.Dir(path)
|
parent := filepath.Dir(path)
|
||||||
|
tail := []Change{}
|
||||||
|
for parent != "/" {
|
||||||
if _, ok := changedDirs[parent]; !ok && parent != "/" {
|
if _, ok := changedDirs[parent]; !ok && parent != "/" {
|
||||||
changes = append(changes, Change{Path: parent, Kind: ChangeModify})
|
tail = append([]Change{{Path: parent, Kind: ChangeModify}}, tail...)
|
||||||
changedDirs[parent] = struct{}{}
|
changedDirs[parent] = struct{}{}
|
||||||
}
|
}
|
||||||
|
parent = filepath.Dir(parent)
|
||||||
|
}
|
||||||
|
changes = append(changes, tail...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record change
|
// Record change
|
||||||
|
78
vendor/github.com/containers/storage/pkg/archive/changes_linux.go
generated
vendored
78
vendor/github.com/containers/storage/pkg/archive/changes_linux.go
generated
vendored
@ -288,26 +288,96 @@ func clen(n []byte) int {
|
|||||||
// OverlayChanges walks the path rw and determines changes for the files in the path,
|
// OverlayChanges walks the path rw and determines changes for the files in the path,
|
||||||
// with respect to the parent layers
|
// with respect to the parent layers
|
||||||
func OverlayChanges(layers []string, rw string) ([]Change, error) {
|
func OverlayChanges(layers []string, rw string) ([]Change, error) {
|
||||||
return changes(layers, rw, overlayDeletedFile, nil)
|
dc := func(root, path string, fi os.FileInfo) (string, error) {
|
||||||
|
return overlayDeletedFile(layers, root, path, fi)
|
||||||
|
}
|
||||||
|
return changes(layers, rw, dc, nil, overlayLowerContainsWhiteout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func overlayDeletedFile(root, path string, fi os.FileInfo) (string, error) {
|
func overlayLowerContainsWhiteout(root, path string) (bool, error) {
|
||||||
|
// Whiteout for a file or directory has the same name, but is for a character
|
||||||
|
// device with major/minor of 0/0.
|
||||||
|
stat, err := os.Stat(filepath.Join(root, path))
|
||||||
|
if err != nil && !os.IsNotExist(err) && !isENOTDIR(err) {
|
||||||
|
// Not sure what happened here.
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if err == nil && stat.Mode()&os.ModeCharDevice != 0 {
|
||||||
|
// Check if there's whiteout for the specified item in the specified layer.
|
||||||
|
s := stat.Sys().(*syscall.Stat_t)
|
||||||
|
if major(s.Rdev) == 0 && minor(s.Rdev) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func overlayDeletedFile(layers []string, root, path string, fi os.FileInfo) (string, error) {
|
||||||
|
// If it's a whiteout item, then a file or directory with that name is removed by this layer.
|
||||||
if fi.Mode()&os.ModeCharDevice != 0 {
|
if fi.Mode()&os.ModeCharDevice != 0 {
|
||||||
s := fi.Sys().(*syscall.Stat_t)
|
s := fi.Sys().(*syscall.Stat_t)
|
||||||
if major(s.Rdev) == 0 && minor(s.Rdev) == 0 {
|
if major(s.Rdev) == 0 && minor(s.Rdev) == 0 {
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fi.Mode()&os.ModeDir != 0 {
|
// After this we only need to pay attention to directories.
|
||||||
|
if !fi.IsDir() {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
// If the directory isn't marked as opaque, then it's just a normal directory.
|
||||||
opaque, err := system.Lgetxattr(filepath.Join(root, path), "trusted.overlay.opaque")
|
opaque, err := system.Lgetxattr(filepath.Join(root, path), "trusted.overlay.opaque")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if len(opaque) == 1 && opaque[0] == 'y' {
|
if len(opaque) != 1 || opaque[0] != 'y' {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// If there are no lower layers, then it can't have been deleted and recreated in this layer.
|
||||||
|
if len(layers) == 0 {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// At this point, we have a directory that's opaque. If it appears in one of the lower
|
||||||
|
// layers, then it was newly-created here, so it wasn't also deleted here.
|
||||||
|
for _, layer := range layers {
|
||||||
|
stat, err := os.Stat(filepath.Join(layer, path))
|
||||||
|
if err != nil && !os.IsNotExist(err) && !isENOTDIR(err) {
|
||||||
|
// Not sure what happened here.
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if stat.Mode()&os.ModeCharDevice != 0 {
|
||||||
|
// It's a whiteout for this directory, so it can't have been
|
||||||
|
// deleted in this layer.
|
||||||
|
s := stat.Sys().(*syscall.Stat_t)
|
||||||
|
if major(s.Rdev) == 0 && minor(s.Rdev) == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// It's not whiteout, so it was there in the older layer, so it has to be
|
||||||
|
// marked as deleted in this layer.
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
for dir := filepath.Dir(path); dir != "" && dir != string(os.PathSeparator); dir = filepath.Dir(dir) {
|
||||||
|
// Check for whiteout for a parent directory.
|
||||||
|
stat, err := os.Stat(filepath.Join(layer, dir))
|
||||||
|
if err != nil && !os.IsNotExist(err) && !isENOTDIR(err) {
|
||||||
|
// Not sure what happened here.
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if stat.Mode()&os.ModeCharDevice != 0 {
|
||||||
|
// If it's whiteout for a parent directory, then the
|
||||||
|
// original directory wasn't inherited into the top layer.
|
||||||
|
s := stat.Sys().(*syscall.Stat_t)
|
||||||
|
if major(s.Rdev) == 0 && minor(s.Rdev) == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We didn't find the same path in any older layers, so it was new in this one.
|
||||||
return "", nil
|
return "", nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
35
vendor/github.com/containers/storage/store.go
generated
vendored
35
vendor/github.com/containers/storage/store.go
generated
vendored
@ -2350,6 +2350,41 @@ func stringSliceWithoutValue(slice []string, value string) []string {
|
|||||||
return modified
|
return modified
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyStringSlice(slice []string) []string {
|
||||||
|
if len(slice) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := make([]string, len(slice))
|
||||||
|
copy(ret, slice)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyStringInt64Map(m map[string]int64) map[string]int64 {
|
||||||
|
ret := make(map[string]int64, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
ret[k] = v
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyStringDigestMap(m map[string]digest.Digest) map[string]digest.Digest {
|
||||||
|
ret := make(map[string]digest.Digest, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
ret[k] = v
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// copyStringInterfaceMap still forces us to assume that the interface{} is
|
||||||
|
// a non-pointer scalar value
|
||||||
|
func copyStringInterfaceMap(m map[string]interface{}) map[string]interface{} {
|
||||||
|
ret := make(map[string]interface{}, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
ret[k] = v
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
const configFile = "/etc/containers/storage.conf"
|
const configFile = "/etc/containers/storage.conf"
|
||||||
|
|
||||||
// OptionsConfig represents the "storage.options" TOML config table.
|
// OptionsConfig represents the "storage.options" TOML config table.
|
||||||
|
Reference in New Issue
Block a user