Ver código fonte

Merge pull request #45993 from thaJeztah/update_fsutils

vendor: github.com/containerd/continuity v0.4.1, tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb
Akihiro Suda 2 anos atrás
pai
commit
29eb0be134
25 arquivos alterados com 350 adições e 109 exclusões
  1. 2 2
      vendor.mod
  2. 4 4
      vendor.sum
  3. 1 1
      vendor/github.com/containerd/continuity/driver/utils.go
  4. 23 15
      vendor/github.com/containerd/continuity/fs/copy.go
  5. 35 0
      vendor/github.com/containerd/continuity/fs/copy_darwin.go
  6. 22 0
      vendor/github.com/containerd/continuity/fs/copy_nondarwin.go
  7. 5 0
      vendor/github.com/containerd/continuity/fs/copy_unix.go
  8. 0 2
      vendor/github.com/containerd/continuity/fs/copy_windows.go
  9. 7 6
      vendor/github.com/containerd/continuity/fs/diff.go
  10. 1 2
      vendor/github.com/containerd/continuity/fs/dtype_linux.go
  11. 5 5
      vendor/github.com/containerd/continuity/fs/du_unix.go
  12. 2 6
      vendor/github.com/containerd/continuity/fs/du_windows.go
  13. 1 3
      vendor/github.com/containerd/continuity/fs/path.go
  14. 1 1
      vendor/github.com/tonistiigi/fsutil/Dockerfile
  15. 56 26
      vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go
  16. 29 19
      vendor/github.com/tonistiigi/fsutil/copy/mkdir_windows.go
  17. 6 2
      vendor/github.com/tonistiigi/fsutil/diskwriter.go
  18. 7 0
      vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
  19. 79 0
      vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go
  20. 1 1
      vendor/github.com/tonistiigi/fsutil/docker-bake.hcl
  21. 10 5
      vendor/github.com/tonistiigi/fsutil/followlinks.go
  22. 14 0
      vendor/github.com/tonistiigi/fsutil/followlinks_unix.go
  23. 15 0
      vendor/github.com/tonistiigi/fsutil/followlinks_windows.go
  24. 20 5
      vendor/github.com/tonistiigi/fsutil/walker.go
  25. 4 4
      vendor/modules.txt

+ 2 - 2
vendor.mod

