diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d0eae24..9d82bc7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: Continuity on: push: - branches: [ master ] + branches: [ main ] pull_request: - branches: [ master ] + branches: [ main ] jobs: @@ -40,7 +40,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.15 + go-version: 1.17 - name: Setup Go binary path shell: bash @@ -76,13 +76,6 @@ jobs: run: make build binaries working-directory: src/github.com/containerd/continuity - - name: Cross-compile - if: startsWith(matrix.os, 'ubuntu') - shell: bash - run: | - GOOS=freebsd make build binaries - working-directory: src/github.com/containerd/continuity - - name: Linux Tests if: startsWith(matrix.os, 'ubuntu') run: | @@ -95,3 +88,36 @@ jobs: shell: bash run: make test-compile working-directory: src/github.com/containerd/continuity + + cross: + name: Cross-compile + runs-on: ubuntu-18.04 + timeout-minutes: 10 + needs: [project] + + strategy: + matrix: + goos: [freebsd, openbsd, netbsd, darwin, solaris] + + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.17 + + - name: Setup Go binary path + shell: bash + run: | + echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV + echo "${{ github.workspace }}/bin" >> $GITHUB_PATH + + - name: Check out code + uses: actions/checkout@v2 + with: + path: src/github.com/containerd/continuity + + - name: Cross-compile ${{matrix.goos}} + shell: bash + run: | + GOOS=${{matrix.goos}} make build binaries + working-directory: src/github.com/containerd/continuity diff --git a/AUTHORS b/AUTHORS index 376ceb93..deef28c1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -12,8 +12,11 @@ Darren Stahl Derek McGowan Derek McGowan Edward Pilatowicz +Fu Wei +Hajime Tazaki Ian Campbell Ivan Markin +Jacob Blain Christen Justin Cormack Justin Cummins Kasper Fabæch Brandt @@ -23,10 +26,11 @@ Michael Crosby Michael Wan Mike Brown Niels de Vos +Phil Estes Phil Estes Phil Estes -Samuel Karp Sam Whited +Samuel Karp Sebastiaan van Stijn Shengjing Zhu Stephen J Day diff --git a/README.md b/README.md index 6fa50e15..f47b4afe 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # continuity [![GoDoc](https://godoc.org/github.com/containerd/continuity?status.svg)](https://godoc.org/github.com/containerd/continuity) -[![Build Status](https://travis-ci.org/containerd/continuity.svg?branch=master)](https://travis-ci.org/containerd/continuity) +[![Build Status](https://travis-ci.org/containerd/continuity.svg?branch=main)](https://travis-ci.org/containerd/continuity) A transport-agnostic, filesystem metadata manifest system @@ -81,8 +81,8 @@ $ go generate ./proto continuity is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). As a containerd sub-project, you will find the: - * [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md), - * [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS), - * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md) + * [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md), + * [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS), + * and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md) information in our [`containerd/project`](https://github.com/containerd/project) repository. diff --git a/commands/mount.go b/commands/mount.go index 20425077..f2873af2 100644 --- a/commands/mount.go +++ b/commands/mount.go @@ -1,3 +1,4 @@ +//go:build linux || darwin || freebsd // +build linux darwin freebsd /* diff --git a/commands/mount_unsupported.go b/commands/mount_unsupported.go index 6606b68d..e626ca37 100644 --- a/commands/mount_unsupported.go +++ b/commands/mount_unsupported.go @@ -1,4 +1,5 @@ -// +build windows solaris +//go:build windows || solaris || openbsd || netbsd +// +build windows solaris openbsd netbsd /* Copyright The containerd Authors. diff --git a/context.go b/context.go index 2166142c..019b185f 100644 --- a/context.go +++ b/context.go @@ -20,7 +20,6 @@ import ( "bytes" "fmt" "io" - "log" "os" "path/filepath" "strings" @@ -152,9 +151,7 @@ func (c *context) Resource(p string, fi os.FileInfo) (Resource, error) { } base.xattrs, err = c.resolveXAttrs(fp, fi, base) - if err == ErrNotSupported { - log.Printf("resolving xattrs on %s not supported", fp) - } else if err != nil { + if err != nil && err != ErrNotSupported { return nil, err } @@ -192,8 +189,7 @@ func (c *context) Resource(p string, fi os.FileInfo) (Resource, error) { if fi.Mode()&os.ModeDevice != 0 { deviceDriver, ok := c.driver.(driverpkg.DeviceInfoDriver) if !ok { - log.Printf("device extraction not supported %s", fp) - return nil, ErrNotSupported + return nil, fmt.Errorf("device extraction is not supported for %s: %w", fp, ErrNotSupported) } // character and block devices merely need to recover the @@ -206,8 +202,7 @@ func (c *context) Resource(p string, fi os.FileInfo) (Resource, error) { return newDevice(*base, base.paths, major, minor) } - log.Printf("%q (%v) is not supported", fp, fi.Mode()) - return nil, ErrNotFound + return nil, fmt.Errorf("%q (%v) is not supported: %w", fp, fi.Mode(), ErrNotFound) } func (c *context) verifyMetadata(resource, target Resource) error { @@ -646,8 +641,7 @@ func (c *context) resolveXAttrs(fp string, fi os.FileInfo, base *resource) (map[ if fi.Mode().IsRegular() || fi.Mode().IsDir() { xattrDriver, ok := c.driver.(driverpkg.XAttrDriver) if !ok { - log.Println("xattr extraction not supported") - return nil, ErrNotSupported + return nil, fmt.Errorf("xattr extraction is not supported: %w", ErrNotSupported) } return xattrDriver.Getxattr(fp) @@ -656,8 +650,7 @@ func (c *context) resolveXAttrs(fp string, fi os.FileInfo, base *resource) (map[ if fi.Mode()&os.ModeSymlink != 0 { lxattrDriver, ok := c.driver.(driverpkg.LXAttrDriver) if !ok { - log.Println("xattr extraction for symlinks not supported") - return nil, ErrNotSupported + return nil, fmt.Errorf("xattr extraction for symlinks is not supported: %w", ErrNotSupported) } return lxattrDriver.LGetxattr(fp) diff --git a/continuityfs/fuse.go b/continuityfs/fuse.go index 962b12f0..981859b0 100644 --- a/continuityfs/fuse.go +++ b/continuityfs/fuse.go @@ -1,3 +1,4 @@ +//go:build linux || darwin || freebsd // +build linux darwin freebsd /* diff --git a/continuityfs/provider.go b/continuityfs/provider.go index c78a5380..9eafe4c3 100644 --- a/continuityfs/provider.go +++ b/continuityfs/provider.go @@ -1,5 +1,3 @@ -// +build linux darwin freebsd - /* Copyright The containerd Authors. diff --git a/devices/devices_unix.go b/devices/devices_unix.go index 225a04b7..3dd3bb42 100644 --- a/devices/devices_unix.go +++ b/devices/devices_unix.go @@ -1,4 +1,5 @@ -// +build linux darwin freebsd solaris +//go:build !windows +// +build !windows /* Copyright The containerd Authors. diff --git a/devices/devices_windows.go b/devices/devices_windows.go index 04627c80..cd551f53 100644 --- a/devices/devices_windows.go +++ b/devices/devices_windows.go @@ -17,11 +17,10 @@ package devices import ( + "fmt" "os" - - "github.com/pkg/errors" ) func DeviceInfo(fi os.FileInfo) (uint64, uint64, error) { - return 0, 0, errors.Wrap(ErrNotSupported, "cannot get device info on windows") + return 0, 0, fmt.Errorf("cannot get device info on windows: %w", ErrNotSupported) } diff --git a/devices/mknod_freebsd.go b/devices/mknod_freebsd.go index 33d18ec8..067ff7de 100644 --- a/devices/mknod_freebsd.go +++ b/devices/mknod_freebsd.go @@ -1,3 +1,4 @@ +//go:build freebsd // +build freebsd /* diff --git a/devices/mknod_unix.go b/devices/mknod_unix.go index d9e7a7a2..5c7f5525 100644 --- a/devices/mknod_unix.go +++ b/devices/mknod_unix.go @@ -1,4 +1,5 @@ -// +build linux darwin solaris +//go:build !(freebsd || windows) +// +build !freebsd,!windows /* Copyright The containerd Authors. diff --git a/driver/driver_unix.go b/driver/driver_unix.go index 3e58d10a..d64dd503 100644 --- a/driver/driver_unix.go +++ b/driver/driver_unix.go @@ -1,4 +1,5 @@ -// +build linux darwin freebsd solaris +//go:build !windows +// +build !windows /* Copyright The containerd Authors. diff --git a/driver/driver_windows.go b/driver/driver_windows.go index 9baea3ba..f539feec 100644 --- a/driver/driver_windows.go +++ b/driver/driver_windows.go @@ -1,3 +1,4 @@ +//go:build go1.13 // +build go1.13 /* diff --git a/driver/lchmod_unix.go b/driver/lchmod_unix.go index b8877a8a..161c79fa 100644 --- a/driver/lchmod_unix.go +++ b/driver/lchmod_unix.go @@ -1,4 +1,5 @@ -// +build darwin freebsd solaris +//go:build darwin || freebsd || netbsd || openbsd || solaris +// +build darwin freebsd netbsd openbsd solaris /* Copyright The containerd Authors. diff --git a/fs/copy.go b/fs/copy.go index 2ee77d1a..8e23934e 100644 --- a/fs/copy.go +++ b/fs/copy.go @@ -17,12 +17,11 @@ package fs import ( + "fmt" "io/ioutil" "os" "path/filepath" "sync" - - "github.com/pkg/errors" ) var bufferPool = &sync.Pool{ @@ -92,35 +91,35 @@ func CopyDir(dst, src string, opts ...CopyDirOpt) error { func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) error { stat, err := os.Stat(src) if err != nil { - return errors.Wrapf(err, "failed to stat %s", src) + return fmt.Errorf("failed to stat %s: %w", src, err) } if !stat.IsDir() { - return errors.Errorf("source %s is not directory", src) + return fmt.Errorf("source %s is not directory", src) } if st, err := os.Stat(dst); err != nil { if err := os.Mkdir(dst, stat.Mode()); err != nil { - return errors.Wrapf(err, "failed to mkdir %s", dst) + return fmt.Errorf("failed to mkdir %s: %w", dst, err) } } else if !st.IsDir() { - return errors.Errorf("cannot copy to non-directory: %s", dst) + return fmt.Errorf("cannot copy to non-directory: %s", dst) } else { if err := os.Chmod(dst, stat.Mode()); err != nil { - return errors.Wrapf(err, "failed to chmod on %s", dst) + return fmt.Errorf("failed to chmod on %s: %w", dst, err) } } fis, err := ioutil.ReadDir(src) if err != nil { - return errors.Wrapf(err, "failed to read %s", src) + return fmt.Errorf("failed to read %s: %w", src, err) } - if err := copyFileInfo(stat, dst); err != nil { - return errors.Wrapf(err, "failed to copy file info for %s", dst) + if err := copyFileInfo(stat, src, dst); err != nil { + return fmt.Errorf("failed to copy file info for %s: %w", dst, err) } if err := copyXAttrs(dst, src, o.xex, o.xeh); err != nil { - return errors.Wrap(err, "failed to copy xattrs") + return fmt.Errorf("failed to copy xattrs: %w", err) } for _, fi := range fis { @@ -136,37 +135,38 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er case (fi.Mode() & os.ModeType) == 0: link, err := getLinkSource(target, fi, inodes) if err != nil { - return errors.Wrap(err, "failed to get hardlink") + return fmt.Errorf("failed to get hardlink: %w", err) } if link != "" { if err := os.Link(link, target); err != nil { - return errors.Wrap(err, "failed to create hard link") + return fmt.Errorf("failed to create hard link: %w", err) } } else if err := CopyFile(target, source); err != nil { - return errors.Wrap(err, "failed to copy files") + return fmt.Errorf("failed to copy files: %w", err) } case (fi.Mode() & os.ModeSymlink) == os.ModeSymlink: link, err := os.Readlink(source) if err != nil { - return errors.Wrapf(err, "failed to read link: %s", source) + return fmt.Errorf("failed to read link: %s: %w", source, err) } if err := os.Symlink(link, target); err != nil { - return errors.Wrapf(err, "failed to create symlink: %s", target) + return fmt.Errorf("failed to create symlink: %s: %w", target, err) } case (fi.Mode() & os.ModeDevice) == os.ModeDevice: if err := copyDevice(target, fi); err != nil { - return errors.Wrapf(err, "failed to create device") + return fmt.Errorf("failed to create device: %w", err) } default: // TODO: Support pipes and sockets - return errors.Wrapf(err, "unsupported mode %s", fi.Mode()) + return fmt.Errorf("unsupported mode %s: %w", fi.Mode(), err) } - if err := copyFileInfo(fi, target); err != nil { - return errors.Wrap(err, "failed to copy file info") + + if err := copyFileInfo(fi, source, target); err != nil { + return fmt.Errorf("failed to copy file info: %w", err) } if err := copyXAttrs(target, source, o.xex, o.xeh); err != nil { - return errors.Wrap(err, "failed to copy xattrs") + return fmt.Errorf("failed to copy xattrs: %w", err) } } @@ -178,12 +178,12 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er func CopyFile(target, source string) error { src, err := os.Open(source) if err != nil { - return errors.Wrapf(err, "failed to open source %s", source) + return fmt.Errorf("failed to open source %s: %w", source, err) } defer src.Close() tgt, err := os.Create(target) if err != nil { - return errors.Wrapf(err, "failed to open target %s", target) + return fmt.Errorf("failed to open target %s: %w", target, err) } defer tgt.Close() diff --git a/fs/copy_darwinopenbsdsolaris.go b/fs/copy_darwin.go similarity index 79% rename from fs/copy_darwinopenbsdsolaris.go rename to fs/copy_darwin.go index 92ccacf9..ce55f0aa 100644 --- a/fs/copy_darwinopenbsdsolaris.go +++ b/fs/copy_darwin.go @@ -1,4 +1,5 @@ -// +build darwin openbsd solaris +//go:build darwin +// +build darwin /* Copyright The containerd Authors. @@ -19,10 +20,10 @@ package fs import ( + "errors" "os" "syscall" - "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -33,8 +34,3 @@ func copyDevice(dst string, fi os.FileInfo) error { } return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev)) } - -func utimesNano(name string, atime, mtime syscall.Timespec) error { - timespec := []syscall.Timespec{atime, mtime} - return syscall.UtimesNano(name, timespec) -} diff --git a/fs/copy_device_unix.go b/fs/copy_device_unix.go new file mode 100644 index 00000000..f821890c --- /dev/null +++ b/fs/copy_device_unix.go @@ -0,0 +1,36 @@ +//go:build openbsd || solaris || netbsd +// +build openbsd solaris netbsd + +/* + 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" + "syscall" + + "golang.org/x/sys/unix" +) + +func copyDevice(dst string, fi os.FileInfo) error { + st, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return errors.New("unsupported stat type") + } + return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev)) +} diff --git a/fs/copy_freebsd.go b/fs/copy_freebsd.go index 4b116c95..4aaf743e 100644 --- a/fs/copy_freebsd.go +++ b/fs/copy_freebsd.go @@ -1,3 +1,4 @@ +//go:build freebsd // +build freebsd /* @@ -19,10 +20,10 @@ package fs import ( + "errors" "os" "syscall" - "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -33,10 +34,3 @@ func copyDevice(dst string, fi os.FileInfo) error { } return unix.Mknod(dst, uint32(fi.Mode()), st.Rdev) } - -func utimesNano(name string, atime, mtime syscall.Timespec) error { - at := unix.NsecToTimespec(atime.Nano()) - mt := unix.NsecToTimespec(mtime.Nano()) - utimes := [2]unix.Timespec{at, mt} - return unix.UtimesNanoAt(unix.AT_FDCWD, name, utimes[0:], unix.AT_SYMLINK_NOFOLLOW) -} diff --git a/fs/copy_linux.go b/fs/copy_linux.go index 85beaee5..93840766 100644 --- a/fs/copy_linux.go +++ b/fs/copy_linux.go @@ -17,16 +17,17 @@ package fs import ( + "errors" + "fmt" "io" "os" "syscall" "github.com/containerd/continuity/sysx" - "github.com/pkg/errors" "golang.org/x/sys/unix" ) -func copyFileInfo(fi os.FileInfo, name string) error { +func copyFileInfo(fi os.FileInfo, src, name string) error { st := fi.Sys().(*syscall.Stat_t) if err := os.Lchown(name, int(st.Uid), int(st.Gid)); err != nil { if os.IsPermission(err) { @@ -41,13 +42,13 @@ func copyFileInfo(fi os.FileInfo, name string) error { } } if err != nil { - return errors.Wrapf(err, "failed to chown %s", name) + return fmt.Errorf("failed to chown %s: %w", name, err) } } if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink { if err := os.Chmod(name, fi.Mode()); err != nil { - return errors.Wrapf(err, "failed to chmod %s", name) + return fmt.Errorf("failed to chmod %s: %w", name, err) } } @@ -56,7 +57,7 @@ func copyFileInfo(fi os.FileInfo, name string) error { unix.NsecToTimespec(syscall.TimespecToNsec(StatMtime(st))), } if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil { - return errors.Wrapf(err, "failed to utime %s", name) + return fmt.Errorf("failed to utime %s: %w", name, err) } return nil @@ -67,7 +68,7 @@ const maxSSizeT = int64(^uint(0) >> 1) func copyFileContent(dst, src *os.File) error { st, err := src.Stat() if err != nil { - return errors.Wrap(err, "unable to stat source") + return fmt.Errorf("unable to stat source: %w", err) } size := st.Size() @@ -88,13 +89,16 @@ func copyFileContent(dst, src *os.File) error { n, err := unix.CopyFileRange(srcFd, nil, dstFd, nil, copySize, 0) if err != nil { if (err != unix.ENOSYS && err != unix.EXDEV) || !first { - return errors.Wrap(err, "copy file range failed") + return fmt.Errorf("copy file range failed: %w", err) } buf := bufferPool.Get().(*[]byte) _, err = io.CopyBuffer(dst, src, *buf) bufferPool.Put(buf) - return errors.Wrap(err, "userspace copy failed") + if err != nil { + return fmt.Errorf("userspace copy failed: %w", err) + } + return nil } first = false @@ -107,7 +111,7 @@ 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 { - e := errors.Wrapf(err, "failed to list xattrs on %s", src) + e := fmt.Errorf("failed to list xattrs on %s: %w", src, err) if errorHandler != nil { e = errorHandler(dst, src, "", e) } @@ -119,7 +123,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt } data, err := sysx.LGetxattr(src, xattr) if err != nil { - e := errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) + e := fmt.Errorf("failed to get xattr %q on %s: %w", xattr, src, err) if errorHandler != nil { if e = errorHandler(dst, src, xattr, e); e == nil { continue @@ -128,7 +132,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt return e } if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil { - e := errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) + e := fmt.Errorf("failed to set xattr %q on %s: %w", xattr, dst, err) if errorHandler != nil { if e = errorHandler(dst, src, xattr, e); e == nil { continue diff --git a/fs/copy_linux_test.go b/fs/copy_linux_test.go index a10a91a0..d91a0437 100644 --- a/fs/copy_linux_test.go +++ b/fs/copy_linux_test.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux /* diff --git a/fs/copy_test.go b/fs/copy_test.go index 4f59aa4c..e27716ac 100644 --- a/fs/copy_test.go +++ b/fs/copy_test.go @@ -18,13 +18,13 @@ package fs import ( _ "crypto/sha256" + "fmt" "io/ioutil" "os" "testing" "time" "github.com/containerd/continuity/fs/fstest" - "github.com/pkg/errors" ) // TODO: Create copy directory which requires privilege @@ -80,22 +80,22 @@ func TestCopyWithLargeFile(t *testing.T) { func testCopy(apply fstest.Applier) error { t1, err := ioutil.TempDir("", "test-copy-src-") if err != nil { - return errors.Wrap(err, "failed to create temporary directory") + return fmt.Errorf("failed to create temporary directory: %w", err) } defer os.RemoveAll(t1) t2, err := ioutil.TempDir("", "test-copy-dst-") if err != nil { - return errors.Wrap(err, "failed to create temporary directory") + return fmt.Errorf("failed to create temporary directory: %w", err) } defer os.RemoveAll(t2) if err := apply.Apply(t1); err != nil { - return errors.Wrap(err, "failed to apply changes") + return fmt.Errorf("failed to apply changes: %w", err) } if err := CopyDir(t2, t1); err != nil { - return errors.Wrap(err, "failed to copy") + return fmt.Errorf("failed to copy: %w", err) } return fstest.CheckDirectoryEqual(t1, t2) diff --git a/fs/copy_unix.go b/fs/copy_unix.go index 923dd5a9..0e68ba9e 100644 --- a/fs/copy_unix.go +++ b/fs/copy_unix.go @@ -1,4 +1,5 @@ -// +build darwin freebsd openbsd solaris +//go:build darwin || freebsd || openbsd || netbsd || solaris +// +build darwin freebsd openbsd netbsd solaris /* Copyright The containerd Authors. @@ -19,15 +20,15 @@ package fs import ( + "fmt" "io" "os" "syscall" "github.com/containerd/continuity/sysx" - "github.com/pkg/errors" ) -func copyFileInfo(fi os.FileInfo, name string) error { +func copyFileInfo(fi os.FileInfo, src, name string) error { st := fi.Sys().(*syscall.Stat_t) if err := os.Lchown(name, int(st.Uid), int(st.Gid)); err != nil { if os.IsPermission(err) { @@ -42,18 +43,18 @@ func copyFileInfo(fi os.FileInfo, name string) error { } } if err != nil { - return errors.Wrapf(err, "failed to chown %s", name) + return fmt.Errorf("failed to chown %s: %w", name, err) } } if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink { if err := os.Chmod(name, fi.Mode()); err != nil { - return errors.Wrapf(err, "failed to chmod %s", name) + return fmt.Errorf("failed to chmod %s: %w", name, err) } } if err := utimesNano(name, StatAtime(st), StatMtime(st)); err != nil { - return errors.Wrapf(err, "failed to utime %s", name) + return fmt.Errorf("failed to utime %s: %w", name, err) } return nil @@ -70,7 +71,7 @@ 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 { - e := errors.Wrapf(err, "failed to list xattrs on %s", src) + e := fmt.Errorf("failed to list xattrs on %s: %w", src, err) if errorHandler != nil { e = errorHandler(dst, src, "", e) } @@ -82,7 +83,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt } data, err := sysx.LGetxattr(src, xattr) if err != nil { - e := errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src) + e := fmt.Errorf("failed to get xattr %q on %s: %w", xattr, src, err) if errorHandler != nil { if e = errorHandler(dst, src, xattr, e); e == nil { continue @@ -91,7 +92,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt return e } if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil { - e := errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst) + e := fmt.Errorf("failed to set xattr %q on %s: %w", xattr, dst, err) if errorHandler != nil { if e = errorHandler(dst, src, xattr, e); e == nil { continue diff --git a/fs/copy_unix_test.go b/fs/copy_unix_test.go index 6c476bdf..6f6d2f41 100644 --- a/fs/copy_unix_test.go +++ b/fs/copy_unix_test.go @@ -1,3 +1,4 @@ +//go:build linux || darwin // +build linux darwin /* diff --git a/fs/copy_windows.go b/fs/copy_windows.go index 0081583f..e3f0cdd5 100644 --- a/fs/copy_windows.go +++ b/fs/copy_windows.go @@ -17,19 +17,60 @@ package fs import ( + "errors" + "fmt" "io" "os" - "github.com/pkg/errors" + winio "github.com/Microsoft/go-winio" + "golang.org/x/sys/windows" ) -func copyFileInfo(fi os.FileInfo, name string) error { +const ( + seTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege" +) + +func 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) + return fmt.Errorf("failed to chmod %s: %w", name, err) + } + + // 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) + + secInfo, err := windows.GetNamedSecurityInfo( + src, windows.SE_FILE_OBJECT, + windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION) + + if err != nil { + return err + } + + dacl, _, err := secInfo.DACL() + if err != nil { + return err } - // TODO: copy windows specific metadata + sid, _, err := secInfo.Owner() + if err != nil { + return err + } + + 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 + } return nil } diff --git a/fs/diff_test.go b/fs/diff_test.go index adb93539..f63be231 100644 --- a/fs/diff_test.go +++ b/fs/diff_test.go @@ -28,7 +28,6 @@ import ( "time" "github.com/containerd/continuity/fs/fstest" - "github.com/pkg/errors" ) // TODO: Additional tests @@ -293,30 +292,30 @@ func TestLchtimes(t *testing.T) { func testDiffWithBase(base, diff fstest.Applier, expected []TestChange) error { t1, err := ioutil.TempDir("", "diff-with-base-lower-") if err != nil { - return errors.Wrap(err, "failed to create temp dir") + return fmt.Errorf("failed to create temp dir: %w", err) } defer os.RemoveAll(t1) t2, err := ioutil.TempDir("", "diff-with-base-upper-") if err != nil { - return errors.Wrap(err, "failed to create temp dir") + return fmt.Errorf("failed to create temp dir: %w", err) } defer os.RemoveAll(t2) if err := base.Apply(t1); err != nil { - return errors.Wrap(err, "failed to apply base filesystem") + return fmt.Errorf("failed to apply base filesystem: %w", err) } if err := CopyDir(t2, t1); err != nil { - return errors.Wrap(err, "failed to copy base directory") + return fmt.Errorf("failed to copy base directory: %w", err) } if err := diff.Apply(t2); err != nil { - return errors.Wrap(err, "failed to apply diff filesystem") + return fmt.Errorf("failed to apply diff filesystem: %w", err) } changes, err := collectChanges(t1, t2) if err != nil { - return errors.Wrap(err, "failed to collect changes") + return fmt.Errorf("failed to collect changes: %w", err) } return checkChanges(t2, changes, expected) @@ -346,17 +345,17 @@ func TestBaseDirectoryChanges(t *testing.T) { func testDiffWithoutBase(apply fstest.Applier, expected []TestChange) error { tmp, err := ioutil.TempDir("", "diff-without-base-") if err != nil { - return errors.Wrap(err, "failed to create temp dir") + return fmt.Errorf("failed to create temp dir: %w", err) } defer os.RemoveAll(tmp) if err := apply.Apply(tmp); err != nil { - return errors.Wrap(err, "failed to apply filesytem changes") + return fmt.Errorf("failed to apply filesytem changes: %w", err) } changes, err := collectChanges("", tmp) if err != nil { - return errors.Wrap(err, "failed to collect changes") + return fmt.Errorf("failed to collect changes: %w", err) } return checkChanges(tmp, changes, expected) @@ -364,30 +363,30 @@ func testDiffWithoutBase(apply fstest.Applier, expected []TestChange) error { func checkChanges(root string, changes, expected []TestChange) error { if len(changes) != len(expected) { - return errors.Errorf("Unexpected number of changes:\n%s", diffString(changes, expected)) + return fmt.Errorf("Unexpected number of changes:\n%s", diffString(changes, expected)) } for i := range changes { if changes[i].Path != expected[i].Path || changes[i].Kind != expected[i].Kind { - return errors.Errorf("Unexpected change at %d:\n%s", i, diffString(changes, expected)) + return fmt.Errorf("Unexpected change at %d:\n%s", i, diffString(changes, expected)) } if changes[i].Kind != ChangeKindDelete { filename := filepath.Join(root, changes[i].Path) efi, err := os.Stat(filename) if err != nil { - return errors.Wrapf(err, "failed to stat %q", filename) + return fmt.Errorf("failed to stat %q: %w", filename, err) } afi := changes[i].FileInfo if afi.Size() != efi.Size() { - return errors.Errorf("Unexpected change size %d, %q has size %d", afi.Size(), filename, efi.Size()) + return fmt.Errorf("Unexpected change size %d, %q has size %d", afi.Size(), filename, efi.Size()) } if afi.Mode() != efi.Mode() { - return errors.Errorf("Unexpected change mode %s, %q has mode %s", afi.Mode(), filename, efi.Mode()) + return fmt.Errorf("Unexpected change mode %s, %q has mode %s", afi.Mode(), filename, efi.Mode()) } if afi.ModTime() != efi.ModTime() { - return errors.Errorf("Unexpected change modtime %s, %q has modtime %s", afi.ModTime(), filename, efi.ModTime()) + return fmt.Errorf("Unexpected change modtime %s, %q has modtime %s", afi.ModTime(), filename, efi.ModTime()) } if expected := filepath.Join(root, changes[i].Path); changes[i].Source != expected { - return errors.Errorf("Unexpected source path %s, expected %s", changes[i].Source, expected) + return fmt.Errorf("Unexpected source path %s, expected %s", changes[i].Source, expected) } } } @@ -417,7 +416,7 @@ func collectChanges(a, b string) ([]TestChange, error) { return nil }) if err != nil { - return nil, errors.Wrap(err, "failed to compute changes") + return nil, fmt.Errorf("failed to compute changes: %w", err) } return changes, nil diff --git a/fs/diff_unix.go b/fs/diff_unix.go index 7913af27..5de9b6b4 100644 --- a/fs/diff_unix.go +++ b/fs/diff_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* @@ -20,11 +21,11 @@ package fs import ( "bytes" + "fmt" "os" "syscall" "github.com/containerd/continuity/sysx" - "github.com/pkg/errors" ) // detectDirDiff returns diff dir options if a directory could @@ -56,11 +57,11 @@ func compareSysStat(s1, s2 interface{}) (bool, error) { func compareCapabilities(p1, p2 string) (bool, error) { c1, err := sysx.LGetxattr(p1, "security.capability") if err != nil && err != sysx.ENODATA { - return false, errors.Wrapf(err, "failed to get xattr for %s", p1) + return false, fmt.Errorf("failed to get xattr for %s: %w", p1, err) } c2, err := sysx.LGetxattr(p2, "security.capability") if err != nil && err != sysx.ENODATA { - return false, errors.Wrapf(err, "failed to get xattr for %s", p2) + return false, fmt.Errorf("failed to get xattr for %s: %w", p2, err) } return bytes.Equal(c1, c2), nil } diff --git a/fs/dtype_linux.go b/fs/dtype_linux.go index 10510d8d..ddd6c793 100644 --- a/fs/dtype_linux.go +++ b/fs/dtype_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux /* diff --git a/fs/dtype_linux_test.go b/fs/dtype_linux_test.go index 403b185d..61c3b694 100644 --- a/fs/dtype_linux_test.go +++ b/fs/dtype_linux_test.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux /* diff --git a/fs/du_cmd_freebsd_test.go b/fs/du_cmd_freebsddarwin_test.go similarity index 95% rename from fs/du_cmd_freebsd_test.go rename to fs/du_cmd_freebsddarwin_test.go index 6b2dcc3b..ecbec9fc 100644 --- a/fs/du_cmd_freebsd_test.go +++ b/fs/du_cmd_freebsddarwin_test.go @@ -1,4 +1,5 @@ -// +build freebsd +//go:build freebsd || darwin +// +build freebsd darwin /* Copyright The containerd Authors. diff --git a/fs/du_cmd_unix_test.go b/fs/du_cmd_unix_test.go index bf0b1ad0..28760a98 100644 --- a/fs/du_cmd_unix_test.go +++ b/fs/du_cmd_unix_test.go @@ -1,4 +1,5 @@ -// +build !windows,!freebsd +//go:build !windows && !freebsd && !darwin +// +build !windows,!freebsd,!darwin /* Copyright The containerd Authors. diff --git a/fs/du_test.go b/fs/du_test.go index 33c9b632..7b1e8c1b 100644 --- a/fs/du_test.go +++ b/fs/du_test.go @@ -18,6 +18,7 @@ package fs import ( "context" + "errors" "io" "io/ioutil" "math/rand" @@ -27,7 +28,6 @@ import ( "testing" "github.com/containerd/continuity/fs/fstest" - "github.com/pkg/errors" ) var errNotImplemented = errors.New("check not implemented") diff --git a/fs/du_unix.go b/fs/du_unix.go index 9da43d1b..bf33c42d 100644 --- a/fs/du_unix.go +++ b/fs/du_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* @@ -41,10 +42,8 @@ type inode struct { func newInode(stat *syscall.Stat_t) inode { return inode{ - // Dev is uint32 on darwin/bsd, uint64 on linux/solaris/freebsd - dev: uint64(stat.Dev), // nolint: unconvert - // Ino is uint32 on bsd, uint64 on darwin/linux/solaris/freebsd - ino: uint64(stat.Ino), // nolint: unconvert + dev: uint64(stat.Dev), //nolint: unconvert // dev is uint32 on darwin/bsd, uint64 on linux/solaris/freebsd + ino: uint64(stat.Ino), //nolint: unconvert // ino is uint32 on bsd, uint64 on darwin/linux/solaris/freebsd } } diff --git a/fs/du_unix_test.go b/fs/du_unix_test.go index e0f19f05..e2d293c2 100644 --- a/fs/du_unix_test.go +++ b/fs/du_unix_test.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* @@ -19,13 +20,13 @@ package fs import ( + "errors" + "fmt" "io/ioutil" "os" "strconv" "strings" "syscall" - - "github.com/pkg/errors" ) func getBsize(root string) (int64, error) { @@ -34,7 +35,7 @@ func getBsize(root string) (int64, error) { return 0, err } - return int64(s.Bsize), nil // nolint: unconvert + return int64(s.Bsize), nil //nolint: unconvert } // getTmpAlign returns filesystem specific size alignment functions @@ -43,13 +44,13 @@ func getBsize(root string) (int64, error) { func getTmpAlign() (func(int64) int64, func(int64) int64, error) { t1, err := ioutil.TempDir("", "compute-align-") if err != nil { - return nil, nil, errors.Wrap(err, "failed to create temp dir") + return nil, nil, fmt.Errorf("failed to create temp dir: %w", err) } defer os.RemoveAll(t1) bsize, err := getBsize(t1) if err != nil { - return nil, nil, errors.Wrap(err, "failed to get bsize") + return nil, nil, fmt.Errorf("failed to get bsize: %w", err) } align := func(size int64) int64 { @@ -66,7 +67,7 @@ func getTmpAlign() (func(int64) int64, func(int64) int64, error) { fi, err := os.Stat(t1) if err != nil { - return nil, nil, errors.Wrap(err, "failed to stat directory") + return nil, nil, fmt.Errorf("failed to stat directory: %w", err) } dirSize := fi.Sys().(*syscall.Stat_t).Blocks * blocksUnitSize @@ -92,6 +93,6 @@ func duCheck(root string) (usage int64, err error) { if err != nil { return 0, err } - return blocks * blocksUnitSize, nil + return blocks * blocksUnitSize, nil } diff --git a/fs/du_windows.go b/fs/du_windows.go index 8f25ec59..08fb2833 100644 --- a/fs/du_windows.go +++ b/fs/du_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows /* diff --git a/fs/fstest/compare.go b/fs/fstest/compare.go index 0d100b62..5ae167e5 100644 --- a/fs/fstest/compare.go +++ b/fs/fstest/compare.go @@ -17,11 +17,11 @@ package fstest import ( + "fmt" "io/ioutil" "os" "github.com/containerd/continuity" - "github.com/pkg/errors" ) // CheckDirectoryEqual compares two directory paths to make sure that @@ -29,27 +29,27 @@ import ( func CheckDirectoryEqual(d1, d2 string) error { c1, err := continuity.NewContext(d1) if err != nil { - return errors.Wrap(err, "failed to build context") + return fmt.Errorf("failed to build context: %w", err) } c2, err := continuity.NewContext(d2) if err != nil { - return errors.Wrap(err, "failed to build context") + return fmt.Errorf("failed to build context: %w", err) } m1, err := continuity.BuildManifest(c1) if err != nil { - return errors.Wrap(err, "failed to build manifest") + return fmt.Errorf("failed to build manifest: %w", err) } m2, err := continuity.BuildManifest(c2) if err != nil { - return errors.Wrap(err, "failed to build manifest") + return fmt.Errorf("failed to build manifest: %w", err) } diff := diffResourceList(m1.Resources, m2.Resources) if diff.HasDiff() { - return errors.Errorf("directory diff between %s and %s\n%s", d1, d2, diff.String()) + return fmt.Errorf("directory diff between %s and %s\n%s", d1, d2, diff.String()) } return nil diff --git a/fs/fstest/compare_unix.go b/fs/fstest/compare_unix.go index 21dcafd0..3cdb9963 100644 --- a/fs/fstest/compare_unix.go +++ b/fs/fstest/compare_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* diff --git a/fs/fstest/file_unix.go b/fs/fstest/file_unix.go index 9451198b..b3ea0931 100644 --- a/fs/fstest/file_unix.go +++ b/fs/fstest/file_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* diff --git a/fs/fstest/file_windows.go b/fs/fstest/file_windows.go index 1fab035b..45fd9f61 100644 --- a/fs/fstest/file_windows.go +++ b/fs/fstest/file_windows.go @@ -17,9 +17,8 @@ package fstest import ( + "errors" "time" - - "github.com/pkg/errors" ) // Lchtimes changes access and mod time of file without following symlink diff --git a/fs/hardlink_unix.go b/fs/hardlink_unix.go index f95f0904..cce8902f 100644 --- a/fs/hardlink_unix.go +++ b/fs/hardlink_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* @@ -29,6 +30,5 @@ func getLinkInfo(fi os.FileInfo) (uint64, bool) { return 0, false } - // Ino is uint32 on bsd, uint64 on darwin/linux/solaris - return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1 // nolint: unconvert + return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1 //nolint: unconvert // ino is uint32 on bsd, uint64 on darwin/linux/solaris } diff --git a/fs/path.go b/fs/path.go index c26be798..97313e2b 100644 --- a/fs/path.go +++ b/fs/path.go @@ -19,11 +19,10 @@ package fs import ( "bytes" "context" + "errors" "io" "os" "path/filepath" - - "github.com/pkg/errors" ) var ( diff --git a/fs/path_test.go b/fs/path_test.go index 84f22ebd..04ccc84d 100644 --- a/fs/path_test.go +++ b/fs/path_test.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* @@ -19,13 +20,13 @@ package fs import ( + "errors" "io/ioutil" "os" "path/filepath" "testing" "github.com/containerd/continuity/fs/fstest" - "github.com/pkg/errors" ) type RootCheck struct { @@ -287,7 +288,7 @@ func makeRootPathTest(t *testing.T, apply fstest.Applier, checks []RootCheck) fu if err == nil { t.Errorf("(Check %d) Expected error %q, %q evaluated as %q", i+1, check.cause.Error(), check.unresolved, actual) } - if errors.Cause(err) != check.cause { + if !errors.Is(err, check.cause) { t.Fatalf("(Check %d) Failed to evaluate root path: %+v", i+1, err) } } else { diff --git a/fs/stat_linuxopenbsd.go b/fs/stat_atim.go similarity index 85% rename from fs/stat_linuxopenbsd.go rename to fs/stat_atim.go index c68df6e5..996b9c1a 100644 --- a/fs/stat_linuxopenbsd.go +++ b/fs/stat_atim.go @@ -1,4 +1,5 @@ -// +build linux openbsd +//go:build linux || openbsd || solaris +// +build linux openbsd solaris /* Copyright The containerd Authors. @@ -40,6 +41,5 @@ func StatMtime(st *syscall.Stat_t) syscall.Timespec { // StatATimeAsTime returns st.Atim as a time.Time func StatATimeAsTime(st *syscall.Stat_t) time.Time { - // The int64 conversions ensure the line compiles for 32-bit systems as well. - return time.Unix(int64(st.Atim.Sec), int64(st.Atim.Nsec)) // nolint: unconvert + return time.Unix(st.Atim.Unix()) } diff --git a/fs/stat_darwinfreebsd.go b/fs/stat_darwinbsd.go similarity index 90% rename from fs/stat_darwinfreebsd.go rename to fs/stat_darwinbsd.go index cb7400a3..dbdb90ec 100644 --- a/fs/stat_darwinfreebsd.go +++ b/fs/stat_darwinbsd.go @@ -1,4 +1,5 @@ -// +build darwin freebsd +//go:build darwin || freebsd || netbsd +// +build darwin freebsd netbsd /* Copyright The containerd Authors. @@ -40,5 +41,5 @@ func StatMtime(st *syscall.Stat_t) syscall.Timespec { // StatATimeAsTime returns the access time as a time.Time func StatATimeAsTime(st *syscall.Stat_t) time.Time { - return time.Unix(int64(st.Atimespec.Sec), int64(st.Atimespec.Nsec)) // nolint: unconvert + return time.Unix(st.Atimespec.Unix()) } diff --git a/fs/utimesnanoat.go b/fs/utimesnanoat.go new file mode 100644 index 00000000..5435398d --- /dev/null +++ b/fs/utimesnanoat.go @@ -0,0 +1,33 @@ +//go:build !(windows || linux) +// +build !windows,!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 ( + "syscall" + + "golang.org/x/sys/unix" +) + +func utimesNano(name string, atime, mtime syscall.Timespec) error { + at := unix.NsecToTimespec(atime.Nano()) + mt := unix.NsecToTimespec(mtime.Nano()) + utimes := [2]unix.Timespec{at, mt} + return unix.UtimesNanoAt(unix.AT_FDCWD, name, utimes[0:], unix.AT_SYMLINK_NOFOLLOW) +} diff --git a/go.mod b/go.mod index 35cea6ae..25d9f2a2 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,13 @@ module github.com/containerd/continuity go 1.13 require ( - bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898 + // 5883e5a4b512fe2e32f915b1c66a1ddfef81cb3f is the last version to support macOS + // see https://github.com/bazil/fuse/commit/60eaf8f021ce00e5c52529cdcba1067e13c1c2c2 + bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 + github.com/Microsoft/go-winio v0.5.1 github.com/dustin/go-humanize v1.0.0 github.com/golang/protobuf v1.3.5 github.com/opencontainers/go-digest v1.0.0 - github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.7.0 github.com/spf13/cobra v1.0.0 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a diff --git a/go.sum b/go.sum index a99faabd..2c279250 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,9 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898 h1:SC+c6A1qTFstO9qmB86mPV2IpYme/2ZoEQ0hrP+wo+Q= -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 h1:SRsZGA7aFnCZETmov57jwPrWuTmaZK6+4R4v5FUe1/c= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -65,7 +67,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -98,6 +99,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -113,7 +116,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -127,6 +129,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/hardlinks_unix.go b/hardlinks_unix.go index 7105a7cf..a1fafb0a 100644 --- a/hardlinks_unix.go +++ b/hardlinks_unix.go @@ -1,4 +1,5 @@ -// +build linux darwin freebsd solaris +//go:build !windows +// +build !windows /* Copyright The containerd Authors. diff --git a/manifest.go b/manifest.go index 299fbcce..8e83317e 100644 --- a/manifest.go +++ b/manifest.go @@ -19,7 +19,6 @@ package continuity import ( "fmt" "io" - "log" "os" "sort" @@ -75,7 +74,7 @@ func MarshalText(w io.Writer, m *Manifest) error { // BuildManifest creates the manifest for the given context func BuildManifest(ctx Context) (*Manifest, error) { resourcesByPath := map[string]Resource{} - hardlinks := newHardlinkManager() + hardLinks := newHardlinkManager() if err := ctx.Walk(func(p string, fi os.FileInfo, err error) error { if err != nil { @@ -92,12 +91,11 @@ func BuildManifest(ctx Context) (*Manifest, error) { if err == ErrNotFound { return nil } - log.Printf("error getting resource %q: %v", p, err) - return err + return fmt.Errorf("failed to get resource %q: %w", p, err) } // add to the hardlink manager - if err := hardlinks.Add(fi, resource); err == nil { + if err := hardLinks.Add(fi, resource); err == nil { // Resource has been accepted by hardlink manager so we don't add // it to the resourcesByPath until we merge at the end. return nil @@ -114,14 +112,12 @@ func BuildManifest(ctx Context) (*Manifest, error) { } // merge and post-process the hardlinks. - // nolint:misspell - hardlinked, err := hardlinks.Merge() + hardLinked, err := hardLinks.Merge() if err != nil { return nil, err } - // nolint:misspell - for _, resource := range hardlinked { + for _, resource := range hardLinked { resourcesByPath[resource.Path()] = resource } diff --git a/manifest_test.go b/manifest_test.go index 72e64b51..0d7fdbc5 100644 --- a/manifest_test.go +++ b/manifest_test.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* diff --git a/manifest_test_darwin.go b/manifest_test_darwin.go index 5ece3a30..49fbdfdf 100644 --- a/manifest_test_darwin.go +++ b/manifest_test_darwin.go @@ -1,3 +1,4 @@ +//go:build ignore // +build ignore /* diff --git a/resource_unix.go b/resource_unix.go index 0e103ccc..eaf7c1da 100644 --- a/resource_unix.go +++ b/resource_unix.go @@ -1,4 +1,5 @@ -// +build linux darwin freebsd solaris +//go:build !windows +// +build !windows /* Copyright The containerd Authors. diff --git a/sysx/nodata_unix.go b/sysx/nodata_unix.go index de4b3d50..e78f77f6 100644 --- a/sysx/nodata_unix.go +++ b/sysx/nodata_unix.go @@ -1,4 +1,5 @@ -// +build darwin freebsd openbsd +//go:build !(linux || solaris || windows) +// +build !linux,!solaris,!windows /* Copyright The containerd Authors. diff --git a/sysx/xattr.go b/sysx/xattr.go index db6fe70f..14973985 100644 --- a/sysx/xattr.go +++ b/sysx/xattr.go @@ -1,3 +1,4 @@ +//go:build linux || darwin // +build linux darwin /* diff --git a/sysx/xattr_unsupported.go b/sysx/xattr_unsupported.go index f8fa8c63..da1e940d 100644 --- a/sysx/xattr_unsupported.go +++ b/sysx/xattr_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux && !darwin // +build !linux,!darwin /* diff --git a/testutil/helpers_unix.go b/testutil/helpers_unix.go index 35568a42..dac3657f 100644 --- a/testutil/helpers_unix.go +++ b/testutil/helpers_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* diff --git a/testutil/loopback/loopback_linux.go b/testutil/loopback/loopback_linux.go index c1750047..a43a70e7 100644 --- a/testutil/loopback/loopback_linux.go +++ b/testutil/loopback/loopback_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux /* @@ -19,13 +20,15 @@ package loopback import ( + "bytes" + "errors" + "fmt" "io/ioutil" "os" "os/exec" "strings" "syscall" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -34,34 +37,35 @@ func New(size int64) (*Loopback, error) { // create temporary file for the disk image file, err := ioutil.TempFile("", "containerd-test-loopback") if err != nil { - return nil, errors.Wrap(err, "could not create temporary file for loopback") + return nil, fmt.Errorf("could not create temporary file for loopback: %w", err) } if err := file.Truncate(size); err != nil { file.Close() os.Remove(file.Name()) - return nil, errors.Wrap(err, "failed to resize temp file") + return nil, fmt.Errorf("failed to resize temp file: %w", err) } file.Close() // create device losetup := exec.Command("losetup", "--find", "--show", file.Name()) - p, err := losetup.Output() - if err != nil { + var stdout, stderr bytes.Buffer + losetup.Stdout = &stdout + losetup.Stderr = &stderr + if err := losetup.Run(); err != nil { os.Remove(file.Name()) - return nil, errors.Wrap(err, "loopback setup failed") + return nil, fmt.Errorf("loopback setup failed (%v): stdout=%q, stderr=%q: %w", losetup.Args, stdout.String(), stderr.String(), err) } - deviceName := strings.TrimSpace(string(p)) + deviceName := strings.TrimSpace(stdout.String()) logrus.Debugf("Created loop device %s (using %s)", deviceName, file.Name()) cleanup := func() error { // detach device logrus.Debugf("Removing loop device %s", deviceName) losetup := exec.Command("losetup", "--detach", deviceName) - err := losetup.Run() - if err != nil { - return errors.Wrapf(err, "Could not remove loop device %s", deviceName) + 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) } // remove file diff --git a/testutil/mount_other.go b/testutil/mount_other.go index 0c7fde57..3ba487ac 100644 --- a/testutil/mount_other.go +++ b/testutil/mount_other.go @@ -1,3 +1,4 @@ +//go:build !linux && !windows // +build !linux,!windows /* diff --git a/vendor/bazil.org/fuse/LICENSE b/vendor/bazil.org/fuse/LICENSE index 4ac7cd83..70840eeb 100644 --- a/vendor/bazil.org/fuse/LICENSE +++ b/vendor/bazil.org/fuse/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2015 Tommi Virtanen. +Copyright (c) 2013-2019 Tommi Virtanen. Copyright (c) 2009, 2011, 2012 The Go Authors. All rights reserved. diff --git a/vendor/bazil.org/fuse/fs/serve.go b/vendor/bazil.org/fuse/fs/serve.go index e9fc5659..b754e3f9 100644 --- a/vendor/bazil.org/fuse/fs/serve.go +++ b/vendor/bazil.org/fuse/fs/serve.go @@ -3,6 +3,8 @@ package fs // import "bazil.org/fuse/fs" import ( + "bytes" + "context" "encoding/binary" "fmt" "hash/fnv" @@ -12,14 +14,9 @@ import ( "runtime" "strings" "sync" + "syscall" "time" - "golang.org/x/net/context" -) - -import ( - "bytes" - "bazil.org/fuse" "bazil.org/fuse/fuseutil" ) @@ -71,6 +68,9 @@ type FSInodeGenerator interface { // // Implementing this is useful to e.g. constrain the range of // inode values used for dynamic inodes. + // + // Non-zero return values should be greater than 1, as that is + // always used for the root inode. GenerateInode(parentInode uint64, name string) uint64 } @@ -205,7 +205,7 @@ type NodeForgetter interface { // method calls. // // Forget is not necessarily seen on unmount, as all nodes are - // implicitly forgotten as part part of the unmount. + // implicitly forgotten as part of the unmount. Forget() } @@ -435,8 +435,6 @@ func Serve(c *fuse.Conn, fs FS) error { return server.Serve(fs) } -type nothing struct{} - type serveRequest struct { Request fuse.Request cancel func() @@ -470,7 +468,6 @@ func (sn *serveNode) attr(ctx context.Context, attr *fuse.Attr) error { type serveHandle struct { handle Handle readData []byte - nodeID fuse.NodeID } // NodeRef is deprecated. It remains here to decrease code churn on @@ -504,9 +501,9 @@ func (c *Server) saveNode(inode uint64, node Node) (id fuse.NodeID, gen uint64) return id, sn.generation } -func (c *Server) saveHandle(handle Handle, nodeID fuse.NodeID) (id fuse.HandleID) { +func (c *Server) saveHandle(handle Handle) (id fuse.HandleID) { c.meta.Lock() - shandle := &serveHandle{handle: handle, nodeID: nodeID} + shandle := &serveHandle{handle: handle} if n := len(c.freeHandle); n > 0 { id = c.freeHandle[n-1] c.freeHandle = c.freeHandle[:n-1] @@ -759,7 +756,7 @@ func (e handleNotReaderError) Error() string { var _ fuse.ErrorNumber = handleNotReaderError{} func (e handleNotReaderError) Errno() fuse.Errno { - return fuse.ENOTSUP + return fuse.Errno(syscall.ENOTSUP) } func initLookupResponse(s *fuse.LookupResponse) { @@ -791,10 +788,11 @@ func (c *Server) serve(r fuse.Request) { } if snode == nil { c.meta.Unlock() + err := syscall.ESTALE c.debug(response{ Op: opName(r), Request: logResponseHeader{ID: hdr.ID}, - Error: fuse.ESTALE.ErrnoName(), + Error: fuse.Errno(err).ErrnoName(), // this is the only place that sets both Error and // Out; not sure if i want to do that; might get rid // of len(c.node) things altogether @@ -802,7 +800,7 @@ func (c *Server) serve(r fuse.Request) { MaxNode: fuse.NodeID(len(c.node)), }, }) - r.RespondError(fuse.ESTALE) + r.RespondError(err) return } node = snode.node @@ -827,17 +825,12 @@ func (c *Server) serve(r fuse.Request) { Request: logResponseHeader{ID: hdr.ID}, } if err, ok := resp.(error); ok { - msg.Error = err.Error() - if ferr, ok := err.(fuse.ErrorNumber); ok { - errno := ferr.Errno() - msg.Errno = errno.ErrnoName() - if errno == err { - // it's just a fuse.Errno with no extra detail; - // skip the textual message for log readability - msg.Error = "" - } - } else { - msg.Errno = fuse.DefaultErrno.ErrnoName() + errno := fuse.ToErrno(err) + msg.Errno = errno.ErrnoName() + if errno != err && syscall.Errno(errno) != err { + // if it's more than just a fuse.Errno or a + // syscall.Errno, log extra detail + msg.Error = err.Error() } } else { msg.Out = resp @@ -890,7 +883,7 @@ func (c *Server) serve(r fuse.Request) { // // Decent write-up on role of EINTR: // http://250bpm.com/blog:12 - err = fuse.EINTR + err = syscall.EINTR default: // nothing } @@ -910,7 +903,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, // Note: To FUSE, ENOSYS means "this server never implements this request." // It would be inappropriate to return ENOSYS for other operations in this // switch that might only be unavailable in some contexts, not all. - return fuse.ENOSYS + return syscall.ENOSYS case *fuse.StatfsRequest: s := &fuse.StatfsResponse{} @@ -959,7 +952,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, initLookupResponse(&s.LookupResponse) n, ok := node.(NodeSymlinker) if !ok { - return fuse.EIO // XXX or EPERM like Mkdir? + return syscall.EIO // XXX or EPERM like Mkdir? } n2, err := n.Symlink(ctx, r) if err != nil { @@ -975,7 +968,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.ReadlinkRequest: n, ok := node.(NodeReadlinker) if !ok { - return fuse.EIO /// XXX or EPERM? + return syscall.EIO /// XXX or EPERM? } target, err := n.Readlink(ctx, r) if err != nil { @@ -988,7 +981,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.LinkRequest: n, ok := node.(NodeLinker) if !ok { - return fuse.EIO /// XXX or EPERM? + return syscall.EIO /// XXX or EPERM? } c.meta.Lock() var oldNode *serveNode @@ -1001,7 +994,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, Request: r.Hdr(), In: r, }) - return fuse.EIO + return syscall.EIO } n2, err := n.Link(ctx, r, oldNode.node) if err != nil { @@ -1019,7 +1012,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.RemoveRequest: n, ok := node.(NodeRemover) if !ok { - return fuse.EIO /// XXX or EPERM? + return syscall.EIO /// XXX or EPERM? } err := n.Remove(ctx, r) if err != nil { @@ -1049,7 +1042,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, } else if n, ok := node.(NodeRequestLookuper); ok { n2, err = n.Lookup(ctx, r, s) } else { - return fuse.ENOENT + return syscall.ENOENT } if err != nil { return err @@ -1066,7 +1059,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, initLookupResponse(&s.LookupResponse) n, ok := node.(NodeMkdirer) if !ok { - return fuse.EPERM + return syscall.EPERM } n2, err := n.Mkdir(ctx, r) if err != nil { @@ -1091,7 +1084,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, } else { h2 = node } - s.Handle = c.saveHandle(h2, r.Hdr().Node) + s.Handle = c.saveHandle(h2) done(s) r.Respond(s) return nil @@ -1100,7 +1093,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, n, ok := node.(NodeCreater) if !ok { // If we send back ENOSYS, FUSE will try mknod+open. - return fuse.EPERM + return syscall.EPERM } s := &fuse.CreateResponse{OpenResponse: fuse.OpenResponse{}} initLookupResponse(&s.LookupResponse) @@ -1111,7 +1104,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, if err := c.saveLookup(ctx, &s.LookupResponse, snode, r.Name, n2); err != nil { return err } - s.Handle = c.saveHandle(h2, r.Hdr().Node) + s.Handle = c.saveHandle(h2) done(s) r.Respond(s) return nil @@ -1119,7 +1112,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.GetxattrRequest: n, ok := node.(NodeGetxattrer) if !ok { - return fuse.ENOTSUP + return syscall.ENOTSUP } s := &fuse.GetxattrResponse{} err := n.Getxattr(ctx, r, s) @@ -1127,7 +1120,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, return err } if r.Size != 0 && uint64(len(s.Xattr)) > uint64(r.Size) { - return fuse.ERANGE + return syscall.ERANGE } done(s) r.Respond(s) @@ -1136,7 +1129,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.ListxattrRequest: n, ok := node.(NodeListxattrer) if !ok { - return fuse.ENOTSUP + return syscall.ENOTSUP } s := &fuse.ListxattrResponse{} err := n.Listxattr(ctx, r, s) @@ -1144,7 +1137,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, return err } if r.Size != 0 && uint64(len(s.Xattr)) > uint64(r.Size) { - return fuse.ERANGE + return syscall.ERANGE } done(s) r.Respond(s) @@ -1153,7 +1146,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.SetxattrRequest: n, ok := node.(NodeSetxattrer) if !ok { - return fuse.ENOTSUP + return syscall.ENOTSUP } err := n.Setxattr(ctx, r) if err != nil { @@ -1166,7 +1159,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.RemovexattrRequest: n, ok := node.(NodeRemovexattrer) if !ok { - return fuse.ENOTSUP + return syscall.ENOTSUP } err := n.Removexattr(ctx, r) if err != nil { @@ -1192,7 +1185,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.ReadRequest: shandle := c.getHandle(r.Handle) if shandle == nil { - return fuse.ESTALE + return syscall.ESTALE } handle := shandle.handle @@ -1257,7 +1250,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.WriteRequest: shandle := c.getHandle(r.Handle) if shandle == nil { - return fuse.ESTALE + return syscall.ESTALE } s := &fuse.WriteResponse{} @@ -1269,12 +1262,12 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, r.Respond(s) return nil } - return fuse.EIO + return syscall.EIO case *fuse.FlushRequest: shandle := c.getHandle(r.Handle) if shandle == nil { - return fuse.ESTALE + return syscall.ESTALE } handle := shandle.handle @@ -1290,7 +1283,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.ReleaseRequest: shandle := c.getHandle(r.Handle) if shandle == nil { - return fuse.ESTALE + return syscall.ESTALE } handle := shandle.handle @@ -1326,11 +1319,11 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, Request: r.Hdr(), In: r, }) - return fuse.EIO + return syscall.EIO } n, ok := node.(NodeRenamer) if !ok { - return fuse.EIO // XXX or EPERM like Mkdir? + return syscall.EIO // XXX or EPERM like Mkdir? } err := n.Rename(ctx, r, newDirNode.node) if err != nil { @@ -1343,7 +1336,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.MknodRequest: n, ok := node.(NodeMknoder) if !ok { - return fuse.EIO + return syscall.EIO } n2, err := n.Mknod(ctx, r) if err != nil { @@ -1361,7 +1354,7 @@ func (c *Server) handleRequest(ctx context.Context, node Node, snode *serveNode, case *fuse.FsyncRequest: n, ok := node.(NodeFsyncer) if !ok { - return fuse.EIO + return syscall.EIO } err := n.Fsync(ctx, r) if err != nil { @@ -1557,11 +1550,12 @@ func GenerateDynamicInode(parent uint64, name string) uint64 { var inode uint64 for { inode = h.Sum64() - if inode != 0 { + if inode > 1 { break } - // there's a tiny probability that result is zero; change the - // input a little and try again + // there's a tiny probability that result is zero or the + // hardcoded root inode 1; change the input a little and try + // again _, _ = h.Write([]byte{'x'}) } return inode diff --git a/vendor/bazil.org/fuse/fs/tree.go b/vendor/bazil.org/fuse/fs/tree.go index 7e078045..329be138 100644 --- a/vendor/bazil.org/fuse/fs/tree.go +++ b/vendor/bazil.org/fuse/fs/tree.go @@ -3,14 +3,12 @@ package fs import ( + "context" "os" pathpkg "path" "strings" + "syscall" - "golang.org/x/net/context" -) - -import ( "bazil.org/fuse" ) @@ -87,7 +85,7 @@ func (t *tree) Lookup(ctx context.Context, name string) (Node, error) { if n != nil { return n, nil } - return nil, fuse.ENOENT + return nil, syscall.ENOENT } func (t *tree) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { diff --git a/vendor/bazil.org/fuse/fuse.go b/vendor/bazil.org/fuse/fuse.go index 6db0ef29..b774a25c 100644 --- a/vendor/bazil.org/fuse/fuse.go +++ b/vendor/bazil.org/fuse/fuse.go @@ -79,7 +79,7 @@ // is cancelled and no longer needed, the context will be cancelled. // Blocking operations should select on a receive from ctx.Done() and attempt to // abort the operation early if the receive succeeds (meaning the channel is closed). -// To indicate that the operation failed because it was aborted, return fuse.EINTR. +// To indicate that the operation failed because it was aborted, return syscall.EINTR. // // If an operation does not block for an indefinite amount of time, supporting // cancellation is not necessary. @@ -90,8 +90,8 @@ // inspect req.Pid, req.Uid, and req.Gid as necessary to implement // permission checking. The kernel FUSE layer normally prevents other // users from accessing the FUSE file system (to change this, see -// AllowOther, AllowRoot), but does not enforce access modes (to -// change this, see DefaultPermissions). +// AllowOther), but does not enforce access modes (to change this, see +// DefaultPermissions). // // Mount Options // @@ -323,6 +323,8 @@ type ErrorNumber interface { Errno() Errno } +// Deprecated: Return a syscall.Errno directly. See ToErrno for exact +// rules. const ( // ENOSYS indicates that the call is not supported. ENOSYS = Errno(syscall.ENOSYS) @@ -348,13 +350,14 @@ const ( const DefaultErrno = EIO var errnoNames = map[Errno]string{ - ENOSYS: "ENOSYS", - ESTALE: "ESTALE", - ENOENT: "ENOENT", - EIO: "EIO", - EPERM: "EPERM", - EINTR: "EINTR", - EEXIST: "EEXIST", + ENOSYS: "ENOSYS", + ESTALE: "ESTALE", + ENOENT: "ENOENT", + EIO: "EIO", + EPERM: "EPERM", + EINTR: "EINTR", + EEXIST: "EEXIST", + Errno(syscall.ENAMETOOLONG): "ENAMETOOLONG", } // Errno implements Error and ErrorNumber using a syscall.Errno. @@ -390,11 +393,28 @@ func (e Errno) MarshalText() ([]byte, error) { return []byte(s), nil } -func (h *Header) RespondError(err error) { - errno := DefaultErrno - if ferr, ok := err.(ErrorNumber); ok { - errno = ferr.Errno() +// ToErrno converts arbitrary errors to Errno. +// +// If the underlying type of err is syscall.Errno, it is used +// directly. No unwrapping is done, to prevent wrong errors from +// leaking via e.g. *os.PathError. +// +// If err unwraps to implement ErrorNumber, that is used. +// +// Finally, returns DefaultErrno. +func ToErrno(err error) Errno { + if err, ok := err.(syscall.Errno); ok { + return Errno(err) } + var errnum ErrorNumber + if errors.As(err, &errnum) { + return Errno(errnum.Errno()) + } + return DefaultErrno +} + +func (h *Header) RespondError(err error) { + errno := ToErrno(err) // FUSE uses negative errors! // TODO: File bug report against OSXFUSE: positive error causes kernel panic. buf := newBuffer(0) @@ -495,9 +515,15 @@ func fileMode(unixMode uint32) os.FileMode { mode |= os.ModeSymlink case syscall.S_IFSOCK: mode |= os.ModeSocket + case 0: + // apparently there's plenty of times when the FUSE request + // does not contain the file type + mode |= os.ModeIrregular default: - // no idea - mode |= os.ModeDevice + // not just unavailable in the kernel codepath; known to + // kernel but unrecognized by us + Debug(fmt.Sprintf("unrecognized file mode type: %04o", unixMode)) + mode |= os.ModeIrregular } if unixMode&syscall.S_ISUID != 0 { mode |= os.ModeSetuid @@ -1004,7 +1030,12 @@ loop: } case opBmap: - panic("opBmap") + // bmap asks to map a byte offset within a file to a single + // uint64. On Linux, it triggers only with blkdev fuse mounts, + // that claim to be backed by an actual block device. FreeBSD + // seems to send it for just any fuse mount, whether there's a + // block device involved or not. + goto unrecognized case opDestroy: req = &DestroyRequest{ @@ -1262,6 +1293,7 @@ func (r *StatfsRequest) Respond(resp *StatfsResponse) { Bfree: resp.Bfree, Bavail: resp.Bavail, Files: resp.Files, + Ffree: resp.Ffree, Bsize: resp.Bsize, Namelen: resp.Namelen, Frsize: resp.Frsize, @@ -1383,8 +1415,6 @@ func (a *Attr) attr(out *attr, proto Protocol) { if proto.GE(Protocol{7, 9}) { out.Blksize = a.BlockSize } - - return } // A GetattrRequest asks for the metadata for the file denoted by r.Node. @@ -1463,7 +1493,7 @@ type GetxattrResponse struct { } func (r *GetxattrResponse) String() string { - return fmt.Sprintf("Getxattr %x", r.Xattr) + return fmt.Sprintf("Getxattr %q", r.Xattr) } // A ListxattrRequest asks to list the extended attributes associated with r.Node. @@ -1499,7 +1529,7 @@ type ListxattrResponse struct { } func (r *ListxattrResponse) String() string { - return fmt.Sprintf("Listxattr %x", r.Xattr) + return fmt.Sprintf("Listxattr %q", r.Xattr) } // Append adds an extended attribute name to the response. @@ -1564,7 +1594,7 @@ func trunc(b []byte, max int) ([]byte, string) { func (r *SetxattrRequest) String() string { xattr, tail := trunc(r.Xattr, 16) - return fmt.Sprintf("Setxattr [%s] %q %x%s fl=%v @%#x", &r.Header, r.Name, xattr, tail, r.Flags, r.Position) + return fmt.Sprintf("Setxattr [%s] %q %q%s fl=%v @%#x", &r.Header, r.Name, xattr, tail, r.Flags, r.Position) } // Respond replies to the request, indicating that the extended attribute was set. @@ -1985,9 +2015,14 @@ type SetattrRequest struct { Size uint64 Atime time.Time Mtime time.Time - Mode os.FileMode - Uid uint32 - Gid uint32 + // Mode is the file mode to set (when valid). + // + // The type of the node (as in os.ModeType, os.ModeDir etc) is not + // guaranteed to be sent by the kernel, in which case + // os.ModeIrregular will be set. + Mode os.FileMode + Uid uint32 + Gid uint32 // OS X only Bkuptime time.Time diff --git a/vendor/bazil.org/fuse/fuse_kernel.go b/vendor/bazil.org/fuse/fuse_kernel.go index 87c5ca1d..416d32aa 100644 --- a/vendor/bazil.org/fuse/fuse_kernel.go +++ b/vendor/bazil.org/fuse/fuse_kernel.go @@ -232,7 +232,7 @@ type OpenResponseFlags uint32 const ( OpenDirectIO OpenResponseFlags = 1 << 0 // bypass page cache for this open file OpenKeepCache OpenResponseFlags = 1 << 1 // don't invalidate the data cache on open - OpenNonSeekable OpenResponseFlags = 1 << 2 // mark the file as non-seekable (not supported on OS X) + OpenNonSeekable OpenResponseFlags = 1 << 2 // mark the file as non-seekable (not supported on OS X or FreeBSD) OpenPurgeAttr OpenResponseFlags = 1 << 30 // OS X OpenPurgeUBC OpenResponseFlags = 1 << 31 // OS X @@ -633,8 +633,6 @@ func (fl WriteFlags) String() string { return flagString(uint32(fl), writeFlagNames) } -const compatStatfsSize = 48 - type statfsOut struct { St kstatfs } diff --git a/vendor/bazil.org/fuse/fuse_kernel_linux.go b/vendor/bazil.org/fuse/fuse_kernel_linux.go index d3ba8661..fe603de9 100644 --- a/vendor/bazil.org/fuse/fuse_kernel_linux.go +++ b/vendor/bazil.org/fuse/fuse_kernel_linux.go @@ -18,7 +18,7 @@ type attr struct { Gid uint32 Rdev uint32 Blksize uint32 - padding uint32 + _ uint32 } func (a *attr) Crtime() time.Time { diff --git a/vendor/bazil.org/fuse/go.mod b/vendor/bazil.org/fuse/go.mod new file mode 100644 index 00000000..a80fda91 --- /dev/null +++ b/vendor/bazil.org/fuse/go.mod @@ -0,0 +1,8 @@ +module bazil.org/fuse + +go 1.13 + +require ( + github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c + golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 +) diff --git a/vendor/bazil.org/fuse/go.sum b/vendor/bazil.org/fuse/go.sum new file mode 100644 index 00000000..ef81dc7c --- /dev/null +++ b/vendor/bazil.org/fuse/go.sum @@ -0,0 +1,4 @@ +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 h1:gSbV7h1NRL2G1xTg/owz62CST1oJBmxy4QpMMregXVQ= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/bazil.org/fuse/options.go b/vendor/bazil.org/fuse/options.go index 65ce8a54..f09ffd4e 100644 --- a/vendor/bazil.org/fuse/options.go +++ b/vendor/bazil.org/fuse/options.go @@ -106,6 +106,14 @@ func NoAppleXattr() MountOption { return noAppleXattr } +// NoBrowse makes OSXFUSE mark the volume as non-browsable, so that +// Finder won't automatically browse it. +// +// OS X only. Others ignore this option. +func NoBrowse() MountOption { + return noBrowse +} + // ExclCreate causes O_EXCL flag to be set for only "truly" exclusive creates, // i.e. create calls for which the initiator explicitly set the O_EXCL flag. // @@ -140,36 +148,14 @@ func DaemonTimeout(name string) MountOption { return daemonTimeout(name) } -var ErrCannotCombineAllowOtherAndAllowRoot = errors.New("cannot combine AllowOther and AllowRoot") - // AllowOther allows other users to access the file system. -// -// Only one of AllowOther or AllowRoot can be used. func AllowOther() MountOption { return func(conf *mountConfig) error { - if _, ok := conf.options["allow_root"]; ok { - return ErrCannotCombineAllowOtherAndAllowRoot - } conf.options["allow_other"] = "" return nil } } -// AllowRoot allows other users to access the file system. -// -// Only one of AllowOther or AllowRoot can be used. -// -// FreeBSD ignores this option. -func AllowRoot() MountOption { - return func(conf *mountConfig) error { - if _, ok := conf.options["allow_other"]; ok { - return ErrCannotCombineAllowOtherAndAllowRoot - } - conf.options["allow_root"] = "" - return nil - } -} - // AllowDev enables interpreting character or block special devices on the // filesystem. func AllowDev() MountOption { @@ -193,7 +179,7 @@ func AllowSUID() MountOption { // // Without this option, the Node itself decides what is and is not // allowed. This is normally ok because FUSE file systems cannot be -// accessed by other users without AllowOther/AllowRoot. +// accessed by other users without AllowOther. // // FreeBSD ignores this option. func DefaultPermissions() MountOption { diff --git a/vendor/bazil.org/fuse/options_darwin.go b/vendor/bazil.org/fuse/options_darwin.go index faa9d78e..a85e64cb 100644 --- a/vendor/bazil.org/fuse/options_darwin.go +++ b/vendor/bazil.org/fuse/options_darwin.go @@ -33,3 +33,8 @@ func exclCreate(conf *mountConfig) error { conf.options["excl_create"] = "" return nil } + +func noBrowse(conf *mountConfig) error { + conf.options["nobrowse"] = "" + return nil +} diff --git a/vendor/bazil.org/fuse/options_freebsd.go b/vendor/bazil.org/fuse/options_freebsd.go index 7c164b13..2c956e7f 100644 --- a/vendor/bazil.org/fuse/options_freebsd.go +++ b/vendor/bazil.org/fuse/options_freebsd.go @@ -26,3 +26,7 @@ func noAppleDouble(conf *mountConfig) error { func exclCreate(conf *mountConfig) error { return nil } + +func noBrowse(conf *mountConfig) error { + return nil +} diff --git a/vendor/bazil.org/fuse/options_linux.go b/vendor/bazil.org/fuse/options_linux.go index 13f0896d..2c925b18 100644 --- a/vendor/bazil.org/fuse/options_linux.go +++ b/vendor/bazil.org/fuse/options_linux.go @@ -23,3 +23,7 @@ func noAppleDouble(conf *mountConfig) error { func exclCreate(conf *mountConfig) error { return nil } + +func noBrowse(conf *mountConfig) error { + return nil +} diff --git a/vendor/github.com/Microsoft/go-winio/.gitignore b/vendor/github.com/Microsoft/go-winio/.gitignore new file mode 100644 index 00000000..b883f1fd --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/.gitignore @@ -0,0 +1 @@ +*.exe diff --git a/vendor/github.com/Microsoft/go-winio/CODEOWNERS b/vendor/github.com/Microsoft/go-winio/CODEOWNERS new file mode 100644 index 00000000..ae1b4942 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/CODEOWNERS @@ -0,0 +1 @@ + * @microsoft/containerplat diff --git a/vendor/github.com/Microsoft/go-winio/LICENSE b/vendor/github.com/Microsoft/go-winio/LICENSE new file mode 100644 index 00000000..b8b569d7 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/Microsoft/go-winio/README.md b/vendor/github.com/Microsoft/go-winio/README.md new file mode 100644 index 00000000..683be1dc --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/README.md @@ -0,0 +1,37 @@ +# go-winio [![Build Status](https://github.com/microsoft/go-winio/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/go-winio/actions/workflows/ci.yml) + +This repository contains utilities for efficiently performing Win32 IO operations in +Go. Currently, this is focused on accessing named pipes and other file handles, and +for using named pipes as a net transport. + +This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go +to reuse the thread to schedule another goroutine. This limits support to Windows Vista and +newer operating systems. This is similar to the implementation of network sockets in Go's net +package. + +Please see the LICENSE file for licensing information. + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) +declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR +appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +We also require that contributors sign their commits using git commit -s or git commit --signoff to certify they either authored the work themselves +or otherwise have permission to use it in this project. Please see https://developercertificate.org/ for more info, as well as to make sure that you can +attest to the rules listed. Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off. + + +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + + + +## Special Thanks +Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe +for another named pipe implementation. diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go new file mode 100644 index 00000000..2be34af4 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/backup.go @@ -0,0 +1,280 @@ +// +build windows + +package winio + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "runtime" + "syscall" + "unicode/utf16" +) + +//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead +//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite + +const ( + BackupData = uint32(iota + 1) + BackupEaData + BackupSecurity + BackupAlternateData + BackupLink + BackupPropertyData + BackupObjectId + BackupReparseData + BackupSparseBlock + BackupTxfsData +) + +const ( + StreamSparseAttributes = uint32(8) +) + +const ( + WRITE_DAC = 0x40000 + WRITE_OWNER = 0x80000 + ACCESS_SYSTEM_SECURITY = 0x1000000 +) + +// BackupHeader represents a backup stream of a file. +type BackupHeader struct { + Id uint32 // The backup stream ID + Attributes uint32 // Stream attributes + Size int64 // The size of the stream in bytes + Name string // The name of the stream (for BackupAlternateData only). + Offset int64 // The offset of the stream in the file (for BackupSparseBlock only). +} + +type win32StreamId struct { + StreamId uint32 + Attributes uint32 + Size uint64 + NameSize uint32 +} + +// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series +// of BackupHeader values. +type BackupStreamReader struct { + r io.Reader + bytesLeft int64 +} + +// NewBackupStreamReader produces a BackupStreamReader from any io.Reader. +func NewBackupStreamReader(r io.Reader) *BackupStreamReader { + return &BackupStreamReader{r, 0} +} + +// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if +// it was not completely read. +func (r *BackupStreamReader) Next() (*BackupHeader, error) { + if r.bytesLeft > 0 { + if s, ok := r.r.(io.Seeker); ok { + // Make sure Seek on io.SeekCurrent sometimes succeeds + // before trying the actual seek. + if _, err := s.Seek(0, io.SeekCurrent); err == nil { + if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil { + return nil, err + } + r.bytesLeft = 0 + } + } + if _, err := io.Copy(ioutil.Discard, r); err != nil { + return nil, err + } + } + var wsi win32StreamId + if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil { + return nil, err + } + hdr := &BackupHeader{ + Id: wsi.StreamId, + Attributes: wsi.Attributes, + Size: int64(wsi.Size), + } + if wsi.NameSize != 0 { + name := make([]uint16, int(wsi.NameSize/2)) + if err := binary.Read(r.r, binary.LittleEndian, name); err != nil { + return nil, err + } + hdr.Name = syscall.UTF16ToString(name) + } + if wsi.StreamId == BackupSparseBlock { + if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil { + return nil, err + } + hdr.Size -= 8 + } + r.bytesLeft = hdr.Size + return hdr, nil +} + +// Read reads from the current backup stream. +func (r *BackupStreamReader) Read(b []byte) (int, error) { + if r.bytesLeft == 0 { + return 0, io.EOF + } + if int64(len(b)) > r.bytesLeft { + b = b[:r.bytesLeft] + } + n, err := r.r.Read(b) + r.bytesLeft -= int64(n) + if err == io.EOF { + err = io.ErrUnexpectedEOF + } else if r.bytesLeft == 0 && err == nil { + err = io.EOF + } + return n, err +} + +// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API. +type BackupStreamWriter struct { + w io.Writer + bytesLeft int64 +} + +// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer. +func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter { + return &BackupStreamWriter{w, 0} +} + +// WriteHeader writes the next backup stream header and prepares for calls to Write(). +func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error { + if w.bytesLeft != 0 { + return fmt.Errorf("missing %d bytes", w.bytesLeft) + } + name := utf16.Encode([]rune(hdr.Name)) + wsi := win32StreamId{ + StreamId: hdr.Id, + Attributes: hdr.Attributes, + Size: uint64(hdr.Size), + NameSize: uint32(len(name) * 2), + } + if hdr.Id == BackupSparseBlock { + // Include space for the int64 block offset + wsi.Size += 8 + } + if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil { + return err + } + if len(name) != 0 { + if err := binary.Write(w.w, binary.LittleEndian, name); err != nil { + return err + } + } + if hdr.Id == BackupSparseBlock { + if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil { + return err + } + } + w.bytesLeft = hdr.Size + return nil +} + +// Write writes to the current backup stream. +func (w *BackupStreamWriter) Write(b []byte) (int, error) { + if w.bytesLeft < int64(len(b)) { + return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft) + } + n, err := w.w.Write(b) + w.bytesLeft -= int64(n) + return n, err +} + +// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API. +type BackupFileReader struct { + f *os.File + includeSecurity bool + ctx uintptr +} + +// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true, +// Read will attempt to read the security descriptor of the file. +func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader { + r := &BackupFileReader{f, includeSecurity, 0} + return r +} + +// Read reads a backup stream from the file by calling the Win32 API BackupRead(). +func (r *BackupFileReader) Read(b []byte) (int, error) { + var bytesRead uint32 + err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) + if err != nil { + return 0, &os.PathError{"BackupRead", r.f.Name(), err} + } + runtime.KeepAlive(r.f) + if bytesRead == 0 { + return 0, io.EOF + } + return int(bytesRead), nil +} + +// Close frees Win32 resources associated with the BackupFileReader. It does not close +// the underlying file. +func (r *BackupFileReader) Close() error { + if r.ctx != 0 { + backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) + runtime.KeepAlive(r.f) + r.ctx = 0 + } + return nil +} + +// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API. +type BackupFileWriter struct { + f *os.File + includeSecurity bool + ctx uintptr +} + +// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true, +// Write() will attempt to restore the security descriptor from the stream. +func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter { + w := &BackupFileWriter{f, includeSecurity, 0} + return w +} + +// Write restores a portion of the file using the provided backup stream. +func (w *BackupFileWriter) Write(b []byte) (int, error) { + var bytesWritten uint32 + err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) + if err != nil { + return 0, &os.PathError{"BackupWrite", w.f.Name(), err} + } + runtime.KeepAlive(w.f) + if int(bytesWritten) != len(b) { + return int(bytesWritten), errors.New("not all bytes could be written") + } + return len(b), nil +} + +// Close frees Win32 resources associated with the BackupFileWriter. It does not +// close the underlying file. +func (w *BackupFileWriter) Close() error { + if w.ctx != 0 { + backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) + runtime.KeepAlive(w.f) + w.ctx = 0 + } + return nil +} + +// OpenForBackup opens a file or directory, potentially skipping access checks if the backup +// or restore privileges have been acquired. +// +// If the file opened was a directory, it cannot be used with Readdir(). +func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) { + winPath, err := syscall.UTF16FromString(path) + if err != nil { + return nil, err + } + h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0) + if err != nil { + err = &os.PathError{Op: "open", Path: path, Err: err} + return nil, err + } + return os.NewFile(uintptr(h), path), nil +} diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go new file mode 100644 index 00000000..4051c1b3 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/ea.go @@ -0,0 +1,137 @@ +package winio + +import ( + "bytes" + "encoding/binary" + "errors" +) + +type fileFullEaInformation struct { + NextEntryOffset uint32 + Flags uint8 + NameLength uint8 + ValueLength uint16 +} + +var ( + fileFullEaInformationSize = binary.Size(&fileFullEaInformation{}) + + errInvalidEaBuffer = errors.New("invalid extended attribute buffer") + errEaNameTooLarge = errors.New("extended attribute name too large") + errEaValueTooLarge = errors.New("extended attribute value too large") +) + +// ExtendedAttribute represents a single Windows EA. +type ExtendedAttribute struct { + Name string + Value []byte + Flags uint8 +} + +func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { + var info fileFullEaInformation + err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info) + if err != nil { + err = errInvalidEaBuffer + return + } + + nameOffset := fileFullEaInformationSize + nameLen := int(info.NameLength) + valueOffset := nameOffset + int(info.NameLength) + 1 + valueLen := int(info.ValueLength) + nextOffset := int(info.NextEntryOffset) + if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) { + err = errInvalidEaBuffer + return + } + + ea.Name = string(b[nameOffset : nameOffset+nameLen]) + ea.Value = b[valueOffset : valueOffset+valueLen] + ea.Flags = info.Flags + if info.NextEntryOffset != 0 { + nb = b[info.NextEntryOffset:] + } + return +} + +// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION +// buffer retrieved from BackupRead, ZwQueryEaFile, etc. +func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { + for len(b) != 0 { + ea, nb, err := parseEa(b) + if err != nil { + return nil, err + } + + eas = append(eas, ea) + b = nb + } + return +} + +func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { + if int(uint8(len(ea.Name))) != len(ea.Name) { + return errEaNameTooLarge + } + if int(uint16(len(ea.Value))) != len(ea.Value) { + return errEaValueTooLarge + } + entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value)) + withPadding := (entrySize + 3) &^ 3 + nextOffset := uint32(0) + if !last { + nextOffset = withPadding + } + info := fileFullEaInformation{ + NextEntryOffset: nextOffset, + Flags: ea.Flags, + NameLength: uint8(len(ea.Name)), + ValueLength: uint16(len(ea.Value)), + } + + err := binary.Write(buf, binary.LittleEndian, &info) + if err != nil { + return err + } + + _, err = buf.Write([]byte(ea.Name)) + if err != nil { + return err + } + + err = buf.WriteByte(0) + if err != nil { + return err + } + + _, err = buf.Write(ea.Value) + if err != nil { + return err + } + + _, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize]) + if err != nil { + return err + } + + return nil +} + +// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION +// buffer for use with BackupWrite, ZwSetEaFile, etc. +func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) { + var buf bytes.Buffer + for i := range eas { + last := false + if i == len(eas)-1 { + last = true + } + + err := writeEa(&buf, &eas[i], last) + if err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go new file mode 100644 index 00000000..0385e410 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -0,0 +1,323 @@ +// +build windows + +package winio + +import ( + "errors" + "io" + "runtime" + "sync" + "sync/atomic" + "syscall" + "time" +) + +//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx +//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort +//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus +//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes +//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult + +type atomicBool int32 + +func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 } +func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) } +func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) } +func (b *atomicBool) swap(new bool) bool { + var newInt int32 + if new { + newInt = 1 + } + return atomic.SwapInt32((*int32)(b), newInt) == 1 +} + +const ( + cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 + cFILE_SKIP_SET_EVENT_ON_HANDLE = 2 +) + +var ( + ErrFileClosed = errors.New("file has already been closed") + ErrTimeout = &timeoutError{} +) + +type timeoutError struct{} + +func (e *timeoutError) Error() string { return "i/o timeout" } +func (e *timeoutError) Timeout() bool { return true } +func (e *timeoutError) Temporary() bool { return true } + +type timeoutChan chan struct{} + +var ioInitOnce sync.Once +var ioCompletionPort syscall.Handle + +// ioResult contains the result of an asynchronous IO operation +type ioResult struct { + bytes uint32 + err error +} + +// ioOperation represents an outstanding asynchronous Win32 IO +type ioOperation struct { + o syscall.Overlapped + ch chan ioResult +} + +func initIo() { + h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) + if err != nil { + panic(err) + } + ioCompletionPort = h + go ioCompletionProcessor(h) +} + +// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall. +// It takes ownership of this handle and will close it if it is garbage collected. +type win32File struct { + handle syscall.Handle + wg sync.WaitGroup + wgLock sync.RWMutex + closing atomicBool + socket bool + readDeadline deadlineHandler + writeDeadline deadlineHandler +} + +type deadlineHandler struct { + setLock sync.Mutex + channel timeoutChan + channelLock sync.RWMutex + timer *time.Timer + timedout atomicBool +} + +// makeWin32File makes a new win32File from an existing file handle +func makeWin32File(h syscall.Handle) (*win32File, error) { + f := &win32File{handle: h} + ioInitOnce.Do(initIo) + _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) + if err != nil { + return nil, err + } + err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) + if err != nil { + return nil, err + } + f.readDeadline.channel = make(timeoutChan) + f.writeDeadline.channel = make(timeoutChan) + return f, nil +} + +func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { + // If we return the result of makeWin32File directly, it can result in an + // interface-wrapped nil, rather than a nil interface value. + f, err := makeWin32File(h) + if err != nil { + return nil, err + } + return f, nil +} + +// closeHandle closes the resources associated with a Win32 handle +func (f *win32File) closeHandle() { + f.wgLock.Lock() + // Atomically set that we are closing, releasing the resources only once. + if !f.closing.swap(true) { + f.wgLock.Unlock() + // cancel all IO and wait for it to complete + cancelIoEx(f.handle, nil) + f.wg.Wait() + // at this point, no new IO can start + syscall.Close(f.handle) + f.handle = 0 + } else { + f.wgLock.Unlock() + } +} + +// Close closes a win32File. +func (f *win32File) Close() error { + f.closeHandle() + return nil +} + +// prepareIo prepares for a new IO operation. +// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. +func (f *win32File) prepareIo() (*ioOperation, error) { + f.wgLock.RLock() + if f.closing.isSet() { + f.wgLock.RUnlock() + return nil, ErrFileClosed + } + f.wg.Add(1) + f.wgLock.RUnlock() + c := &ioOperation{} + c.ch = make(chan ioResult) + return c, nil +} + +// ioCompletionProcessor processes completed async IOs forever +func ioCompletionProcessor(h syscall.Handle) { + for { + var bytes uint32 + var key uintptr + var op *ioOperation + err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE) + if op == nil { + panic(err) + } + op.ch <- ioResult{bytes, err} + } +} + +// asyncIo processes the return value from ReadFile or WriteFile, blocking until +// the operation has actually completed. +func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { + if err != syscall.ERROR_IO_PENDING { + return int(bytes), err + } + + if f.closing.isSet() { + cancelIoEx(f.handle, &c.o) + } + + var timeout timeoutChan + if d != nil { + d.channelLock.Lock() + timeout = d.channel + d.channelLock.Unlock() + } + + var r ioResult + select { + case r = <-c.ch: + err = r.err + if err == syscall.ERROR_OPERATION_ABORTED { + if f.closing.isSet() { + err = ErrFileClosed + } + } else if err != nil && f.socket { + // err is from Win32. Query the overlapped structure to get the winsock error. + var bytes, flags uint32 + err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags) + } + case <-timeout: + cancelIoEx(f.handle, &c.o) + r = <-c.ch + err = r.err + if err == syscall.ERROR_OPERATION_ABORTED { + err = ErrTimeout + } + } + + // runtime.KeepAlive is needed, as c is passed via native + // code to ioCompletionProcessor, c must remain alive + // until the channel read is complete. + runtime.KeepAlive(c) + return int(r.bytes), err +} + +// Read reads from a file handle. +func (f *win32File) Read(b []byte) (int, error) { + c, err := f.prepareIo() + if err != nil { + return 0, err + } + defer f.wg.Done() + + if f.readDeadline.timedout.isSet() { + return 0, ErrTimeout + } + + var bytes uint32 + err = syscall.ReadFile(f.handle, b, &bytes, &c.o) + n, err := f.asyncIo(c, &f.readDeadline, bytes, err) + runtime.KeepAlive(b) + + // Handle EOF conditions. + if err == nil && n == 0 && len(b) != 0 { + return 0, io.EOF + } else if err == syscall.ERROR_BROKEN_PIPE { + return 0, io.EOF + } else { + return n, err + } +} + +// Write writes to a file handle. +func (f *win32File) Write(b []byte) (int, error) { + c, err := f.prepareIo() + if err != nil { + return 0, err + } + defer f.wg.Done() + + if f.writeDeadline.timedout.isSet() { + return 0, ErrTimeout + } + + var bytes uint32 + err = syscall.WriteFile(f.handle, b, &bytes, &c.o) + n, err := f.asyncIo(c, &f.writeDeadline, bytes, err) + runtime.KeepAlive(b) + return n, err +} + +func (f *win32File) SetReadDeadline(deadline time.Time) error { + return f.readDeadline.set(deadline) +} + +func (f *win32File) SetWriteDeadline(deadline time.Time) error { + return f.writeDeadline.set(deadline) +} + +func (f *win32File) Flush() error { + return syscall.FlushFileBuffers(f.handle) +} + +func (f *win32File) Fd() uintptr { + return uintptr(f.handle) +} + +func (d *deadlineHandler) set(deadline time.Time) error { + d.setLock.Lock() + defer d.setLock.Unlock() + + if d.timer != nil { + if !d.timer.Stop() { + <-d.channel + } + d.timer = nil + } + d.timedout.setFalse() + + select { + case <-d.channel: + d.channelLock.Lock() + d.channel = make(chan struct{}) + d.channelLock.Unlock() + default: + } + + if deadline.IsZero() { + return nil + } + + timeoutIO := func() { + d.timedout.setTrue() + close(d.channel) + } + + now := time.Now() + duration := deadline.Sub(now) + if deadline.After(now) { + // Deadline is in the future, set a timer to wait + d.timer = time.AfterFunc(duration, timeoutIO) + } else { + // Deadline is in the past. Cancel all pending IO now. + timeoutIO() + } + return nil +} diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go new file mode 100644 index 00000000..3ab6bff6 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go @@ -0,0 +1,73 @@ +// +build windows + +package winio + +import ( + "os" + "runtime" + "unsafe" + + "golang.org/x/sys/windows" +) + +// FileBasicInfo contains file access time and file attributes information. +type FileBasicInfo struct { + CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime + FileAttributes uint32 + pad uint32 // padding +} + +// GetFileBasicInfo retrieves times and attributes for a file. +func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { + bi := &FileBasicInfo{} + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return bi, nil +} + +// SetFileBasicInfo sets times and attributes for a file. +func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { + if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return nil +} + +// FileStandardInfo contains extended information for the file. +// FILE_STANDARD_INFO in WinBase.h +// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info +type FileStandardInfo struct { + AllocationSize, EndOfFile int64 + NumberOfLinks uint32 + DeletePending, Directory bool +} + +// GetFileStandardInfo retrieves ended information for the file. +func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { + si := &FileStandardInfo{} + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil { + return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return si, nil +} + +// FileIDInfo contains the volume serial number and file ID for a file. This pair should be +// unique on a system. +type FileIDInfo struct { + VolumeSerialNumber uint64 + FileID [16]byte +} + +// GetFileID retrieves the unique (volume, file ID) pair for a file. +func GetFileID(f *os.File) (*FileIDInfo, error) { + fileID := &FileIDInfo{} + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { + return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return fileID, nil +} diff --git a/vendor/github.com/Microsoft/go-winio/go.mod b/vendor/github.com/Microsoft/go-winio/go.mod new file mode 100644 index 00000000..98a8dea0 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/go.mod @@ -0,0 +1,9 @@ +module github.com/Microsoft/go-winio + +go 1.12 + +require ( + github.com/pkg/errors v0.9.1 + github.com/sirupsen/logrus v1.7.0 + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c +) diff --git a/vendor/github.com/Microsoft/go-winio/go.sum b/vendor/github.com/Microsoft/go-winio/go.sum new file mode 100644 index 00000000..aa6ad3b5 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/go.sum @@ -0,0 +1,14 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go new file mode 100644 index 00000000..b632f8f8 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/hvsock.go @@ -0,0 +1,307 @@ +// +build windows + +package winio + +import ( + "fmt" + "io" + "net" + "os" + "syscall" + "time" + "unsafe" + + "github.com/Microsoft/go-winio/pkg/guid" +) + +//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind + +const ( + afHvSock = 34 // AF_HYPERV + + socketError = ^uintptr(0) +) + +// An HvsockAddr is an address for a AF_HYPERV socket. +type HvsockAddr struct { + VMID guid.GUID + ServiceID guid.GUID +} + +type rawHvsockAddr struct { + Family uint16 + _ uint16 + VMID guid.GUID + ServiceID guid.GUID +} + +// Network returns the address's network name, "hvsock". +func (addr *HvsockAddr) Network() string { + return "hvsock" +} + +func (addr *HvsockAddr) String() string { + return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID) +} + +// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port. +func VsockServiceID(port uint32) guid.GUID { + g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3") + g.Data1 = port + return g +} + +func (addr *HvsockAddr) raw() rawHvsockAddr { + return rawHvsockAddr{ + Family: afHvSock, + VMID: addr.VMID, + ServiceID: addr.ServiceID, + } +} + +func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) { + addr.VMID = raw.VMID + addr.ServiceID = raw.ServiceID +} + +// HvsockListener is a socket listener for the AF_HYPERV address family. +type HvsockListener struct { + sock *win32File + addr HvsockAddr +} + +// HvsockConn is a connected socket of the AF_HYPERV address family. +type HvsockConn struct { + sock *win32File + local, remote HvsockAddr +} + +func newHvSocket() (*win32File, error) { + fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1) + if err != nil { + return nil, os.NewSyscallError("socket", err) + } + f, err := makeWin32File(fd) + if err != nil { + syscall.Close(fd) + return nil, err + } + f.socket = true + return f, nil +} + +// ListenHvsock listens for connections on the specified hvsock address. +func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { + l := &HvsockListener{addr: *addr} + sock, err := newHvSocket() + if err != nil { + return nil, l.opErr("listen", err) + } + sa := addr.raw() + err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa))) + if err != nil { + return nil, l.opErr("listen", os.NewSyscallError("socket", err)) + } + err = syscall.Listen(sock.handle, 16) + if err != nil { + return nil, l.opErr("listen", os.NewSyscallError("listen", err)) + } + return &HvsockListener{sock: sock, addr: *addr}, nil +} + +func (l *HvsockListener) opErr(op string, err error) error { + return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err} +} + +// Addr returns the listener's network address. +func (l *HvsockListener) Addr() net.Addr { + return &l.addr +} + +// Accept waits for the next connection and returns it. +func (l *HvsockListener) Accept() (_ net.Conn, err error) { + sock, err := newHvSocket() + if err != nil { + return nil, l.opErr("accept", err) + } + defer func() { + if sock != nil { + sock.Close() + } + }() + c, err := l.sock.prepareIo() + if err != nil { + return nil, l.opErr("accept", err) + } + defer l.sock.wg.Done() + + // AcceptEx, per documentation, requires an extra 16 bytes per address. + const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{})) + var addrbuf [addrlen * 2]byte + + var bytes uint32 + err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o) + _, err = l.sock.asyncIo(c, nil, bytes, err) + if err != nil { + return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) + } + conn := &HvsockConn{ + sock: sock, + } + conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0]))) + conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen]))) + sock = nil + return conn, nil +} + +// Close closes the listener, causing any pending Accept calls to fail. +func (l *HvsockListener) Close() error { + return l.sock.Close() +} + +/* Need to finish ConnectEx handling +func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) { + sock, err := newHvSocket() + if err != nil { + return nil, err + } + defer func() { + if sock != nil { + sock.Close() + } + }() + c, err := sock.prepareIo() + if err != nil { + return nil, err + } + defer sock.wg.Done() + var bytes uint32 + err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o) + _, err = sock.asyncIo(ctx, c, nil, bytes, err) + if err != nil { + return nil, err + } + conn := &HvsockConn{ + sock: sock, + remote: *addr, + } + sock = nil + return conn, nil +} +*/ + +func (conn *HvsockConn) opErr(op string, err error) error { + return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err} +} + +func (conn *HvsockConn) Read(b []byte) (int, error) { + c, err := conn.sock.prepareIo() + if err != nil { + return 0, conn.opErr("read", err) + } + defer conn.sock.wg.Done() + buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + var flags, bytes uint32 + err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) + n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err) + if err != nil { + if _, ok := err.(syscall.Errno); ok { + err = os.NewSyscallError("wsarecv", err) + } + return 0, conn.opErr("read", err) + } else if n == 0 { + err = io.EOF + } + return n, err +} + +func (conn *HvsockConn) Write(b []byte) (int, error) { + t := 0 + for len(b) != 0 { + n, err := conn.write(b) + if err != nil { + return t + n, err + } + t += n + b = b[n:] + } + return t, nil +} + +func (conn *HvsockConn) write(b []byte) (int, error) { + c, err := conn.sock.prepareIo() + if err != nil { + return 0, conn.opErr("write", err) + } + defer conn.sock.wg.Done() + buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + var bytes uint32 + err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) + n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err) + if err != nil { + if _, ok := err.(syscall.Errno); ok { + err = os.NewSyscallError("wsasend", err) + } + return 0, conn.opErr("write", err) + } + return n, err +} + +// Close closes the socket connection, failing any pending read or write calls. +func (conn *HvsockConn) Close() error { + return conn.sock.Close() +} + +func (conn *HvsockConn) shutdown(how int) error { + err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) + if err != nil { + return os.NewSyscallError("shutdown", err) + } + return nil +} + +// CloseRead shuts down the read end of the socket. +func (conn *HvsockConn) CloseRead() error { + err := conn.shutdown(syscall.SHUT_RD) + if err != nil { + return conn.opErr("close", err) + } + return nil +} + +// CloseWrite shuts down the write end of the socket, notifying the other endpoint that +// no more data will be written. +func (conn *HvsockConn) CloseWrite() error { + err := conn.shutdown(syscall.SHUT_WR) + if err != nil { + return conn.opErr("close", err) + } + return nil +} + +// LocalAddr returns the local address of the connection. +func (conn *HvsockConn) LocalAddr() net.Addr { + return &conn.local +} + +// RemoteAddr returns the remote address of the connection. +func (conn *HvsockConn) RemoteAddr() net.Addr { + return &conn.remote +} + +// SetDeadline implements the net.Conn SetDeadline method. +func (conn *HvsockConn) SetDeadline(t time.Time) error { + conn.SetReadDeadline(t) + conn.SetWriteDeadline(t) + return nil +} + +// SetReadDeadline implements the net.Conn SetReadDeadline method. +func (conn *HvsockConn) SetReadDeadline(t time.Time) error { + return conn.sock.SetReadDeadline(t) +} + +// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +func (conn *HvsockConn) SetWriteDeadline(t time.Time) error { + return conn.sock.SetWriteDeadline(t) +} diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go new file mode 100644 index 00000000..96700a73 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pipe.go @@ -0,0 +1,517 @@ +// +build windows + +package winio + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "os" + "runtime" + "syscall" + "time" + "unsafe" +) + +//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe +//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW +//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW +//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo +//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW +//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc +//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile +//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb +//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U +//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl + +type ioStatusBlock struct { + Status, Information uintptr +} + +type objectAttributes struct { + Length uintptr + RootDirectory uintptr + ObjectName *unicodeString + Attributes uintptr + SecurityDescriptor *securityDescriptor + SecurityQoS uintptr +} + +type unicodeString struct { + Length uint16 + MaximumLength uint16 + Buffer uintptr +} + +type securityDescriptor struct { + Revision byte + Sbz1 byte + Control uint16 + Owner uintptr + Group uintptr + Sacl uintptr + Dacl uintptr +} + +type ntstatus int32 + +func (status ntstatus) Err() error { + if status >= 0 { + return nil + } + return rtlNtStatusToDosError(status) +} + +const ( + cERROR_PIPE_BUSY = syscall.Errno(231) + cERROR_NO_DATA = syscall.Errno(232) + cERROR_PIPE_CONNECTED = syscall.Errno(535) + cERROR_SEM_TIMEOUT = syscall.Errno(121) + + cSECURITY_SQOS_PRESENT = 0x100000 + cSECURITY_ANONYMOUS = 0 + + cPIPE_TYPE_MESSAGE = 4 + + cPIPE_READMODE_MESSAGE = 2 + + cFILE_OPEN = 1 + cFILE_CREATE = 2 + + cFILE_PIPE_MESSAGE_TYPE = 1 + cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2 + + cSE_DACL_PRESENT = 4 +) + +var ( + // ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed. + // This error should match net.errClosing since docker takes a dependency on its text. + ErrPipeListenerClosed = errors.New("use of closed network connection") + + errPipeWriteClosed = errors.New("pipe has been closed for write") +) + +type win32Pipe struct { + *win32File + path string +} + +type win32MessageBytePipe struct { + win32Pipe + writeClosed bool + readEOF bool +} + +type pipeAddress string + +func (f *win32Pipe) LocalAddr() net.Addr { + return pipeAddress(f.path) +} + +func (f *win32Pipe) RemoteAddr() net.Addr { + return pipeAddress(f.path) +} + +func (f *win32Pipe) SetDeadline(t time.Time) error { + f.SetReadDeadline(t) + f.SetWriteDeadline(t) + return nil +} + +// CloseWrite closes the write side of a message pipe in byte mode. +func (f *win32MessageBytePipe) CloseWrite() error { + if f.writeClosed { + return errPipeWriteClosed + } + err := f.win32File.Flush() + if err != nil { + return err + } + _, err = f.win32File.Write(nil) + if err != nil { + return err + } + f.writeClosed = true + return nil +} + +// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since +// they are used to implement CloseWrite(). +func (f *win32MessageBytePipe) Write(b []byte) (int, error) { + if f.writeClosed { + return 0, errPipeWriteClosed + } + if len(b) == 0 { + return 0, nil + } + return f.win32File.Write(b) +} + +// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message +// mode pipe will return io.EOF, as will all subsequent reads. +func (f *win32MessageBytePipe) Read(b []byte) (int, error) { + if f.readEOF { + return 0, io.EOF + } + n, err := f.win32File.Read(b) + if err == io.EOF { + // If this was the result of a zero-byte read, then + // it is possible that the read was due to a zero-size + // message. Since we are simulating CloseWrite with a + // zero-byte message, ensure that all future Read() calls + // also return EOF. + f.readEOF = true + } else if err == syscall.ERROR_MORE_DATA { + // ERROR_MORE_DATA indicates that the pipe's read mode is message mode + // and the message still has more bytes. Treat this as a success, since + // this package presents all named pipes as byte streams. + err = nil + } + return n, err +} + +func (s pipeAddress) Network() string { + return "pipe" +} + +func (s pipeAddress) String() string { + return string(s) +} + +// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout. +func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) { + for { + + select { + case <-ctx.Done(): + return syscall.Handle(0), ctx.Err() + default: + h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) + if err == nil { + return h, nil + } + if err != cERROR_PIPE_BUSY { + return h, &os.PathError{Err: err, Op: "open", Path: *path} + } + // Wait 10 msec and try again. This is a rather simplistic + // view, as we always try each 10 milliseconds. + time.Sleep(10 * time.Millisecond) + } + } +} + +// DialPipe connects to a named pipe by path, timing out if the connection +// takes longer than the specified duration. If timeout is nil, then we use +// a default timeout of 2 seconds. (We do not use WaitNamedPipe.) +func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { + var absTimeout time.Time + if timeout != nil { + absTimeout = time.Now().Add(*timeout) + } else { + absTimeout = time.Now().Add(2 * time.Second) + } + ctx, _ := context.WithDeadline(context.Background(), absTimeout) + conn, err := DialPipeContext(ctx, path) + if err == context.DeadlineExceeded { + return nil, ErrTimeout + } + return conn, err +} + +// DialPipeContext attempts to connect to a named pipe by `path` until `ctx` +// cancellation or timeout. +func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { + return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE) +} + +// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx` +// cancellation or timeout. +func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) { + var err error + var h syscall.Handle + h, err = tryDialPipe(ctx, &path, access) + if err != nil { + return nil, err + } + + var flags uint32 + err = getNamedPipeInfo(h, &flags, nil, nil, nil) + if err != nil { + return nil, err + } + + f, err := makeWin32File(h) + if err != nil { + syscall.Close(h) + return nil, err + } + + // If the pipe is in message mode, return a message byte pipe, which + // supports CloseWrite(). + if flags&cPIPE_TYPE_MESSAGE != 0 { + return &win32MessageBytePipe{ + win32Pipe: win32Pipe{win32File: f, path: path}, + }, nil + } + return &win32Pipe{win32File: f, path: path}, nil +} + +type acceptResponse struct { + f *win32File + err error +} + +type win32PipeListener struct { + firstHandle syscall.Handle + path string + config PipeConfig + acceptCh chan (chan acceptResponse) + closeCh chan int + doneCh chan int +} + +func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) { + path16, err := syscall.UTF16FromString(path) + if err != nil { + return 0, &os.PathError{Op: "open", Path: path, Err: err} + } + + var oa objectAttributes + oa.Length = unsafe.Sizeof(oa) + + var ntPath unicodeString + if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil { + return 0, &os.PathError{Op: "open", Path: path, Err: err} + } + defer localFree(ntPath.Buffer) + oa.ObjectName = &ntPath + + // The security descriptor is only needed for the first pipe. + if first { + if sd != nil { + len := uint32(len(sd)) + sdb := localAlloc(0, len) + defer localFree(sdb) + copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) + oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) + } else { + // Construct the default named pipe security descriptor. + var dacl uintptr + if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { + return 0, fmt.Errorf("getting default named pipe ACL: %s", err) + } + defer localFree(dacl) + + sdb := &securityDescriptor{ + Revision: 1, + Control: cSE_DACL_PRESENT, + Dacl: dacl, + } + oa.SecurityDescriptor = sdb + } + } + + typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS) + if c.MessageMode { + typ |= cFILE_PIPE_MESSAGE_TYPE + } + + disposition := uint32(cFILE_OPEN) + access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE) + if first { + disposition = cFILE_CREATE + // By not asking for read or write access, the named pipe file system + // will put this pipe into an initially disconnected state, blocking + // client connections until the next call with first == false. + access = syscall.SYNCHRONIZE + } + + timeout := int64(-50 * 10000) // 50ms + + var ( + h syscall.Handle + iosb ioStatusBlock + ) + err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() + if err != nil { + return 0, &os.PathError{Op: "open", Path: path, Err: err} + } + + runtime.KeepAlive(ntPath) + return h, nil +} + +func (l *win32PipeListener) makeServerPipe() (*win32File, error) { + h, err := makeServerPipeHandle(l.path, nil, &l.config, false) + if err != nil { + return nil, err + } + f, err := makeWin32File(h) + if err != nil { + syscall.Close(h) + return nil, err + } + return f, nil +} + +func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) { + p, err := l.makeServerPipe() + if err != nil { + return nil, err + } + + // Wait for the client to connect. + ch := make(chan error) + go func(p *win32File) { + ch <- connectPipe(p) + }(p) + + select { + case err = <-ch: + if err != nil { + p.Close() + p = nil + } + case <-l.closeCh: + // Abort the connect request by closing the handle. + p.Close() + p = nil + err = <-ch + if err == nil || err == ErrFileClosed { + err = ErrPipeListenerClosed + } + } + return p, err +} + +func (l *win32PipeListener) listenerRoutine() { + closed := false + for !closed { + select { + case <-l.closeCh: + closed = true + case responseCh := <-l.acceptCh: + var ( + p *win32File + err error + ) + for { + p, err = l.makeConnectedServerPipe() + // If the connection was immediately closed by the client, try + // again. + if err != cERROR_NO_DATA { + break + } + } + responseCh <- acceptResponse{p, err} + closed = err == ErrPipeListenerClosed + } + } + syscall.Close(l.firstHandle) + l.firstHandle = 0 + // Notify Close() and Accept() callers that the handle has been closed. + close(l.doneCh) +} + +// PipeConfig contain configuration for the pipe listener. +type PipeConfig struct { + // SecurityDescriptor contains a Windows security descriptor in SDDL format. + SecurityDescriptor string + + // MessageMode determines whether the pipe is in byte or message mode. In either + // case the pipe is read in byte mode by default. The only practical difference in + // this implementation is that CloseWrite() is only supported for message mode pipes; + // CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only + // transferred to the reader (and returned as io.EOF in this implementation) + // when the pipe is in message mode. + MessageMode bool + + // InputBufferSize specifies the size of the input buffer, in bytes. + InputBufferSize int32 + + // OutputBufferSize specifies the size of the output buffer, in bytes. + OutputBufferSize int32 +} + +// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe. +// The pipe must not already exist. +func ListenPipe(path string, c *PipeConfig) (net.Listener, error) { + var ( + sd []byte + err error + ) + if c == nil { + c = &PipeConfig{} + } + if c.SecurityDescriptor != "" { + sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor) + if err != nil { + return nil, err + } + } + h, err := makeServerPipeHandle(path, sd, c, true) + if err != nil { + return nil, err + } + l := &win32PipeListener{ + firstHandle: h, + path: path, + config: *c, + acceptCh: make(chan (chan acceptResponse)), + closeCh: make(chan int), + doneCh: make(chan int), + } + go l.listenerRoutine() + return l, nil +} + +func connectPipe(p *win32File) error { + c, err := p.prepareIo() + if err != nil { + return err + } + defer p.wg.Done() + + err = connectNamedPipe(p.handle, &c.o) + _, err = p.asyncIo(c, nil, 0, err) + if err != nil && err != cERROR_PIPE_CONNECTED { + return err + } + return nil +} + +func (l *win32PipeListener) Accept() (net.Conn, error) { + ch := make(chan acceptResponse) + select { + case l.acceptCh <- ch: + response := <-ch + err := response.err + if err != nil { + return nil, err + } + if l.config.MessageMode { + return &win32MessageBytePipe{ + win32Pipe: win32Pipe{win32File: response.f, path: l.path}, + }, nil + } + return &win32Pipe{win32File: response.f, path: l.path}, nil + case <-l.doneCh: + return nil, ErrPipeListenerClosed + } +} + +func (l *win32PipeListener) Close() error { + select { + case l.closeCh <- 1: + <-l.doneCh + case <-l.doneCh: + } + return nil +} + +func (l *win32PipeListener) Addr() net.Addr { + return pipeAddress(l.path) +} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go new file mode 100644 index 00000000..f497c0e3 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go @@ -0,0 +1,237 @@ +// +build windows + +// Package guid provides a GUID type. The backing structure for a GUID is +// identical to that used by the golang.org/x/sys/windows GUID type. +// There are two main binary encodings used for a GUID, the big-endian encoding, +// and the Windows (mixed-endian) encoding. See here for details: +// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding +package guid + +import ( + "crypto/rand" + "crypto/sha1" + "encoding" + "encoding/binary" + "fmt" + "strconv" + + "golang.org/x/sys/windows" +) + +// Variant specifies which GUID variant (or "type") of the GUID. It determines +// how the entirety of the rest of the GUID is interpreted. +type Variant uint8 + +// The variants specified by RFC 4122. +const ( + // VariantUnknown specifies a GUID variant which does not conform to one of + // the variant encodings specified in RFC 4122. + VariantUnknown Variant = iota + VariantNCS + VariantRFC4122 + VariantMicrosoft + VariantFuture +) + +// Version specifies how the bits in the GUID were generated. For instance, a +// version 4 GUID is randomly generated, and a version 5 is generated from the +// hash of an input string. +type Version uint8 + +var _ = (encoding.TextMarshaler)(GUID{}) +var _ = (encoding.TextUnmarshaler)(&GUID{}) + +// GUID represents a GUID/UUID. It has the same structure as +// golang.org/x/sys/windows.GUID so that it can be used with functions expecting +// that type. It is defined as its own type so that stringification and +// marshaling can be supported. The representation matches that used by native +// Windows code. +type GUID windows.GUID + +// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122. +func NewV4() (GUID, error) { + var b [16]byte + if _, err := rand.Read(b[:]); err != nil { + return GUID{}, err + } + + g := FromArray(b) + g.setVersion(4) // Version 4 means randomly generated. + g.setVariant(VariantRFC4122) + + return g, nil +} + +// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing) +// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name, +// and the sample code treats it as a series of bytes, so we do the same here. +// +// Some implementations, such as those found on Windows, treat the name as a +// big-endian UTF16 stream of bytes. If that is desired, the string can be +// encoded as such before being passed to this function. +func NewV5(namespace GUID, name []byte) (GUID, error) { + b := sha1.New() + namespaceBytes := namespace.ToArray() + b.Write(namespaceBytes[:]) + b.Write(name) + + a := [16]byte{} + copy(a[:], b.Sum(nil)) + + g := FromArray(a) + g.setVersion(5) // Version 5 means generated from a string. + g.setVariant(VariantRFC4122) + + return g, nil +} + +func fromArray(b [16]byte, order binary.ByteOrder) GUID { + var g GUID + g.Data1 = order.Uint32(b[0:4]) + g.Data2 = order.Uint16(b[4:6]) + g.Data3 = order.Uint16(b[6:8]) + copy(g.Data4[:], b[8:16]) + return g +} + +func (g GUID) toArray(order binary.ByteOrder) [16]byte { + b := [16]byte{} + order.PutUint32(b[0:4], g.Data1) + order.PutUint16(b[4:6], g.Data2) + order.PutUint16(b[6:8], g.Data3) + copy(b[8:16], g.Data4[:]) + return b +} + +// FromArray constructs a GUID from a big-endian encoding array of 16 bytes. +func FromArray(b [16]byte) GUID { + return fromArray(b, binary.BigEndian) +} + +// ToArray returns an array of 16 bytes representing the GUID in big-endian +// encoding. +func (g GUID) ToArray() [16]byte { + return g.toArray(binary.BigEndian) +} + +// FromWindowsArray constructs a GUID from a Windows encoding array of bytes. +func FromWindowsArray(b [16]byte) GUID { + return fromArray(b, binary.LittleEndian) +} + +// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows +// encoding. +func (g GUID) ToWindowsArray() [16]byte { + return g.toArray(binary.LittleEndian) +} + +func (g GUID) String() string { + return fmt.Sprintf( + "%08x-%04x-%04x-%04x-%012x", + g.Data1, + g.Data2, + g.Data3, + g.Data4[:2], + g.Data4[2:]) +} + +// FromString parses a string containing a GUID and returns the GUID. The only +// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` +// format. +func FromString(s string) (GUID, error) { + if len(s) != 36 { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + + var g GUID + + data1, err := strconv.ParseUint(s[0:8], 16, 32) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data1 = uint32(data1) + + data2, err := strconv.ParseUint(s[9:13], 16, 16) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data2 = uint16(data2) + + data3, err := strconv.ParseUint(s[14:18], 16, 16) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data3 = uint16(data3) + + for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} { + v, err := strconv.ParseUint(s[x:x+2], 16, 8) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data4[i] = uint8(v) + } + + return g, nil +} + +func (g *GUID) setVariant(v Variant) { + d := g.Data4[0] + switch v { + case VariantNCS: + d = (d & 0x7f) + case VariantRFC4122: + d = (d & 0x3f) | 0x80 + case VariantMicrosoft: + d = (d & 0x1f) | 0xc0 + case VariantFuture: + d = (d & 0x0f) | 0xe0 + case VariantUnknown: + fallthrough + default: + panic(fmt.Sprintf("invalid variant: %d", v)) + } + g.Data4[0] = d +} + +// Variant returns the GUID variant, as defined in RFC 4122. +func (g GUID) Variant() Variant { + b := g.Data4[0] + if b&0x80 == 0 { + return VariantNCS + } else if b&0xc0 == 0x80 { + return VariantRFC4122 + } else if b&0xe0 == 0xc0 { + return VariantMicrosoft + } else if b&0xe0 == 0xe0 { + return VariantFuture + } + return VariantUnknown +} + +func (g *GUID) setVersion(v Version) { + g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12) +} + +// Version returns the GUID version, as defined in RFC 4122. +func (g GUID) Version() Version { + return Version((g.Data3 & 0xF000) >> 12) +} + +// MarshalText returns the textual representation of the GUID. +func (g GUID) MarshalText() ([]byte, error) { + return []byte(g.String()), nil +} + +// UnmarshalText takes the textual representation of a GUID, and unmarhals it +// into this GUID. +func (g *GUID) UnmarshalText(text []byte) error { + g2, err := FromString(string(text)) + if err != nil { + return err + } + *g = g2 + return nil +} diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go new file mode 100644 index 00000000..c3dd7c21 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/privilege.go @@ -0,0 +1,203 @@ +// +build windows + +package winio + +import ( + "bytes" + "encoding/binary" + "fmt" + "runtime" + "sync" + "syscall" + "unicode/utf16" + + "golang.org/x/sys/windows" +) + +//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges +//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf +//sys revertToSelf() (err error) = advapi32.RevertToSelf +//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken +//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread +//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW +//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW +//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW + +const ( + SE_PRIVILEGE_ENABLED = 2 + + ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 + + SeBackupPrivilege = "SeBackupPrivilege" + SeRestorePrivilege = "SeRestorePrivilege" + SeSecurityPrivilege = "SeSecurityPrivilege" +) + +const ( + securityAnonymous = iota + securityIdentification + securityImpersonation + securityDelegation +) + +var ( + privNames = make(map[string]uint64) + privNameMutex sync.Mutex +) + +// PrivilegeError represents an error enabling privileges. +type PrivilegeError struct { + privileges []uint64 +} + +func (e *PrivilegeError) Error() string { + s := "" + if len(e.privileges) > 1 { + s = "Could not enable privileges " + } else { + s = "Could not enable privilege " + } + for i, p := range e.privileges { + if i != 0 { + s += ", " + } + s += `"` + s += getPrivilegeName(p) + s += `"` + } + return s +} + +// RunWithPrivilege enables a single privilege for a function call. +func RunWithPrivilege(name string, fn func() error) error { + return RunWithPrivileges([]string{name}, fn) +} + +// RunWithPrivileges enables privileges for a function call. +func RunWithPrivileges(names []string, fn func() error) error { + privileges, err := mapPrivileges(names) + if err != nil { + return err + } + runtime.LockOSThread() + defer runtime.UnlockOSThread() + token, err := newThreadToken() + if err != nil { + return err + } + defer releaseThreadToken(token) + err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED) + if err != nil { + return err + } + return fn() +} + +func mapPrivileges(names []string) ([]uint64, error) { + var privileges []uint64 + privNameMutex.Lock() + defer privNameMutex.Unlock() + for _, name := range names { + p, ok := privNames[name] + if !ok { + err := lookupPrivilegeValue("", name, &p) + if err != nil { + return nil, err + } + privNames[name] = p + } + privileges = append(privileges, p) + } + return privileges, nil +} + +// EnableProcessPrivileges enables privileges globally for the process. +func EnableProcessPrivileges(names []string) error { + return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED) +} + +// DisableProcessPrivileges disables privileges globally for the process. +func DisableProcessPrivileges(names []string) error { + return enableDisableProcessPrivilege(names, 0) +} + +func enableDisableProcessPrivilege(names []string, action uint32) error { + privileges, err := mapPrivileges(names) + if err != nil { + return err + } + + p, _ := windows.GetCurrentProcess() + var token windows.Token + err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token) + if err != nil { + return err + } + + defer token.Close() + return adjustPrivileges(token, privileges, action) +} + +func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error { + var b bytes.Buffer + binary.Write(&b, binary.LittleEndian, uint32(len(privileges))) + for _, p := range privileges { + binary.Write(&b, binary.LittleEndian, p) + binary.Write(&b, binary.LittleEndian, action) + } + prevState := make([]byte, b.Len()) + reqSize := uint32(0) + success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize) + if !success { + return err + } + if err == ERROR_NOT_ALL_ASSIGNED { + return &PrivilegeError{privileges} + } + return nil +} + +func getPrivilegeName(luid uint64) string { + var nameBuffer [256]uint16 + bufSize := uint32(len(nameBuffer)) + err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize) + if err != nil { + return fmt.Sprintf("", luid) + } + + var displayNameBuffer [256]uint16 + displayBufSize := uint32(len(displayNameBuffer)) + var langID uint32 + err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langID) + if err != nil { + return fmt.Sprintf("", string(utf16.Decode(nameBuffer[:bufSize]))) + } + + return string(utf16.Decode(displayNameBuffer[:displayBufSize])) +} + +func newThreadToken() (windows.Token, error) { + err := impersonateSelf(securityImpersonation) + if err != nil { + return 0, err + } + + var token windows.Token + err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token) + if err != nil { + rerr := revertToSelf() + if rerr != nil { + panic(rerr) + } + return 0, err + } + return token, nil +} + +func releaseThreadToken(h windows.Token) { + err := revertToSelf() + if err != nil { + panic(err) + } + h.Close() +} diff --git a/vendor/github.com/Microsoft/go-winio/reparse.go b/vendor/github.com/Microsoft/go-winio/reparse.go new file mode 100644 index 00000000..fc1ee4d3 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/reparse.go @@ -0,0 +1,128 @@ +package winio + +import ( + "bytes" + "encoding/binary" + "fmt" + "strings" + "unicode/utf16" + "unsafe" +) + +const ( + reparseTagMountPoint = 0xA0000003 + reparseTagSymlink = 0xA000000C +) + +type reparseDataBuffer struct { + ReparseTag uint32 + ReparseDataLength uint16 + Reserved uint16 + SubstituteNameOffset uint16 + SubstituteNameLength uint16 + PrintNameOffset uint16 + PrintNameLength uint16 +} + +// ReparsePoint describes a Win32 symlink or mount point. +type ReparsePoint struct { + Target string + IsMountPoint bool +} + +// UnsupportedReparsePointError is returned when trying to decode a non-symlink or +// mount point reparse point. +type UnsupportedReparsePointError struct { + Tag uint32 +} + +func (e *UnsupportedReparsePointError) Error() string { + return fmt.Sprintf("unsupported reparse point %x", e.Tag) +} + +// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink +// or a mount point. +func DecodeReparsePoint(b []byte) (*ReparsePoint, error) { + tag := binary.LittleEndian.Uint32(b[0:4]) + return DecodeReparsePointData(tag, b[8:]) +} + +func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) { + isMountPoint := false + switch tag { + case reparseTagMountPoint: + isMountPoint = true + case reparseTagSymlink: + default: + return nil, &UnsupportedReparsePointError{tag} + } + nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6]) + if !isMountPoint { + nameOffset += 4 + } + nameLength := binary.LittleEndian.Uint16(b[6:8]) + name := make([]uint16, nameLength/2) + err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name) + if err != nil { + return nil, err + } + return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil +} + +func isDriveLetter(c byte) bool { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') +} + +// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or +// mount point. +func EncodeReparsePoint(rp *ReparsePoint) []byte { + // Generate an NT path and determine if this is a relative path. + var ntTarget string + relative := false + if strings.HasPrefix(rp.Target, `\\?\`) { + ntTarget = `\??\` + rp.Target[4:] + } else if strings.HasPrefix(rp.Target, `\\`) { + ntTarget = `\??\UNC\` + rp.Target[2:] + } else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' { + ntTarget = `\??\` + rp.Target + } else { + ntTarget = rp.Target + relative = true + } + + // The paths must be NUL-terminated even though they are counted strings. + target16 := utf16.Encode([]rune(rp.Target + "\x00")) + ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00")) + + size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8 + size += len(ntTarget16)*2 + len(target16)*2 + + tag := uint32(reparseTagMountPoint) + if !rp.IsMountPoint { + tag = reparseTagSymlink + size += 4 // Add room for symlink flags + } + + data := reparseDataBuffer{ + ReparseTag: tag, + ReparseDataLength: uint16(size), + SubstituteNameOffset: 0, + SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2), + PrintNameOffset: uint16(len(ntTarget16) * 2), + PrintNameLength: uint16((len(target16) - 1) * 2), + } + + var b bytes.Buffer + binary.Write(&b, binary.LittleEndian, &data) + if !rp.IsMountPoint { + flags := uint32(0) + if relative { + flags |= 1 + } + binary.Write(&b, binary.LittleEndian, flags) + } + + binary.Write(&b, binary.LittleEndian, ntTarget16) + binary.Write(&b, binary.LittleEndian, target16) + return b.Bytes() +} diff --git a/vendor/github.com/Microsoft/go-winio/sd.go b/vendor/github.com/Microsoft/go-winio/sd.go new file mode 100644 index 00000000..db1b370a --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/sd.go @@ -0,0 +1,98 @@ +// +build windows + +package winio + +import ( + "syscall" + "unsafe" +) + +//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW +//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW +//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW +//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW +//sys localFree(mem uintptr) = LocalFree +//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength + +const ( + cERROR_NONE_MAPPED = syscall.Errno(1332) +) + +type AccountLookupError struct { + Name string + Err error +} + +func (e *AccountLookupError) Error() string { + if e.Name == "" { + return "lookup account: empty account name specified" + } + var s string + switch e.Err { + case cERROR_NONE_MAPPED: + s = "not found" + default: + s = e.Err.Error() + } + return "lookup account " + e.Name + ": " + s +} + +type SddlConversionError struct { + Sddl string + Err error +} + +func (e *SddlConversionError) Error() string { + return "convert " + e.Sddl + ": " + e.Err.Error() +} + +// LookupSidByName looks up the SID of an account by name +func LookupSidByName(name string) (sid string, err error) { + if name == "" { + return "", &AccountLookupError{name, cERROR_NONE_MAPPED} + } + + var sidSize, sidNameUse, refDomainSize uint32 + err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) + if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { + return "", &AccountLookupError{name, err} + } + sidBuffer := make([]byte, sidSize) + refDomainBuffer := make([]uint16, refDomainSize) + err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) + if err != nil { + return "", &AccountLookupError{name, err} + } + var strBuffer *uint16 + err = convertSidToStringSid(&sidBuffer[0], &strBuffer) + if err != nil { + return "", &AccountLookupError{name, err} + } + sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:]) + localFree(uintptr(unsafe.Pointer(strBuffer))) + return sid, nil +} + +func SddlToSecurityDescriptor(sddl string) ([]byte, error) { + var sdBuffer uintptr + err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil) + if err != nil { + return nil, &SddlConversionError{sddl, err} + } + defer localFree(sdBuffer) + sd := make([]byte, getSecurityDescriptorLength(sdBuffer)) + copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)]) + return sd, nil +} + +func SecurityDescriptorToSddl(sd []byte) (string, error) { + var sddl *uint16 + // The returned string length seems to including an aribtrary number of terminating NULs. + // Don't use it. + err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil) + if err != nil { + return "", err + } + defer localFree(uintptr(unsafe.Pointer(sddl))) + return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil +} diff --git a/vendor/github.com/Microsoft/go-winio/syscall.go b/vendor/github.com/Microsoft/go-winio/syscall.go new file mode 100644 index 00000000..5955c99f --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/syscall.go @@ -0,0 +1,3 @@ +package winio + +//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go new file mode 100644 index 00000000..176ff75e --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go @@ -0,0 +1,427 @@ +// Code generated by 'go generate'; DO NOT EDIT. + +package winio + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return errERROR_EINVAL + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + modntdll = windows.NewLazySystemDLL("ntdll.dll") + modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") + + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") + procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") + procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") + procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") + procBackupRead = modkernel32.NewProc("BackupRead") + procBackupWrite = modkernel32.NewProc("BackupWrite") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") + procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") + procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") + procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procLocalAlloc = modkernel32.NewProc("LocalAlloc") + procLocalFree = modkernel32.NewProc("LocalFree") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") + procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") + procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") + procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") + procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") + procbind = modws2_32.NewProc("bind") +) + +func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { + var _p0 uint32 + if releaseAll { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) + success = r0 != 0 + if true { + err = errnoErr(e1) + } + return +} + +func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func convertSidToStringSid(sid *byte, str **uint16) (err error) { + r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(str) + if err != nil { + return + } + return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) +} + +func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getSecurityDescriptorLength(sd uintptr) (len uint32) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) + len = uint32(r0) + return +} + +func impersonateSelf(level uint32) (err error) { + r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(accountName) + if err != nil { + return + } + return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) +} + +func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId) +} + +func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + return _lookupPrivilegeName(_p0, luid, buffer, size) +} + +func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + var _p1 *uint16 + _p1, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _lookupPrivilegeValue(_p0, _p1, luid) +} + +func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) { + r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { + var _p0 uint32 + if openAsSelf { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func revertToSelf() (err error) { + r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { + var _p0 *byte + if len(b) > 0 { + _p0 = &b[0] + } + var _p1 uint32 + if abort { + _p1 = 1 + } + var _p2 uint32 + if processSecurity { + _p2 = 1 + } + r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { + var _p0 *byte + if len(b) > 0 { + _p0 = &b[0] + } + var _p1 uint32 + if abort { + _p1 = 1 + } + var _p2 uint32 + if processSecurity { + _p2 = 1 + } + r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) +} + +func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + err = errnoErr(e1) + } + return +} + +func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) + newport = syscall.Handle(r0) + if newport == 0 { + err = errnoErr(e1) + } + return +} + +func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) +} + +func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + err = errnoErr(e1) + } + return +} + +func getCurrentThread() (h syscall.Handle) { + r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) + h = syscall.Handle(r0) + return +} + +func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { + r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) + ptr = uintptr(r0) + return +} + +func localFree(mem uintptr) { + syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) + return +} + +func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { + r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) + status = ntstatus(r0) + return +} + +func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { + r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) + status = ntstatus(r0) + return +} + +func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { + r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) + status = ntstatus(r0) + return +} + +func rtlNtStatusToDosError(status ntstatus) (winerr error) { + r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) + if r0 != 0 { + winerr = syscall.Errno(r0) + } + return +} + +func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socketError { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore deleted file mode 100644 index daf913b1..00000000 --- a/vendor/github.com/pkg/errors/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml deleted file mode 100644 index 9159de03..00000000 --- a/vendor/github.com/pkg/errors/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go -go_import_path: github.com/pkg/errors -go: - - 1.11.x - - 1.12.x - - 1.13.x - - tip - -script: - - make check diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE deleted file mode 100644 index 835ba3e7..00000000 --- a/vendor/github.com/pkg/errors/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2015, Dave Cheney -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile deleted file mode 100644 index ce9d7cde..00000000 --- a/vendor/github.com/pkg/errors/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -PKGS := github.com/pkg/errors -SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) -GO := go - -check: test vet gofmt misspell unconvert staticcheck ineffassign unparam - -test: - $(GO) test $(PKGS) - -vet: | test - $(GO) vet $(PKGS) - -staticcheck: - $(GO) get honnef.co/go/tools/cmd/staticcheck - staticcheck -checks all $(PKGS) - -misspell: - $(GO) get github.com/client9/misspell/cmd/misspell - misspell \ - -locale GB \ - -error \ - *.md *.go - -unconvert: - $(GO) get github.com/mdempsky/unconvert - unconvert -v $(PKGS) - -ineffassign: - $(GO) get github.com/gordonklaus/ineffassign - find $(SRCDIRS) -name '*.go' | xargs ineffassign - -pedantic: check errcheck - -unparam: - $(GO) get mvdan.cc/unparam - unparam ./... - -errcheck: - $(GO) get github.com/kisielk/errcheck - errcheck $(PKGS) - -gofmt: - @echo Checking code is gofmted - @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md deleted file mode 100644 index 54dfdcb1..00000000 --- a/vendor/github.com/pkg/errors/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) - -Package errors provides simple error handling primitives. - -`go get github.com/pkg/errors` - -The traditional error handling idiom in Go is roughly akin to -```go -if err != nil { - return err -} -``` -which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. - -## Adding context to an error - -The errors.Wrap function returns a new error that adds context to the original error. For example -```go -_, err := ioutil.ReadAll(r) -if err != nil { - return errors.Wrap(err, "read failed") -} -``` -## Retrieving the cause of an error - -Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. -```go -type causer interface { - Cause() error -} -``` -`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: -```go -switch err := errors.Cause(err).(type) { -case *MyError: - // handle specifically -default: - // unknown error -} -``` - -[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). - -## Roadmap - -With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: - -- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) -- 1.0. Final release. - -## Contributing - -Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. - -Before sending a PR, please discuss your change by raising an issue. - -## License - -BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml deleted file mode 100644 index a932eade..00000000 --- a/vendor/github.com/pkg/errors/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: build-{build}.{branch} - -clone_folder: C:\gopath\src\github.com\pkg\errors -shallow_clone: true # for startup speed - -environment: - GOPATH: C:\gopath - -platform: - - x64 - -# http://www.appveyor.com/docs/installed-software -install: - # some helpful output for debugging builds - - go version - - go env - # pre-installed MinGW at C:\MinGW is 32bit only - # but MSYS2 at C:\msys64 has mingw64 - - set PATH=C:\msys64\mingw64\bin;%PATH% - - gcc --version - - g++ --version - -build_script: - - go install -v ./... - -test_script: - - set PATH=C:\gopath\bin;%PATH% - - go test -v ./... - -#artifacts: -# - path: '%GOPATH%\bin\*.exe' -deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go deleted file mode 100644 index 161aea25..00000000 --- a/vendor/github.com/pkg/errors/errors.go +++ /dev/null @@ -1,288 +0,0 @@ -// Package errors provides simple error handling primitives. -// -// The traditional error handling idiom in Go is roughly akin to -// -// if err != nil { -// return err -// } -// -// which when applied recursively up the call stack results in error reports -// without context or debugging information. The errors package allows -// programmers to add context to the failure path in their code in a way -// that does not destroy the original value of the error. -// -// Adding context to an error -// -// The errors.Wrap function returns a new error that adds context to the -// original error by recording a stack trace at the point Wrap is called, -// together with the supplied message. For example -// -// _, err := ioutil.ReadAll(r) -// if err != nil { -// return errors.Wrap(err, "read failed") -// } -// -// If additional control is required, the errors.WithStack and -// errors.WithMessage functions destructure errors.Wrap into its component -// operations: annotating an error with a stack trace and with a message, -// respectively. -// -// Retrieving the cause of an error -// -// Using errors.Wrap constructs a stack of errors, adding context to the -// preceding error. Depending on the nature of the error it may be necessary -// to reverse the operation of errors.Wrap to retrieve the original error -// for inspection. Any error value which implements this interface -// -// type causer interface { -// Cause() error -// } -// -// can be inspected by errors.Cause. errors.Cause will recursively retrieve -// the topmost error that does not implement causer, which is assumed to be -// the original cause. For example: -// -// switch err := errors.Cause(err).(type) { -// case *MyError: -// // handle specifically -// default: -// // unknown error -// } -// -// Although the causer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// Formatted printing of errors -// -// All error values returned from this package implement fmt.Formatter and can -// be formatted by the fmt package. The following verbs are supported: -// -// %s print the error. If the error has a Cause it will be -// printed recursively. -// %v see %s -// %+v extended format. Each Frame of the error's StackTrace will -// be printed in detail. -// -// Retrieving the stack trace of an error or wrapper -// -// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are -// invoked. This information can be retrieved with the following interface: -// -// type stackTracer interface { -// StackTrace() errors.StackTrace -// } -// -// The returned errors.StackTrace type is defined as -// -// type StackTrace []Frame -// -// The Frame type represents a call site in the stack trace. Frame supports -// the fmt.Formatter interface that can be used for printing information about -// the stack trace of this error. For example: -// -// if err, ok := err.(stackTracer); ok { -// for _, f := range err.StackTrace() { -// fmt.Printf("%+s:%d\n", f, f) -// } -// } -// -// Although the stackTracer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// See the documentation for Frame.Format for more details. -package errors - -import ( - "fmt" - "io" -) - -// New returns an error with the supplied message. -// New also records the stack trace at the point it was called. -func New(message string) error { - return &fundamental{ - msg: message, - stack: callers(), - } -} - -// Errorf formats according to a format specifier and returns the string -// as a value that satisfies error. -// Errorf also records the stack trace at the point it was called. -func Errorf(format string, args ...interface{}) error { - return &fundamental{ - msg: fmt.Sprintf(format, args...), - stack: callers(), - } -} - -// fundamental is an error that has a message and a stack, but no caller. -type fundamental struct { - msg string - *stack -} - -func (f *fundamental) Error() string { return f.msg } - -func (f *fundamental) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - io.WriteString(s, f.msg) - f.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, f.msg) - case 'q': - fmt.Fprintf(s, "%q", f.msg) - } -} - -// WithStack annotates err with a stack trace at the point WithStack was called. -// If err is nil, WithStack returns nil. -func WithStack(err error) error { - if err == nil { - return nil - } - return &withStack{ - err, - callers(), - } -} - -type withStack struct { - error - *stack -} - -func (w *withStack) Cause() error { return w.error } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withStack) Unwrap() error { return w.error } - -func (w *withStack) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v", w.Cause()) - w.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, w.Error()) - case 'q': - fmt.Fprintf(s, "%q", w.Error()) - } -} - -// Wrap returns an error annotating err with a stack trace -// at the point Wrap is called, and the supplied message. -// If err is nil, Wrap returns nil. -func Wrap(err error, message string) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: message, - } - return &withStack{ - err, - callers(), - } -} - -// Wrapf returns an error annotating err with a stack trace -// at the point Wrapf is called, and the format specifier. -// If err is nil, Wrapf returns nil. -func Wrapf(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } - return &withStack{ - err, - callers(), - } -} - -// WithMessage annotates err with a new message. -// If err is nil, WithMessage returns nil. -func WithMessage(err error, message string) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: message, - } -} - -// WithMessagef annotates err with the format specifier. -// If err is nil, WithMessagef returns nil. -func WithMessagef(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } -} - -type withMessage struct { - cause error - msg string -} - -func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } -func (w *withMessage) Cause() error { return w.cause } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withMessage) Unwrap() error { return w.cause } - -func (w *withMessage) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v\n", w.Cause()) - io.WriteString(s, w.msg) - return - } - fallthrough - case 's', 'q': - io.WriteString(s, w.Error()) - } -} - -// Cause returns the underlying cause of the error, if possible. -// An error value has a cause if it implements the following -// interface: -// -// type causer interface { -// Cause() error -// } -// -// If the error does not implement Cause, the original error will -// be returned. If the error is nil, nil will be returned without further -// investigation. -func Cause(err error) error { - type causer interface { - Cause() error - } - - for err != nil { - cause, ok := err.(causer) - if !ok { - break - } - err = cause.Cause() - } - return err -} diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go deleted file mode 100644 index be0d10d0..00000000 --- a/vendor/github.com/pkg/errors/go113.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.13 - -package errors - -import ( - stderrors "errors" -) - -// Is reports whether any error in err's chain matches target. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error is considered to match a target if it is equal to that target or if -// it implements a method Is(error) bool such that Is(target) returns true. -func Is(err, target error) bool { return stderrors.Is(err, target) } - -// As finds the first error in err's chain that matches target, and if so, sets -// target to that error value and returns true. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error matches target if the error's concrete value is assignable to the value -// pointed to by target, or if the error has a method As(interface{}) bool such that -// As(target) returns true. In the latter case, the As method is responsible for -// setting target. -// -// As will panic if target is not a non-nil pointer to either a type that implements -// error, or to any interface type. As returns false if err is nil. -func As(err error, target interface{}) bool { return stderrors.As(err, target) } - -// Unwrap returns the result of calling the Unwrap method on err, if err's -// type contains an Unwrap method returning error. -// Otherwise, Unwrap returns nil. -func Unwrap(err error) error { - return stderrors.Unwrap(err) -} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go deleted file mode 100644 index 779a8348..00000000 --- a/vendor/github.com/pkg/errors/stack.go +++ /dev/null @@ -1,177 +0,0 @@ -package errors - -import ( - "fmt" - "io" - "path" - "runtime" - "strconv" - "strings" -) - -// Frame represents a program counter inside a stack frame. -// For historical reasons if Frame is interpreted as a uintptr -// its value represents the program counter + 1. -type Frame uintptr - -// pc returns the program counter for this frame; -// multiple frames may have the same PC value. -func (f Frame) pc() uintptr { return uintptr(f) - 1 } - -// file returns the full path to the file that contains the -// function for this Frame's pc. -func (f Frame) file() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - file, _ := fn.FileLine(f.pc()) - return file -} - -// line returns the line number of source code of the -// function for this Frame's pc. -func (f Frame) line() int { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return 0 - } - _, line := fn.FileLine(f.pc()) - return line -} - -// name returns the name of this function, if known. -func (f Frame) name() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - return fn.Name() -} - -// Format formats the frame according to the fmt.Formatter interface. -// -// %s source file -// %d source line -// %n function name -// %v equivalent to %s:%d -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+s function name and path of source file relative to the compile time -// GOPATH separated by \n\t (\n\t) -// %+v equivalent to %+s:%d -func (f Frame) Format(s fmt.State, verb rune) { - switch verb { - case 's': - switch { - case s.Flag('+'): - io.WriteString(s, f.name()) - io.WriteString(s, "\n\t") - io.WriteString(s, f.file()) - default: - io.WriteString(s, path.Base(f.file())) - } - case 'd': - io.WriteString(s, strconv.Itoa(f.line())) - case 'n': - io.WriteString(s, funcname(f.name())) - case 'v': - f.Format(s, 's') - io.WriteString(s, ":") - f.Format(s, 'd') - } -} - -// MarshalText formats a stacktrace Frame as a text string. The output is the -// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. -func (f Frame) MarshalText() ([]byte, error) { - name := f.name() - if name == "unknown" { - return []byte(name), nil - } - return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil -} - -// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). -type StackTrace []Frame - -// Format formats the stack of Frames according to the fmt.Formatter interface. -// -// %s lists source files for each Frame in the stack -// %v lists the source file and line number for each Frame in the stack -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+v Prints filename, function, and line number for each Frame in the stack. -func (st StackTrace) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case s.Flag('+'): - for _, f := range st { - io.WriteString(s, "\n") - f.Format(s, verb) - } - case s.Flag('#'): - fmt.Fprintf(s, "%#v", []Frame(st)) - default: - st.formatSlice(s, verb) - } - case 's': - st.formatSlice(s, verb) - } -} - -// formatSlice will format this StackTrace into the given buffer as a slice of -// Frame, only valid when called with '%s' or '%v'. -func (st StackTrace) formatSlice(s fmt.State, verb rune) { - io.WriteString(s, "[") - for i, f := range st { - if i > 0 { - io.WriteString(s, " ") - } - f.Format(s, verb) - } - io.WriteString(s, "]") -} - -// stack represents a stack of program counters. -type stack []uintptr - -func (s *stack) Format(st fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case st.Flag('+'): - for _, pc := range *s { - f := Frame(pc) - fmt.Fprintf(st, "\n%+v", f) - } - } - } -} - -func (s *stack) StackTrace() StackTrace { - f := make([]Frame, len(*s)) - for i := 0; i < len(f); i++ { - f[i] = Frame((*s)[i]) - } - return f -} - -func callers() *stack { - const depth = 32 - var pcs [depth]uintptr - n := runtime.Callers(3, pcs[:]) - var st stack = pcs[0:n] - return &st -} - -// funcname removes the path prefix component of a function's name reported by func.Name(). -func funcname(name string) string { - i := strings.LastIndex(name, "/") - name = name[i+1:] - i = strings.Index(name, ".") - return name[i+1:] -} diff --git a/vendor/golang.org/x/net/AUTHORS b/vendor/golang.org/x/net/AUTHORS deleted file mode 100644 index 15167cd7..00000000 --- a/vendor/golang.org/x/net/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/net/CONTRIBUTORS b/vendor/golang.org/x/net/CONTRIBUTORS deleted file mode 100644 index 1c4577e9..00000000 --- a/vendor/golang.org/x/net/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE deleted file mode 100644 index 6a66aea5..00000000 --- a/vendor/golang.org/x/net/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS deleted file mode 100644 index 73309904..00000000 --- a/vendor/golang.org/x/net/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go deleted file mode 100644 index a3c021d3..00000000 --- a/vendor/golang.org/x/net/context/context.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package context defines the Context type, which carries deadlines, -// cancelation signals, and other request-scoped values across API boundaries -// and between processes. -// As of Go 1.7 this package is available in the standard library under the -// name context. https://golang.org/pkg/context. -// -// Incoming requests to a server should create a Context, and outgoing calls to -// servers should accept a Context. The chain of function calls between must -// propagate the Context, optionally replacing it with a modified copy created -// using WithDeadline, WithTimeout, WithCancel, or WithValue. -// -// Programs that use Contexts should follow these rules to keep interfaces -// consistent across packages and enable static analysis tools to check context -// propagation: -// -// Do not store Contexts inside a struct type; instead, pass a Context -// explicitly to each function that needs it. The Context should be the first -// parameter, typically named ctx: -// -// func DoSomething(ctx context.Context, arg Arg) error { -// // ... use ctx ... -// } -// -// Do not pass a nil Context, even if a function permits it. Pass context.TODO -// if you are unsure about which Context to use. -// -// Use context Values only for request-scoped data that transits processes and -// APIs, not for passing optional parameters to functions. -// -// The same Context may be passed to functions running in different goroutines; -// Contexts are safe for simultaneous use by multiple goroutines. -// -// See http://blog.golang.org/context for example code for a server that uses -// Contexts. -package context // import "golang.org/x/net/context" - -// Background returns a non-nil, empty Context. It is never canceled, has no -// values, and has no deadline. It is typically used by the main function, -// initialization, and tests, and as the top-level Context for incoming -// requests. -func Background() Context { - return background -} - -// TODO returns a non-nil, empty Context. Code should use context.TODO when -// it's unclear which Context to use or it is not yet available (because the -// surrounding function has not yet been extended to accept a Context -// parameter). TODO is recognized by static analysis tools that determine -// whether Contexts are propagated correctly in a program. -func TODO() Context { - return todo -} diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go deleted file mode 100644 index d20f52b7..00000000 --- a/vendor/golang.org/x/net/context/go17.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.7 - -package context - -import ( - "context" // standard library's context, as of Go 1.7 - "time" -) - -var ( - todo = context.TODO() - background = context.Background() -) - -// Canceled is the error returned by Context.Err when the context is canceled. -var Canceled = context.Canceled - -// DeadlineExceeded is the error returned by Context.Err when the context's -// deadline passes. -var DeadlineExceeded = context.DeadlineExceeded - -// WithCancel returns a copy of parent with a new Done channel. The returned -// context's Done channel is closed when the returned cancel function is called -// or when the parent context's Done channel is closed, whichever happens first. -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this Context complete. -func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { - ctx, f := context.WithCancel(parent) - return ctx, CancelFunc(f) -} - -// WithDeadline returns a copy of the parent context with the deadline adjusted -// to be no later than d. If the parent's deadline is already earlier than d, -// WithDeadline(parent, d) is semantically equivalent to parent. The returned -// context's Done channel is closed when the deadline expires, when the returned -// cancel function is called, or when the parent context's Done channel is -// closed, whichever happens first. -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this Context complete. -func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { - ctx, f := context.WithDeadline(parent, deadline) - return ctx, CancelFunc(f) -} - -// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this Context complete: -// -// func slowOperationWithTimeout(ctx context.Context) (Result, error) { -// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) -// defer cancel() // releases resources if slowOperation completes before timeout elapses -// return slowOperation(ctx) -// } -func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { - return WithDeadline(parent, time.Now().Add(timeout)) -} - -// WithValue returns a copy of parent in which the value associated with key is -// val. -// -// Use context Values only for request-scoped data that transits processes and -// APIs, not for passing optional parameters to functions. -func WithValue(parent Context, key interface{}, val interface{}) Context { - return context.WithValue(parent, key, val) -} diff --git a/vendor/golang.org/x/net/context/go19.go b/vendor/golang.org/x/net/context/go19.go deleted file mode 100644 index d88bd1db..00000000 --- a/vendor/golang.org/x/net/context/go19.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.9 - -package context - -import "context" // standard library's context, as of Go 1.7 - -// A Context carries a deadline, a cancelation signal, and other values across -// API boundaries. -// -// Context's methods may be called by multiple goroutines simultaneously. -type Context = context.Context - -// A CancelFunc tells an operation to abandon its work. -// A CancelFunc does not wait for the work to stop. -// After the first call, subsequent calls to a CancelFunc do nothing. -type CancelFunc = context.CancelFunc diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go deleted file mode 100644 index 0f35592d..00000000 --- a/vendor/golang.org/x/net/context/pre_go17.go +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.7 - -package context - -import ( - "errors" - "fmt" - "sync" - "time" -) - -// An emptyCtx is never canceled, has no values, and has no deadline. It is not -// struct{}, since vars of this type must have distinct addresses. -type emptyCtx int - -func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { - return -} - -func (*emptyCtx) Done() <-chan struct{} { - return nil -} - -func (*emptyCtx) Err() error { - return nil -} - -func (*emptyCtx) Value(key interface{}) interface{} { - return nil -} - -func (e *emptyCtx) String() string { - switch e { - case background: - return "context.Background" - case todo: - return "context.TODO" - } - return "unknown empty Context" -} - -var ( - background = new(emptyCtx) - todo = new(emptyCtx) -) - -// Canceled is the error returned by Context.Err when the context is canceled. -var Canceled = errors.New("context canceled") - -// DeadlineExceeded is the error returned by Context.Err when the context's -// deadline passes. -var DeadlineExceeded = errors.New("context deadline exceeded") - -// WithCancel returns a copy of parent with a new Done channel. The returned -// context's Done channel is closed when the returned cancel function is called -// or when the parent context's Done channel is closed, whichever happens first. -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this Context complete. -func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { - c := newCancelCtx(parent) - propagateCancel(parent, c) - return c, func() { c.cancel(true, Canceled) } -} - -// newCancelCtx returns an initialized cancelCtx. -func newCancelCtx(parent Context) *cancelCtx { - return &cancelCtx{ - Context: parent, - done: make(chan struct{}), - } -} - -// propagateCancel arranges for child to be canceled when parent is. -func propagateCancel(parent Context, child canceler) { - if parent.Done() == nil { - return // parent is never canceled - } - if p, ok := parentCancelCtx(parent); ok { - p.mu.Lock() - if p.err != nil { - // parent has already been canceled - child.cancel(false, p.err) - } else { - if p.children == nil { - p.children = make(map[canceler]bool) - } - p.children[child] = true - } - p.mu.Unlock() - } else { - go func() { - select { - case <-parent.Done(): - child.cancel(false, parent.Err()) - case <-child.Done(): - } - }() - } -} - -// parentCancelCtx follows a chain of parent references until it finds a -// *cancelCtx. This function understands how each of the concrete types in this -// package represents its parent. -func parentCancelCtx(parent Context) (*cancelCtx, bool) { - for { - switch c := parent.(type) { - case *cancelCtx: - return c, true - case *timerCtx: - return c.cancelCtx, true - case *valueCtx: - parent = c.Context - default: - return nil, false - } - } -} - -// removeChild removes a context from its parent. -func removeChild(parent Context, child canceler) { - p, ok := parentCancelCtx(parent) - if !ok { - return - } - p.mu.Lock() - if p.children != nil { - delete(p.children, child) - } - p.mu.Unlock() -} - -// A canceler is a context type that can be canceled directly. The -// implementations are *cancelCtx and *timerCtx. -type canceler interface { - cancel(removeFromParent bool, err error) - Done() <-chan struct{} -} - -// A cancelCtx can be canceled. When canceled, it also cancels any children -// that implement canceler. -type cancelCtx struct { - Context - - done chan struct{} // closed by the first cancel call. - - mu sync.Mutex - children map[canceler]bool // set to nil by the first cancel call - err error // set to non-nil by the first cancel call -} - -func (c *cancelCtx) Done() <-chan struct{} { - return c.done -} - -func (c *cancelCtx) Err() error { - c.mu.Lock() - defer c.mu.Unlock() - return c.err -} - -func (c *cancelCtx) String() string { - return fmt.Sprintf("%v.WithCancel", c.Context) -} - -// cancel closes c.done, cancels each of c's children, and, if -// removeFromParent is true, removes c from its parent's children. -func (c *cancelCtx) cancel(removeFromParent bool, err error) { - if err == nil { - panic("context: internal error: missing cancel error") - } - c.mu.Lock() - if c.err != nil { - c.mu.Unlock() - return // already canceled - } - c.err = err - close(c.done) - for child := range c.children { - // NOTE: acquiring the child's lock while holding parent's lock. - child.cancel(false, err) - } - c.children = nil - c.mu.Unlock() - - if removeFromParent { - removeChild(c.Context, c) - } -} - -// WithDeadline returns a copy of the parent context with the deadline adjusted -// to be no later than d. If the parent's deadline is already earlier than d, -// WithDeadline(parent, d) is semantically equivalent to parent. The returned -// context's Done channel is closed when the deadline expires, when the returned -// cancel function is called, or when the parent context's Done channel is -// closed, whichever happens first. -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this Context complete. -func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { - if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { - // The current deadline is already sooner than the new one. - return WithCancel(parent) - } - c := &timerCtx{ - cancelCtx: newCancelCtx(parent), - deadline: deadline, - } - propagateCancel(parent, c) - d := deadline.Sub(time.Now()) - if d <= 0 { - c.cancel(true, DeadlineExceeded) // deadline has already passed - return c, func() { c.cancel(true, Canceled) } - } - c.mu.Lock() - defer c.mu.Unlock() - if c.err == nil { - c.timer = time.AfterFunc(d, func() { - c.cancel(true, DeadlineExceeded) - }) - } - return c, func() { c.cancel(true, Canceled) } -} - -// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to -// implement Done and Err. It implements cancel by stopping its timer then -// delegating to cancelCtx.cancel. -type timerCtx struct { - *cancelCtx - timer *time.Timer // Under cancelCtx.mu. - - deadline time.Time -} - -func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { - return c.deadline, true -} - -func (c *timerCtx) String() string { - return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) -} - -func (c *timerCtx) cancel(removeFromParent bool, err error) { - c.cancelCtx.cancel(false, err) - if removeFromParent { - // Remove this timerCtx from its parent cancelCtx's children. - removeChild(c.cancelCtx.Context, c) - } - c.mu.Lock() - if c.timer != nil { - c.timer.Stop() - c.timer = nil - } - c.mu.Unlock() -} - -// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). -// -// Canceling this context releases resources associated with it, so code should -// call cancel as soon as the operations running in this Context complete: -// -// func slowOperationWithTimeout(ctx context.Context) (Result, error) { -// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) -// defer cancel() // releases resources if slowOperation completes before timeout elapses -// return slowOperation(ctx) -// } -func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { - return WithDeadline(parent, time.Now().Add(timeout)) -} - -// WithValue returns a copy of parent in which the value associated with key is -// val. -// -// Use context Values only for request-scoped data that transits processes and -// APIs, not for passing optional parameters to functions. -func WithValue(parent Context, key interface{}, val interface{}) Context { - return &valueCtx{parent, key, val} -} - -// A valueCtx carries a key-value pair. It implements Value for that key and -// delegates all other calls to the embedded Context. -type valueCtx struct { - Context - key, val interface{} -} - -func (c *valueCtx) String() string { - return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) -} - -func (c *valueCtx) Value(key interface{}) interface{} { - if c.key == key { - return c.val - } - return c.Context.Value(key) -} diff --git a/vendor/golang.org/x/net/context/pre_go19.go b/vendor/golang.org/x/net/context/pre_go19.go deleted file mode 100644 index b105f80b..00000000 --- a/vendor/golang.org/x/net/context/pre_go19.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.9 - -package context - -import "time" - -// A Context carries a deadline, a cancelation signal, and other values across -// API boundaries. -// -// Context's methods may be called by multiple goroutines simultaneously. -type Context interface { - // Deadline returns the time when work done on behalf of this context - // should be canceled. Deadline returns ok==false when no deadline is - // set. Successive calls to Deadline return the same results. - Deadline() (deadline time.Time, ok bool) - - // Done returns a channel that's closed when work done on behalf of this - // context should be canceled. Done may return nil if this context can - // never be canceled. Successive calls to Done return the same value. - // - // WithCancel arranges for Done to be closed when cancel is called; - // WithDeadline arranges for Done to be closed when the deadline - // expires; WithTimeout arranges for Done to be closed when the timeout - // elapses. - // - // Done is provided for use in select statements: - // - // // Stream generates values with DoSomething and sends them to out - // // until DoSomething returns an error or ctx.Done is closed. - // func Stream(ctx context.Context, out chan<- Value) error { - // for { - // v, err := DoSomething(ctx) - // if err != nil { - // return err - // } - // select { - // case <-ctx.Done(): - // return ctx.Err() - // case out <- v: - // } - // } - // } - // - // See http://blog.golang.org/pipelines for more examples of how to use - // a Done channel for cancelation. - Done() <-chan struct{} - - // Err returns a non-nil error value after Done is closed. Err returns - // Canceled if the context was canceled or DeadlineExceeded if the - // context's deadline passed. No other values for Err are defined. - // After Done is closed, successive calls to Err return the same value. - Err() error - - // Value returns the value associated with this context for key, or nil - // if no value is associated with key. Successive calls to Value with - // the same key returns the same result. - // - // Use context values only for request-scoped data that transits - // processes and API boundaries, not for passing optional parameters to - // functions. - // - // A key identifies a specific value in a Context. Functions that wish - // to store values in Context typically allocate a key in a global - // variable then use that key as the argument to context.WithValue and - // Context.Value. A key can be any type that supports equality; - // packages should define keys as an unexported type to avoid - // collisions. - // - // Packages that define a Context key should provide type-safe accessors - // for the values stores using that key: - // - // // Package user defines a User type that's stored in Contexts. - // package user - // - // import "golang.org/x/net/context" - // - // // User is the type of value stored in the Contexts. - // type User struct {...} - // - // // key is an unexported type for keys defined in this package. - // // This prevents collisions with keys defined in other packages. - // type key int - // - // // userKey is the key for user.User values in Contexts. It is - // // unexported; clients use user.NewContext and user.FromContext - // // instead of using this key directly. - // var userKey key = 0 - // - // // NewContext returns a new Context that carries value u. - // func NewContext(ctx context.Context, u *User) context.Context { - // return context.WithValue(ctx, userKey, u) - // } - // - // // FromContext returns the User value stored in ctx, if any. - // func FromContext(ctx context.Context) (*User, bool) { - // u, ok := ctx.Value(userKey).(*User) - // return u, ok - // } - Value(key interface{}) interface{} -} - -// A CancelFunc tells an operation to abandon its work. -// A CancelFunc does not wait for the work to stop. -// After the first call, subsequent calls to a CancelFunc do nothing. -type CancelFunc func() diff --git a/vendor/modules.txt b/vendor/modules.txt index 3f05e696..aac4cd28 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,7 +1,10 @@ -# bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898 +# bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 bazil.org/fuse bazil.org/fuse/fs bazil.org/fuse/fuseutil +# github.com/Microsoft/go-winio v0.5.1 +github.com/Microsoft/go-winio +github.com/Microsoft/go-winio/pkg/guid # github.com/dustin/go-humanize v1.0.0 github.com/dustin/go-humanize # github.com/golang/protobuf v1.3.5 @@ -10,16 +13,12 @@ github.com/golang/protobuf/proto github.com/inconshreveable/mousetrap # github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest -# github.com/pkg/errors v0.9.1 -github.com/pkg/errors # github.com/sirupsen/logrus v1.7.0 github.com/sirupsen/logrus # github.com/spf13/cobra v1.0.0 github.com/spf13/cobra # github.com/spf13/pflag v1.0.3 github.com/spf13/pflag -# golang.org/x/net v0.0.0-20190522155817-f3200d17e092 -golang.org/x/net/context # golang.org/x/sync v0.0.0-20201207232520-09787c993a3a golang.org/x/sync/errgroup # golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c