소스 검색

Merge pull request #36684 from cpuguy83/bump_containerd_client

Bump containerd client
Vincent Demeester 7 년 전
부모
커밋
8bb5a28eed
100개의 변경된 파일2203개의 추가작업 그리고 1671개의 파일을 삭제
  1. 7 0
      libcontainerd/client_daemon.go
  2. 2 11
      libcontainerd/remote_daemon.go
  3. 0 16
      libcontainerd/remote_daemon_options_linux.go
  4. 1 1
      vendor.conf
  5. 0 0
      vendor/github.com/containerd/containerd/LICENSE
  6. 2 1
      vendor/github.com/containerd/containerd/README.md
  7. 1 3
      vendor/github.com/containerd/containerd/api/events/container.pb.go
  8. 16 0
      vendor/github.com/containerd/containerd/api/events/doc.go
  9. 16 0
      vendor/github.com/containerd/containerd/api/services/events/v1/doc.go
  10. 1 3
      vendor/github.com/containerd/containerd/api/services/events/v1/events.pb.go
  11. 16 0
      vendor/github.com/containerd/containerd/api/services/images/v1/docs.go
  12. 16 0
      vendor/github.com/containerd/containerd/api/services/introspection/v1/doc.go
  13. 16 0
      vendor/github.com/containerd/containerd/api/services/leases/v1/doc.go
  14. 16 0
      vendor/github.com/containerd/containerd/api/types/doc.go
  15. 68 0
      vendor/github.com/containerd/containerd/archive/strconv.go
  16. 170 97
      vendor/github.com/containerd/containerd/archive/tar.go
  17. 20 0
      vendor/github.com/containerd/containerd/archive/tar_opts.go
  18. 23 0
      vendor/github.com/containerd/containerd/archive/tar_opts_unix.go
  19. 44 0
      vendor/github.com/containerd/containerd/archive/tar_opts_windows.go
  20. 28 2
      vendor/github.com/containerd/containerd/archive/tar_unix.go
  21. 343 0
      vendor/github.com/containerd/containerd/archive/tar_windows.go
  22. 16 0
      vendor/github.com/containerd/containerd/archive/time.go
  23. 16 0
      vendor/github.com/containerd/containerd/archive/time_darwin.go
  24. 16 0
      vendor/github.com/containerd/containerd/archive/time_unix.go
  25. 16 0
      vendor/github.com/containerd/containerd/archive/time_windows.go
  26. 38 3
      vendor/github.com/containerd/containerd/cio/io.go
  27. 38 6
      vendor/github.com/containerd/containerd/cio/io_unix.go
  28. 31 3
      vendor/github.com/containerd/containerd/cio/io_windows.go
  29. 65 63
      vendor/github.com/containerd/containerd/client.go
  30. 16 0
      vendor/github.com/containerd/containerd/client_opts.go
  31. 16 0
      vendor/github.com/containerd/containerd/container.go
  32. 16 0
      vendor/github.com/containerd/containerd/container_opts.go
  33. 39 19
      vendor/github.com/containerd/containerd/container_opts_unix.go
  34. 16 0
      vendor/github.com/containerd/containerd/containers/containers.go
  35. 16 0
      vendor/github.com/containerd/containerd/containerstore.go
  36. 16 0
      vendor/github.com/containerd/containerd/content/content.go
  37. 33 16
      vendor/github.com/containerd/containerd/content/helpers.go
  38. 16 0
      vendor/github.com/containerd/containerd/content/local/locks.go
  39. 16 0
      vendor/github.com/containerd/containerd/content/local/readerat.go
  40. 16 0
      vendor/github.com/containerd/containerd/content/local/store.go
  41. 17 2
      vendor/github.com/containerd/containerd/content/local/store_unix.go
  42. 16 0
      vendor/github.com/containerd/containerd/content/local/store_windows.go
  43. 16 0
      vendor/github.com/containerd/containerd/content/local/writer.go
  44. 16 0
      vendor/github.com/containerd/containerd/content_reader.go
  45. 16 0
      vendor/github.com/containerd/containerd/content_store.go
  46. 16 0
      vendor/github.com/containerd/containerd/content_writer.go
  47. 35 0
      vendor/github.com/containerd/containerd/defaults/defaults_unix.go
  48. 43 0
      vendor/github.com/containerd/containerd/defaults/defaults_windows.go
  49. 19 0
      vendor/github.com/containerd/containerd/defaults/doc.go
  50. 17 1
      vendor/github.com/containerd/containerd/dialer/dialer.go
  51. 16 0
      vendor/github.com/containerd/containerd/dialer/dialer_unix.go
  52. 16 0
      vendor/github.com/containerd/containerd/dialer/dialer_windows.go
  53. 26 3
      vendor/github.com/containerd/containerd/diff.go
  54. 30 10
      vendor/github.com/containerd/containerd/diff/diff.go
  55. 16 0
      vendor/github.com/containerd/containerd/errdefs/errors.go
  56. 16 0
      vendor/github.com/containerd/containerd/errdefs/grpc.go
  57. 18 2
      vendor/github.com/containerd/containerd/events/events.go
  58. 16 0
      vendor/github.com/containerd/containerd/events/exchange/exchange.go
  59. 16 0
      vendor/github.com/containerd/containerd/filters/adaptor.go
  60. 16 0
      vendor/github.com/containerd/containerd/filters/filter.go
  61. 16 0
      vendor/github.com/containerd/containerd/filters/parser.go
  62. 16 0
      vendor/github.com/containerd/containerd/filters/quote.go
  63. 16 0
      vendor/github.com/containerd/containerd/filters/scanner.go
  64. 0 119
      vendor/github.com/containerd/containerd/fs/copy.go
  65. 0 83
      vendor/github.com/containerd/containerd/fs/copy_linux.go
  66. 0 68
      vendor/github.com/containerd/containerd/fs/copy_unix.go
  67. 0 33
      vendor/github.com/containerd/containerd/fs/copy_windows.go
  68. 0 381
      vendor/github.com/containerd/containerd/fs/diff.go
  69. 0 58
      vendor/github.com/containerd/containerd/fs/diff_unix.go
  70. 0 32
      vendor/github.com/containerd/containerd/fs/diff_windows.go
  71. 0 87
      vendor/github.com/containerd/containerd/fs/dtype_linux.go
  72. 0 22
      vendor/github.com/containerd/containerd/fs/du.go
  73. 0 83
      vendor/github.com/containerd/containerd/fs/du_unix.go
  74. 0 60
      vendor/github.com/containerd/containerd/fs/du_windows.go
  75. 0 27
      vendor/github.com/containerd/containerd/fs/hardlink.go
  76. 0 17
      vendor/github.com/containerd/containerd/fs/hardlink_unix.go
  77. 0 7
      vendor/github.com/containerd/containerd/fs/hardlink_windows.go
  78. 0 276
      vendor/github.com/containerd/containerd/fs/path.go
  79. 0 13
      vendor/github.com/containerd/containerd/fs/time.go
  80. 22 0
      vendor/github.com/containerd/containerd/gc/gc.go
  81. 16 0
      vendor/github.com/containerd/containerd/grpc.go
  82. 16 0
      vendor/github.com/containerd/containerd/identifiers/validate.go
  83. 16 0
      vendor/github.com/containerd/containerd/image.go
  84. 16 0
      vendor/github.com/containerd/containerd/image_store.go
  85. 89 2
      vendor/github.com/containerd/containerd/images/handlers.go
  86. 39 25
      vendor/github.com/containerd/containerd/images/image.go
  87. 17 1
      vendor/github.com/containerd/containerd/images/importexport.go
  88. 16 0
      vendor/github.com/containerd/containerd/images/mediatypes.go
  89. 16 0
      vendor/github.com/containerd/containerd/labels/validate.go
  90. 16 0
      vendor/github.com/containerd/containerd/lease.go
  91. 16 0
      vendor/github.com/containerd/containerd/leases/context.go
  92. 16 0
      vendor/github.com/containerd/containerd/leases/grpc.go
  93. 20 10
      vendor/github.com/containerd/containerd/linux/bundle.go
  94. 20 0
      vendor/github.com/containerd/containerd/linux/proc/deleted_state.go
  95. 16 0
      vendor/github.com/containerd/containerd/linux/proc/exec.go
  96. 16 0
      vendor/github.com/containerd/containerd/linux/proc/exec_state.go
  97. 18 2
      vendor/github.com/containerd/containerd/linux/proc/init.go
  98. 49 0
      vendor/github.com/containerd/containerd/linux/proc/init_state.go
  99. 34 3
      vendor/github.com/containerd/containerd/linux/proc/io.go
  100. 16 0
      vendor/github.com/containerd/containerd/linux/proc/process.go

+ 7 - 0
libcontainerd/client_daemon.go

@@ -114,6 +114,13 @@ type client struct {
 	containers map[string]*container
 }
 
