Merge pull request #10901 from containerd/dependabot/go_modules/github.com/containerd/continuity-0.4.4

build(deps): bump github.com/containerd/continuity from 0.4.3 to 0.4.4
This commit is contained in:
Phil Estes 2024-10-28 16:39:06 +00:00 committed by GitHub
commit e69a299b5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 509 additions and 80 deletions

2
go.mod
View File

@ -14,7 +14,7 @@ require (
github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/cgroups/v3 v3.0.3
github.com/containerd/console v1.0.4 github.com/containerd/console v1.0.4
github.com/containerd/containerd/api v1.8.0-rc.4 github.com/containerd/containerd/api v1.8.0-rc.4
github.com/containerd/continuity v0.4.3 github.com/containerd/continuity v0.4.4
github.com/containerd/errdefs v0.3.0 github.com/containerd/errdefs v0.3.0
github.com/containerd/errdefs/pkg v0.3.0 github.com/containerd/errdefs/pkg v0.3.0
github.com/containerd/fifo v1.1.0 github.com/containerd/fifo v1.1.0

4
go.sum
View File

@ -673,8 +673,8 @@ github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZG
github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
github.com/containerd/containerd/api v1.8.0-rc.4 h1:Z650GHP0OxsoTwwii5U2hyTt7eCRQvvDnRM7pEH/DE0= github.com/containerd/containerd/api v1.8.0-rc.4 h1:Z650GHP0OxsoTwwii5U2hyTt7eCRQvvDnRM7pEH/DE0=
github.com/containerd/containerd/api v1.8.0-rc.4/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/api v1.8.0-rc.4/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=

View File

@ -33,7 +33,17 @@ const umountflags int = 0
var rootEnabled bool var rootEnabled bool
func init() { func init() {
if flag.Lookup("test.root") == nil {
flag.BoolVar(&rootEnabled, "test.root", false, "enable tests that require root") flag.BoolVar(&rootEnabled, "test.root", false, "enable tests that require root")
} else {
// The flag is already registered by continuity/testutil
for _, f := range os.Args {
if f == "-test.root" || f == "-test.root=true" {
rootEnabled = true
break
}
}
}
} }
// DumpDir prints the contents of the directory to the testing logger. // DumpDir prints the contents of the directory to the testing logger.

View File

@ -12,5 +12,11 @@ linters:
disable: disable:
- errcheck - errcheck
issues:
exclude-rules:
- linters:
- revive
text: "unused-parameter"
run: run:
timeout: 3m timeout: 3m

View File

@ -57,7 +57,7 @@ test:
root-test: root-test:
@echo "+ $@" @echo "+ $@"
@go test -exec sudo ${TEST_REQUIRES_ROOT_PACKAGES} -test.root @go test -exec sudo ${TEST_REQUIRES_ROOT_PACKAGES} -test.root -test.v
test-compile: test-compile:
@echo "+ $@" @echo "+ $@"

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build freebsd || dragonfly //go:build freebsd || dragonfly
// +build freebsd dragonfly
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !(freebsd || windows) //go:build !(freebsd || windows)
// +build !freebsd,!windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build go1.13 //go:build go1.13
// +build go1.13
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build darwin || freebsd || netbsd || openbsd || dragonfly || solaris //go:build darwin || freebsd || netbsd || openbsd || dragonfly || solaris
// +build darwin freebsd netbsd openbsd dragonfly solaris
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -22,7 +22,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/sirupsen/logrus" "github.com/containerd/log"
) )
// XAttrErrorHandler transform a non-nil xattr error. // XAttrErrorHandler transform a non-nil xattr error.
@ -161,7 +161,7 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
return fmt.Errorf("failed to create irregular file: %w", err) return fmt.Errorf("failed to create irregular file: %w", err)
} }
default: default:
logrus.Warnf("unsupported mode: %s: %s", source, fileInfo.Mode()) log.L.Warnf("unsupported mode: %s: %s", source, fileInfo.Mode())
return nil return nil
} }

