vendor: update buildkit to master@c36941f4a10e

Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
Justin Chadwell
2023-05-30 09:10:52 +01:00
parent 17bdbbd3c3
commit 6c62225d1b
141 changed files with 1402 additions and 1161 deletions

View File

@ -188,7 +188,7 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts
}
name := desc.Annotations[images.AnnotationImageName]
if name != "" && !eo.skipDockerManifest {
if name != "" {
mt.names = append(mt.names, name)
}
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
@ -227,26 +227,24 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts
records = append(records, r...)
}
if !eo.skipDockerManifest {
if len(manifests) >= 1 {
if len(manifests) > 1 {
sort.SliceStable(manifests, func(i, j int) bool {
if manifests[i].Platform == nil {
return false
}
if manifests[j].Platform == nil {
return true
}
return eo.platform.Less(*manifests[i].Platform, *manifests[j].Platform)
})
}
d = manifests[0].Digest
dManifests[d] = &exportManifest{
manifest: manifests[0],
}
} else if eo.platform != nil {
return fmt.Errorf("no manifest found for platform: %w", errdefs.ErrNotFound)
if len(manifests) >= 1 {
if len(manifests) > 1 {
sort.SliceStable(manifests, func(i, j int) bool {
if manifests[i].Platform == nil {
return false
}
if manifests[j].Platform == nil {
return true
}
return eo.platform.Less(*manifests[i].Platform, *manifests[j].Platform)
})
}
d = manifests[0].Digest
dManifests[d] = &exportManifest{
manifest: manifests[0],
}
} else if eo.platform != nil {
return fmt.Errorf("no manifest found for platform: %w", errdefs.ErrNotFound)
}
resolvedIndex[desc.Digest] = d
}
@ -262,7 +260,7 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts
}
}
if len(dManifests) > 0 {
if !eo.skipDockerManifest && len(dManifests) > 0 {
tr, err := manifestsRecord(ctx, store, dManifests)
if err != nil {
return fmt.Errorf("unable to create manifests file: %w", err)

View File

@ -23,7 +23,7 @@ var (
Package = "github.com/containerd/containerd"
// Version holds the complete version number. Filled in at linking time.
Version = "1.7.0+unknown"
Version = "1.7.1+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time.

View File

@ -1,7 +1,5 @@
linters:
enable:
- structcheck
- varcheck
- staticcheck
- unconvert
- gofmt

View File

@ -18,6 +18,7 @@ package continuity
import (
"bytes"
"errors"
"fmt"
"io"
"os"
@ -151,7 +152,7 @@ func (c *context) Resource(p string, fi os.FileInfo) (Resource, error) {
}
base.xattrs, err = c.resolveXAttrs(fp, fi, base)
if err != nil && err != ErrNotSupported {
if err != nil && !errors.Is(err, ErrNotSupported) {
return nil, err
}
@ -410,7 +411,7 @@ func (c *context) Apply(resource Resource) error {
return fmt.Errorf("resource %v escapes root", resource)
}
var chmod = true
chmod := true
fi, err := c.driver.Lstat(fp)
if err != nil {
if !os.IsNotExist(err) {

View File

@ -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 {

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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
}

View File

@ -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!

View File

@ -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 {

View File

@ -16,9 +16,22 @@
package fstest
// TODO: Any more metadata files generated by Windows layers?
// TODO: Also skip Recycle Bin contents in Windows layers which is used to store deleted files in some cases
var metadataFiles = map[string]bool{
"\\System Volume Information": true,
"\\WcSandboxState": true,
"\\System Volume Information": true,
"\\WcSandboxState": true,
"\\WcSandboxState\\Hives": true,
"\\WcSandboxState\\Hives\\DefaultUser_Delta": true,
"\\WcSandboxState\\Hives\\Sam_Delta": true,
"\\WcSandboxState\\Hives\\Security_Delta": true,
"\\WcSandboxState\\Hives\\Software_Delta": true,
"\\WcSandboxState\\Hives\\System_Delta": true,
"\\WcSandboxState\\initialized": true,
"\\Windows": true,
"\\Windows\\System32": true,
"\\Windows\\System32\\config": true,
"\\Windows\\System32\\config\\DEFAULT": true,
"\\Windows\\System32\\config\\SAM": true,
"\\Windows\\System32\\config\\SECURITY": true,
"\\Windows\\System32\\config\\SOFTWARE": true,
"\\Windows\\System32\\config\\SYSTEM": true,
}

View File

@ -129,7 +129,6 @@ func compareResource(r1, r2 continuity.Resource) bool {
// TODO(dmcgowan): Check if is XAttrer
return compareResourceTypes(r1, r2)
}
func compareResourceTypes(r1, r2 continuity.Resource) bool {

View File

@ -32,13 +32,13 @@ func Lchtimes(name string, atime, mtime time.Time) Applier {
// that the filter will mount. It is used for testing the snapshotter
func Base() Applier {
return Apply(
CreateDir("Windows", 0755),
CreateDir("Windows/System32", 0755),
CreateDir("Windows/System32/Config", 0755),
CreateFile("Windows/System32/Config/SYSTEM", []byte("foo\n"), 0777),
CreateFile("Windows/System32/Config/SOFTWARE", []byte("foo\n"), 0777),
CreateFile("Windows/System32/Config/SAM", []byte("foo\n"), 0777),
CreateFile("Windows/System32/Config/SECURITY", []byte("foo\n"), 0777),
CreateFile("Windows/System32/Config/DEFAULT", []byte("foo\n"), 0777),
CreateDir("Windows", 0o755),
CreateDir("Windows/System32", 0o755),
CreateDir("Windows/System32/Config", 0o755),
CreateFile("Windows/System32/Config/SYSTEM", []byte("foo\n"), 0o777),
CreateFile("Windows/System32/Config/SOFTWARE", []byte("foo\n"), 0o777),
CreateFile("Windows/System32/Config/SAM", []byte("foo\n"), 0o777),
CreateFile("Windows/System32/Config/SECURITY", []byte("foo\n"), 0o777),
CreateFile("Windows/System32/Config/DEFAULT", []byte("foo\n"), 0o777),
)
}

View File

@ -81,14 +81,14 @@ var (
// baseApplier creates a basic filesystem layout
// with multiple types of files for basic tests.
baseApplier = Apply(
CreateDir("/etc/", 0755),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
CreateDir("/etc/", 0o755),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0o644),
Link("/etc/hosts", "/etc/hosts.allow"),
CreateDir("/usr/local/lib", 0755),
CreateFile("/usr/local/lib/libnothing.so", []byte{0x00, 0x00}, 0755),
CreateDir("/usr/local/lib", 0o755),
CreateFile("/usr/local/lib/libnothing.so", []byte{0x00, 0x00}, 0o755),
Symlink("libnothing.so", "/usr/local/lib/libnothing.so.2"),
CreateDir("/home", 0755),
CreateDir("/home/derek", 0700),
CreateDir("/home", 0o755),
CreateDir("/home/derek", 0o700),
// TODO: CreateSocket: how should Sockets be handled in continuity?
)
@ -96,10 +96,10 @@ var (
basicTest = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0600),
CreateFile("/etc/badfile", []byte(""), 0666),
CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0640),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0o600),
CreateFile("/etc/badfile", []byte(""), 0o666),
CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0o640),
),
Apply(
Remove("/etc/badfile"),
@ -111,8 +111,8 @@ var (
),
Apply(
RemoveAll("/home"),
CreateDir("/home/derek", 0700),
CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0640),
CreateDir("/home/derek", 0o700),
CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0o640),
Link("/etc/hosts", "/etc/hosts.allow"),
),
}
@ -121,58 +121,58 @@ var (
// deletions are properly picked up and applied
deletionTest = []Applier{
Apply(
CreateDir("/test/somedir", 0755),
CreateDir("/lib", 0700),
CreateFile("/lib/hidden", []byte{}, 0644),
CreateDir("/test/somedir", 0o755),
CreateDir("/lib", 0o700),
CreateFile("/lib/hidden", []byte{}, 0o644),
),
Apply(
CreateFile("/test/a", []byte{}, 0644),
CreateFile("/test/b", []byte{}, 0644),
CreateDir("/test/otherdir", 0755),
CreateFile("/test/otherdir/.empty", []byte{}, 0644),
CreateFile("/test/a", []byte{}, 0o644),
CreateFile("/test/b", []byte{}, 0o644),
CreateDir("/test/otherdir", 0o755),
CreateFile("/test/otherdir/.empty", []byte{}, 0o644),
RemoveAll("/lib"),
CreateDir("/lib", 0700),
CreateFile("/lib/not-hidden", []byte{}, 0644),
CreateDir("/lib", 0o700),
CreateFile("/lib/not-hidden", []byte{}, 0o644),
),
Apply(
Remove("/test/a"),
Remove("/test/b"),
RemoveAll("/test/otherdir"),
CreateFile("/lib/newfile", []byte{}, 0644),
CreateFile("/lib/newfile", []byte{}, 0o644),
),
}
// updateTest covers file updates for content and permission
updateTest = []Applier{
Apply(
CreateDir("/d1", 0755),
CreateDir("/d2", 0700),
CreateFile("/d1/f1", []byte("something..."), 0644),
CreateFile("/d1/f2", []byte("else..."), 0644),
CreateFile("/d1/f3", []byte("entirely..."), 0644),
CreateDir("/d1", 0o755),
CreateDir("/d2", 0o700),
CreateFile("/d1/f1", []byte("something..."), 0o644),
CreateFile("/d1/f2", []byte("else..."), 0o644),
CreateFile("/d1/f3", []byte("entirely..."), 0o644),
),
Apply(
CreateFile("/d1/f1", []byte("file content of a different length"), 0664),
CreateFile("/d1/f1", []byte("file content of a different length"), 0o664),
Remove("/d1/f3"),
CreateFile("/d1/f3", []byte("updated content"), 0664),
Chmod("/d1/f2", 0766),
Chmod("/d2", 0777),
CreateFile("/d1/f3", []byte("updated content"), 0o664),
Chmod("/d1/f2", 0o766),
Chmod("/d2", 0o777),
),
}
// directoryPermissionsTest covers directory permissions on update
directoryPermissionsTest = []Applier{
Apply(
CreateDir("/d1", 0700),
CreateDir("/d2", 0751),
CreateDir("/d3", 0777),
CreateDir("/d1", 0o700),
CreateDir("/d2", 0o751),
CreateDir("/d3", 0o777),
),
Apply(
CreateFile("/d1/f", []byte("irrelevant"), 0644),
CreateDir("/d1/d", 0700),
CreateFile("/d1/d/f", []byte("irrelevant"), 0644),
CreateFile("/d2/f", []byte("irrelevant"), 0644),
CreateFile("/d3/f", []byte("irrelevant"), 0644),
CreateFile("/d1/f", []byte("irrelevant"), 0o644),
CreateDir("/d1/d", 0o700),
CreateFile("/d1/d/f", []byte("irrelevant"), 0o644),
CreateFile("/d2/f", []byte("irrelevant"), 0o644),
CreateFile("/d3/f", []byte("irrelevant"), 0o644),
),
}
@ -180,28 +180,28 @@ var (
// files
parentDirectoryPermissionsTest = []Applier{
Apply(
CreateDir("/d1", 0700),
CreateDir("/d1/a", 0700),
CreateDir("/d1/a/b", 0700),
CreateDir("/d1/a/b/c", 0700),
CreateFile("/d1/a/b/f", []byte("content1"), 0644),
CreateDir("/d2", 0751),
CreateDir("/d2/a/b", 0751),
CreateDir("/d2/a/b/c", 0751),
CreateFile("/d2/a/b/f", []byte("content1"), 0644),
CreateDir("/d1", 0o700),
CreateDir("/d1/a", 0o700),
CreateDir("/d1/a/b", 0o700),
CreateDir("/d1/a/b/c", 0o700),
CreateFile("/d1/a/b/f", []byte("content1"), 0o644),
CreateDir("/d2", 0o751),
CreateDir("/d2/a/b", 0o751),
CreateDir("/d2/a/b/c", 0o751),
CreateFile("/d2/a/b/f", []byte("content1"), 0o644),
),
Apply(
CreateFile("/d1/a/b/f", []byte("content1"), 0644),
Chmod("/d1/a/b/c", 0700),
CreateFile("/d2/a/b/f", []byte("content2"), 0644),
Chmod("/d2/a/b/c", 0751),
CreateFile("/d1/a/b/f", []byte("content1"), 0o644),
Chmod("/d1/a/b/c", 0o700),
CreateFile("/d2/a/b/f", []byte("content2"), 0o644),
Chmod("/d2/a/b/c", 0o751),
),
}
hardlinkUnmodified = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
),
Apply(
Link("/etc/hosts", "/etc/hosts.deny"),
@ -213,7 +213,7 @@ var (
hardlinkBeforeUnmodified = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
),
Apply(
Link("/etc/hosts", "/etc/before-hosts"),
@ -225,11 +225,11 @@ var (
hardlinkBeforeModified = []Applier{
baseApplier,
Apply(
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0o644),
),
Apply(
Remove("/etc/hosts"),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0o644),
Link("/etc/hosts", "/etc/before-hosts"),
),
}

View File

@ -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

View File

@ -21,9 +21,7 @@ import (
"os"
)
var (
errNotAHardLink = fmt.Errorf("invalid hardlink")
)
var errNotAHardLink = fmt.Errorf("invalid hardlink")
type hardlinkManager struct {
hardlinks map[hardlinkKey][]Resource

View File

@ -37,26 +37,32 @@ func atomicWriteFile(filename string, r io.Reader, dataSize int64, perm os.FileM
if err != nil {
return err
}
needClose := true
defer func() {
if needClose {
f.Close()
}
}()
err = os.Chmod(f.Name(), perm)
if err != nil {
f.Close()
return err
}
n, err := io.Copy(f, r)
if err == nil && n < dataSize {
f.Close()
return io.ErrShortWrite
}
if err != nil {
f.Close()
return err
}
if err := f.Sync(); err != nil {
f.Close()
if err = f.Sync(); err != nil {
return err
}
needClose = false
if err := f.Close(); err != nil {
return err
}
return os.Rename(f.Name(), filename)
}

View File

@ -1,7 +1,5 @@
linters:
enable:
- structcheck
- varcheck
- staticcheck
- unconvert
- gofmt

View File

@ -151,7 +151,7 @@ install-protobuild:
coverage: ## generate coverprofiles from the unit tests, except tests that require root
@echo "$(WHALE) $@"
@rm -f coverage.txt
@$(GO) test -i ${TESTFLAGS} ${TESTPACKAGES} 2> /dev/null
@$(GO) test ${TESTFLAGS} ${TESTPACKAGES} 2> /dev/null
@( for pkg in ${PACKAGES}; do \
$(GO) test ${TESTFLAGS} \
-cover \

View File

@ -214,60 +214,66 @@ func (cs *clientStream) RecvMsg(m interface{}) error {
if cs.remoteClosed {
return io.EOF
}
var msg *streamMessage
select {
case <-cs.ctx.Done():
return cs.ctx.Err()
case msg, ok := <-cs.s.recv:
if !ok {
case <-cs.s.recvClose:
// If recv has a pending message, process that first
select {
case msg = <-cs.s.recv:
default:
return cs.s.recvErr
}
case msg = <-cs.s.recv:
}
if msg.header.Type == messageTypeResponse {
resp := &Response{}
err := proto.Unmarshal(msg.payload[:msg.header.Length], resp)
// return the payload buffer for reuse
cs.c.channel.putmbuf(msg.payload)
if err != nil {
return err
}
if msg.header.Type == messageTypeResponse {
resp := &Response{}
err := proto.Unmarshal(msg.payload[:msg.header.Length], resp)
// return the payload buffer for reuse
cs.c.channel.putmbuf(msg.payload)
if err != nil {
return err
}
if err := cs.c.codec.Unmarshal(resp.Payload, m); err != nil {
return err
}
if err := cs.c.codec.Unmarshal(resp.Payload, m); err != nil {
return err
}
if resp.Status != nil && resp.Status.Code != int32(codes.OK) {
return status.ErrorProto(resp.Status)
}
if resp.Status != nil && resp.Status.Code != int32(codes.OK) {
return status.ErrorProto(resp.Status)
}
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
return nil
} else if msg.header.Type == messageTypeData {
if !cs.desc.StreamingServer {
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
return fmt.Errorf("received data from non-streaming server: %w", ErrProtocol)
}
if msg.header.Flags&flagRemoteClosed == flagRemoteClosed {
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
return nil
} else if msg.header.Type == messageTypeData {
if !cs.desc.StreamingServer {
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
return fmt.Errorf("received data from non-streaming server: %w", ErrProtocol)
if msg.header.Flags&flagNoData == flagNoData {
return io.EOF
}
if msg.header.Flags&flagRemoteClosed == flagRemoteClosed {
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
if msg.header.Flags&flagNoData == flagNoData {
return io.EOF
}
}
err := cs.c.codec.Unmarshal(msg.payload[:msg.header.Length], m)
cs.c.channel.putmbuf(msg.payload)
if err != nil {
return err
}
return nil
}
return fmt.Errorf("unexpected %q message received: %w", msg.header.Type, ErrProtocol)
err := cs.c.codec.Unmarshal(msg.payload[:msg.header.Length], m)
cs.c.channel.putmbuf(msg.payload)
if err != nil {
return err
}
return nil
}
return fmt.Errorf("unexpected %q message received: %w", msg.header.Type, ErrProtocol)
}
// Close closes the ttrpc connection and underlying connection
@ -477,25 +483,30 @@ func (c *Client) dispatch(ctx context.Context, req *Request, resp *Response) err
}
defer c.deleteStream(s)
var msg *streamMessage
select {
case <-ctx.Done():
return ctx.Err()
case <-c.ctx.Done():
return ErrClosed
case msg, ok := <-s.recv:
if !ok {
case <-s.recvClose:
// If recv has a pending message, process that first
select {
case msg = <-s.recv:
default:
return s.recvErr
}
if msg.header.Type == messageTypeResponse {
err = proto.Unmarshal(msg.payload[:msg.header.Length], resp)
} else {
err = fmt.Errorf("unexpected %q message received: %w", msg.header.Type, ErrProtocol)
}
// return the payload buffer for reuse
c.channel.putmbuf(msg.payload)
return err
case msg = <-s.recv:
}
if msg.header.Type == messageTypeResponse {
err = proto.Unmarshal(msg.payload[:msg.header.Length], resp)
} else {
err = fmt.Errorf("unexpected %q message received: %w", msg.header.Type, ErrProtocol)
}
// return the payload buffer for reuse
c.channel.putmbuf(msg.payload)
return err
}

View File

@ -547,7 +547,7 @@ func (c *serverConn) run(sctx context.Context) {
// branch. Basically, it means that we are no longer receiving
// requests due to a terminal error.
recvErr = nil // connection is now "closing"
if err == io.EOF || err == io.ErrUnexpectedEOF || errors.Is(err, syscall.ECONNRESET) {
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, syscall.ECONNRESET) {
// The client went away and we should stop processing
// requests, so that the client connection is closed
return

View File

@ -35,27 +35,26 @@ type stream struct {
closeOnce sync.Once
recvErr error
recvClose chan struct{}
}
func newStream(id streamID, send sender) *stream {
return &stream{
id: id,
sender: send,
recv: make(chan *streamMessage, 1),
id: id,
sender: send,
recv: make(chan *streamMessage, 1),
recvClose: make(chan struct{}),
}
}
func (s *stream) closeWithError(err error) error {
s.closeOnce.Do(func() {
if s.recv != nil {
close(s.recv)
if err != nil {
s.recvErr = err
} else {
s.recvErr = ErrClosed
}
if err != nil {
s.recvErr = err
} else {
s.recvErr = ErrClosed
}
close(s.recvClose)
})
return nil
}
@ -65,10 +64,14 @@ func (s *stream) send(mt messageType, flags uint8, b []byte) error {
}
func (s *stream) receive(ctx context.Context, msg *streamMessage) error {
if s.recvErr != nil {
select {
case <-s.recvClose:
return s.recvErr
default:
}
select {
case <-s.recvClose:
return s.recvErr
case s.recv <- msg:
return nil
case <-ctx.Done():

View File

@ -194,10 +194,6 @@ func UnmarshalToByTypeURL(typeURL string, value []byte, out interface{}) error {
}
func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
if value == nil {
return nil, nil
}
t, err := getTypeByUrl(typeURL)
if err != nil {
return nil, err