+func (c *client) reconnect() error {
+	c.Lock()
+	err := c.remote.Reconnect()
+	c.Unlock()
+	return err
+}
+
 func (c *client) setRemote(remote *containerd.Client) {
 	c.Lock()
 	c.remote = remote

+ 2 - 11
libcontainerd/remote_daemon.go

@@ -311,20 +311,17 @@ func (r *remote) monitorConnection(monitor *containerd.Client) {
 			<-r.daemonWaitCh
 		}
 
-		monitor.Close()
 		os.Remove(r.GRPC.Address)
 		if err := r.startContainerd(); err != nil {
 			r.logger.WithError(err).Error("failed restarting containerd")
 			continue
 		}
 
-		newMonitor, err := containerd.New(r.GRPC.Address)
-		if err != nil {
+		if err := monitor.Reconnect(); err != nil {
 			r.logger.WithError(err).Error("failed connect to containerd")
 			continue
 		}
 
-		monitor = newMonitor
 		var wg sync.WaitGroup
 
 		for _, c := range r.clients {
@@ -333,18 +330,12 @@ func (r *remote) monitorConnection(monitor *containerd.Client) {
 			go func(c *client) {
 				defer wg.Done()
 				c.logger.WithField("namespace", c.namespace).Debug("creating new containerd remote client")
-				c.remote.Close()
-
-				remote, err := containerd.New(r.GRPC.Address, containerd.WithDefaultNamespace(c.namespace))
-				if err != nil {
+				if err := c.reconnect(); err != nil {
 					r.logger.WithError(err).Error("failed to connect to containerd")
 					// TODO: Better way to handle this?
 					// This *shouldn't* happen, but this could wind up where the daemon
 					// is not able to communicate with an eventually up containerd
-					return
 				}
-
-				c.setRemote(remote)
 			}(c)
 
 			wg.Wait()

+ 0 - 16
libcontainerd/remote_daemon_options_linux.go

@@ -16,19 +16,3 @@ func (o oomScore) Apply(r Remote) error {
 	}
 	return fmt.Errorf("WithOOMScore option not supported for this remote")
 }
-
-// WithSubreaper sets whether containerd should register itself as a
-// subreaper
-func WithSubreaper(reap bool) RemoteOption {
-	return subreaper(reap)
-}
-
-type subreaper bool
-
-func (s subreaper) Apply(r Remote) error {
-	if remote, ok := r.(*remote); ok {
-		remote.NoSubreaper = !bool(s)
-		return nil
-	}
-	return fmt.Errorf("WithSubreaper option not supported for this remote")
-}

+ 1 - 1
vendor.conf

@@ -108,7 +108,7 @@ github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7
 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
 
 # containerd
-github.com/containerd/containerd 3fa104f843ec92328912e042b767d26825f202aa
+github.com/containerd/containerd 4ac4fd0b6a268fe6f38b2b2e32e40daa7e424fac
 github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6
 github.com/containerd/continuity d8fb8589b0e8e85b8c8bbaa8840226d0dfeb7371
 github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130

+ 0 - 0
vendor/github.com/containerd/containerd/LICENSE.code → vendor/github.com/containerd/containerd/LICENSE


+ 2 - 1
vendor/github.com/containerd/containerd/README.md

@@ -4,6 +4,7 @@
 [![Build Status](https://travis-ci.org/containerd/containerd.svg?branch=master)](https://travis-ci.org/containerd/containerd)
 [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd?ref=badge_shield)
 [![Go Report Card](https://goreportcard.com/badge/github.com/containerd/containerd)](https://goreportcard.com/report/github.com/containerd/containerd)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1271/badge)](https://bestpractices.coreinfrastructure.org/projects/1271)
 
 containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc.
 
@@ -13,7 +14,7 @@ containerd is designed to be embedded into a larger system, rather than being us
 
 ## Getting Started
 
-See our documentation on [containerd.io](containerd.io):
+See our documentation on [containerd.io](https://containerd.io):
 * [for ops and admins](docs/ops.md)
 * [namespaces](docs/namespaces.md)
 * [client options](docs/client-opts.md)

+ 1 - 3
vendor/github.com/containerd/containerd/api/events/container.pb.go

@@ -158,9 +158,7 @@ func (m *ContainerCreate_Runtime) Field(fieldpath []string) (string, bool) {
 			return "", false
 		}
 
-		adaptor, ok := decoded.(interface {
-			Field([]string) (string, bool)
-		})
+		adaptor, ok := decoded.(interface{ Field([]string) (string, bool) })
 		if !ok {
 			return "", false
 		}

+ 16 - 0
vendor/github.com/containerd/containerd/api/events/doc.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 // Package events has protobuf types for various events that are used in
 // containerd.
 package events

+ 16 - 0
vendor/github.com/containerd/containerd/api/services/events/v1/doc.go

@@ -1,2 +1,18 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 // Package events defines the event pushing and subscription service.
 package events

+ 1 - 3
vendor/github.com/containerd/containerd/api/services/events/v1/events.pb.go

@@ -115,9 +115,7 @@ func (m *Envelope) Field(fieldpath []string) (string, bool) {
 			return "", false
 		}
 
-		adaptor, ok := decoded.(interface {
-			Field([]string) (string, bool)
-		})
+		adaptor, ok := decoded.(interface{ Field([]string) (string, bool) })
 		if !ok {
 			return "", false
 		}

+ 16 - 0
vendor/github.com/containerd/containerd/api/services/images/v1/docs.go

@@ -1 +1,17 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package images

+ 16 - 0
vendor/github.com/containerd/containerd/api/services/introspection/v1/doc.go

@@ -1 +1,17 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package introspection

+ 16 - 0
vendor/github.com/containerd/containerd/api/services/leases/v1/doc.go

@@ -1 +1,17 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package leases

+ 16 - 0
vendor/github.com/containerd/containerd/api/types/doc.go

@@ -1 +1,17 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package types

+ 68 - 0
vendor/github.com/containerd/containerd/archive/strconv.go

@@ -0,0 +1,68 @@
+// +build windows
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package archive
+
+import (
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/dmcgowan/go-tar"
+)
+
+// Forked from https://github.com/golang/go/blob/master/src/archive/tar/strconv.go
+// as archive/tar doesn't support CreationTime, but does handle PAX time parsing,
+// and there's no need to re-invent the wheel.
+
+// parsePAXTime takes a string of the form %d.%d as described in the PAX
+// specification. Note that this implementation allows for negative timestamps,
+// which is allowed for by the PAX specification, but not always portable.
+func parsePAXTime(s string) (time.Time, error) {
+	const maxNanoSecondDigits = 9
+
+	// Split string into seconds and sub-seconds parts.
+	ss, sn := s, ""
+	if pos := strings.IndexByte(s, '.'); pos >= 0 {
+		ss, sn = s[:pos], s[pos+1:]
+	}
+
+	// Parse the seconds.
+	secs, err := strconv.ParseInt(ss, 10, 64)
+	if err != nil {
+		return time.Time{}, tar.ErrHeader
+	}
+	if len(sn) == 0 {
+		return time.Unix(secs, 0), nil // No sub-second values
+	}
+
+	// Parse the nanoseconds.
+	if strings.Trim(sn, "0123456789") != "" {
+		return time.Time{}, tar.ErrHeader
+	}
+	if len(sn) < maxNanoSecondDigits {
+		sn += strings.Repeat("0", maxNanoSecondDigits-len(sn)) // Right pad
+	} else {
+		sn = sn[:maxNanoSecondDigits] // Right truncate
+	}
+	nsecs, _ := strconv.ParseInt(sn, 10, 64) // Must succeed
+	if len(ss) > 0 && ss[0] == '-' {
+		return time.Unix(secs, -nsecs), nil // Negative correction
+	}
+	return time.Unix(secs, nsecs), nil
+}

+ 170 - 97
vendor/github.com/containerd/containerd/archive/tar.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package archive
 
 import (
@@ -13,19 +29,21 @@ import (
 	"syscall"
 	"time"
 
-	"github.com/containerd/containerd/fs"
 	"github.com/containerd/containerd/log"
+	"github.com/containerd/continuity/fs"
 	"github.com/dmcgowan/go-tar"
 	"github.com/pkg/errors"
 )
 
-var bufferPool = &sync.Pool{
+var bufPool = &sync.Pool{
 	New: func() interface{} {
 		buffer := make([]byte, 32*1024)
 		return &buffer
 	},
 }
 
+var errInvalidArchive = errors.New("invalid archive")
+
 // Diff returns a tar stream of the computed filesystem
 // difference between the provided directories.
 //
@@ -87,12 +105,23 @@ const (
 
 // Apply applies a tar stream of an OCI style diff tar.
 // See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
-func Apply(ctx context.Context, root string, r io.Reader) (int64, error) {
+func Apply(ctx context.Context, root string, r io.Reader, opts ...ApplyOpt) (int64, error) {
 	root = filepath.Clean(root)
 
+	var options ApplyOptions
+	for _, opt := range opts {
+		if err := opt(&options); err != nil {
+			return 0, errors.Wrap(err, "failed to apply option")
+		}
+	}
+
+	return apply(ctx, root, tar.NewReader(r), options)
+}
+
+// applyNaive applies a tar stream of an OCI style diff tar.
+// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
+func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
 	var (
-		tr   = tar.NewReader(r)
-		size int64
 		dirs []*tar.Header
 
 		// Used for handling opaque directory markers which
@@ -220,6 +249,15 @@ func Apply(ctx context.Context, root string, r io.Reader) (int64, error) {
 
 			originalBase := base[len(whiteoutPrefix):]
 			originalPath := filepath.Join(dir, originalBase)
+
+			// Ensure originalPath is under dir
+			if dir[len(dir)-1] != filepath.Separator {
+				dir += string(filepath.Separator)
+			}
+			if !strings.HasPrefix(originalPath, dir) {
+				return 0, errors.Wrapf(errInvalidArchive, "invalid whiteout name: %v", base)
+			}
+
 			if err := os.RemoveAll(originalPath); err != nil {
 				return 0, err
 			}
@@ -285,12 +323,106 @@ func Apply(ctx context.Context, root string, r io.Reader) (int64, error) {
 	return size, nil
 }
 
+func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header, reader io.Reader) error {
+	// hdr.Mode is in linux format, which we can use for syscalls,
+	// but for os.Foo() calls we need the mode converted to os.FileMode,
+	// so use hdrInfo.Mode() (they differ for e.g. setuid bits)
+	hdrInfo := hdr.FileInfo()
+
+	switch hdr.Typeflag {
+	case tar.TypeDir:
+		// Create directory unless it exists as a directory already.
+		// In that case we just want to merge the two
+		if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
+			if err := mkdir(path, hdrInfo.Mode()); err != nil {
+				return err
+			}
+		}
+
+	case tar.TypeReg, tar.TypeRegA:
+		file, err := openFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, hdrInfo.Mode())
+		if err != nil {
+			return err
+		}
+
+		_, err = copyBuffered(ctx, file, reader)
+		if err1 := file.Close(); err == nil {
+			err = err1
+		}
+		if err != nil {
+			return err
+		}
+
+	case tar.TypeBlock, tar.TypeChar:
+		// Handle this is an OS-specific way
+		if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
+			return err
+		}
+
+	case tar.TypeFifo:
+		// Handle this is an OS-specific way
+		if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
+			return err
+		}
+
+	case tar.TypeLink:
+		targetPath, err := fs.RootPath(extractDir, hdr.Linkname)
+		if err != nil {
+			return err
+		}
+		if err := os.Link(targetPath, path); err != nil {
+			return err
+		}
+
+	case tar.TypeSymlink:
+		if err := os.Symlink(hdr.Linkname, path); err != nil {
+			return err
+		}
+
+	case tar.TypeXGlobalHeader:
+		log.G(ctx).Debug("PAX Global Extended Headers found and ignored")
+		return nil
+
+	default:
+		return errors.Errorf("unhandled tar header type %d\n", hdr.Typeflag)
+	}
+
+	// Lchown is not supported on Windows.
+	if runtime.GOOS != "windows" {
+		if err := os.Lchown(path, hdr.Uid, hdr.Gid); err != nil {
+			return err
+		}
+	}
+
+	for key, value := range hdr.PAXRecords {
+		if strings.HasPrefix(key, paxSchilyXattr) {
+			key = key[len(paxSchilyXattr):]
+			if err := setxattr(path, key, value); err != nil {
+				if errors.Cause(err) == syscall.ENOTSUP {
+					log.G(ctx).WithError(err).Warnf("ignored xattr %s in archive", key)
+					continue
+				}
+				return err
+			}
+		}
+	}
+
+	// There is no LChmod, so ignore mode for symlink. Also, this
+	// must happen after chown, as that can modify the file mode
+	if err := handleLChmod(hdr, path, hdrInfo); err != nil {
+		return err
+	}
+
+	return chtimes(path, boundTime(latestTime(hdr.AccessTime, hdr.ModTime)), boundTime(hdr.ModTime))
+}
+
 type changeWriter struct {
 	tw        *tar.Writer
 	source    string
 	whiteoutT time.Time
 	inodeSrc  map[uint64]string
 	inodeRefs map[uint64][]string
+	addedDirs map[string]struct{}
 }
 
 func newChangeWriter(w io.Writer, source string) *changeWriter {
@@ -300,6 +432,7 @@ func newChangeWriter(w io.Writer, source string) *changeWriter {
 		whiteoutT: time.Now(),
 		inodeSrc:  map[uint64]string{},
 		inodeRefs: map[uint64][]string{},
+		addedDirs: map[string]struct{}{},
 	}
 }
 
@@ -312,12 +445,16 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
 		whiteOutBase := filepath.Base(p)
 		whiteOut := filepath.Join(whiteOutDir, whiteoutPrefix+whiteOutBase)
 		hdr := &tar.Header{
+			Typeflag:   tar.TypeReg,
 			Name:       whiteOut[1:],
 			Size:       0,
 			ModTime:    cw.whiteoutT,
 			AccessTime: cw.whiteoutT,
 			ChangeTime: cw.whiteoutT,
 		}
+		if err := cw.includeParents(hdr); err != nil {
+			return err
+		}
 		if err := cw.tw.WriteHeader(hdr); err != nil {
 			return errors.Wrap(err, "failed to write whiteout header")
 		}
@@ -381,10 +518,8 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
 				additionalLinks = cw.inodeRefs[inode]
 				delete(cw.inodeRefs, inode)
 			}
-		} else if k == fs.ChangeKindUnmodified && !f.IsDir() {
+		} else if k == fs.ChangeKindUnmodified {
 			// Nothing to write to diff
-			// Unmodified directories should still be written to keep
-			// directory permissions correct on direct unpack
 			return nil
 		}
 
@@ -397,6 +532,9 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
 			hdr.PAXRecords[paxSchilyXattr+"security.capability"] = string(capability)
 		}
 
+		if err := cw.includeParents(hdr); err != nil {
+			return err
+		}
 		if err := cw.tw.WriteHeader(hdr); err != nil {
 			return errors.Wrap(err, "failed to write file header")
 		}
@@ -408,9 +546,7 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
 			}
 			defer file.Close()
 
-			buf := bufferPool.Get().(*[]byte)
-			n, err := io.CopyBuffer(cw.tw, file, *buf)
-			bufferPool.Put(buf)
+			n, err := copyBuffered(context.TODO(), cw.tw, file)
 			if err != nil {
 				return errors.Wrap(err, "failed to copy")
 			}
@@ -426,6 +562,10 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
 				hdr.Typeflag = tar.TypeLink
 				hdr.Linkname = source
 				hdr.Size = 0
+
+				if err := cw.includeParents(hdr); err != nil {
+					return err
+				}
 				if err := cw.tw.WriteHeader(hdr); err != nil {
 					return errors.Wrap(err, "failed to write file header")
 				}
@@ -442,102 +582,35 @@ func (cw *changeWriter) Close() error {
 	return nil
 }
 
-func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header, reader io.Reader) error {
-	// hdr.Mode is in linux format, which we can use for syscalls,
-	// but for os.Foo() calls we need the mode converted to os.FileMode,
-	// so use hdrInfo.Mode() (they differ for e.g. setuid bits)
-	hdrInfo := hdr.FileInfo()
-
-	switch hdr.Typeflag {
-	case tar.TypeDir:
-		// Create directory unless it exists as a directory already.
-		// In that case we just want to merge the two
-		if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
-			if err := mkdir(path, hdrInfo.Mode()); err != nil {
+func (cw *changeWriter) includeParents(hdr *tar.Header) error {
+	name := strings.TrimRight(hdr.Name, "/")
+	fname := filepath.Join(cw.source, name)
+	parent := filepath.Dir(name)
+	pname := filepath.Join(cw.source, parent)
+
+	// Do not include root directory as parent
+	if fname != cw.source && pname != cw.source {
+		_, ok := cw.addedDirs[parent]
+		if !ok {
+			cw.addedDirs[parent] = struct{}{}
+			fi, err := os.Stat(pname)
+			if err != nil {
 				return err
 			}
-		}
-
-	case tar.TypeReg, tar.TypeRegA:
-		file, err := openFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, hdrInfo.Mode())
-		if err != nil {
-			return err
-		}
-
-		_, err = copyBuffered(ctx, file, reader)
-		if err1 := file.Close(); err == nil {
-			err = err1
-		}
-		if err != nil {
-			return err
-		}
-
-	case tar.TypeBlock, tar.TypeChar:
-		// Handle this is an OS-specific way
-		if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
-			return err
-		}
-
-	case tar.TypeFifo:
-		// Handle this is an OS-specific way
-		if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
-			return err
-		}
-
-	case tar.TypeLink:
-		targetPath, err := fs.RootPath(extractDir, hdr.Linkname)
-		if err != nil {
-			return err
-		}
-		if err := os.Link(targetPath, path); err != nil {
-			return err
-		}
-
-	case tar.TypeSymlink:
-		if err := os.Symlink(hdr.Linkname, path); err != nil {
-			return err
-		}
-
-	case tar.TypeXGlobalHeader:
-		log.G(ctx).Debug("PAX Global Extended Headers found and ignored")
-		return nil
-
-	default:
-		return errors.Errorf("unhandled tar header type %d\n", hdr.Typeflag)
-	}
-
-	// Lchown is not supported on Windows.
-	if runtime.GOOS != "windows" {
-		if err := os.Lchown(path, hdr.Uid, hdr.Gid); err != nil {
-			return err
-		}
-	}
-
-	for key, value := range hdr.PAXRecords {
-		if strings.HasPrefix(key, paxSchilyXattr) {
-			key = key[len(paxSchilyXattr):]
-			if err := setxattr(path, key, value); err != nil {
-				if errors.Cause(err) == syscall.ENOTSUP {
-					log.G(ctx).WithError(err).Warnf("ignored xattr %s in archive", key)
-					continue
-				}
+			if err := cw.HandleChange(fs.ChangeKindModify, parent, fi, nil); err != nil {
 				return err
 			}
 		}
 	}
-
-	// There is no LChmod, so ignore mode for symlink. Also, this
-	// must happen after chown, as that can modify the file mode
-	if err := handleLChmod(hdr, path, hdrInfo); err != nil {
-		return err
+	if hdr.Typeflag == tar.TypeDir {
+		cw.addedDirs[name] = struct{}{}
 	}
-
-	return chtimes(path, boundTime(latestTime(hdr.AccessTime, hdr.ModTime)), boundTime(hdr.ModTime))
+	return nil
 }
 
 func copyBuffered(ctx context.Context, dst io.Writer, src io.Reader) (written int64, err error) {
-	buf := bufferPool.Get().(*[]byte)
-	defer bufferPool.Put(buf)
+	buf := bufPool.Get().(*[]byte)
+	defer bufPool.Put(buf)
 
 	for {
 		select {

+ 20 - 0
vendor/github.com/containerd/containerd/archive/tar_opts.go

@@ -0,0 +1,20 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package archive
+
+// ApplyOpt allows setting mutable archive apply properties on creation
+type ApplyOpt func(options *ApplyOptions) error

+ 23 - 0
vendor/github.com/containerd/containerd/archive/tar_opts_unix.go

@@ -0,0 +1,23 @@
+// +build !windows
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package archive
+
+// ApplyOptions provides additional options for an Apply operation
+type ApplyOptions struct {
+}

+ 44 - 0
vendor/github.com/containerd/containerd/archive/tar_opts_windows.go

@@ -0,0 +1,44 @@
+// +build windows
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package archive
+
+// ApplyOptions provides additional options for an Apply operation
+type ApplyOptions struct {
+	ParentLayerPaths        []string // Parent layer paths used for Windows layer apply
+	IsWindowsContainerLayer bool     // True if the tar stream to be applied is a Windows Container Layer
+}
+
+// WithParentLayers adds parent layers to the apply process this is required
+// for all Windows layers except the base layer.
+func WithParentLayers(parentPaths []string) ApplyOpt {
+	return func(options *ApplyOptions) error {
+		options.ParentLayerPaths = parentPaths
+		return nil
+	}
+}
+
+// AsWindowsContainerLayer indicates that the tar stream to apply is that of
+// a Windows Container Layer. The caller must be holding SeBackupPrivilege and
+// SeRestorePrivilege.
+func AsWindowsContainerLayer() ApplyOpt {
+	return func(options *ApplyOptions) error {
+		options.IsWindowsContainerLayer = true
+		return nil
+	}
+}

+ 28 - 2
vendor/github.com/containerd/containerd/archive/tar_unix.go

@@ -1,8 +1,25 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package archive
 
 import (
+	"context"
 	"os"
 	"sync"
 	"syscall"
@@ -28,11 +45,14 @@ func setHeaderForSpecialDevice(hdr *tar.Header, name string, fi os.FileInfo) err
 		return errors.New("unsupported stat type")
 	}
 
+	// Rdev is int32 on darwin/bsd, int64 on linux/solaris
+	rdev := uint64(s.Rdev) // nolint: unconvert
+
 	// Currently go does not fill in the major/minors
 	if s.Mode&syscall.S_IFBLK != 0 ||
 		s.Mode&syscall.S_IFCHR != 0 {
-		hdr.Devmajor = int64(unix.Major(uint64(s.Rdev)))
-		hdr.Devminor = int64(unix.Minor(uint64(s.Rdev)))
+		hdr.Devmajor = int64(unix.Major(rdev))
+		hdr.Devminor = int64(unix.Minor(rdev))
 	}
 
 	return nil
@@ -128,3 +148,9 @@ func getxattr(path, attr string) ([]byte, error) {
 func setxattr(path, key, value string) error {
 	return sysx.LSetxattr(path, key, []byte(value), 0)
 }
+
+// apply applies a tar stream of an OCI style diff tar.
+// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
+func apply(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
+	return applyNaive(ctx, root, tr, options)
+}

+ 343 - 0
vendor/github.com/containerd/containerd/archive/tar_windows.go

@@ -1,15 +1,71 @@
+// +build windows
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package archive
 
 import (
+	"bufio"
+	"context"
+	"encoding/base64"
 	"errors"
 	"fmt"
+	"io"
 	"os"
+	"path"
+	"path/filepath"
+	"strconv"
 	"strings"
+	"syscall"
 
+	"github.com/Microsoft/go-winio"
+	"github.com/Microsoft/hcsshim"
+	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/sys"
 	"github.com/dmcgowan/go-tar"
 )
 
+const (
+	// MSWINDOWS pax vendor extensions
+	hdrMSWindowsPrefix = "MSWINDOWS."
+
+	hdrFileAttributes        = hdrMSWindowsPrefix + "fileattr"
+	hdrSecurityDescriptor    = hdrMSWindowsPrefix + "sd"
+	hdrRawSecurityDescriptor = hdrMSWindowsPrefix + "rawsd"
+	hdrMountPoint            = hdrMSWindowsPrefix + "mountpoint"
+	hdrEaPrefix              = hdrMSWindowsPrefix + "xattr."
+
+	// LIBARCHIVE pax vendor extensions
+	hdrLibArchivePrefix = "LIBARCHIVE."
+
+	hdrCreateTime = hdrLibArchivePrefix + "creationtime"
+)
+
+var (
+	// mutatedFiles is a list of files that are mutated by the import process
+	// and must be backed up and restored.
+	mutatedFiles = map[string]string{
+		"UtilityVM/Files/EFI/Microsoft/Boot/BCD":      "bcd.bak",
+		"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG":  "bcd.log.bak",
+		"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG1": "bcd.log1.bak",
+		"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG2": "bcd.log2.bak",
+	}
+)
+
 // tarName returns platform-specific filepath
 // to canonical posix-style path for tar archival. p is relative
 // path.
@@ -101,3 +157,290 @@ func setxattr(path, key, value string) error {
 	// since xattrs should not exist in windows diff archives
 	return errors.New("xattrs not supported on Windows")
 }
+
+// apply applies a tar stream of an OCI style diff tar of a Windows layer.
+// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
+func apply(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
+	if options.IsWindowsContainerLayer {
+		return applyWindowsLayer(ctx, root, tr, options)
+	}
+	return applyNaive(ctx, root, tr, options)
+}
+
+// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows layer.
+// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
+func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
+	home, id := filepath.Split(root)
+	info := hcsshim.DriverInfo{
+		HomeDir: home,
+	}
+
+	w, err := hcsshim.NewLayerWriter(info, id, options.ParentLayerPaths)
+	if err != nil {
+		return 0, err
+	}
+	defer func() {
+		if err := w.Close(); err != nil {
+			log.G(ctx).Errorf("failed to close layer writer: %v", err)
+		}
+	}()
+
+	buf := bufio.NewWriter(nil)
+	hdr, nextErr := tr.Next()
+	// Iterate through the files in the archive.
+	for {
+		select {
+		case <-ctx.Done():
+			return 0, ctx.Err()
+		default:
+		}
+
+		if nextErr == io.EOF {
+			// end of tar archive
+			break
+		}
+		if nextErr != nil {
+			return 0, nextErr
+		}
+
+		// Note: path is used instead of filepath to prevent OS specific handling
+		// of the tar path
+		base := path.Base(hdr.Name)
+		if strings.HasPrefix(base, whiteoutPrefix) {
+			dir := path.Dir(hdr.Name)
+			originalBase := base[len(whiteoutPrefix):]
+			originalPath := path.Join(dir, originalBase)
+			if err := w.Remove(filepath.FromSlash(originalPath)); err != nil {
+				return 0, err
+			}
+			hdr, nextErr = tr.Next()
+		} else if hdr.Typeflag == tar.TypeLink {
+			err := w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
+			if err != nil {
+				return 0, err
+			}
+			hdr, nextErr = tr.Next()
+		} else {
+			name, fileSize, fileInfo, err := fileInfoFromHeader(hdr)
+			if err != nil {
+				return 0, err
+			}
+			if err := w.Add(filepath.FromSlash(name), fileInfo); err != nil {
+				return 0, err
+			}
+			size += fileSize
+			hdr, nextErr = tarToBackupStreamWithMutatedFiles(buf, w, tr, hdr, root)
+		}
+	}
+
+	return
+}
+
+// fileInfoFromHeader retrieves basic Win32 file information from a tar header, using the additional metadata written by
+// WriteTarFileFromBackupStream.
+func fileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *winio.FileBasicInfo, err error) {
+	name = hdr.Name
+	if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA {
+		size = hdr.Size
+	}
+	fileInfo = &winio.FileBasicInfo{
+		LastAccessTime: syscall.NsecToFiletime(hdr.AccessTime.UnixNano()),
+		LastWriteTime:  syscall.NsecToFiletime(hdr.ModTime.UnixNano()),
+		ChangeTime:     syscall.NsecToFiletime(hdr.ChangeTime.UnixNano()),
+
+		// Default CreationTime to ModTime, updated below if MSWINDOWS.createtime exists
+		CreationTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()),
+	}
+	if attrStr, ok := hdr.PAXRecords[hdrFileAttributes]; ok {
+		attr, err := strconv.ParseUint(attrStr, 10, 32)
+		if err != nil {
+			return "", 0, nil, err
+		}
+		fileInfo.FileAttributes = uintptr(attr)
+	} else {
+		if hdr.Typeflag == tar.TypeDir {
+			fileInfo.FileAttributes |= syscall.FILE_ATTRIBUTE_DIRECTORY
+		}
+	}
+	if createStr, ok := hdr.PAXRecords[hdrCreateTime]; ok {
+		createTime, err := parsePAXTime(createStr)
+		if err != nil {
+			return "", 0, nil, err
+		}
+		fileInfo.CreationTime = syscall.NsecToFiletime(createTime.UnixNano())
+	}
+	return
+}
+
+// tarToBackupStreamWithMutatedFiles reads data from a tar stream and
+// writes it to a backup stream, and also saves any files that will be mutated
+// by the import layer process to a backup location.
+func tarToBackupStreamWithMutatedFiles(buf *bufio.Writer, w io.Writer, t *tar.Reader, hdr *tar.Header, root string) (nextHdr *tar.Header, err error) {
+	var (
+		bcdBackup       *os.File
+		bcdBackupWriter *winio.BackupFileWriter
+	)
+	if backupPath, ok := mutatedFiles[hdr.Name]; ok {
+		bcdBackup, err = os.Create(filepath.Join(root, backupPath))
+		if err != nil {
+			return nil, err
+		}
+		defer func() {
+			cerr := bcdBackup.Close()
+			if err == nil {
+				err = cerr
+			}
+		}()
+
+		bcdBackupWriter = winio.NewBackupFileWriter(bcdBackup, false)
+		defer func() {
+			cerr := bcdBackupWriter.Close()
+			if err == nil {
+				err = cerr
+			}
+		}()
+
+		buf.Reset(io.MultiWriter(w, bcdBackupWriter))
+	} else {
+		buf.Reset(w)
+	}
+
+	defer func() {
+		ferr := buf.Flush()
+		if err == nil {
+			err = ferr
+		}
+	}()
+
+	return writeBackupStreamFromTarFile(buf, t, hdr)
+}
+
+// writeBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple
+// tar file entries in order to collect all the alternate data streams for the file, it returns the next
+// tar file that was not processed, or io.EOF is there are no more.
+func writeBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (*tar.Header, error) {
+	bw := winio.NewBackupStreamWriter(w)
+	var sd []byte
+	var err error
+	// Maintaining old SDDL-based behavior for backward compatibility.  All new tar headers written
+	// by this library will have raw binary for the security descriptor.
+	if sddl, ok := hdr.PAXRecords[hdrSecurityDescriptor]; ok {
+		sd, err = winio.SddlToSecurityDescriptor(sddl)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if sdraw, ok := hdr.PAXRecords[hdrRawSecurityDescriptor]; ok {
+		sd, err = base64.StdEncoding.DecodeString(sdraw)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if len(sd) != 0 {
+		bhdr := winio.BackupHeader{
+			Id:   winio.BackupSecurity,
+			Size: int64(len(sd)),
+		}
+		err := bw.WriteHeader(&bhdr)
+		if err != nil {
+			return nil, err
+		}
+		_, err = bw.Write(sd)
+		if err != nil {
+			return nil, err
+		}
+	}
+	var eas []winio.ExtendedAttribute
+	for k, v := range hdr.PAXRecords {
+		if !strings.HasPrefix(k, hdrEaPrefix) {
+			continue
+		}
+		data, err := base64.StdEncoding.DecodeString(v)
+		if err != nil {
+			return nil, err
+		}
+		eas = append(eas, winio.ExtendedAttribute{
+			Name:  k[len(hdrEaPrefix):],
+			Value: data,
+		})
+	}
+	if len(eas) != 0 {
+		eadata, err := winio.EncodeExtendedAttributes(eas)
+		if err != nil {
+			return nil, err
+		}
+		bhdr := winio.BackupHeader{
+			Id:   winio.BackupEaData,
+			Size: int64(len(eadata)),
+		}
+		err = bw.WriteHeader(&bhdr)
+		if err != nil {
+			return nil, err
+		}
+		_, err = bw.Write(eadata)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if hdr.Typeflag == tar.TypeSymlink {
+		_, isMountPoint := hdr.PAXRecords[hdrMountPoint]
+		rp := winio.ReparsePoint{
+			Target:       filepath.FromSlash(hdr.Linkname),
+			IsMountPoint: isMountPoint,
+		}
+		reparse := winio.EncodeReparsePoint(&rp)
+		bhdr := winio.BackupHeader{
+			Id:   winio.BackupReparseData,
+			Size: int64(len(reparse)),
+		}
+		err := bw.WriteHeader(&bhdr)
+		if err != nil {
+			return nil, err
+		}
+		_, err = bw.Write(reparse)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	buf := bufPool.Get().(*[]byte)
+	defer bufPool.Put(buf)
+
+	if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA {
+		bhdr := winio.BackupHeader{
+			Id:   winio.BackupData,
+			Size: hdr.Size,
+		}
+		err := bw.WriteHeader(&bhdr)
+		if err != nil {
+			return nil, err
+		}
+		_, err = io.CopyBuffer(bw, t, *buf)
+		if err != nil {
+			return nil, err
+		}
+	}
+	// Copy all the alternate data streams and return the next non-ADS header.
+	for {
+		ahdr, err := t.Next()
+		if err != nil {
+			return nil, err
+		}
+		if ahdr.Typeflag != tar.TypeReg || !strings.HasPrefix(ahdr.Name, hdr.Name+":") {
+			return ahdr, nil
+		}
+		bhdr := winio.BackupHeader{
+			Id:   winio.BackupAlternateData,
+			Size: ahdr.Size,
+			Name: ahdr.Name[len(hdr.Name):] + ":$DATA",
+		}
+		err = bw.WriteHeader(&bhdr)
+		if err != nil {
+			return nil, err
+		}
+		_, err = io.CopyBuffer(bw, t, *buf)
+		if err != nil {
+			return nil, err
+		}
+	}
+}

+ 16 - 0
vendor/github.com/containerd/containerd/archive/time.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package archive
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/archive/time_darwin.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package archive
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/archive/time_unix.go

@@ -1,5 +1,21 @@
 // +build linux freebsd solaris
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package archive
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/archive/time_windows.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package archive
 
 import (

+ 38 - 3
vendor/github.com/containerd/containerd/cio/io.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package cio
 
 import (
@@ -6,8 +22,17 @@ import (
 	"io"
 	"os"
 	"sync"
+
+	"github.com/containerd/containerd/defaults"
 )
 
+var bufPool = sync.Pool{
+	New: func() interface{} {
+		buffer := make([]byte, 32<<10)
+		return &buffer
+	},
+}
+
 // Config holds the IO configurations.
 type Config struct {
 	// Terminal is true if one has been allocated
@@ -68,6 +93,7 @@ type Streams struct {
 	Stdout   io.Writer
 	Stderr   io.Writer
 	Terminal bool
+	FIFODir  string
 }
 
 // Opt customize options for creating a Creator or Attach
@@ -92,16 +118,25 @@ func WithStreams(stdin io.Reader, stdout, stderr io.Writer) Opt {
 	}
 }
 
+// WithFIFODir sets the fifo directory.
+// e.g. "/run/containerd/fifo", "/run/users/1001/containerd/fifo"
+func WithFIFODir(dir string) Opt {
+	return func(opt *Streams) {
+		opt.FIFODir = dir
+	}
+}
+
 // NewCreator returns an IO creator from the options
 func NewCreator(opts ...Opt) Creator {
 	streams := &Streams{}
 	for _, opt := range opts {
 		opt(streams)
 	}
+	if streams.FIFODir == "" {
+		streams.FIFODir = defaults.DefaultFIFODir
+	}
 	return func(id string) (IO, error) {
-		// TODO: accept root as a param
-		root := "/run/containerd/fifo"
-		fifos, err := NewFIFOSetInDir(root, id, streams.Terminal)
+		fifos, err := NewFIFOSetInDir(streams.FIFODir, id, streams.Terminal)
 		if err != nil {
 			return nil, err
 		}

+ 38 - 6
vendor/github.com/containerd/containerd/cio/io_unix.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package cio
 
 import (
@@ -47,7 +63,10 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 
 	if fifos.Stdin != "" {
 		go func() {
-			io.Copy(pipes.Stdin, ioset.Stdin)
+			p := bufPool.Get().(*[]byte)
+			defer bufPool.Put(p)
+
+			io.CopyBuffer(pipes.Stdin, ioset.Stdin, *p)
 			pipes.Stdin.Close()
 		}()
 	}
@@ -55,7 +74,10 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 	var wg = &sync.WaitGroup{}
 	wg.Add(1)
 	go func() {
-		io.Copy(ioset.Stdout, pipes.Stdout)
+		p := bufPool.Get().(*[]byte)
+		defer bufPool.Put(p)
+
+		io.CopyBuffer(ioset.Stdout, pipes.Stdout, *p)
 		pipes.Stdout.Close()
 		wg.Done()
 	}()
@@ -63,7 +85,10 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 	if !fifos.Terminal {
 		wg.Add(1)
 		go func() {
-			io.Copy(ioset.Stderr, pipes.Stderr)
+			p := bufPool.Get().(*[]byte)
+			defer bufPool.Put(p)
+
+			io.CopyBuffer(ioset.Stderr, pipes.Stderr, *p)
 			pipes.Stderr.Close()
 			wg.Done()
 		}()
@@ -89,17 +114,24 @@ func openFifos(ctx context.Context, fifos *FIFOSet) (pipes, error) {
 		if f.Stdin, err = fifo.OpenFifo(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
 			return f, errors.Wrapf(err, "failed to open stdin fifo")
 		}
+		defer func() {
+			if err != nil && f.Stdin != nil {
+				f.Stdin.Close()
+			}
+		}()
 	}
 	if fifos.Stdout != "" {
 		if f.Stdout, err = fifo.OpenFifo(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
-			f.Stdin.Close()
 			return f, errors.Wrapf(err, "failed to open stdout fifo")
 		}
+		defer func() {
+			if err != nil && f.Stdout != nil {
+				f.Stdout.Close()
+			}
+		}()
 	}
 	if fifos.Stderr != "" {
 		if f.Stderr, err = fifo.OpenFifo(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
-			f.Stdin.Close()
-			f.Stdout.Close()
 			return f, errors.Wrapf(err, "failed to open stderr fifo")
 		}
 	}

+ 31 - 3
vendor/github.com/containerd/containerd/cio/io_windows.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package cio
 
 import (
@@ -47,7 +63,11 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 				log.L.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.Stdin)
 				return
 			}
-			io.Copy(c, ioset.Stdin)
+
+			p := bufPool.Get().(*[]byte)
+			defer bufPool.Put(p)
+
+			io.CopyBuffer(c, ioset.Stdin, *p)
 			c.Close()
 			l.Close()
 		}()
@@ -73,7 +93,11 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 				log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout)
 				return
 			}
-			io.Copy(ioset.Stdout, c)
+
+			p := bufPool.Get().(*[]byte)
+			defer bufPool.Put(p)
+
+			io.CopyBuffer(ioset.Stdout, c, *p)
 			c.Close()
 			l.Close()
 		}()
@@ -99,7 +123,11 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 				log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr)
 				return
 			}
-			io.Copy(ioset.Stderr, c)
+
+			p := bufPool.Get().(*[]byte)
+			defer bufPool.Put(p)
+
+			io.CopyBuffer(ioset.Stderr, c, *p)
 			c.Close()
 			l.Close()
 		}()

+ 65 - 63
vendor/github.com/containerd/containerd/client.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (
@@ -7,8 +23,6 @@ import (
 	"net/http"
 	"runtime"
 	"strconv"
-	"strings"
-	"sync"
 	"time"
 
 	containersapi "github.com/containerd/containerd/api/services/containers/v1"
@@ -24,7 +38,6 @@ import (
 	"github.com/containerd/containerd/containers"
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/dialer"
-	"github.com/containerd/containerd/diff"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/namespaces"
@@ -80,11 +93,22 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
 			grpc.WithStreamInterceptor(stream),
 		)
 	}
-	conn, err := grpc.Dial(dialer.DialAddress(address), gopts...)
+	connector := func() (*grpc.ClientConn, error) {
+		conn, err := grpc.Dial(dialer.DialAddress(address), gopts...)
+		if err != nil {
+			return nil, errors.Wrapf(err, "failed to dial %q", address)
+		}
+		return conn, nil
+	}
+	conn, err := connector()
 	if err != nil {
-		return nil, errors.Wrapf(err, "failed to dial %q", address)
+		return nil, err
 	}
-	return NewWithConn(conn, opts...)
+	return &Client{
+		conn:      conn,
+		connector: connector,
+		runtime:   fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
+	}, nil
 }
 
 // NewWithConn returns a new containerd client that is connected to the containerd
@@ -99,8 +123,23 @@ func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) {
 // Client is the client to interact with containerd and its various services
 // using a uniform interface
 type Client struct {
-	conn    *grpc.ClientConn
-	runtime string
+	conn      *grpc.ClientConn
+	runtime   string
+	connector func() (*grpc.ClientConn, error)
+}
+
+// Reconnect re-establishes the GRPC connection to the containerd daemon
+func (c *Client) Reconnect() error {
+	if c.connector == nil {
+		return errors.New("unable to reconnect to containerd, no connector available")
+	}
+	c.conn.Close()
+	conn, err := c.connector()
+	if err != nil {
+		return err
+	}
+	c.conn = conn
+	return nil
 }
 
 // IsServing returns true if the client can successfully connect to the
@@ -222,11 +261,11 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
 
 	name, desc, err := pullCtx.Resolver.Resolve(ctx, ref)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrapf(err, "failed to resolve reference %q", ref)
 	}
 	fetcher, err := pullCtx.Resolver.Fetcher(ctx, name)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrapf(err, "failed to get fetcher for %q", name)
 	}
 
 	var (
@@ -237,10 +276,17 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
 		schema1Converter = schema1.NewConverter(store, fetcher)
 		handler = images.Handlers(append(pullCtx.BaseHandlers, schema1Converter)...)
 	} else {
+		// Get all the children for a descriptor
+		childrenHandler := images.ChildrenHandler(store)
+		// Set any children labels for that content
+		childrenHandler = images.SetChildrenLabels(store, childrenHandler)
+		// Filter the childen by the platform
+		childrenHandler = images.FilterPlatform(platforms.Default(), childrenHandler)
+
 		handler = images.Handlers(append(pullCtx.BaseHandlers,
 			remotes.FetchHandler(store, fetcher),
-			images.ChildrenHandler(store, platforms.Default()))...,
-		)
+			childrenHandler,
+		)...)
 	}
 
 	if err := images.Dispatch(ctx, handler, desc); err != nil {
@@ -281,7 +327,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
 	}
 	if pullCtx.Unpack {
 		if err := img.Unpack(ctx, pullCtx.Snapshotter); err != nil {
-			return nil, err
+			errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
 		}
 	}
 	return img, nil
@@ -301,51 +347,7 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
 		return err
 	}
 
-	var m sync.Mutex
-	manifestStack := []ocispec.Descriptor{}
-
-	filterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
-		switch desc.MediaType {
-		case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest,
-			images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
-			m.Lock()
-			manifestStack = append(manifestStack, desc)
-			m.Unlock()
-			return nil, images.ErrStopHandler
-		default:
-			return nil, nil
-		}
-	})
-
-	cs := c.ContentStore()
-	pushHandler := remotes.PushHandler(cs, pusher)
-
-	handlers := append(pushCtx.BaseHandlers,
-		images.ChildrenHandler(cs, platforms.Default()),
-		filterHandler,
-		pushHandler,
-	)
-
-	if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil {
-		return err
-	}
-
-	// Iterate in reverse order as seen, parent always uploaded after child
-	for i := len(manifestStack) - 1; i >= 0; i-- {
-		_, err := pushHandler(ctx, manifestStack[i])
-		if err != nil {
-			// TODO(estesp): until we have a more complete method for index push, we need to report
-			// missing dependencies in an index/manifest list by sensing the "400 Bad Request"
-			// as a marker for this problem
-			if (manifestStack[i].MediaType == ocispec.MediaTypeImageIndex ||
-				manifestStack[i].MediaType == images.MediaTypeDockerSchema2ManifestList) &&
-				errors.Cause(err) != nil && strings.Contains(errors.Cause(err).Error(), "400 Bad Request") {
-				return errors.Wrap(err, "manifest list/index references to blobs and/or manifests are missing in your target registry")
-			}
-			return err
-		}
-	}
-	return nil
+	return remotes.PushContent(ctx, pusher, desc, c.ContentStore(), pushCtx.BaseHandlers...)
 }
 
 // GetImage returns an existing image
@@ -378,11 +380,11 @@ func (c *Client) ListImages(ctx context.Context, filters ...string) ([]Image, er
 
 // Subscribe to events that match one or more of the provided filters.
 //
-// Callers should listen on both the envelope channel and errs channel. If the
-// errs channel returns nil or an error, the subscriber should terminate.
+// Callers should listen on both the envelope and errs channels. If the errs
+// channel returns nil or an error, the subscriber should terminate.
 //
-// To cancel shutdown reciept of events, cancel the provided context. The errs
-// channel will be closed and return a nil error.
+// The subscriber can stop receiving events by canceling the provided context.
+// The errs channel will be closed and return a nil error.
 func (c *Client) Subscribe(ctx context.Context, filters ...string) (ch <-chan *eventsapi.Envelope, errs <-chan error) {
 	var (
 		evq  = make(chan *eventsapi.Envelope)
@@ -458,7 +460,7 @@ func (c *Client) ImageService() images.Store {
 }
 
 // DiffService returns the underlying Differ
-func (c *Client) DiffService() diff.Differ {
+func (c *Client) DiffService() DiffService {
 	return NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn))
 }
 

+ 16 - 0
vendor/github.com/containerd/containerd/client_opts.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/container.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/container_opts.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 39 - 19
vendor/github.com/containerd/containerd/container_opts_unix.go

@@ -1,12 +1,27 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"syscall"
@@ -16,6 +31,7 @@ import (
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/images"
+	"github.com/containerd/containerd/linux/runctypes"
 	"github.com/containerd/containerd/mount"
 	"github.com/containerd/containerd/platforms"
 	"github.com/gogo/protobuf/proto"
@@ -115,7 +131,7 @@ func WithTaskCheckpoint(im Image) NewTaskOpts {
 	}
 }
 
-func decodeIndex(ctx context.Context, store content.Store, id digest.Digest) (*v1.Index, error) {
+func decodeIndex(ctx context.Context, store content.Provider, id digest.Digest) (*v1.Index, error) {
 	var index v1.Index
 	p, err := content.ReadBlob(ctx, store, id)
 	if err != nil {
@@ -166,7 +182,7 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool
 		if err != nil {
 			return err
 		}
-		if err := remapRootFS(mounts, uid, gid); err != nil {
+		if err := remapRootFS(ctx, mounts, uid, gid); err != nil {
 			snapshotter.Remove(ctx, usernsID)
 			return err
 		}
@@ -187,22 +203,10 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool
 	}
 }
 
-func remapRootFS(mounts []mount.Mount, uid, gid uint32) error {
-	root, err := ioutil.TempDir("", "ctd-remap")
-	if err != nil {
-		return err
-	}
-	defer os.Remove(root)
-	for _, m := range mounts {
-		if err := m.Mount(root); err != nil {
-			return err
-		}
-	}
-	err = filepath.Walk(root, incrementFS(root, uid, gid))
-	if uerr := mount.Unmount(root, 0); err == nil {
-		err = uerr
-	}
-	return err
+func remapRootFS(ctx context.Context, mounts []mount.Mount, uid, gid uint32) error {
+	return mount.WithTempMount(ctx, mounts, func(root string) error {
+		return filepath.Walk(root, incrementFS(root, uid, gid))
+	})
 }
 
 func incrementFS(root string, uidInc, gidInc uint32) filepath.WalkFunc {
@@ -218,3 +222,19 @@ func incrementFS(root string, uidInc, gidInc uint32) filepath.WalkFunc {
 		return os.Lchown(path, u, g)
 	}
 }
+
+// WithNoPivotRoot instructs the runtime not to you pivot_root
+func WithNoPivotRoot(_ context.Context, _ *Client, info *TaskInfo) error {
+	if info.Options == nil {
+		info.Options = &runctypes.CreateOptions{
+			NoPivotRoot: true,
+		}
+		return nil
+	}
+	copts, ok := info.Options.(*runctypes.CreateOptions)
+	if !ok {
+		return errors.New("invalid options type, expected runctypes.CreateOptions")
+	}
+	copts.NoPivotRoot = true
+	return nil
+}

+ 16 - 0
vendor/github.com/containerd/containerd/containers/containers.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containers
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/containerstore.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/content/content.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package content
 
 import (

+ 33 - 16
vendor/github.com/containerd/containerd/content/helpers.go

@@ -1,8 +1,25 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package content
 
 import (
 	"context"
 	"io"
+	"io/ioutil"
 	"sync"
 
 	"github.com/containerd/containerd/errdefs"
@@ -76,14 +93,7 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
 	if ws.Offset > 0 {
 		r, err = seekReader(r, ws.Offset, size)
 		if err != nil {
-			if !isUnseekable(err) {
-				return errors.Wrapf(err, "unable to resume write to %v", ws.Ref)
-			}
-
-			// reader is unseekable, try to move the writer back to the start.
-			if err := cw.Truncate(0); err != nil {
-				return errors.Wrapf(err, "content writer truncate failed")
-			}
+			return errors.Wrapf(err, "unable to resume write to %v", ws.Ref)
 		}
 	}
 
@@ -103,14 +113,9 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
 	return nil
 }
 
-var errUnseekable = errors.New("seek not supported")
-
-func isUnseekable(err error) bool {
-	return errors.Cause(err) == errUnseekable
-}
-
 // seekReader attempts to seek the reader to the given offset, either by
-// resolving `io.Seeker` or by detecting `io.ReaderAt`.
+// resolving `io.Seeker`, by detecting `io.ReaderAt`, or discarding
+// up to the given offset.
 func seekReader(r io.Reader, offset, size int64) (io.Reader, error) {
 	// attempt to resolve r as a seeker and setup the offset.
 	seeker, ok := r.(io.Seeker)
@@ -134,5 +139,17 @@ func seekReader(r io.Reader, offset, size int64) (io.Reader, error) {
 		return sr, nil
 	}
 
-	return r, errors.Wrapf(errUnseekable, "seek to offset %v failed", offset)
+	// well then, let's just discard up to the offset
+	buf := bufPool.Get().(*[]byte)
+	defer bufPool.Put(buf)
+
+	n, err := io.CopyBuffer(ioutil.Discard, io.LimitReader(r, offset), *buf)
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to discard to offset")
+	}
+	if n != offset {
+		return nil, errors.Errorf("unable to discard to offset")
+	}
+
+	return r, nil
 }

+ 16 - 0
vendor/github.com/containerd/containerd/content/local/locks.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package local
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/content/local/readerat.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package local
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/content/local/store.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package local
 
 import (

+ 17 - 2
vendor/github.com/containerd/containerd/content/local/store_unix.go

@@ -1,5 +1,21 @@
 // +build linux solaris darwin freebsd
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package local
 
 import (
@@ -12,8 +28,7 @@ import (
 
 func getATime(fi os.FileInfo) time.Time {
 	if st, ok := fi.Sys().(*syscall.Stat_t); ok {
-		return time.Unix(int64(sys.StatAtime(st).Sec),
-			int64(sys.StatAtime(st).Nsec))
+		return sys.StatATimeAsTime(st)
 	}
 
 	return fi.ModTime()

+ 16 - 0
vendor/github.com/containerd/containerd/content/local/store_windows.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package local
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/content/local/writer.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package local
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/content_reader.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/content_store.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/content_writer.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 35 - 0
vendor/github.com/containerd/containerd/defaults/defaults_unix.go

@@ -0,0 +1,35 @@
+// +build !windows
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package defaults
+
+const (
+	// DefaultRootDir is the default location used by containerd to store
+	// persistent data
+	DefaultRootDir = "/var/lib/containerd"
+	// DefaultStateDir is the default location used by containerd to store
+	// transient data
+	DefaultStateDir = "/run/containerd"
+	// DefaultAddress is the default unix socket address
+	DefaultAddress = "/run/containerd/containerd.sock"
+	// DefaultDebugAddress is the default unix socket address for pprof data
+	DefaultDebugAddress = "/run/containerd/debug.sock"
+	// DefaultFIFODir is the default location used by client-side cio library
+	// to store FIFOs.
+	DefaultFIFODir = "/run/containerd/fifo"
+)

+ 43 - 0
vendor/github.com/containerd/containerd/defaults/defaults_windows.go

@@ -0,0 +1,43 @@
+// +build windows
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package defaults
+
+import (
+	"os"
+	"path/filepath"
+)
+
+var (
+	// DefaultRootDir is the default location used by containerd to store
+	// persistent data
+	DefaultRootDir = filepath.Join(os.Getenv("programfiles"), "containerd", "root")
+	// DefaultStateDir is the default location used by containerd to store
+	// transient data
+	DefaultStateDir = filepath.Join(os.Getenv("programfiles"), "containerd", "state")
+)
+
+const (
+	// DefaultAddress is the default winpipe address
+	DefaultAddress = `\\.\pipe\containerd-containerd`
+	// DefaultDebugAddress is the default winpipe address for pprof data
+	DefaultDebugAddress = `\\.\pipe\containerd-debug`
+	// DefaultFIFODir is the default location used by client-side cio library
+	// to store FIFOs. Unused on Windows.
+	DefaultFIFODir = ""
+)

+ 19 - 0
vendor/github.com/containerd/containerd/defaults/doc.go

@@ -0,0 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+// Package defaults provides several common defaults for interacting wtih
+// containerd. These can be used on the client-side or server-side.
+package defaults

+ 17 - 1
vendor/github.com/containerd/containerd/dialer/dialer.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package dialer
 
 import (
@@ -42,7 +58,7 @@ func Dialer(address string, timeout time.Duration) (net.Conn, error) {
 		close(stopC)
 		go func() {
 			dr := <-synC
-			if dr != nil {
+			if dr != nil && dr.c != nil {
 				dr.c.Close()
 			}
 		}()

+ 16 - 0
vendor/github.com/containerd/containerd/dialer/dialer_unix.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package dialer
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/dialer/dialer_windows.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package dialer
 
 import (

+ 26 - 3
vendor/github.com/containerd/containerd/diff.go

@@ -1,17 +1,40 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (
+	"context"
+
 	diffapi "github.com/containerd/containerd/api/services/diff/v1"
 	"github.com/containerd/containerd/api/types"
 	"github.com/containerd/containerd/diff"
 	"github.com/containerd/containerd/mount"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
-	"golang.org/x/net/context"
 )
 
+// DiffService handles the computation and application of diffs
+type DiffService interface {
+	diff.Comparer
+	diff.Applier
+}
+
 // NewDiffServiceFromClient returns a new diff service which communicates
 // over a GRPC connection.
-func NewDiffServiceFromClient(client diffapi.DiffClient) diff.Differ {
+func NewDiffServiceFromClient(client diffapi.DiffClient) DiffService {
 	return &diffRemote{
 		client: client,
 	}
@@ -33,7 +56,7 @@ func (r *diffRemote) Apply(ctx context.Context, diff ocispec.Descriptor, mounts
 	return toDescriptor(resp.Applied), nil
 }
 
-func (r *diffRemote) DiffMounts(ctx context.Context, a, b []mount.Mount, opts ...diff.Opt) (ocispec.Descriptor, error) {
+func (r *diffRemote) Compare(ctx context.Context, a, b []mount.Mount, opts ...diff.Opt) (ocispec.Descriptor, error) {
 	var config diff.Config
 	for _, opt := range opts {
 		if err := opt(&config); err != nil {

+ 30 - 10
vendor/github.com/containerd/containerd/diff/diff.go

@@ -1,9 +1,26 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package diff
 
 import (
+	"context"
+
 	"github.com/containerd/containerd/mount"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
-	"golang.org/x/net/context"
 )
 
 // Config is used to hold parameters needed for a diff operation
@@ -24,21 +41,24 @@ type Config struct {
 // Opt is used to configure a diff operation
 type Opt func(*Config) error
 
-// Differ allows the apply and creation of filesystem diffs between mounts
-type Differ interface {
+// Comparer allows creation of filesystem diffs between mounts
+type Comparer interface {
+	// Compare computes the difference between two mounts and returns a
+	// descriptor for the computed diff. The options can provide
+	// a ref which can be used to track the content creation of the diff.
+	// The media type which is used to determine the format of the created
+	// content can also be provided as an option.
+	Compare(ctx context.Context, lower, upper []mount.Mount, opts ...Opt) (ocispec.Descriptor, error)
+}
+
+// Applier allows applying diffs between mounts
+type Applier interface {
 	// Apply applies the content referred to by the given descriptor to
 	// the provided mount. The method of applying is based on the
 	// implementation and content descriptor. For example, in the common
 	// case the descriptor is a file system difference in tar format,
 	// that tar would be applied on top of the mounts.
 	Apply(ctx context.Context, desc ocispec.Descriptor, mount []mount.Mount) (ocispec.Descriptor, error)
-
-	// DiffMounts computes the difference between two mounts and returns a
-	// descriptor for the computed diff. The options can provide
-	// a ref which can be used to track the content creation of the diff.
-	// The media type which is used to determine the format of the created
-	// content can also be provided as an option.
-	DiffMounts(ctx context.Context, lower, upper []mount.Mount, opts ...Opt) (ocispec.Descriptor, error)
 }
 
 // WithMediaType sets the media type to use for creating the diff, without

+ 16 - 0
vendor/github.com/containerd/containerd/errdefs/errors.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 // Package errdefs defines the common errors used throughout containerd
 // packages.
 //

+ 16 - 0
vendor/github.com/containerd/containerd/errdefs/grpc.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package errdefs
 
 import (

+ 18 - 2
vendor/github.com/containerd/containerd/events/events.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package events
 
 import (
@@ -26,9 +42,9 @@ func (e *Envelope) Field(fieldpath []string) (string, bool) {
 	switch fieldpath[0] {
 	// unhandled: timestamp
 	case "namespace":
-		return string(e.Namespace), len(e.Namespace) > 0
+		return e.Namespace, len(e.Namespace) > 0
 	case "topic":
-		return string(e.Topic), len(e.Topic) > 0
+		return e.Topic, len(e.Topic) > 0
 	case "event":
 		decoded, err := typeurl.UnmarshalAny(e.Event)
 		if err != nil {

+ 16 - 0
vendor/github.com/containerd/containerd/events/exchange/exchange.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package exchange
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/filters/adaptor.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package filters
 
 // Adaptor specifies the mapping of fieldpaths to a type. For the given field

+ 16 - 0
vendor/github.com/containerd/containerd/filters/filter.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 // Package filters defines a syntax and parser that can be used for the
 // filtration of items across the containerd API. The core is built on the
 // concept of protobuf field paths, with quoting.  Several operators allow the

+ 16 - 0
vendor/github.com/containerd/containerd/filters/parser.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package filters
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/filters/quote.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package filters
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/filters/scanner.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package filters
 
 import (

+ 0 - 119
vendor/github.com/containerd/containerd/fs/copy.go

@@ -1,119 +0,0 @@
-package fs
-
-import (
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"sync"
-
-	"github.com/pkg/errors"
-)
-
-var bufferPool = &sync.Pool{
-	New: func() interface{} {
-		buffer := make([]byte, 32*1024)
-		return &buffer
-	},
-}
-
-// CopyDir copies the directory from src to dst.
-// Most efficient copy of files is attempted.
-func CopyDir(dst, src string) error {
-	inodes := map[uint64]string{}
-	return copyDirectory(dst, src, inodes)
-}
-
-func copyDirectory(dst, src string, inodes map[uint64]string) error {
-	stat, err := os.Stat(src)
-	if err != nil {
-		return errors.Wrapf(err, "failed to stat %s", src)
-	}
-	if !stat.IsDir() {
-		return errors.Errorf("source is not directory")
-	}
-
-	if st, err := os.Stat(dst); err != nil {
-		if err := os.Mkdir(dst, stat.Mode()); err != nil {
-			return errors.Wrapf(err, "failed to mkdir %s", dst)
-		}
-	} else if !st.IsDir() {
-		return errors.Errorf("cannot copy to non-directory: %s", dst)
-	} else {
-		if err := os.Chmod(dst, stat.Mode()); err != nil {
-			return errors.Wrapf(err, "failed to chmod on %s", dst)
-		}
-	}
-
-	fis, err := ioutil.ReadDir(src)
-	if err != nil {
-		return errors.Wrapf(err, "failed to read %s", src)
-	}
-
-	if err := copyFileInfo(stat, dst); err != nil {
-		return errors.Wrapf(err, "failed to copy file info for %s", dst)
-	}
-
-	for _, fi := range fis {
-		source := filepath.Join(src, fi.Name())
-		target := filepath.Join(dst, fi.Name())
-
-		switch {
-		case fi.IsDir():
-			if err := copyDirectory(target, source, inodes); err != nil {
-				return err
-			}
-			continue
-		case (fi.Mode() & os.ModeType) == 0:
-			link, err := getLinkSource(target, fi, inodes)
-			if err != nil {
-				return errors.Wrap(err, "failed to get hardlink")
-			}
-			if link != "" {
-				if err := os.Link(link, target); err != nil {
-					return errors.Wrap(err, "failed to create hard link")
-				}
-			} else if err := copyFile(source, target); err != nil {
-				return errors.Wrap(err, "failed to copy files")
-			}
-		case (fi.Mode() & os.ModeSymlink) == os.ModeSymlink:
-			link, err := os.Readlink(source)
-			if err != nil {
-				return errors.Wrapf(err, "failed to read link: %s", source)
-			}
-			if err := os.Symlink(link, target); err != nil {
-				return errors.Wrapf(err, "failed to create symlink: %s", target)
-			}
-		case (fi.Mode() & os.ModeDevice) == os.ModeDevice:
-			if err := copyDevice(target, fi); err != nil {
-				return errors.Wrapf(err, "failed to create device")
-			}
-		default:
-			// TODO: Support pipes and sockets
-			return errors.Wrapf(err, "unsupported mode %s", fi.Mode())
-		}
-		if err := copyFileInfo(fi, target); err != nil {
-			return errors.Wrap(err, "failed to copy file info")
-		}
-
-		if err := copyXAttrs(target, source); err != nil {
-			return errors.Wrap(err, "failed to copy xattrs")
-		}
-	}
-
-	return nil
-}
-
-func copyFile(source, target string) error {
-	src, err := os.Open(source)
-	if err != nil {
-		return errors.Wrapf(err, "failed to open source %s", source)
-	}
-	defer src.Close()
-	tgt, err := os.Create(target)
-	if err != nil {
-		return errors.Wrapf(err, "failed to open target %s", target)
-	}
-	defer tgt.Close()
-
-	return copyFileContent(tgt, src)
-}

+ 0 - 83
vendor/github.com/containerd/containerd/fs/copy_linux.go

@@ -1,83 +0,0 @@
-package fs
-
-import (
-	"io"
-	"os"
-	"syscall"
-
-	"github.com/containerd/containerd/sys"
-	"github.com/containerd/continuity/sysx"
-	"github.com/pkg/errors"
-	"golang.org/x/sys/unix"
-)
-
-func copyFileInfo(fi os.FileInfo, name string) error {
-	st := fi.Sys().(*syscall.Stat_t)
-	if err := os.Lchown(name, int(st.Uid), int(st.Gid)); err != nil {
-		return errors.Wrapf(err, "failed to chown %s", name)
-	}
-
-	if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink {
-		if err := os.Chmod(name, fi.Mode()); err != nil {
-			return errors.Wrapf(err, "failed to chmod %s", name)
-		}
-	}
-
-	timespec := []unix.Timespec{unix.Timespec(sys.StatAtime(st)), unix.Timespec(sys.StatMtime(st))}
-	if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
-		return errors.Wrapf(err, "failed to utime %s", name)
-	}
-
-	return nil
-}
-
-func copyFileContent(dst, src *os.File) error {
-	st, err := src.Stat()
-	if err != nil {
-		return errors.Wrap(err, "unable to stat source")
-	}
-
-	n, err := unix.CopyFileRange(int(src.Fd()), nil, int(dst.Fd()), nil, int(st.Size()), 0)
-	if err != nil {
-		if err != unix.ENOSYS && err != unix.EXDEV {
-			return errors.Wrap(err, "copy file range failed")
-		}
-
-		buf := bufferPool.Get().(*[]byte)
-		_, err = io.CopyBuffer(dst, src, *buf)
-		bufferPool.Put(buf)
-		return err
-	}
-
-	if int64(n) != st.Size() {
-		return errors.Wrapf(err, "short copy: %d of %d", int64(n), st.Size())
-	}
-
-	return nil
-}
-
-func copyXAttrs(dst, src string) error {
-	xattrKeys, err := sysx.LListxattr(src)
-	if err != nil {
-		return errors.Wrapf(err, "failed to list xattrs on %s", src)
-	}
-	for _, xattr := range xattrKeys {
-		data, err := sysx.LGetxattr(src, xattr)
-		if err != nil {
-			return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src)
-		}
-		if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil {
-			return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst)
-		}
-	}
-
-	return nil
-}
-
-func copyDevice(dst string, fi os.FileInfo) error {
-	st, ok := fi.Sys().(*syscall.Stat_t)
-	if !ok {
-		return errors.New("unsupported stat type")
-	}
-	return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev))
-}

+ 0 - 68
vendor/github.com/containerd/containerd/fs/copy_unix.go

@@ -1,68 +0,0 @@
-// +build solaris darwin freebsd
-
-package fs
-
-import (
-	"io"
-	"os"
-	"syscall"
-
-	"github.com/containerd/containerd/sys"
-	"github.com/containerd/continuity/sysx"
-	"github.com/pkg/errors"
-	"golang.org/x/sys/unix"
-)
-
-func copyFileInfo(fi os.FileInfo, name string) error {
-	st := fi.Sys().(*syscall.Stat_t)
-	if err := os.Lchown(name, int(st.Uid), int(st.Gid)); err != nil {
-		return errors.Wrapf(err, "failed to chown %s", name)
-	}
-
-	if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink {
-		if err := os.Chmod(name, fi.Mode()); err != nil {
-			return errors.Wrapf(err, "failed to chmod %s", name)
-		}
-	}
-
-	timespec := []syscall.Timespec{sys.StatAtime(st), sys.StatMtime(st)}
-	if err := syscall.UtimesNano(name, timespec); err != nil {
-		return errors.Wrapf(err, "failed to utime %s", name)
-	}
-
-	return nil
-}
-
-func copyFileContent(dst, src *os.File) error {
-	buf := bufferPool.Get().(*[]byte)
-	_, err := io.CopyBuffer(dst, src, *buf)
-	bufferPool.Put(buf)
-
-	return err
-}
-
-func copyXAttrs(dst, src string) error {
-	xattrKeys, err := sysx.LListxattr(src)
-	if err != nil {
-		return errors.Wrapf(err, "failed to list xattrs on %s", src)
-	}
-	for _, xattr := range xattrKeys {
-		data, err := sysx.LGetxattr(src, xattr)
-		if err != nil {
-			return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src)
-		}
-		if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil {
-			return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst)
-		}
-	}
-
-	return nil
-}
-
-func copyDevice(dst string, fi os.FileInfo) error {
-	st, ok := fi.Sys().(*syscall.Stat_t)
-	if !ok {
-		return errors.New("unsupported stat type")
-	}
-	return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev))
-}

+ 0 - 33
vendor/github.com/containerd/containerd/fs/copy_windows.go

@@ -1,33 +0,0 @@
-package fs
-
-import (
-	"io"
-	"os"
-
-	"github.com/pkg/errors"
-)
-
-func copyFileInfo(fi os.FileInfo, name string) error {
-	if err := os.Chmod(name, fi.Mode()); err != nil {
-		return errors.Wrapf(err, "failed to chmod %s", name)
-	}
-
-	// TODO: copy windows specific metadata
-
-	return nil
-}
-
-func copyFileContent(dst, src *os.File) error {
-	buf := bufferPool.Get().(*[]byte)
-	_, err := io.CopyBuffer(dst, src, *buf)
-	bufferPool.Put(buf)
-	return err
-}
-
-func copyXAttrs(dst, src string) error {
-	return nil
-}
-
-func copyDevice(dst string, fi os.FileInfo) error {
-	return errors.New("device copy not supported")
-}

+ 0 - 381
vendor/github.com/containerd/containerd/fs/diff.go

@@ -1,381 +0,0 @@
-package fs
-
-import (
-	"context"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"golang.org/x/sync/errgroup"
-
-	"github.com/sirupsen/logrus"
-)
-
-// ChangeKind is the type of modification that
-// a change is making.
-type ChangeKind int
-
-const (
-	// ChangeKindUnmodified represents an unmodified
-	// file
-	ChangeKindUnmodified = iota
-
-	// ChangeKindAdd represents an addition of
-	// a file
-	ChangeKindAdd
-
-	// ChangeKindModify represents a change to
-	// an existing file
-	ChangeKindModify
-
-	// ChangeKindDelete represents a delete of
-	// a file
-	ChangeKindDelete
-)
-
-func (k ChangeKind) String() string {
-	switch k {
-	case ChangeKindUnmodified:
-		return "unmodified"
-	case ChangeKindAdd:
-		return "add"
-	case ChangeKindModify:
-		return "modify"
-	case ChangeKindDelete:
-		return "delete"
-	default:
-		return ""
-	}
-}
-
-// Change represents single change between a diff and its parent.
-type Change struct {
-	Kind ChangeKind
-	Path string
-}
-
-// ChangeFunc is the type of function called for each change
-// computed during a directory changes calculation.
-type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
-
-// Changes computes changes between two directories calling the
-// given change function for each computed change. The first
-// directory is intended to the base directory and second
-// directory the changed directory.
-//
-// The change callback is called by the order of path names and
-// should be appliable in that order.
-//  Due to this apply ordering, the following is true
-//  - Removed directory trees only create a single change for the root
-//    directory removed. Remaining changes are implied.
-//  - A directory which is modified to become a file will not have
-//    delete entries for sub-path items, their removal is implied
-//    by the removal of the parent directory.
-//
-// Opaque directories will not be treated specially and each file
-// removed from the base directory will show up as a removal.
-//
-// File content comparisons will be done on files which have timestamps
-// which may have been truncated. If either of the files being compared
-// has a zero value nanosecond value, each byte will be compared for
-// differences. If 2 files have the same seconds value but different
-// nanosecond values where one of those values is zero, the files will
-// be considered unchanged if the content is the same. This behavior
-// is to account for timestamp truncation during archiving.
-func Changes(ctx context.Context, a, b string, changeFn ChangeFunc) error {
-	if a == "" {
-		logrus.Debugf("Using single walk diff for %s", b)
-		return addDirChanges(ctx, changeFn, b)
-	} else if diffOptions := detectDirDiff(b, a); diffOptions != nil {
-		logrus.Debugf("Using single walk diff for %s from %s", diffOptions.diffDir, a)
-		return diffDirChanges(ctx, changeFn, a, diffOptions)
-	}
-
-	logrus.Debugf("Using double walk diff for %s from %s", b, a)
-	return doubleWalkDiff(ctx, changeFn, a, b)
-}
-
-func addDirChanges(ctx context.Context, changeFn ChangeFunc, root string) error {
-	return filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-
-		// Rebase path
-		path, err = filepath.Rel(root, path)
-		if err != nil {
-			return err
-		}
-
-		path = filepath.Join(string(os.PathSeparator), path)
-
-		// Skip root
-		if path == string(os.PathSeparator) {
-			return nil
-		}
-
-		return changeFn(ChangeKindAdd, path, f, nil)
-	})
-}
-
-// diffDirOptions is used when the diff can be directly calculated from
-// a diff directory to its base, without walking both trees.
-type diffDirOptions struct {
-	diffDir      string
-	skipChange   func(string) (bool, error)
-	deleteChange func(string, string, os.FileInfo) (string, error)
-}
-
-// diffDirChanges walks the diff directory and compares changes against the base.
-func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *diffDirOptions) error {
-	changedDirs := make(map[string]struct{})
-	return filepath.Walk(o.diffDir, func(path string, f os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-
-		// Rebase path
-		path, err = filepath.Rel(o.diffDir, path)
-		if err != nil {
-			return err
-		}
-
-		path = filepath.Join(string(os.PathSeparator), path)
-
-		// Skip root
-		if path == string(os.PathSeparator) {
-			return nil
-		}
-
-		// TODO: handle opaqueness, start new double walker at this
-		// location to get deletes, and skip tree in single walker
-
-		if o.skipChange != nil {
-			if skip, err := o.skipChange(path); skip {
-				return err
-			}
-		}
-
-		var kind ChangeKind
-
-		deletedFile, err := o.deleteChange(o.diffDir, path, f)
-		if err != nil {
-			return err
-		}
-
-		// Find out what kind of modification happened
-		if deletedFile != "" {
-			path = deletedFile
-			kind = ChangeKindDelete
-			f = nil
-		} else {
-			// Otherwise, the file was added
-			kind = ChangeKindAdd
-
-			// ...Unless it already existed in a base, in which case, it's a modification
-			stat, err := os.Stat(filepath.Join(base, path))
-			if err != nil && !os.IsNotExist(err) {
-				return err
-			}
-			if err == nil {
-				// The file existed in the base, so that's a modification
-
-				// However, if it's a directory, maybe it wasn't actually modified.
-				// If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar
-				if stat.IsDir() && f.IsDir() {
-					if f.Size() == stat.Size() && f.Mode() == stat.Mode() && sameFsTime(f.ModTime(), stat.ModTime()) {
-						// Both directories are the same, don't record the change
-						return nil
-					}
-				}
-				kind = ChangeKindModify
-			}
-		}
-
-		// If /foo/bar/file.txt is modified, then /foo/bar must be part of the changed files.
-		// This block is here to ensure the change is recorded even if the
-		// modify time, mode and size of the parent directory in the rw and ro layers are all equal.
-		// Check https://github.com/docker/docker/pull/13590 for details.
-		if f.IsDir() {
-			changedDirs[path] = struct{}{}
-		}
-		if kind == ChangeKindAdd || kind == ChangeKindDelete {
-			parent := filepath.Dir(path)
-			if _, ok := changedDirs[parent]; !ok && parent != "/" {
-				pi, err := os.Stat(filepath.Join(o.diffDir, parent))
-				if err := changeFn(ChangeKindModify, parent, pi, err); err != nil {
-					return err
-				}
-				changedDirs[parent] = struct{}{}
-			}
-		}
-
-		return changeFn(kind, path, f, nil)
-	})
-}
-
-// doubleWalkDiff walks both directories to create a diff
-func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b string) (err error) {
-	g, ctx := errgroup.WithContext(ctx)
-
-	var (
-		c1 = make(chan *currentPath)
-		c2 = make(chan *currentPath)
-
-		f1, f2         *currentPath
-		rmdir          string
-		lastEmittedDir = string(filepath.Separator)
-		parents        []os.FileInfo
-	)
-	g.Go(func() error {
-		defer close(c1)
-		return pathWalk(ctx, a, c1)
-	})
-	g.Go(func() error {
-		defer close(c2)
-		return pathWalk(ctx, b, c2)
-	})
-	g.Go(func() error {
-		for c1 != nil || c2 != nil {
-			if f1 == nil && c1 != nil {
-				f1, err = nextPath(ctx, c1)
-				if err != nil {
-					return err
-				}
-				if f1 == nil {
-					c1 = nil
-				}
-			}
-
-			if f2 == nil && c2 != nil {
-				f2, err = nextPath(ctx, c2)
-				if err != nil {
-					return err
-				}
-				if f2 == nil {
-					c2 = nil
-				}
-			}
-			if f1 == nil && f2 == nil {
-				continue
-			}
-
-			var (
-				f    os.FileInfo
-				emit = true
-			)
-			k, p := pathChange(f1, f2)
-			switch k {
-			case ChangeKindAdd:
-				if rmdir != "" {
-					rmdir = ""
-				}
-				f = f2.f
-				f2 = nil
-			case ChangeKindDelete:
-				// Check if this file is already removed by being
-				// under of a removed directory
-				if rmdir != "" && strings.HasPrefix(f1.path, rmdir) {
-					f1 = nil
-					continue
-				} else if rmdir == "" && f1.f.IsDir() {
-					rmdir = f1.path + string(os.PathSeparator)
-				} else if rmdir != "" {
-					rmdir = ""
-				}
-				f1 = nil
-			case ChangeKindModify:
-				same, err := sameFile(f1, f2)
-				if err != nil {
-					return err
-				}
-				if f1.f.IsDir() && !f2.f.IsDir() {
-					rmdir = f1.path + string(os.PathSeparator)
-				} else if rmdir != "" {
-					rmdir = ""
-				}
-				f = f2.f
-				f1 = nil
-				f2 = nil
-				if same {
-					if !isLinked(f) {
-						emit = false
-					}
-					k = ChangeKindUnmodified
-				}
-			}
-			if emit {
-				emittedDir, emitParents := commonParents(lastEmittedDir, p, parents)
-				for _, pf := range emitParents {
-					p := filepath.Join(emittedDir, pf.Name())
-					if err := changeFn(ChangeKindUnmodified, p, pf, nil); err != nil {
-						return err
-					}
-					emittedDir = p
-				}
-
-				if err := changeFn(k, p, f, nil); err != nil {
-					return err
-				}
-
-				if f != nil && f.IsDir() {
-					lastEmittedDir = p
-				} else {
-					lastEmittedDir = emittedDir
-				}
-
-				parents = parents[:0]
-			} else if f.IsDir() {
-				lastEmittedDir, parents = commonParents(lastEmittedDir, p, parents)
-				parents = append(parents, f)
-			}
-		}
-		return nil
-	})
-
-	return g.Wait()
-}
-
-func commonParents(base, updated string, dirs []os.FileInfo) (string, []os.FileInfo) {
-	if basePrefix := makePrefix(base); strings.HasPrefix(updated, basePrefix) {
-		var (
-			parents []os.FileInfo
-			last    = base
-		)
-		for _, d := range dirs {
-			next := filepath.Join(last, d.Name())
-			if strings.HasPrefix(updated, makePrefix(last)) {
-				parents = append(parents, d)
-				last = next
-			} else {
-				break
-			}
-		}
-		return base, parents
-	}
-
-	baseS := strings.Split(base, string(filepath.Separator))
-	updatedS := strings.Split(updated, string(filepath.Separator))
-	commonS := []string{string(filepath.Separator)}
-
-	min := len(baseS)
-	if len(updatedS) < min {
-		min = len(updatedS)
-	}
-	for i := 0; i < min; i++ {
-		if baseS[i] == updatedS[i] {
-			commonS = append(commonS, baseS[i])
-		} else {
-			break
-		}
-	}
-
-	return filepath.Join(commonS...), []os.FileInfo{}
-}
-
-func makePrefix(d string) string {
-	if d == "" || d[len(d)-1] != filepath.Separator {
-		return d + string(filepath.Separator)
-	}
-	return d
-}

+ 0 - 58
vendor/github.com/containerd/containerd/fs/diff_unix.go

@@ -1,58 +0,0 @@
-// +build !windows
-
-package fs
-
-import (
-	"bytes"
-	"os"
-	"syscall"
-
-	"github.com/containerd/continuity/sysx"
-	"github.com/pkg/errors"
-)
-
-// detectDirDiff returns diff dir options if a directory could
-// be found in the mount info for upper which is the direct
-// diff with the provided lower directory
-func detectDirDiff(upper, lower string) *diffDirOptions {
-	// TODO: get mount options for upper
-	// TODO: detect AUFS
-	// TODO: detect overlay
-	return nil
-}
-
-// compareSysStat returns whether the stats are equivalent,
-// whether the files are considered the same file, and
-// an error
-func compareSysStat(s1, s2 interface{}) (bool, error) {
-	ls1, ok := s1.(*syscall.Stat_t)
-	if !ok {
-		return false, nil
-	}
-	ls2, ok := s2.(*syscall.Stat_t)
-	if !ok {
-		return false, nil
-	}
-
-	return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Rdev == ls2.Rdev, nil
-}
-
-func compareCapabilities(p1, p2 string) (bool, error) {
-	c1, err := sysx.LGetxattr(p1, "security.capability")
-	if err != nil && err != sysx.ENODATA {
-		return false, errors.Wrapf(err, "failed to get xattr for %s", p1)
-	}
-	c2, err := sysx.LGetxattr(p2, "security.capability")
-	if err != nil && err != sysx.ENODATA {
-		return false, errors.Wrapf(err, "failed to get xattr for %s", p2)
-	}
-	return bytes.Equal(c1, c2), nil
-}
-
-func isLinked(f os.FileInfo) bool {
-	s, ok := f.Sys().(*syscall.Stat_t)
-	if !ok {
-		return false
-	}
-	return !f.IsDir() && s.Nlink > 1
-}

+ 0 - 32
vendor/github.com/containerd/containerd/fs/diff_windows.go

@@ -1,32 +0,0 @@
-package fs
-
-import (
-	"os"
-
-	"golang.org/x/sys/windows"
-)
-
-func detectDirDiff(upper, lower string) *diffDirOptions {
-	return nil
-}
-
-func compareSysStat(s1, s2 interface{}) (bool, error) {
-	f1, ok := s1.(windows.Win32FileAttributeData)
-	if !ok {
-		return false, nil
-	}
-	f2, ok := s2.(windows.Win32FileAttributeData)
-	if !ok {
-		return false, nil
-	}
-	return f1.FileAttributes == f2.FileAttributes, nil
-}
-
-func compareCapabilities(p1, p2 string) (bool, error) {
-	// TODO: Use windows equivalent
-	return true, nil
-}
-
-func isLinked(os.FileInfo) bool {
-	return false
-}

+ 0 - 87
vendor/github.com/containerd/containerd/fs/dtype_linux.go

@@ -1,87 +0,0 @@
-// +build linux
-
-package fs
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"syscall"
-	"unsafe"
-)
-
-func locateDummyIfEmpty(path string) (string, error) {
-	children, err := ioutil.ReadDir(path)
-	if err != nil {
-		return "", err
-	}
-	if len(children) != 0 {
-		return "", nil
-	}
-	dummyFile, err := ioutil.TempFile(path, "fsutils-dummy")
-	if err != nil {
-		return "", err
-	}
-	name := dummyFile.Name()
-	err = dummyFile.Close()
-	return name, err
-}
-
-// SupportsDType returns whether the filesystem mounted on path supports d_type
-func SupportsDType(path string) (bool, error) {
-	// locate dummy so that we have at least one dirent
-	dummy, err := locateDummyIfEmpty(path)
-	if err != nil {
-		return false, err
-	}
-	if dummy != "" {
-		defer os.Remove(dummy)
-	}
-
-	visited := 0
-	supportsDType := true
-	fn := func(ent *syscall.Dirent) bool {
-		visited++
-		if ent.Type == syscall.DT_UNKNOWN {
-			supportsDType = false
-			// stop iteration
-			return true
-		}
-		// continue iteration
-		return false
-	}
-	if err = iterateReadDir(path, fn); err != nil {
-		return false, err
-	}
-	if visited == 0 {
-		return false, fmt.Errorf("did not hit any dirent during iteration %s", path)
-	}
-	return supportsDType, nil
-}
-
-func iterateReadDir(path string, fn func(*syscall.Dirent) bool) error {
-	d, err := os.Open(path)
-	if err != nil {
-		return err
-	}
-	defer d.Close()
-	fd := int(d.Fd())
-	buf := make([]byte, 4096)
-	for {
-		nbytes, err := syscall.ReadDirent(fd, buf)
-		if err != nil {
-			return err
-		}
-		if nbytes == 0 {
-			break
-		}
-		for off := 0; off < nbytes; {
-			ent := (*syscall.Dirent)(unsafe.Pointer(&buf[off]))
-			if stop := fn(ent); stop {
-				return nil
-			}
-			off += int(ent.Reclen)
-		}
-	}
-	return nil
-}

+ 0 - 22
vendor/github.com/containerd/containerd/fs/du.go

@@ -1,22 +0,0 @@
-package fs
-
-import "context"
-
-// Usage of disk information
-type Usage struct {
-	Inodes int64
-	Size   int64
-}
-
-// DiskUsage counts the number of inodes and disk usage for the resources under
-// path.
-func DiskUsage(roots ...string) (Usage, error) {
-	return diskUsage(roots...)
-}
-
-// DiffUsage counts the numbers of inodes and disk usage in the
-// diff between the 2 directories. The first path is intended
-// as the base directory and the second as the changed directory.
-func DiffUsage(ctx context.Context, a, b string) (Usage, error) {
-	return diffUsage(ctx, a, b)
-}

+ 0 - 83
vendor/github.com/containerd/containerd/fs/du_unix.go

@@ -1,83 +0,0 @@
-// +build !windows
-
-package fs
-
-import (
-	"context"
-	"os"
-	"path/filepath"
-	"syscall"
-)
-
-type inode struct {
-	// TODO(stevvooe): Can probably reduce memory usage by not tracking
-	// device, but we can leave this right for now.
-	dev, ino uint64
-}
-
-func diskUsage(roots ...string) (Usage, error) {
-
-	var (
-		size   int64
-		inodes = map[inode]struct{}{} // expensive!
-	)
-
-	for _, root := range roots {
-		if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
-			if err != nil {
-				return err
-			}
-
-			stat := fi.Sys().(*syscall.Stat_t)
-
-			inoKey := inode{dev: uint64(stat.Dev), ino: uint64(stat.Ino)}
-			if _, ok := inodes[inoKey]; !ok {
-				inodes[inoKey] = struct{}{}
-				size += fi.Size()
-			}
-
-			return nil
-		}); err != nil {
-			return Usage{}, err
-		}
-	}
-
-	return Usage{
-		Inodes: int64(len(inodes)),
-		Size:   size,
-	}, nil
-}
-
-func diffUsage(ctx context.Context, a, b string) (Usage, error) {
-	var (
-		size   int64
-		inodes = map[inode]struct{}{} // expensive!
-	)
-
-	if err := Changes(ctx, a, b, func(kind ChangeKind, _ string, fi os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-
-		if kind == ChangeKindAdd || kind == ChangeKindModify {
-			stat := fi.Sys().(*syscall.Stat_t)
-
-			inoKey := inode{dev: uint64(stat.Dev), ino: uint64(stat.Ino)}
-			if _, ok := inodes[inoKey]; !ok {
-				inodes[inoKey] = struct{}{}
-				size += fi.Size()
-			}
-
-			return nil
-
-		}
-		return nil
-	}); err != nil {
-		return Usage{}, err
-	}
-
-	return Usage{
-		Inodes: int64(len(inodes)),
-		Size:   size,
-	}, nil
-}

+ 0 - 60
vendor/github.com/containerd/containerd/fs/du_windows.go

@@ -1,60 +0,0 @@
-// +build windows
-
-package fs
-
-import (
-	"context"
-	"os"
-	"path/filepath"
-)
-
-func diskUsage(roots ...string) (Usage, error) {
-	var (
-		size int64
-	)
-
-	// TODO(stevvooe): Support inodes (or equivalent) for windows.
-
-	for _, root := range roots {
-		if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
-			if err != nil {
-				return err
-			}
-
-			size += fi.Size()
-			return nil
-		}); err != nil {
-			return Usage{}, err
-		}
-	}
-
-	return Usage{
-		Size: size,
-	}, nil
-}
-
-func diffUsage(ctx context.Context, a, b string) (Usage, error) {
-	var (
-		size int64
-	)
-
-	if err := Changes(ctx, a, b, func(kind ChangeKind, _ string, fi os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-
-		if kind == ChangeKindAdd || kind == ChangeKindModify {
-			size += fi.Size()
-
-			return nil
-
-		}
-		return nil
-	}); err != nil {
-		return Usage{}, err
-	}
-
-	return Usage{
-		Size: size,
-	}, nil
-}

+ 0 - 27
vendor/github.com/containerd/containerd/fs/hardlink.go

@@ -1,27 +0,0 @@
-package fs
-
-import "os"
-
-// GetLinkInfo returns an identifier representing the node a hardlink is pointing
-// to. If the file is not hard linked then 0 will be returned.
-func GetLinkInfo(fi os.FileInfo) (uint64, bool) {
-	return getLinkInfo(fi)
-}
-
-// getLinkSource returns a path for the given name and
-// file info to its link source in the provided inode
-// map. If the given file name is not in the map and
-// has other links, it is added to the inode map
-// to be a source for other link locations.
-func getLinkSource(name string, fi os.FileInfo, inodes map[uint64]string) (string, error) {
-	inode, isHardlink := getLinkInfo(fi)
-	if !isHardlink {
-		return "", nil
-	}
-
-	path, ok := inodes[inode]
-	if !ok {
-		inodes[inode] = name
-	}
-	return path, nil
-}

+ 0 - 17
vendor/github.com/containerd/containerd/fs/hardlink_unix.go

@@ -1,17 +0,0 @@
-// +build !windows
-
-package fs
-
-import (
-	"os"
-	"syscall"
-)
-
-func getLinkInfo(fi os.FileInfo) (uint64, bool) {
-	s, ok := fi.Sys().(*syscall.Stat_t)
-	if !ok {
-		return 0, false
-	}
-
-	return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1
-}

+ 0 - 7
vendor/github.com/containerd/containerd/fs/hardlink_windows.go

@@ -1,7 +0,0 @@
-package fs
-
-import "os"
-
-func getLinkInfo(fi os.FileInfo) (uint64, bool) {
-	return 0, false
-}

+ 0 - 276
vendor/github.com/containerd/containerd/fs/path.go

@@ -1,276 +0,0 @@
-package fs
-
-import (
-	"bytes"
-	"context"
-	"io"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"github.com/pkg/errors"
-)
-
-var (
-	errTooManyLinks = errors.New("too many links")
-)
-
-type currentPath struct {
-	path     string
-	f        os.FileInfo
-	fullPath string
-}
-
-func pathChange(lower, upper *currentPath) (ChangeKind, string) {
-	if lower == nil {
-		if upper == nil {
-			panic("cannot compare nil paths")
-		}
-		return ChangeKindAdd, upper.path
-	}
-	if upper == nil {
-		return ChangeKindDelete, lower.path
-	}
-	// TODO: compare by directory
-
-	switch i := strings.Compare(lower.path, upper.path); {
-	case i < 0:
-		// File in lower that is not in upper
-		return ChangeKindDelete, lower.path
-	case i > 0:
-		// File in upper that is not in lower
-		return ChangeKindAdd, upper.path
-	default:
-		return ChangeKindModify, upper.path
-	}
-}
-
-func sameFile(f1, f2 *currentPath) (bool, error) {
-	if os.SameFile(f1.f, f2.f) {
-		return true, nil
-	}
-
-	equalStat, err := compareSysStat(f1.f.Sys(), f2.f.Sys())
-	if err != nil || !equalStat {
-		return equalStat, err
-	}
-
-	if eq, err := compareCapabilities(f1.fullPath, f2.fullPath); err != nil || !eq {
-		return eq, err
-	}
-
-	// If not a directory also check size, modtime, and content
-	if !f1.f.IsDir() {
-		if f1.f.Size() != f2.f.Size() {
-			return false, nil
-		}
-		t1 := f1.f.ModTime()
-		t2 := f2.f.ModTime()
-
-		if t1.Unix() != t2.Unix() {
-			return false, nil
-		}
-
-		// If the timestamp may have been truncated in one of the
-		// files, check content of file to determine difference
-		if t1.Nanosecond() == 0 || t2.Nanosecond() == 0 {
-			var eq bool
-			if (f1.f.Mode() & os.ModeSymlink) == os.ModeSymlink {
-				eq, err = compareSymlinkTarget(f1.fullPath, f2.fullPath)
-			} else if f1.f.Size() > 0 {
-				eq, err = compareFileContent(f1.fullPath, f2.fullPath)
-			}
-			if err != nil || !eq {
-				return eq, err
-			}
-		} else if t1.Nanosecond() != t2.Nanosecond() {
-			return false, nil
-		}
-	}
-
-	return true, nil
-}
-
-func compareSymlinkTarget(p1, p2 string) (bool, error) {
-	t1, err := os.Readlink(p1)
-	if err != nil {
-		return false, err
-	}
-	t2, err := os.Readlink(p2)
-	if err != nil {
-		return false, err
-	}
-	return t1 == t2, nil
-}
-
-const compareChuckSize = 32 * 1024
-
-// compareFileContent compares the content of 2 same sized files
-// by comparing each byte.
-func compareFileContent(p1, p2 string) (bool, error) {
-	f1, err := os.Open(p1)
-	if err != nil {
-		return false, err
-	}
-	defer f1.Close()
-	f2, err := os.Open(p2)
-	if err != nil {
-		return false, err
-	}
-	defer f2.Close()
-
-	b1 := make([]byte, compareChuckSize)
-	b2 := make([]byte, compareChuckSize)
-	for {
-		n1, err1 := f1.Read(b1)
-		if err1 != nil && err1 != io.EOF {
-			return false, err1
-		}
-		n2, err2 := f2.Read(b2)
-		if err2 != nil && err2 != io.EOF {
-			return false, err2
-		}
-		if n1 != n2 || !bytes.Equal(b1[:n1], b2[:n2]) {
-			return false, nil
-		}
-		if err1 == io.EOF && err2 == io.EOF {
-			return true, nil
-		}
-	}
-}
-
-func pathWalk(ctx context.Context, root string, pathC chan<- *currentPath) error {
-	return filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-
-		// Rebase path
-		path, err = filepath.Rel(root, path)
-		if err != nil {
-			return err
-		}
-
-		path = filepath.Join(string(os.PathSeparator), path)
-
-		// Skip root
-		if path == string(os.PathSeparator) {
-			return nil
-		}
-
-		p := &currentPath{
-			path:     path,
-			f:        f,
-			fullPath: filepath.Join(root, path),
-		}
-
-		select {
-		case <-ctx.Done():
-			return ctx.Err()
-		case pathC <- p:
-			return nil
-		}
-	})
-}
-
-func nextPath(ctx context.Context, pathC <-chan *currentPath) (*currentPath, error) {
-	select {
-	case <-ctx.Done():
-		return nil, ctx.Err()
-	case p := <-pathC:
-		return p, nil
-	}
-}
-
-// RootPath joins a path with a root, evaluating and bounding any
-// symlink to the root directory.
-func RootPath(root, path string) (string, error) {
-	if path == "" {
-		return root, nil
-	}
-	var linksWalked int // to protect against cycles
-	for {
-		i := linksWalked
-		newpath, err := walkLinks(root, path, &linksWalked)
-		if err != nil {
-			return "", err
-		}
-		path = newpath
-		if i == linksWalked {
-			newpath = filepath.Join("/", newpath)
-			if path == newpath {
-				return filepath.Join(root, newpath), nil
-			}
-			path = newpath
-		}
-	}
-}
-
-func walkLink(root, path string, linksWalked *int) (newpath string, islink bool, err error) {
-	if *linksWalked > 255 {
-		return "", false, errTooManyLinks
-	}
-
-	path = filepath.Join("/", path)
-	if path == "/" {
-		return path, false, nil
-	}
-	realPath := filepath.Join(root, path)
-
-	fi, err := os.Lstat(realPath)
-	if err != nil {
-		// If path does not yet exist, treat as non-symlink
-		if os.IsNotExist(err) {
-			return path, false, nil
-		}
-		return "", false, err
-	}
-	if fi.Mode()&os.ModeSymlink == 0 {
-		return path, false, nil
-	}
-	newpath, err = os.Readlink(realPath)
-	if err != nil {
-		return "", false, err
-	}
-	if filepath.IsAbs(newpath) && strings.HasPrefix(newpath, root) {
-		newpath = newpath[:len(root)]
-		if !strings.HasPrefix(newpath, "/") {
-			newpath = "/" + newpath
-		}
-	}
-	*linksWalked++
-	return newpath, true, nil
-}
-
-func walkLinks(root, path string, linksWalked *int) (string, error) {
-	switch dir, file := filepath.Split(path); {
-	case dir == "":
-		newpath, _, err := walkLink(root, file, linksWalked)
-		return newpath, err
-	case file == "":
-		if os.IsPathSeparator(dir[len(dir)-1]) {
-			if dir == "/" {
-				return dir, nil
-			}
-			return walkLinks(root, dir[:len(dir)-1], linksWalked)
-		}
-		newpath, _, err := walkLink(root, dir, linksWalked)
-		return newpath, err
-	default:
-		newdir, err := walkLinks(root, dir, linksWalked)
-		if err != nil {
-			return "", err
-		}
-		newpath, islink, err := walkLink(root, filepath.Join(newdir, file), linksWalked)
-		if err != nil {
-			return "", err
-		}
-		if !islink {
-			return newpath, nil
-		}
-		if filepath.IsAbs(newpath) {
-			return newpath, nil
-		}
-		return filepath.Join(newdir, newpath), nil
-	}
-}

+ 0 - 13
vendor/github.com/containerd/containerd/fs/time.go

@@ -1,13 +0,0 @@
-package fs
-
-import "time"
-
-// Gnu tar and the go tar writer don't have sub-second mtime
-// precision, which is problematic when we apply changes via tar
-// files, we handle this by comparing for exact times, *or* same
-// second count and either a or b having exactly 0 nanoseconds
-func sameFsTime(a, b time.Time) bool {
-	return a == b ||
-		(a.Unix() == b.Unix() &&
-			(a.Nanosecond() == 0 || b.Nanosecond() == 0))
-}

+ 22 - 0
vendor/github.com/containerd/containerd/gc/gc.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 // Package gc experiments with providing central gc tooling to ensure
 // deterministic resource removal within containerd.
 //
@@ -8,6 +24,7 @@ package gc
 import (
 	"context"
 	"sync"
+	"time"
 )
 
 // ResourceType represents type of resource at a node
@@ -21,6 +38,11 @@ type Node struct {
 	Key       string
 }
 
+// Stats about a garbage collection run
+type Stats interface {
+	Elapsed() time.Duration
+}
+
 // Tricolor implements basic, single-thread tri-color GC. Given the roots, the
 // complete set and a refs function, this function returns a map of all
 // reachable objects.

+ 16 - 0
vendor/github.com/containerd/containerd/grpc.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/identifiers/validate.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 // Package identifiers provides common validation for identifiers and keys
 // across containerd.
 //

+ 16 - 0
vendor/github.com/containerd/containerd/image.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/image_store.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 89 - 2
vendor/github.com/containerd/containerd/images/handlers.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package images
 
 import (
@@ -5,6 +21,7 @@ import (
 	"fmt"
 
 	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/platforms"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"golang.org/x/sync/errgroup"
@@ -128,8 +145,78 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor)
 //
 // One can also replace this with another implementation to allow descending of
 // arbitrary types.
-func ChildrenHandler(provider content.Provider, platform string) HandlerFunc {
+func ChildrenHandler(provider content.Provider) HandlerFunc {
+	return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
+		return Children(ctx, provider, desc)
+	}
+}
+
+// SetChildrenLabels is a handler wrapper which sets labels for the content on
+// the children returned by the handler and passes through the children.
+// Must follow a handler that returns the children to be labeled.
+func SetChildrenLabels(manager content.Manager, f HandlerFunc) HandlerFunc {
 	return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
-		return Children(ctx, provider, desc, platform)
+		children, err := f(ctx, desc)
+		if err != nil {
+			return children, err
+		}
+
+		if len(children) > 0 {
+			info := content.Info{
+				Digest: desc.Digest,
+				Labels: map[string]string{},
+			}
+			fields := []string{}
+			for i, ch := range children {
+				info.Labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = ch.Digest.String()
+				fields = append(fields, fmt.Sprintf("labels.containerd.io/gc.ref.content.%d", i))
+			}
+
+			_, err := manager.Update(ctx, info, fields...)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		return children, err
+	}
+}
+
+// FilterPlatform is a handler wrapper which limits the descriptors returned
+// by a handler to a single platform.
+func FilterPlatform(platform string, f HandlerFunc) HandlerFunc {
+	return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
+		children, err := f(ctx, desc)
+		if err != nil {
+			return children, err
+		}
+
+		var descs []ocispec.Descriptor
+		if platform != "" && isMultiPlatform(desc.MediaType) {
+			matcher, err := platforms.Parse(platform)
+			if err != nil {
+				return nil, err
+			}
+
+			for _, d := range children {
+				if d.Platform == nil || matcher.Match(*d.Platform) {
+					descs = append(descs, d)
+				}
+			}
+		} else {
+			descs = children
+		}
+
+		return descs, nil
+	}
+
+}
+
+func isMultiPlatform(mediaType string) bool {
+	switch mediaType {
+	case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
+		return true
+	default:
+		return false
 	}
 }

+ 39 - 25
vendor/github.com/containerd/containerd/images/image.go

@@ -1,8 +1,25 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package images
 
 import (
 	"context"
 	"encoding/json"
+	"strings"
 	"time"
 
 	"github.com/containerd/containerd/content"
@@ -101,7 +118,7 @@ func (image *Image) Size(ctx context.Context, provider content.Provider, platfor
 		}
 		size += desc.Size
 		return nil, nil
-	}), ChildrenHandler(provider, platform)), image.Target)
+	}), FilterPlatform(platform, ChildrenHandler(provider))), image.Target)
 }
 
 // Manifest resolves a manifest from the image for the given platform.
@@ -237,7 +254,7 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des
 				platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture}))
 		}
 		return nil, nil