View File

@ -1,5 +1,4 @@
//go:build !windows && !freebsd //go:build !windows && !freebsd
// +build !windows,!freebsd
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -17,6 +17,7 @@
package fs package fs
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"syscall" "syscall"
@ -64,6 +65,9 @@ func copyFileInfo(fi os.FileInfo, src, name string) error {
func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error { func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
xattrKeys, err := sysx.LListxattr(src) xattrKeys, err := sysx.LListxattr(src)
if err != nil { if err != nil {
if errors.Is(err, unix.ENOTSUP) {
return nil
}
e := fmt.Errorf("failed to list xattrs on %s: %w", src, err) e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
if errorHandler != nil { if errorHandler != nil {
e = errorHandler(dst, src, "", e) e = errorHandler(dst, src, "", e)

View File

@ -1,5 +1,4 @@
//go:build !darwin //go:build !darwin
// +build !darwin
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build darwin || freebsd || openbsd || netbsd || dragonfly || solaris //go:build darwin || freebsd || openbsd || netbsd || dragonfly || solaris
// +build darwin freebsd openbsd netbsd dragonfly solaris
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.
@ -20,12 +19,14 @@
package fs package fs
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"syscall" "syscall"
"github.com/containerd/continuity/sysx" "github.com/containerd/continuity/sysx"
"golang.org/x/sys/unix"
) )
func copyFileInfo(fi os.FileInfo, src, name string) error { func copyFileInfo(fi os.FileInfo, src, name string) error {
@ -67,6 +68,9 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt
// On darwin, character devices do not permit listing xattrs // On darwin, character devices do not permit listing xattrs
return nil return nil
} }
if errors.Is(err, unix.ENOTSUP) {
return nil
}
e := fmt.Errorf("failed to list xattrs on %s: %w", src, err) e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
if errorHandler != nil { if errorHandler != nil {
e = errorHandler(dst, src, "", e) e = errorHandler(dst, src, "", e)

View File

@ -18,11 +18,12 @@ package fs
import ( import (
"context" "context"
"errors"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/sirupsen/logrus" "github.com/containerd/log"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@ -100,14 +101,11 @@ type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
// is to account for timestamp truncation during archiving. // is to account for timestamp truncation during archiving.
func Changes(ctx context.Context, a, b string, changeFn ChangeFunc) error { func Changes(ctx context.Context, a, b string, changeFn ChangeFunc) error {
if a == "" { if a == "" {
logrus.Debugf("Using single walk diff for %s", b) log.G(ctx).Debugf("Using single walk diff for %s", b)
return addDirChanges(ctx, changeFn, 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) log.G(ctx).Debugf("Using double walk diff for %s from %s", b, a)
return doubleWalkDiff(ctx, changeFn, a, b) return doubleWalkDiff(ctx, changeFn, a, b)
} }
@ -134,24 +132,53 @@ func addDirChanges(ctx context.Context, changeFn ChangeFunc, root string) error
}) })
} }
// DiffChangeSource is the source of diff directory.
type DiffSource int
const (
// DiffSourceOverlayFS indicates that a diff directory is from
// OverlayFS.
DiffSourceOverlayFS DiffSource = iota
)
// diffDirOptions is used when the diff can be directly calculated from // diffDirOptions is used when the diff can be directly calculated from
// a diff directory to its base, without walking both trees. // a diff directory to its base, without walking both trees.
type diffDirOptions struct { type diffDirOptions struct {
diffDir string skipChange func(string, os.FileInfo) (bool, error)
skipChange func(string) (bool, error) deleteChange func(string, string, os.FileInfo, ChangeFunc) (bool, error)
deleteChange func(string, string, os.FileInfo) (string, error)
} }
// diffDirChanges walks the diff directory and compares changes against the base. // DiffDirChanges walks the diff directory and compares changes against the base.
func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *diffDirOptions) error { //
// NOTE: If all the children of a dir are removed, or that dir are recreated
// after remove, we will mark non-existing `.wh..opq` file as deleted. It's
// unlikely to create explicit whiteout files for all the children and all
// descendants. And based on OCI spec, it's not possible to create a file or
// dir with a name beginning with `.wh.`. So, after `.wh..opq` file has been
// deleted, the ChangeFunc, the receiver will add whiteout prefix to create a
// opaque whiteout `.wh..wh..opq`.
//
// REF: https://github.com/opencontainers/image-spec/blob/v1.0/layer.md#whiteouts
func DiffDirChanges(ctx context.Context, baseDir, diffDir string, source DiffSource, changeFn ChangeFunc) error {
var o *diffDirOptions
switch source {
case DiffSourceOverlayFS:
o = &diffDirOptions{
deleteChange: overlayFSWhiteoutConvert,
}
default:
return errors.New("unknown diff change source")
}
changedDirs := make(map[string]struct{}) changedDirs := make(map[string]struct{})
return filepath.Walk(o.diffDir, func(path string, f os.FileInfo, err error) error { return filepath.Walk(diffDir, func(path string, f os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
// Rebase path // Rebase path
path, err = filepath.Rel(o.diffDir, path) path, err = filepath.Rel(diffDir, path)
if err != nil { if err != nil {
return err return err
} }
@ -163,38 +190,45 @@ func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *di
return nil 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 o.skipChange != nil {
if skip, err := o.skipChange(path); skip { if skip, err := o.skipChange(path, f); skip {
return err return err
} }
} }
var kind ChangeKind var kind ChangeKind
deletedFile, err := o.deleteChange(o.diffDir, path, f) deletedFile := false
if o.deleteChange != nil {
deletedFile, err = o.deleteChange(diffDir, path, f, changeFn)
if err != nil { if err != nil {
return err return err
} }
_, err = os.Stat(filepath.Join(baseDir, path))
if err != nil {
if !os.IsNotExist(err) {
return err
}
deletedFile = false
}
}
// Find out what kind of modification happened // Find out what kind of modification happened
if deletedFile != "" { if deletedFile {
path = deletedFile
kind = ChangeKindDelete kind = ChangeKindDelete
f = nil
} else { } else {
// Otherwise, the file was added // Otherwise, the file was added
kind = ChangeKindAdd kind = ChangeKindAdd
// ...Unless it already existed in a base, in which case, it's a modification // ...Unless it already existed in a baseDir, in which case, it's a modification
stat, err := os.Stat(filepath.Join(base, path)) stat, err := os.Stat(filepath.Join(baseDir, path))
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return err return err
} }
if err == nil { if err == nil {
// The file existed in the base, so that's a modification // The file existed in the baseDir, so that's a modification
// However, if it's a directory, maybe it wasn't actually modified. // 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 you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar
@ -215,10 +249,12 @@ func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *di
if f.IsDir() { if f.IsDir() {
changedDirs[path] = struct{}{} changedDirs[path] = struct{}{}
} }
if kind == ChangeKindAdd || kind == ChangeKindDelete { if kind == ChangeKindAdd || kind == ChangeKindDelete {
parent := filepath.Dir(path) parent := filepath.Dir(path)
if _, ok := changedDirs[parent]; !ok && parent != "/" { if _, ok := changedDirs[parent]; !ok && parent != "/" {
pi, err := os.Stat(filepath.Join(o.diffDir, parent)) pi, err := os.Stat(filepath.Join(diffDir, parent))
if err := changeFn(ChangeKindModify, parent, pi, err); err != nil { if err := changeFn(ChangeKindModify, parent, pi, err); err != nil {
return err return err
} }
@ -226,6 +262,9 @@ func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *di
} }
} }
if kind == ChangeKindDelete {
f = nil
}
return changeFn(kind, path, f, nil) return changeFn(kind, path, f, nil)
}) })
} }

View File

@ -0,0 +1,101 @@
/*
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"
"os"
"path/filepath"
"syscall"
"github.com/containerd/continuity/devices"
"github.com/containerd/continuity/sysx"
"golang.org/x/sys/unix"
)
const (
// whiteoutPrefix prefix means file is a whiteout. If this is followed
// by a filename this means that file has been removed from the base
// layer.
//
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#whiteouts
whiteoutPrefix = ".wh."
)
// overlayFSWhiteoutConvert detects whiteouts and opaque directories.
//
// It returns deleted indicator if the file is a character device with 0/0
// device number. And call changeFn with ChangeKindDelete for opaque
// directories.
//
// Check: https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt
func overlayFSWhiteoutConvert(diffDir, path string, f os.FileInfo, changeFn ChangeFunc) (deleted bool, _ error) {
if f.Mode()&os.ModeCharDevice != 0 {
if _, ok := f.Sys().(*syscall.Stat_t); !ok {
return false, nil
}
maj, min, err := devices.DeviceInfo(f)
if err != nil {
return false, err
}
return (maj == 0 && min == 0), nil
}
if f.IsDir() {
originalPath := filepath.Join(diffDir, path)
opaque, err := getOpaqueValue(originalPath)
if err != nil {
if errors.Is(err, unix.ENODATA) {
return false, nil
}
return false, err
}
if len(opaque) == 1 && opaque[0] == 'y' {
opaqueDirPath := filepath.Join(path, whiteoutPrefix+".opq")
return false, changeFn(ChangeKindDelete, opaqueDirPath, nil, nil)
}
}
return false, nil
}
// getOpaqueValue returns opaque value for a given file.
func getOpaqueValue(filePath string) ([]byte, error) {
for _, xattr := range []string{
"trusted.overlay.opaque",
// TODO(fuweid):
//
// user.overlay.* is available since 5.11. We should check
// kernel version before read.
//
// REF: https://github.com/torvalds/linux/commit/2d2f2d7322ff43e0fe92bf8cccdc0b09449bf2e1
"user.overlay.opaque",
} {
opaque, err := sysx.LGetxattr(filePath, xattr)
if err != nil {
if errors.Is(err, unix.ENODATA) || errors.Is(err, unix.ENOTSUP) {
continue
}
return nil, fmt.Errorf("failed to retrieve %s attr: %w", xattr, err)
}
return opaque, nil
}
return nil, unix.ENODATA
}

View File

@ -0,0 +1,28 @@
//go: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 fs
import (
"errors"
"os"
)
func overlayFSWhiteoutConvert(string, string, os.FileInfo, ChangeFunc) (bool, error) {
return false, errors.New("unsupported")
}

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.
@ -28,16 +27,6 @@ import (
"github.com/containerd/continuity/sysx" "github.com/containerd/continuity/sysx"
) )
// 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, // compareSysStat returns whether the stats are equivalent,
// whether the files are considered the same file, and // whether the files are considered the same file, and
// an error // an error

View File

@ -22,10 +22,6 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
func detectDirDiff(upper, lower string) *diffDirOptions {
return nil
}
func compareSysStat(s1, s2 interface{}) (bool, error) { func compareSysStat(s1, s2 interface{}) (bool, error) {
f1, ok := s1.(windows.Win32FileAttributeData) f1, ok := s1.(windows.Win32FileAttributeData)
if !ok { if !ok {

View File

@ -1,5 +1,4 @@
//go:build linux //go:build linux
// +build linux
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build windows //go:build windows
// +build windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.
@ -20,9 +19,11 @@
package fstest package fstest
import ( import (
"os"
"path/filepath" "path/filepath"
"time" "time"
"github.com/containerd/continuity/devices"
"github.com/containerd/continuity/sysx" "github.com/containerd/continuity/sysx"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -46,6 +47,14 @@ func Lchtimes(name string, atime, mtime time.Time) Applier {
}) })
} }
// CreateDeviceFile provides creates devices Applier.
func CreateDeviceFile(name string, mode os.FileMode, maj, min int) Applier {
return applyFn(func(root string) error {
fullPath := filepath.Join(root, name)
return devices.Mknod(fullPath, mode, maj, min)
})
}
func Base() Applier { func Base() Applier {
return applyFn(func(root string) error { return applyFn(func(root string) error {
// do nothing, as the base is not special // do nothing, as the base is not special

View File

@ -18,9 +18,17 @@ package fstest
import ( import (
"errors" "errors"
"os"
"time" "time"
) )
// SetXAttr sets the xatter for the file
func SetXAttr(name, key, value string) Applier {
return applyFn(func(root string) error {
return errors.New("Not implemented")
})
}
// Lchtimes changes access and mod time of file without following symlink // Lchtimes changes access and mod time of file without following symlink
func Lchtimes(name string, atime, mtime time.Time) Applier { func Lchtimes(name string, atime, mtime time.Time) Applier {
return applyFn(func(root string) error { return applyFn(func(root string) error {
@ -28,6 +36,13 @@ func Lchtimes(name string, atime, mtime time.Time) Applier {
}) })
} }
// CreateDeviceFile provides creates devices Applier.
func CreateDeviceFile(name string, mode os.FileMode, maj, min int) Applier {
return applyFn(func(root string) error {
return errors.New("Not implemented")
})
}
// Base applies the files required to make a valid Windows container layer // Base applies the files required to make a valid Windows container layer
// that the filter will mount. It is used for testing the snapshotter // that the filter will mount. It is used for testing the snapshotter
func Base() Applier { func Base() Applier {

View File

@ -0,0 +1,44 @@
/*
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 fstest
import (
"os/exec"
"testing"
"github.com/containerd/continuity/testutil"
"github.com/containerd/continuity/testutil/loopback"
)
func WithMkfs(t *testing.T, f func(), mkfs ...string) {
testutil.RequiresRoot(t)
mnt := t.TempDir()
loop, err := loopback.New(100 << 20) // 100 MB
if err != nil {
t.Fatal(err)
}
defer loop.Close()
if out, err := exec.Command(mkfs[0], append(mkfs[1:], loop.Device)...).CombinedOutput(); err != nil {
t.Fatalf("could not mkfs (%v) %s: %v (out: %q)", mkfs, loop.Device, err, string(out))
}
if out, err := exec.Command("mount", loop.Device, mnt).CombinedOutput(); err != nil {
t.Fatalf("could not mount %s: %v (out: %q)", loop.Device, err, string(out))
}
defer testutil.Unmount(t, mnt)
t.Setenv("TMPDIR", mnt)
f()
}

View File

@ -0,0 +1,25 @@
//go: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 fstest
import "testing"
func WithMkfs(t *testing.T, f func(), mkfs ...string) {
t.Fatal("WithMkfs requires Linux")
}

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -0,0 +1,123 @@
/*
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.
*/
/*
Copyright 2013-2018 Docker, Inc.
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
https://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.
*/
// Original source: https://github.com/moby/moby/blob/v26.0.0/daemon/graphdriver/driver_linux.go
package fs
import (
"path/filepath"
"syscall"
)
// Magic unsigned id of the filesystem in use.
type Magic uint32
const (
// MagicUnsupported is a predefined constant value other than a valid filesystem id.
MagicUnsupported = Magic(0x00000000)
)
const (
// MagicAufs filesystem id for Aufs
MagicAufs = Magic(0x61756673)
// MagicBtrfs filesystem id for Btrfs
MagicBtrfs = Magic(0x9123683E)
// MagicCramfs filesystem id for Cramfs
MagicCramfs = Magic(0x28cd3d45)
// MagicEcryptfs filesystem id for eCryptfs
MagicEcryptfs = Magic(0xf15f)
// MagicExtfs filesystem id for Extfs
MagicExtfs = Magic(0x0000EF53)
// MagicF2fs filesystem id for F2fs
MagicF2fs = Magic(0xF2F52010)
// MagicGPFS filesystem id for GPFS
MagicGPFS = Magic(0x47504653)
// MagicJffs2Fs filesystem if for Jffs2Fs
MagicJffs2Fs = Magic(0x000072b6)
// MagicJfs filesystem id for Jfs
MagicJfs = Magic(0x3153464a)
// MagicNfsFs filesystem id for NfsFs
MagicNfsFs = Magic(0x00006969)
// MagicRAMFs filesystem id for RamFs
MagicRAMFs = Magic(0x858458f6)
// MagicReiserFs filesystem id for ReiserFs
MagicReiserFs = Magic(0x52654973)
// MagicSmbFs filesystem id for SmbFs
MagicSmbFs = Magic(0x0000517B)
// MagicSquashFs filesystem id for SquashFs
MagicSquashFs = Magic(0x73717368)
// MagicTmpFs filesystem id for TmpFs
MagicTmpFs = Magic(0x01021994)
// MagicVxFS filesystem id for VxFs
MagicVxFS = Magic(0xa501fcf5)
// MagicXfs filesystem id for Xfs
MagicXfs = Magic(0x58465342)
// MagicZfs filesystem id for Zfs
MagicZfs = Magic(0x2fc12fc1)
// MagicOverlay filesystem id for overlay
MagicOverlay = Magic(0x794C7630)
)
var (
// FsNames maps filesystem id to name of the filesystem.
FsNames = map[Magic]string{
MagicAufs: "aufs",
MagicBtrfs: "btrfs",
MagicCramfs: "cramfs",
MagicExtfs: "extfs",
MagicF2fs: "f2fs",
MagicGPFS: "gpfs",
MagicJffs2Fs: "jffs2",
MagicJfs: "jfs",
MagicNfsFs: "nfs",
MagicOverlay: "overlayfs",
MagicRAMFs: "ramfs",
MagicReiserFs: "reiserfs",
MagicSmbFs: "smb",
MagicSquashFs: "squashfs",
MagicTmpFs: "tmpfs",
MagicUnsupported: "unsupported",
MagicVxFS: "vxfs",
MagicXfs: "xfs",
MagicZfs: "zfs",
}
)
// GetMagic returns the filesystem id given the path.
func GetMagic(rootpath string) (Magic, error) {
var buf syscall.Statfs_t
if err := syscall.Statfs(filepath.Dir(rootpath), &buf); err != nil {
return 0, err
}
return Magic(buf.Type), nil
}

View File

@ -1,5 +1,4 @@
//go:build darwin || freebsd || netbsd //go:build darwin || freebsd || netbsd
// +build darwin freebsd netbsd
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build linux || openbsd || dragonfly || solaris //go:build linux || openbsd || dragonfly || solaris
// +build linux openbsd dragonfly solaris
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.
@ -20,10 +19,36 @@
package fs package fs
import ( import (
"fmt"
"io/fs"
"syscall" "syscall"
"time" "time"
) )
func Atime(st fs.FileInfo) (time.Time, error) {
stSys, ok := st.Sys().(*syscall.Stat_t)
if !ok {
return time.Time{}, fmt.Errorf("expected st.Sys() to be *syscall.Stat_t, got %T", st.Sys())
}
return StatATimeAsTime(stSys), nil
}
func Ctime(st fs.FileInfo) (time.Time, error) {
stSys, ok := st.Sys().(*syscall.Stat_t)
if !ok {
return time.Time{}, fmt.Errorf("expected st.Sys() to be *syscall.Stat_t, got %T", st.Sys())
}
return time.Unix(stSys.Atim.Unix()), nil
}
func Mtime(st fs.FileInfo) (time.Time, error) {
stSys, ok := st.Sys().(*syscall.Stat_t)
if !ok {
return time.Time{}, fmt.Errorf("expected st.Sys() to be *syscall.Stat_t, got %T", st.Sys())
}
return time.Unix(stSys.Mtim.Unix()), nil
}
// StatAtime returns the Atim // StatAtime returns the Atim
func StatAtime(st *syscall.Stat_t) syscall.Timespec { func StatAtime(st *syscall.Stat_t) syscall.Timespec {
return st.Atim return st.Atim

View File

@ -0,0 +1,33 @@
/*
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 (
"fmt"
"io/fs"
"syscall"
"time"
)
func Atime(st fs.FileInfo) (time.Time, error) {
stSys, ok := st.Sys().(*syscall.Win32FileAttributeData)
if !ok {
return time.Time{}, fmt.Errorf("expected st.Sys() to be *syscall.Win32FileAttributeData, got %T", st.Sys())
}
// ref: https://github.com/golang/go/blob/go1.19.2/src/os/types_windows.go#L230
return time.Unix(0, stSys.LastAccessTime.Nanoseconds()), nil
}

View File

@ -1,5 +1,4 @@
//go:build !(windows || linux) //go:build !(windows || linux)
// +build !windows,!linux
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !(linux || solaris || windows) //go:build !(linux || solaris || windows)
// +build !linux,!solaris,!windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build linux || darwin //go:build linux || darwin
// +build linux darwin
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !linux && !darwin //go:build !linux && !darwin
// +build !linux,!darwin
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@ -28,7 +28,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/sirupsen/logrus" "github.com/containerd/log"
) )
// New creates a loopback device // New creates a loopback device
@ -57,18 +57,18 @@ func New(size int64) (*Loopback, error) {
} }
deviceName := strings.TrimSpace(stdout.String()) deviceName := strings.TrimSpace(stdout.String())
logrus.Debugf("Created loop device %s (using %s)", deviceName, file.Name()) log.L.Debugf("Created loop device %s (using %s)", deviceName, file.Name())
cleanup := func() error { cleanup := func() error {
// detach device // detach device
logrus.Debugf("Removing loop device %s", deviceName) log.L.Debugf("Removing loop device %s", deviceName)
losetup := exec.Command("losetup", "--detach", deviceName) losetup := exec.Command("losetup", "--detach", deviceName)
if out, err := losetup.CombinedOutput(); err != nil { if out, err := losetup.CombinedOutput(); err != nil {
return fmt.Errorf("Could not remove loop device %s (%v): %q: %w", deviceName, losetup.Args, string(out), err) return fmt.Errorf("Could not remove loop device %s (%v): %q: %w", deviceName, losetup.Args, string(out), err)
} }
// remove file // remove file
logrus.Debugf("Removing temporary file %s", file.Name()) log.L.Debugf("Removing temporary file %s", file.Name())
return os.Remove(file.Name()) return os.Remove(file.Name())
} }

View File

@ -1,5 +1,4 @@
//go:build !linux && !windows //go:build !linux && !windows
// +build !linux,!windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

4
vendor/modules.txt vendored
View File

@ -134,8 +134,8 @@ github.com/containerd/containerd/api/types/runc/options
github.com/containerd/containerd/api/types/runtimeoptions/v1 github.com/containerd/containerd/api/types/runtimeoptions/v1
github.com/containerd/containerd/api/types/task github.com/containerd/containerd/api/types/task
github.com/containerd/containerd/api/types/transfer github.com/containerd/containerd/api/types/transfer
# github.com/containerd/continuity v0.4.3 # github.com/containerd/continuity v0.4.4
## explicit; go 1.19 ## explicit; go 1.21
github.com/containerd/continuity github.com/containerd/continuity
github.com/containerd/continuity/devices github.com/containerd/continuity/devices
github.com/containerd/continuity/driver github.com/containerd/continuity/driver