@@ -27,7 +27,7 @@ require (
 	github.com/container-orchestrated-devices/container-device-interface v0.6.0
 	github.com/containerd/cgroups/v3 v3.0.2
 	github.com/containerd/containerd v1.6.21
-	github.com/containerd/continuity v0.3.0
+	github.com/containerd/continuity v0.4.1
 	github.com/containerd/fifo v1.1.0
 	github.com/containerd/typeurl/v2 v2.1.0
 	github.com/coreos/go-systemd/v22 v22.5.0
@@ -173,7 +173,7 @@ require (
 	github.com/spdx/tools-golang v0.3.1-0.20230104082527-d6f58551be3f // indirect
 	github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
 	github.com/tinylib/msgp v1.1.8 // indirect
-	github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa // indirect
+	github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb // indirect
 	github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7 // indirect
 	github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect

+ 4 - 4
vendor.sum

@@ -384,8 +384,8 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE
 github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
 github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
 github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
-github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
-github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
+github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU=
+github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
 github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
 github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
 github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
@@ -1397,8 +1397,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1
 github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
 github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
 github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85/go.mod h1:a7cilN64dG941IOXfhJhlH0qB92hxJ9A1ewrdUmJ6xo=
-github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa h1:XOFp/3aBXlqmOFAg3r6e0qQjPnK5I970LilqX+Is1W8=
-github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa/go.mod h1:AvLEd1LEIl64G2Jpgwo7aVV5lGH0ePcKl0ygGIHNYl8=
+github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb h1:uUe8rNyVXM8moActoBol6Xf6xX2GMr7SosR2EywMvGg=
+github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb/go.mod h1:SxX/oNQ/ag6Vaoli547ipFK9J7BZn5JqJG0JE8lf8bA=
 github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7 h1:8eY6m1mjgyB8XySUR7WvebTM8D/Vs86jLJzD/Tw7zkc=
 github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7/go.mod h1:qqvyZqkfwkoJuPU/bw61bItaoO0SJ8YSW0vSVRRvsRg=
 github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0=

+ 1 - 1
vendor/github.com/containerd/continuity/driver/utils.go

@@ -56,7 +56,7 @@ func WriteFile(r Driver, filename string, data []byte, perm os.FileMode) error {
 	return nil
 }
 
-// ReadDir works the same as ioutil.ReadDir with the Driver abstraction
+// ReadDir works the same as os.ReadDir with the Driver abstraction
 func ReadDir(r Driver, dirname string) ([]os.FileInfo, error) {
 	f, err := r.Open(dirname)
 	if err != nil {

+ 23 - 15
vendor/github.com/containerd/continuity/fs/copy.go

@@ -18,7 +18,6 @@ package fs
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"sync"
@@ -111,7 +110,7 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
 		}
 	}
 
-	fis, err := ioutil.ReadDir(src)
+	entries, err := os.ReadDir(src)
 	if err != nil {
 		return fmt.Errorf("failed to read %s: %w", src, err)
 	}
@@ -124,18 +123,23 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
 		return fmt.Errorf("failed to copy xattrs: %w", err)
 	}
 
-	for _, fi := range fis {
-		source := filepath.Join(src, fi.Name())
-		target := filepath.Join(dst, fi.Name())
+	for _, entry := range entries {
+		source := filepath.Join(src, entry.Name())
+		target := filepath.Join(dst, entry.Name())
+
+		fileInfo, err := entry.Info()
+		if err != nil {
+			return fmt.Errorf("failed to get file info for %s: %w", entry.Name(), err)
+		}
 
 		switch {
-		case fi.IsDir():
+		case entry.IsDir():
 			if err := copyDirectory(target, source, inodes, o); err != nil {
 				return err
 			}
 			continue
-		case (fi.Mode() & os.ModeType) == 0:
-			link, err := getLinkSource(target, fi, inodes)
+		case (fileInfo.Mode() & os.ModeType) == 0:
+			link, err := getLinkSource(target, fileInfo, inodes)
 			if err != nil {
 				return fmt.Errorf("failed to get hardlink: %w", err)
 			}
@@ -146,7 +150,7 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
 			} else if err := CopyFile(target, source); err != nil {
 				return fmt.Errorf("failed to copy files: %w", err)
 			}
-		case (fi.Mode() & os.ModeSymlink) == os.ModeSymlink:
+		case (fileInfo.Mode() & os.ModeSymlink) == os.ModeSymlink:
 			link, err := os.Readlink(source)
 			if err != nil {
 				return fmt.Errorf("failed to read link: %s: %w", source, err)
@@ -154,18 +158,18 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
 			if err := os.Symlink(link, target); err != nil {
 				return fmt.Errorf("failed to create symlink: %s: %w", target, err)
 			}
-		case (fi.Mode() & os.ModeDevice) == os.ModeDevice,
-			(fi.Mode() & os.ModeNamedPipe) == os.ModeNamedPipe,
-			(fi.Mode() & os.ModeSocket) == os.ModeSocket:
-			if err := copyIrregular(target, fi); err != nil {
+		case (fileInfo.Mode() & os.ModeDevice) == os.ModeDevice,
+			(fileInfo.Mode() & os.ModeNamedPipe) == os.ModeNamedPipe,
+			(fileInfo.Mode() & os.ModeSocket) == os.ModeSocket:
+			if err := copyIrregular(target, fileInfo); err != nil {
 				return fmt.Errorf("failed to create irregular file: %w", err)
 			}
 		default:
-			logrus.Warnf("unsupported mode: %s: %s", source, fi.Mode())
+			logrus.Warnf("unsupported mode: %s: %s", source, fileInfo.Mode())
 			continue
 		}
 
-		if err := copyFileInfo(fi, source, target); err != nil {
+		if err := copyFileInfo(fileInfo, source, target); err != nil {
 			return fmt.Errorf("failed to copy file info: %w", err)
 		}
 
@@ -180,6 +184,10 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
 // CopyFile copies the source file to the target.
 // The most efficient means of copying is used for the platform.
 func CopyFile(target, source string) error {
+	return copyFile(target, source)
+}
+
+func openAndCopyFile(target, source string) error {
 	src, err := os.Open(source)
 	if err != nil {
 		return fmt.Errorf("failed to open source %s: %w", source, err)

+ 35 - 0
vendor/github.com/containerd/continuity/fs/copy_darwin.go

@@ -0,0 +1,35 @@
+/*
+   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 fs
+
+import (
+	"errors"
+	"fmt"
+
+	"golang.org/x/sys/unix"
+)
+
+func copyFile(target, source string) error {
+	if err := unix.Clonefile(source, target, unix.CLONE_NOFOLLOW); err != nil {
+		if !errors.Is(err, unix.ENOTSUP) && !errors.Is(err, unix.EXDEV) {
+			return fmt.Errorf("clonefile failed: %w", err)
+		}
+
+		return openAndCopyFile(target, source)
+	}
+	return nil
+}

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

@@ -0,0 +1,22 @@
+//go:build !darwin
+// +build !darwin
+
+/*
+   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 fs
+
+var copyFile = openAndCopyFile

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

@@ -23,6 +23,7 @@ import (
 	"fmt"
 	"io"
 	"os"
+	"runtime"
 	"syscall"
 
 	"github.com/containerd/continuity/sysx"
@@ -71,6 +72,10 @@ func copyFileContent(dst, src *os.File) error {
 func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
 	xattrKeys, err := sysx.LListxattr(src)
 	if err != nil {
+		if os.IsPermission(err) && runtime.GOOS == "darwin" {
+			// On darwin, character devices do not permit listing xattrs
+			return nil
+		}
 		e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
 		if errorHandler != nil {
 			e = errorHandler(dst, src, "", e)

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

@@ -49,7 +49,6 @@ func copyFileInfo(fi os.FileInfo, src, name string) error {
 	secInfo, err := windows.GetNamedSecurityInfo(
 		src, windows.SE_FILE_OBJECT,
 		windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION)
-
 	if err != nil {
 		return err
 	}
@@ -68,7 +67,6 @@ func copyFileInfo(fi os.FileInfo, src, name string) error {
 		name, windows.SE_FILE_OBJECT,
 		windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION,
 		sid, nil, dacl, nil); err != nil {
-
 		return err
 	}
 	return nil

+ 7 - 6
vendor/github.com/containerd/continuity/fs/diff.go

@@ -80,12 +80,13 @@ type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
 //
 // 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.
+//
+//	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.

+ 1 - 2
vendor/github.com/containerd/continuity/fs/dtype_linux.go

@@ -21,14 +21,13 @@ package fs
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"syscall"
 	"unsafe"
 )
 
 func locateDummyIfEmpty(path string) (string, error) {
-	children, err := ioutil.ReadDir(path)
+	children, err := os.ReadDir(path)
 	if err != nil {
 		return "", err
 	}

+ 5 - 5
vendor/github.com/containerd/continuity/fs/du_unix.go

@@ -28,10 +28,11 @@ import (
 
 // blocksUnitSize is the unit used by `st_blocks` in `stat` in bytes.
 // See https://man7.org/linux/man-pages/man2/stat.2.html
-//   st_blocks
-//     This field indicates the number of blocks allocated to the
-//     file, in 512-byte units.  (This may be smaller than
-//     st_size/512 when the file has holes.)
+//
+//	st_blocks
+//	  This field indicates the number of blocks allocated to the
+//	  file, in 512-byte units.  (This may be smaller than
+//	  st_size/512 when the file has holes.)
 const blocksUnitSize = 512
 
 type inode struct {
@@ -48,7 +49,6 @@ func newInode(stat *syscall.Stat_t) inode {
 }
 
 func diskUsage(ctx context.Context, roots ...string) (Usage, error) {
-
 	var (
 		size   int64
 		inodes = map[inode]struct{}{} // expensive!

+ 2 - 6
vendor/github.com/containerd/continuity/fs/du_windows.go

@@ -26,9 +26,7 @@ import (
 )
 
 func diskUsage(ctx context.Context, roots ...string) (Usage, error) {
-	var (
-		size int64
-	)
+	var size int64
 
 	// TODO(stevvooe): Support inodes (or equivalent) for windows.
 
@@ -57,9 +55,7 @@ func diskUsage(ctx context.Context, roots ...string) (Usage, error) {
 }
 
 func diffUsage(ctx context.Context, a, b string) (Usage, error) {
-	var (
-		size int64
-	)
+	var size int64
 
 	if err := Changes(ctx, a, b, func(kind ChangeKind, _ string, fi os.FileInfo, err error) error {
 		if err != nil {

+ 1 - 3
vendor/github.com/containerd/continuity/fs/path.go

@@ -25,9 +25,7 @@ import (
 	"path/filepath"
 )
 
-var (
-	errTooManyLinks = errors.New("too many links")
-)
+var errTooManyLinks = errors.New("too many links")
 
 type currentPath struct {
 	path     string

+ 1 - 1
vendor/github.com/tonistiigi/fsutil/Dockerfile

@@ -1,5 +1,5 @@
 #syntax=docker/dockerfile:1
-ARG GO_VERSION=1.18
+ARG GO_VERSION=1.20
 
 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.1.0 AS xx
 

+ 56 - 26
vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go

@@ -13,53 +13,83 @@ const (
 	seTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege"
 )
 
-func (c *copier) copyFileInfo(fi os.FileInfo, src, name string) error {
-	if err := os.Chmod(name, fi.Mode()); err != nil {
-		return errors.Wrapf(err, "failed to chmod %s", name)
-	}
-
-	// Copy file ownership and ACL
-	// We need SeRestorePrivilege and SeTakeOwnershipPrivilege in order
-	// to restore security info on a file, especially if we're trying to
-	// apply security info which includes SIDs not necessarily present on
-	// the host.
-	privileges := []string{winio.SeRestorePrivilege, seTakeOwnershipPrivilege}
-	if err := winio.EnableProcessPrivileges(privileges); err != nil {
-		return err
-	}
-	defer winio.DisableProcessPrivileges(privileges)
+func getUIDGID(fi os.FileInfo) (uid, gid int) {
+	return 0, 0
+}
 
+func getFileSecurityInfo(name string) (*windows.SID, *windows.ACL, error) {
 	secInfo, err := windows.GetNamedSecurityInfo(
-		src, windows.SE_FILE_OBJECT,
+		name, windows.SE_FILE_OBJECT,
 		windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION)
 
 	if err != nil {
-		return err
+		return nil, nil, errors.Wrap(err, "fetching security info")
+	}
+	sid, _, err := secInfo.Owner()
+	if err != nil {
+		return nil, nil, errors.Wrap(err, "fetching owner SID")
 	}
-
 	dacl, _, err := secInfo.DACL()
 	if err != nil {
-		return err
+		return nil, nil, errors.Wrap(err, "fetching dacl")
 	}
+	return sid, dacl, nil
+}
 
-	sid, _, err := secInfo.Owner()
+func (c *copier) copyFileInfo(fi os.FileInfo, src, name string) error {
+	if err := os.Chmod(name, fi.Mode()); err != nil {
+		return errors.Wrapf(err, "failed to chmod %s", name)
+	}
+
+	sid, dacl, err := getFileSecurityInfo(src)
 	if err != nil {
-		return err
+		return errors.Wrap(err, "getting file info")
 	}
 
-	if err := windows.SetNamedSecurityInfo(
-		name, windows.SE_FILE_OBJECT,
-		windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION,
-		sid, nil, dacl, nil); err != nil {
+	if c.chown != nil {
+		// Use the defined chowner.
+		usr := &User{SID: sid.String()}
+		if err := Chown(name, usr, c.chown); err != nil {
+			return errors.Wrapf(err, "failed to chown %s", name)
+		}
+		return nil
+	} else {
+		// Copy file ownership and ACL from the source file.
+		// We need SeRestorePrivilege and SeTakeOwnershipPrivilege in order
+		// to restore security info on a file, especially if we're trying to
+		// apply security info which includes SIDs not necessarily present on
+		// the host.
+		privileges := []string{winio.SeRestorePrivilege, seTakeOwnershipPrivilege}
+		if err := winio.EnableProcessPrivileges(privileges); err != nil {
+			return err
+		}
+		defer winio.DisableProcessPrivileges(privileges)
+
+		if err := windows.SetNamedSecurityInfo(
+			name, windows.SE_FILE_OBJECT,
+			windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION,
+			sid, nil, dacl, nil); err != nil {
+
+			return err
+		}
+	}
 
+	if err := c.copyFileTimestamp(fi, name); err != nil {
 		return err
 	}
 	return nil
 }
 
 func (c *copier) copyFileTimestamp(fi os.FileInfo, name string) error {
-	// TODO: copy windows specific metadata
+	if c.utime != nil {
+		return Utimes(name, c.utime)
+	}
 
+	if fi.Mode()&os.ModeSymlink == 0 {
+		if err := os.Chtimes(name, fi.ModTime(), fi.ModTime()); err != nil {
+			return errors.Wrap(err, "changing mtime")
+		}
+	}
 	return nil
 }
 

+ 29 - 19
vendor/github.com/tonistiigi/fsutil/copy/mkdir_windows.go

@@ -28,6 +28,15 @@ func fixRootDirectory(p string) string {
 }
 
 func Utimes(p string, tm *time.Time) error {
+	info, err := os.Lstat(p)
+	if err != nil {
+		return errors.Wrap(err, "fetching file info")
+	}
+	if tm != nil && info.Mode()&os.ModeSymlink == 0 {
+		if err := os.Chtimes(p, *tm, *tm); err != nil {
+			return errors.Wrap(err, "changing times")
+		}
+	}
 	return nil
 }
 
@@ -39,22 +48,14 @@ func Chown(p string, old *User, fn Chowner) error {
 	if err != nil {
 		return errors.WithStack(err)
 	}
-
-	userSIDstring := user.SID
+	var userSIDstring string
+	if user != nil && user.SID != "" {
+		userSIDstring = user.SID
+	}
 	if userSIDstring == "" {
 		userSIDstring = containerAdministratorSidString
 
 	}
-	// Copy file ownership and ACL
-	// We need SeRestorePrivilege and SeTakeOwnershipPrivilege in order
-	// to restore security info on a file, especially if we're trying to
-	// apply security info which includes SIDs not necessarily present on
-	// the host.
-	privileges := []string{winio.SeRestorePrivilege, seTakeOwnershipPrivilege}
-	if err := winio.EnableProcessPrivileges(privileges); err != nil {
-		return err
-	}
-	defer winio.DisableProcessPrivileges(privileges)
 
 	sidPtr, err := syscall.UTF16PtrFromString(userSIDstring)
 	if err != nil {
@@ -81,13 +82,22 @@ func Chown(p string, old *User, fn Chowner) error {
 		return fmt.Errorf("adding acls: %w", err)
 	}
 
-	if err := windows.SetNamedSecurityInfo(
-		p, windows.SE_FILE_OBJECT,
-		windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION,
-		userSID, nil, newAcl, nil); err != nil {
+	// Copy file ownership and ACL
+	// We need SeRestorePrivilege and SeTakeOwnershipPrivilege in order
+	// to restore security info on a file, especially if we're trying to
+	// apply security info which includes SIDs not necessarily present on
+	// the host.
+	privileges := []string{winio.SeRestorePrivilege, seTakeOwnershipPrivilege}
+	err = winio.RunWithPrivileges(privileges, func() error {
+		if err := windows.SetNamedSecurityInfo(
+			p, windows.SE_FILE_OBJECT,
+			windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION,
+			userSID, nil, newAcl, nil); err != nil {
 
-		return err
-	}
+			return err
+		}
+		return nil
+	})
 
-	return nil
+	return err
 }

+ 6 - 2
vendor/github.com/tonistiigi/fsutil/diskwriter.go

@@ -162,6 +162,10 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
 	switch {
 	case fi.IsDir():
 		if err := os.Mkdir(newPath, fi.Mode()); err != nil {
+			if errors.Is(err, syscall.EEXIST) {
+				// we saw a race to create this directory, so try again
+				return dw.HandleChange(kind, p, fi, nil)
+			}
 			return errors.Wrapf(err, "failed to create dir %s", newPath)
 		}
 		dw.dirModTimes[destPath] = statCopy.ModTime
@@ -188,7 +192,6 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
 				file.Close()
 				return err
 			}
-			break
 		}
 		if err := file.Close(); err != nil {
 			return errors.Wrapf(err, "failed to close %s", newPath)
@@ -205,7 +208,8 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
 				return errors.Wrapf(err, "failed to remove %s", destPath)
 			}
 		}
-		if err := os.Rename(newPath, destPath); err != nil {
+
+		if err := renameFile(newPath, destPath); err != nil {
 			return errors.Wrapf(err, "failed to rename %s to %s", newPath, destPath)
 		}
 	}

+ 7 - 0
vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go

@@ -51,3 +51,10 @@ func handleTarTypeBlockCharFifo(path string, stat *types.Stat) error {
 	}
 	return nil
 }
+
+func renameFile(src, dst string) error {
+	if err := os.Rename(src, dst); err != nil {
+		return errors.Wrapf(err, "failed to rename %s to %s", src, dst)
+	}
+	return nil
+}

+ 79 - 0
vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go

@@ -1,8 +1,15 @@
+//go:build windows
 // +build windows
 
 package fsutil
 
 import (
+	"fmt"
+	iofs "io/fs"
+	"os"
+	"syscall"
+
+	"github.com/Microsoft/go-winio"
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil/types"
 )
@@ -16,3 +23,75 @@ func rewriteMetadata(p string, stat *types.Stat) error {
 func handleTarTypeBlockCharFifo(path string, stat *types.Stat) error {
 	return errors.New("Not implemented on windows")
 }
+
+func getFileHandle(path string, info iofs.FileInfo) (syscall.Handle, error) {
+	p, err := syscall.UTF16PtrFromString(path)
+	if err != nil {
+		return 0, errors.Wrap(err, "converting string to UTF-16")
+	}
+	attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)
+	if info.Mode()&os.ModeSymlink != 0 {
+		// Use FILE_FLAG_OPEN_REPARSE_POINT, otherwise CreateFile will follow symlink.
+		// See https://docs.microsoft.com/en-us/windows/desktop/FileIO/symbolic-link-effects-on-file-systems-functions#createfile-and-createfiletransacted
+		attrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT
+	}
+	h, err := syscall.CreateFile(p, 0, 0, nil, syscall.OPEN_EXISTING, attrs, 0)
+	if err != nil {
+		return 0, errors.Wrap(err, "getting file handle")
+	}
+	return h, nil
+}
+
+func readlink(path string, info iofs.FileInfo) ([]byte, error) {
+	h, err := getFileHandle(path, info)
+	if err != nil {
+		return nil, errors.Wrap(err, "getting file handle")
+	}
+	defer syscall.CloseHandle(h)
+
+	rdbbuf := make([]byte, syscall.MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
+	var bytesReturned uint32
+	err = syscall.DeviceIoControl(h, syscall.FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
+	if err != nil {
+		return nil, errors.Wrap(err, "sending I/O control command")
+	}
+	return rdbbuf[:bytesReturned], nil
+}
+
+func getReparsePoint(path string, info iofs.FileInfo) (*winio.ReparsePoint, error) {
+	target, err := readlink(path, info)
+	if err != nil {
+		return nil, errors.Wrap(err, "fetching link")
+	}
+	rp, err := winio.DecodeReparsePoint(target)
+	if err != nil {
+		return nil, errors.Wrap(err, "decoding reparse point")
+	}
+	return rp, nil
+}
+
+func renameFile(src, dst string) error {
+	info, err := os.Lstat(dst)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			return errors.Wrap(err, "getting file info")
+		}
+	}
+
+	if info != nil && info.Mode()&os.ModeSymlink != 0 {
+		dstInfoRp, err := getReparsePoint(dst, info)
+		if err != nil {
+			return errors.Wrap(err, "getting reparse point")
+		}
+		if dstInfoRp.IsMountPoint {
+			return fmt.Errorf("%s is a mount point", dst)
+		}
+		if err := os.Remove(dst); err != nil {
+			return errors.Wrapf(err, "removing %s", dst)
+		}
+	}
+	if err := os.Rename(src, dst); err != nil {
+		return errors.Wrapf(err, "failed to rename %s to %s", src, dst)
+	}
+	return nil
+}

+ 1 - 1
vendor/github.com/tonistiigi/fsutil/docker-bake.hcl

@@ -1,5 +1,5 @@
 variable "GO_VERSION" {
-  default = "1.18"
+  default = "1.20"
 }
 
 group "default" {

+ 10 - 5
vendor/github.com/tonistiigi/fsutil/followlinks.go

@@ -19,7 +19,7 @@ func FollowLinks(root string, paths []string) ([]string, error) {
 	}
 	res := make([]string, 0, len(r.resolved))
 	for r := range r.resolved {
-		res = append(res, r)
+		res = append(res, filepath.ToSlash(r))
 	}
 	sort.Strings(res)
 	return dedupePaths(res), nil
@@ -31,6 +31,12 @@ type symlinkResolver struct {
 }
 
 func (r *symlinkResolver) append(p string) error {
+	if runtime.GOOS == "windows" && filepath.IsAbs(filepath.FromSlash(p)) {
+		absParts := strings.SplitN(p, ":", 2)
+		if len(absParts) == 2 {
+			p = absParts[1]
+		}
+	}
 	p = filepath.Join(".", p)
 	current := "."
 	for {
@@ -41,7 +47,6 @@ func (r *symlinkResolver) append(p string) error {
 		if err != nil {
 			return err
 		}
-
 		p = ""
 		if len(parts) == 2 {
 			p = parts[1]
@@ -76,7 +81,7 @@ func (r *symlinkResolver) readSymlink(p string, allowWildcard bool) ([]string, e
 	if allowWildcard && containsWildcards(base) {
 		fis, err := os.ReadDir(filepath.Dir(realPath))
 		if err != nil {
-			if errors.Is(err, os.ErrNotExist) {
+			if isNotFound(err) {
 				return nil, nil
 			}
 			return nil, errors.Wrap(err, "readdir")
@@ -96,7 +101,7 @@ func (r *symlinkResolver) readSymlink(p string, allowWildcard bool) ([]string, e
 
 	fi, err := os.Lstat(realPath)
 	if err != nil {
-		if errors.Is(err, os.ErrNotExist) {
+		if isNotFound(err) {
 			return nil, nil
 		}
 		return nil, errors.WithStack(err)
@@ -139,7 +144,7 @@ func dedupePaths(in []string) []string {
 		if s == "." {
 			return nil
 		}
-		if strings.HasPrefix(s, last+string(filepath.Separator)) {
+		if strings.HasPrefix(s, last+"/") {
 			continue
 		}
 		out = append(out, s)

+ 14 - 0
vendor/github.com/tonistiigi/fsutil/followlinks_unix.go

@@ -0,0 +1,14 @@
+//go:build !windows
+// +build !windows
+
+package fsutil
+
+import (
+	"os"
+
+	"github.com/pkg/errors"
+)
+
+func isNotFound(err error) bool {
+	return errors.Is(err, os.ErrNotExist)
+}

+ 15 - 0
vendor/github.com/tonistiigi/fsutil/followlinks_windows.go

@@ -0,0 +1,15 @@
+package fsutil
+
+import (
+	"os"
+
+	"github.com/pkg/errors"
+	"golang.org/x/sys/windows"
+)
+
+func isNotFound(err error) bool {
+	if errors.Is(err, os.ErrNotExist) || errors.Is(err, windows.ERROR_INVALID_NAME) {
+		return true
+	}
+	return false
+}

+ 20 - 5
vendor/github.com/tonistiigi/fsutil/walker.go

@@ -2,6 +2,7 @@ package fsutil
 
 import (
 	"context"
+	gofs "io/fs"
 	"os"
 	"path/filepath"
 	"strings"
@@ -47,11 +48,11 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
 	if err != nil {
 		return errors.WithStack(&os.PathError{Op: "resolve", Path: root, Err: err})
 	}
-	fi, err := os.Stat(root)
+	rootFI, err := os.Stat(root)
 	if err != nil {
 		return errors.WithStack(err)
 	}
-	if !fi.IsDir() {
+	if !rootFI.IsDir() {
 		return errors.WithStack(&os.PathError{Op: "walk", Path: root, Err: syscall.ENOTDIR})
 	}
 
@@ -126,7 +127,7 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
 	var parentDirs []visitedDir
 
 	seenFiles := make(map[uint64]string)
-	return filepath.Walk(root, func(path string, fi os.FileInfo, walkErr error) (retErr error) {
+	return filepath.WalkDir(root, func(path string, dirEntry gofs.DirEntry, walkErr error) (retErr error) {
 		defer func() {
 			if retErr != nil && isNotExist(retErr) {
 				retErr = filepath.SkipDir
@@ -146,9 +147,10 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
 		var (
 			dir   visitedDir
 			isDir bool
+			fi    gofs.FileInfo
 		)
-		if fi != nil {
-			isDir = fi.IsDir()
+		if dirEntry != nil {
+			isDir = dirEntry.IsDir()
 		}
 
 		if includeMatcher != nil || excludeMatcher != nil {
@@ -161,6 +163,11 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
 			}
 
 			if isDir {
+				fi, err = dirEntry.Info()
+				if err != nil {
+					return err
+				}
+
 				dir = visitedDir{
 					fi:          fi,
 					path:        path,
@@ -268,6 +275,14 @@ func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) err
 
 		dir.calledFn = true
 
+		// The FileInfo might have already been read further up.
+		if fi == nil {
+			fi, err = dirEntry.Info()
+			if err != nil {
+				return err
+			}
+		}
+
 		stat, err := mkstat(origpath, path, fi, seenFiles)
 		if err != nil {
 			return err

+ 4 - 4
vendor/modules.txt

@@ -307,8 +307,8 @@ github.com/containerd/containerd/snapshots/proxy
 github.com/containerd/containerd/sys
 github.com/containerd/containerd/sys/reaper
 github.com/containerd/containerd/version
-# github.com/containerd/continuity v0.3.0
-## explicit; go 1.17
+# github.com/containerd/continuity v0.4.1
+## explicit; go 1.19
 github.com/containerd/continuity/devices
 github.com/containerd/continuity/driver
 github.com/containerd/continuity/fs
@@ -969,8 +969,8 @@ github.com/syndtr/gocapability/capability
 # github.com/tinylib/msgp v1.1.8
 ## explicit; go 1.15
 github.com/tinylib/msgp/msgp
-# github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa
-## explicit; go 1.18
+# github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb
+## explicit; go 1.19
 github.com/tonistiigi/fsutil
 github.com/tonistiigi/fsutil/copy
 github.com/tonistiigi/fsutil/types