-	}), ChildrenHandler(provider, "")), image)
+	}), ChildrenHandler(provider)), image)
 }
 
 // Check returns nil if the all components of an image are available in the
@@ -284,7 +301,7 @@ func Check(ctx context.Context, provider content.Provider, image ocispec.Descrip
 }
 
 // Children returns the immediate children of content described by the descriptor.
-func Children(ctx context.Context, provider content.Provider, desc ocispec.Descriptor, platform string) ([]ocispec.Descriptor, error) {
+func Children(ctx context.Context, provider content.Provider, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
 	var descs []ocispec.Descriptor
 	switch desc.MediaType {
 	case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
@@ -313,21 +330,7 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr
 			return nil, err
 		}
 
-		if platform != "" {
-			matcher, err := platforms.Parse(platform)
-			if err != nil {
-				return nil, err
-			}
-
-			for _, d := range index.Manifests {
-				if d.Platform == nil || matcher.Match(*d.Platform) {
-					descs = append(descs, d)
-				}
-			}
-		} else {
-			descs = append(descs, index.Manifests...)
-		}
-
+		descs = append(descs, index.Manifests...)
 	case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
 		MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip,
 		MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
@@ -357,13 +360,24 @@ func RootFS(ctx context.Context, provider content.Provider, configDesc ocispec.D
 	if err := json.Unmarshal(p, &config); err != nil {
 		return nil, err
 	}
+	return config.RootFS.DiffIDs, nil
+}
 
-	// TODO(stevvooe): Remove this bit when OCI structure uses correct type for
-	// rootfs.DiffIDs.
-	var diffIDs []digest.Digest
-	for _, diffID := range config.RootFS.DiffIDs {
-		diffIDs = append(diffIDs, digest.Digest(diffID))
+// IsCompressedDiff returns true if mediaType is a known compressed diff media type.
+// It returns false if the media type is a diff, but not compressed. If the media type
+// is not a known diff type, it returns errdefs.ErrNotImplemented
+func IsCompressedDiff(ctx context.Context, mediaType string) (bool, error) {
+	switch mediaType {
+	case ocispec.MediaTypeImageLayer, MediaTypeDockerSchema2Layer:
+	case ocispec.MediaTypeImageLayerGzip, MediaTypeDockerSchema2LayerGzip:
+		return true, nil
+	default:
+		// Still apply all generic media types *.tar[.+]gzip and *.tar
+		if strings.HasSuffix(mediaType, ".tar.gzip") || strings.HasSuffix(mediaType, ".tar+gzip") {
+			return true, nil
+		} else if !strings.HasSuffix(mediaType, ".tar") {
+			return false, errdefs.ErrNotImplemented
+		}
 	}
-
-	return diffIDs, nil
+	return false, nil
 }

+ 17 - 1
vendor/github.com/containerd/containerd/images/importexport.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package images
 
 import (
@@ -17,5 +33,5 @@ type Importer interface {
 // Exporter is the interface for image exporter.
 type Exporter interface {
 	// Export exports an image to a tar stream.
-	Export(ctx context.Context, store content.Store, desc ocispec.Descriptor, writer io.Writer) error
+	Export(ctx context.Context, store content.Provider, desc ocispec.Descriptor, writer io.Writer) error
 }

+ 16 - 0
vendor/github.com/containerd/containerd/images/mediatypes.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package images
 
 // mediatype definitions for image components handled in containerd.

+ 16 - 0
vendor/github.com/containerd/containerd/labels/validate.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package labels
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/lease.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package containerd
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/leases/context.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package leases
 
 import "context"

+ 16 - 0
vendor/github.com/containerd/containerd/leases/grpc.go

@@ -1,3 +1,19 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package leases
 
 import (

+ 20 - 10
vendor/github.com/containerd/containerd/linux/bundle.go

@@ -1,11 +1,26 @@
 // +build linux
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package linux
 
 import (
-	"bytes"
 	"context"
-	"io"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 
@@ -52,12 +67,7 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) {
 	if err := os.Mkdir(filepath.Join(path, "rootfs"), 0711); err != nil {
 		return nil, err
 	}
-	f, err := os.Create(filepath.Join(path, configFilename))
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-	_, err = io.Copy(f, bytes.NewReader(spec))
+	err = ioutil.WriteFile(filepath.Join(path, configFilename), spec, 0666)
 	return &bundle{
 		id:      id,
 		path:    path,
@@ -90,9 +100,9 @@ func ShimLocal(exchange *exchange.Exchange) ShimOpt {
 }
 
 // ShimConnect is a ShimOpt for connecting to an existing remote shim
-func ShimConnect() ShimOpt {
+func ShimConnect(onClose func()) ShimOpt {
 	return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
-		return b.shimConfig(ns, ropts), client.WithConnect(b.shimAddress(ns))
+		return b.shimConfig(ns, ropts), client.WithConnect(b.shimAddress(ns), onClose)
 	}
 }
 

+ 20 - 0
vendor/github.com/containerd/containerd/linux/proc/deleted_state.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proc
 
 import (
@@ -48,3 +64,7 @@ func (s *deletedState) Kill(ctx context.Context, sig uint32, all bool) error {
 func (s *deletedState) SetExited(status int) {
 	// no op
 }
+
+func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
+	return nil, errors.Errorf("cannot exec in a deleted state")
+}

+ 16 - 0
vendor/github.com/containerd/containerd/linux/proc/exec.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proc
 
 import (

+ 16 - 0
vendor/github.com/containerd/containerd/linux/proc/exec_state.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proc
 
 import (

+ 18 - 2
vendor/github.com/containerd/containerd/linux/proc/init.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proc
 
 import (
@@ -346,8 +362,8 @@ func (p *Init) Runtime() *runc.Runc {
 	return p.runtime
 }
 
-// Exec returns a new exec'd process
-func (p *Init) Exec(context context.Context, path string, r *ExecConfig) (Process, error) {
+// exec returns a new exec'd process
+func (p *Init) exec(context context.Context, path string, r *ExecConfig) (Process, error) {
 	// process exec request
 	var spec specs.Process
 	if err := json.Unmarshal(r.Spec.Value, &spec); err != nil {

+ 49 - 0
vendor/github.com/containerd/containerd/linux/proc/init_state.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proc
 
 import (
@@ -22,6 +38,7 @@ type initState interface {
 	Resume(context.Context) error
 	Update(context.Context, *google_protobuf.Any) error
 	Checkpoint(context.Context, *CheckpointConfig) error
+	Exec(context.Context, string, *ExecConfig) (Process, error)
 }
 
 type createdState struct {
@@ -113,6 +130,12 @@ func (s *createdState) SetExited(status int) {
 	}
 }
 
+func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
+	s.p.mu.Lock()
+	defer s.p.mu.Unlock()
+	return s.p.exec(ctx, path, r)
+}
+
 type createdCheckpointState struct {
 	p    *Init
 	opts *runc.RestoreOpts
@@ -227,6 +250,13 @@ func (s *createdCheckpointState) SetExited(status int) {
 	}
 }
 
+func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
+	s.p.mu.Lock()
+	defer s.p.mu.Unlock()
+
+	return nil, errors.Errorf("cannot exec in a created state")
+}
+
 type runningState struct {
 	p *Init
 }
@@ -312,6 +342,12 @@ func (s *runningState) SetExited(status int) {
 	}
 }
 
+func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
+	s.p.mu.Lock()
+	defer s.p.mu.Unlock()
+	return s.p.exec(ctx, path, r)
+}
+
 type pausedState struct {
 	p *Init
 }
@@ -396,7 +432,13 @@ func (s *pausedState) SetExited(status int) {
 	if err := s.transition("stopped"); err != nil {
 		panic(err)
 	}
+}
 
+func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
+	s.p.mu.Lock()
+	defer s.p.mu.Unlock()
+
+	return nil, errors.Errorf("cannot exec in a paused state")
 }
 
 type stoppedState struct {
@@ -471,3 +513,10 @@ func (s *stoppedState) Kill(ctx context.Context, sig uint32, all bool) error {
 func (s *stoppedState) SetExited(status int) {
 	// no op
 }
+
+func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
+	s.p.mu.Lock()
+	defer s.p.mu.Unlock()
+
+	return nil, errors.Errorf("cannot exec in a stopped state")
+}

+ 34 - 3
vendor/github.com/containerd/containerd/linux/proc/io.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proc
 
 import (
@@ -13,6 +29,13 @@ import (
 	runc "github.com/containerd/go-runc"
 )
 
+var bufPool = sync.Pool{
+	New: func() interface{} {
+		buffer := make([]byte, 32<<10)
+		return &buffer
+	},
+}
+
 func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, wg, cwg *sync.WaitGroup) error {
 	for name, dest := range map[string]func(wc io.WriteCloser, rc io.Closer){
 		stdout: func(wc io.WriteCloser, rc io.Closer) {
@@ -20,7 +43,9 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
 			cwg.Add(1)
 			go func() {
 				cwg.Done()
-				io.Copy(wc, rio.Stdout())
+				p := bufPool.Get().(*[]byte)
+				defer bufPool.Put(p)
+				io.CopyBuffer(wc, rio.Stdout(), *p)
 				wg.Done()
 				wc.Close()
 				rc.Close()
@@ -31,7 +56,10 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
 			cwg.Add(1)
 			go func() {
 				cwg.Done()
-				io.Copy(wc, rio.Stderr())
+				p := bufPool.Get().(*[]byte)
+				defer bufPool.Put(p)
+
+				io.CopyBuffer(wc, rio.Stderr(), *p)
 				wg.Done()
 				wc.Close()
 				rc.Close()
@@ -59,7 +87,10 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
 	cwg.Add(1)
 	go func() {
 		cwg.Done()
-		io.Copy(rio.Stdin(), f)
+		p := bufPool.Get().(*[]byte)
+		defer bufPool.Put(p)
+
+		io.CopyBuffer(rio.Stdin(), f, *p)
 		rio.Stdin().Close()
 		f.Close()
 	}()

+ 16 - 0
vendor/github.com/containerd/containerd/linux/proc/process.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package proc
 
 import (

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.