diff --git a/vendor.conf b/vendor.conf index aae9ba7c8d..83cedfd52b 100644 --- a/vendor.conf +++ b/vendor.conf @@ -102,6 +102,8 @@ google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 # containerd github.com/containerd/containerd 3addd840653146c90a254301d6c3a663c7fd6429 github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 +github.com/stevvooe/continuity cd7a8e21e2b6f84799f5dd4b65faf49c8d3ee02d +github.com/tonistiigi/fsutil 0ac4c11b053b9c5c7c47558f81f96c7100ce50fb # cluster github.com/docker/swarmkit a4bf0135f63fb60f0e76ae81579cde87f580db6e diff --git a/vendor/github.com/stevvooe/continuity/LICENSE b/vendor/github.com/stevvooe/continuity/LICENSE new file mode 100644 index 0000000000..8f71f43fee --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor 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, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/vendor/github.com/stevvooe/continuity/README.md b/vendor/github.com/stevvooe/continuity/README.md new file mode 100644 index 0000000000..50b64c20f3 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/README.md @@ -0,0 +1,19 @@ +# 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) + +A transport-agnostic, filesystem metadata manifest system + +This project is a staging area for experiments in providing transport agnostic +metadata storage. + +Please see https://github.com/opencontainers/specs/issues/11 for more details. + +## Building Proto Package + +If you change the proto file you will need to rebuild the generated Go with `go generate`. + +``` +go generate ./proto +``` diff --git a/vendor/github.com/stevvooe/continuity/sysx/asm.s b/vendor/github.com/stevvooe/continuity/sysx/asm.s new file mode 100644 index 0000000000..8ed2fdb94b --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/asm.s @@ -0,0 +1,10 @@ +// 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 !gccgo + +#include "textflag.h" + +TEXT ·use(SB),NOSPLIT,$0 + RET diff --git a/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin.go b/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin.go new file mode 100644 index 0000000000..e3ae2b7bbf --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin.go @@ -0,0 +1,18 @@ +package sysx + +const ( + // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in + AtSymlinkNofollow = 0x20 +) + +const ( + + // SYS_FCHMODAT defined from golang.org/sys/unix + SYS_FCHMODAT = 467 +) + +// These functions will be generated by generate.sh +// $ GOOS=darwin GOARCH=386 ./generate.sh chmod +// $ GOOS=darwin GOARCH=amd64 ./generate.sh chmod + +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) diff --git a/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin_386.go b/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin_386.go new file mode 100644 index 0000000000..5a8cf5b57d --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin_386.go @@ -0,0 +1,25 @@ +// mksyscall.pl -l32 chmod_darwin.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + use(unsafe.Pointer(_p0)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin_amd64.go b/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin_amd64.go new file mode 100644 index 0000000000..3287d1d579 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/chmod_darwin_amd64.go @@ -0,0 +1,25 @@ +// mksyscall.pl chmod_darwin.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + use(unsafe.Pointer(_p0)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/chmod_freebsd.go b/vendor/github.com/stevvooe/continuity/sysx/chmod_freebsd.go new file mode 100644 index 0000000000..b64a708be1 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/chmod_freebsd.go @@ -0,0 +1,17 @@ +package sysx + +const ( + // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in + AtSymlinkNofollow = 0x200 +) + +const ( + + // SYS_FCHMODAT defined from golang.org/sys/unix + SYS_FCHMODAT = 490 +) + +// These functions will be generated by generate.sh +// $ GOOS=freebsd GOARCH=amd64 ./generate.sh chmod + +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) diff --git a/vendor/github.com/stevvooe/continuity/sysx/chmod_freebsd_amd64.go b/vendor/github.com/stevvooe/continuity/sysx/chmod_freebsd_amd64.go new file mode 100644 index 0000000000..5a271abb1e --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/chmod_freebsd_amd64.go @@ -0,0 +1,25 @@ +// mksyscall.pl chmod_freebsd.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + use(unsafe.Pointer(_p0)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/chmod_linux.go b/vendor/github.com/stevvooe/continuity/sysx/chmod_linux.go new file mode 100644 index 0000000000..89df6d38ef --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/chmod_linux.go @@ -0,0 +1,12 @@ +package sysx + +import "syscall" + +const ( + // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in /usr/include/linux/fcntl.h + AtSymlinkNofollow = 0x100 +) + +func Fchmodat(dirfd int, path string, mode uint32, flags int) error { + return syscall.Fchmodat(dirfd, path, mode, flags) +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/copy_linux.go b/vendor/github.com/stevvooe/continuity/sysx/copy_linux.go new file mode 100644 index 0000000000..d7ccbb26ee --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/copy_linux.go @@ -0,0 +1,9 @@ +package sysx + +// These functions will be generated by generate.sh +// $ GOOS=linux GOARCH=386 ./generate.sh copy +// $ GOOS=linux GOARCH=amd64 ./generate.sh copy +// $ GOOS=linux GOARCH=arm ./generate.sh copy +// $ GOOS=linux GOARCH=arm64 ./generate.sh copy + +//sys CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) diff --git a/vendor/github.com/stevvooe/continuity/sysx/copy_linux_386.go b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_386.go new file mode 100644 index 0000000000..c1368c5723 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_386.go @@ -0,0 +1,20 @@ +// mksyscall.pl -l32 copy_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) { + r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/copy_linux_amd64.go b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_amd64.go new file mode 100644 index 0000000000..9941b01f09 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_amd64.go @@ -0,0 +1,20 @@ +// mksyscall.pl copy_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) { + r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/copy_linux_arm.go b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_arm.go new file mode 100644 index 0000000000..c1368c5723 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_arm.go @@ -0,0 +1,20 @@ +// mksyscall.pl -l32 copy_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) { + r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/copy_linux_arm64.go b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_arm64.go new file mode 100644 index 0000000000..9941b01f09 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/copy_linux_arm64.go @@ -0,0 +1,20 @@ +// mksyscall.pl copy_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func CopyFileRange(fdin uintptr, offin *int64, fdout uintptr, offout *int64, len int, flags int) (n int, err error) { + r0, _, e1 := syscall.Syscall6(SYS_COPY_FILE_RANGE, uintptr(fdin), uintptr(unsafe.Pointer(offin)), uintptr(fdout), uintptr(unsafe.Pointer(offout)), uintptr(len), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/nodata_linux.go b/vendor/github.com/stevvooe/continuity/sysx/nodata_linux.go new file mode 100644 index 0000000000..fc47ddb8dc --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/nodata_linux.go @@ -0,0 +1,7 @@ +package sysx + +import ( + "syscall" +) + +const ENODATA = syscall.ENODATA diff --git a/vendor/github.com/stevvooe/continuity/sysx/nodata_unix.go b/vendor/github.com/stevvooe/continuity/sysx/nodata_unix.go new file mode 100644 index 0000000000..7e6851209f --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/nodata_unix.go @@ -0,0 +1,9 @@ +// +build darwin freebsd + +package sysx + +import ( + "syscall" +) + +const ENODATA = syscall.ENOATTR diff --git a/vendor/github.com/stevvooe/continuity/sysx/sys.go b/vendor/github.com/stevvooe/continuity/sysx/sys.go new file mode 100644 index 0000000000..0bb1676283 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/sys.go @@ -0,0 +1,37 @@ +package sysx + +import ( + "syscall" + "unsafe" +) + +var _zero uintptr + +// use is a no-op, but the compiler cannot see that it is. +// Calling use(p) ensures that p is kept live until that point. +//go:noescape +func use(p unsafe.Pointer) + +// Do the interface allocations only once for common +// Errno values. +var ( + errEAGAIN error = syscall.EAGAIN + errEINVAL error = syscall.EINVAL + errENOENT error = syscall.ENOENT +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case syscall.EAGAIN: + return errEAGAIN + case syscall.EINVAL: + return errEINVAL + case syscall.ENOENT: + return errENOENT + } + return e +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_386.go b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_386.go new file mode 100644 index 0000000000..0063f8a913 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_386.go @@ -0,0 +1,7 @@ +package sysx + +const ( + // SYS_COPYFILERANGE defined in Kernel 4.5+ + // Number defined in /usr/include/asm/unistd_32.h + SYS_COPY_FILE_RANGE = 377 +) diff --git a/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_amd64.go b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_amd64.go new file mode 100644 index 0000000000..4170540c5d --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_amd64.go @@ -0,0 +1,7 @@ +package sysx + +const ( + // SYS_COPYFILERANGE defined in Kernel 4.5+ + // Number defined in /usr/include/asm/unistd_64.h + SYS_COPY_FILE_RANGE = 326 +) diff --git a/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_arm.go b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_arm.go new file mode 100644 index 0000000000..a05dcbb5ef --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_arm.go @@ -0,0 +1,7 @@ +package sysx + +const ( + // SYS_COPY_FILE_RANGE defined in Kernel 4.5+ + // Number defined in /usr/include/arm-linux-gnueabihf/asm/unistd.h + SYS_COPY_FILE_RANGE = 391 +) diff --git a/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_arm64.go b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_arm64.go new file mode 100644 index 0000000000..da31bbd908 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/sysnum_linux_arm64.go @@ -0,0 +1,7 @@ +package sysx + +const ( + // SYS_COPY_FILE_RANGE defined in Kernel 4.5+ + // Number defined in /usr/include/asm-generic/unistd.h + SYS_COPY_FILE_RANGE = 285 +) diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr.go b/vendor/github.com/stevvooe/continuity/sysx/xattr.go new file mode 100644 index 0000000000..20937c2d4d --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr.go @@ -0,0 +1,67 @@ +package sysx + +import ( + "bytes" + "fmt" + "syscall" +) + +const defaultXattrBufferSize = 5 + +var ErrNotSupported = fmt.Errorf("not supported") + +type listxattrFunc func(path string, dest []byte) (int, error) + +func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) { + var p []byte // nil on first execution + + for { + n, err := listFunc(path, p) // first call gets buffer size. + if err != nil { + return nil, err + } + + if n > len(p) { + p = make([]byte, n) + continue + } + + p = p[:n] + + ps := bytes.Split(bytes.TrimSuffix(p, []byte{0}), []byte{0}) + var entries []string + for _, p := range ps { + s := string(p) + if s != "" { + entries = append(entries, s) + } + } + + return entries, nil + } +} + +type getxattrFunc func(string, string, []byte) (int, error) + +func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) { + p := make([]byte, defaultXattrBufferSize) + for { + n, err := getFunc(path, attr, p) + if err != nil { + if errno, ok := err.(syscall.Errno); ok && errno == syscall.ERANGE { + p = make([]byte, len(p)*2) // this can't be ideal. + continue // try again! + } + + return nil, err + } + + // realloc to correct size and repeat + if n > len(p) { + p = make([]byte, n) + continue + } + + return p[:n], nil + } +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin.go new file mode 100644 index 0000000000..1164a7d11c --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin.go @@ -0,0 +1,71 @@ +package sysx + +// These functions will be generated by generate.sh +// $ GOOS=darwin GOARCH=386 ./generate.sh xattr +// $ GOOS=darwin GOARCH=amd64 ./generate.sh xattr + +//sys getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) +//sys setxattr(path string, attr string, data []byte, flags int) (err error) +//sys removexattr(path string, attr string, options int) (err error) +//sys listxattr(path string, dest []byte, options int) (sz int, err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) + +const ( + xattrNoFollow = 0x01 +) + +func listxattrFollow(path string, dest []byte) (sz int, err error) { + return listxattr(path, dest, 0) +} + +// Listxattr calls syscall getxattr +func Listxattr(path string) ([]string, error) { + return listxattrAll(path, listxattrFollow) +} + +// Removexattr calls syscall getxattr +func Removexattr(path string, attr string) (err error) { + return removexattr(path, attr, 0) +} + +// Setxattr calls syscall setxattr +func Setxattr(path string, attr string, data []byte, flags int) (err error) { + return setxattr(path, attr, data, flags) +} + +func getxattrFollow(path, attr string, dest []byte) (sz int, err error) { + return getxattr(path, attr, dest, 0, 0) +} + +// Getxattr calls syscall getxattr +func Getxattr(path, attr string) ([]byte, error) { + return getxattrAll(path, attr, getxattrFollow) +} + +func listxattrNoFollow(path string, dest []byte) (sz int, err error) { + return listxattr(path, dest, xattrNoFollow) +} + +// LListxattr calls syscall listxattr with XATTR_NOFOLLOW +func LListxattr(path string) ([]string, error) { + return listxattrAll(path, listxattrNoFollow) +} + +// LRemovexattr calls syscall removexattr with XATTR_NOFOLLOW +func LRemovexattr(path string, attr string) (err error) { + return removexattr(path, attr, xattrNoFollow) +} + +// Setxattr calls syscall setxattr with XATTR_NOFOLLOW +func LSetxattr(path string, attr string, data []byte, flags int) (err error) { + return setxattr(path, attr, data, flags|xattrNoFollow) +} + +func getxattrNoFollow(path, attr string, dest []byte) (sz int, err error) { + return getxattr(path, attr, dest, 0, xattrNoFollow) +} + +// LGetxattr calls syscall getxattr with XATTR_NOFOLLOW +func LGetxattr(path, attr string) ([]byte, error) { + return getxattrAll(path, attr, getxattrNoFollow) +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin_386.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin_386.go new file mode 100644 index 0000000000..aa896b57fc --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin_386.go @@ -0,0 +1,111 @@ +// mksyscall.pl -l32 xattr_darwin.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func removexattr(path string, attr string, options int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func listxattr(path string, dest []byte, options int) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin_amd64.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin_amd64.go new file mode 100644 index 0000000000..6ff27e2703 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_darwin_amd64.go @@ -0,0 +1,111 @@ +// mksyscall.pl xattr_darwin.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func removexattr(path string, attr string, options int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func listxattr(path string, dest []byte, options int) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_freebsd.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_freebsd.go new file mode 100644 index 0000000000..80dba49aa5 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_freebsd.go @@ -0,0 +1,53 @@ +package sysx + +import ( + "errors" +) + +// Initial stub version for FreeBSD. FreeBSD has a different +// syscall API from Darwin and Linux for extended attributes; +// it is also not widely used. It is not exposed at all by the +// Go syscall package, so we need to implement directly eventually. + +var unsupported error = errors.New("extended attributes unsupported on FreeBSD") + +// Listxattr calls syscall listxattr and reads all content +// and returns a string array +func Listxattr(path string) ([]string, error) { + return []string{}, nil +} + +// Removexattr calls syscall removexattr +func Removexattr(path string, attr string) (err error) { + return unsupported +} + +// Setxattr calls syscall setxattr +func Setxattr(path string, attr string, data []byte, flags int) (err error) { + return unsupported +} + +// Getxattr calls syscall getxattr +func Getxattr(path, attr string) ([]byte, error) { + return []byte{}, nil +} + +// LListxattr lists xattrs, not following symlinks +func LListxattr(path string) ([]string, error) { + return []string{}, nil +} + +// LRemovexattr removes an xattr, not following symlinks +func LRemovexattr(path string, attr string) (err error) { + return unsupported +} + +// LSetxattr sets an xattr, not following symlinks +func LSetxattr(path string, attr string, data []byte, flags int) (err error) { + return unsupported +} + +// LGetxattr gets an xattr, not following symlinks +func LGetxattr(path, attr string) ([]byte, error) { + return []byte{}, nil +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux.go new file mode 100644 index 0000000000..cd18136343 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux.go @@ -0,0 +1,61 @@ +package sysx + +import "syscall" + +// These functions will be generated by generate.sh +// $ GOOS=linux GOARCH=386 ./generate.sh xattr +// $ GOOS=linux GOARCH=amd64 ./generate.sh xattr +// $ GOOS=linux GOARCH=arm ./generate.sh xattr +// $ GOOS=linux GOARCH=arm64 ./generate.sh xattr +// $ GOOS=linux GOARCH=ppc64 ./generate.sh xattr +// $ GOOS=linux GOARCH=ppc64le ./generate.sh xattr +// $ GOOS=linux GOARCH=s390x ./generate.sh xattr + +// Listxattr calls syscall listxattr and reads all content +// and returns a string array +func Listxattr(path string) ([]string, error) { + return listxattrAll(path, syscall.Listxattr) +} + +// Removexattr calls syscall removexattr +func Removexattr(path string, attr string) (err error) { + return syscall.Removexattr(path, attr) +} + +// Setxattr calls syscall setxattr +func Setxattr(path string, attr string, data []byte, flags int) (err error) { + return syscall.Setxattr(path, attr, data, flags) +} + +// Getxattr calls syscall getxattr +func Getxattr(path, attr string) ([]byte, error) { + return getxattrAll(path, attr, syscall.Getxattr) +} + +//sys llistxattr(path string, dest []byte) (sz int, err error) + +// LListxattr lists xattrs, not following symlinks +func LListxattr(path string) ([]string, error) { + return listxattrAll(path, llistxattr) +} + +//sys lremovexattr(path string, attr string) (err error) + +// LRemovexattr removes an xattr, not following symlinks +func LRemovexattr(path string, attr string) (err error) { + return lremovexattr(path, attr) +} + +//sys lsetxattr(path string, attr string, data []byte, flags int) (err error) + +// LSetxattr sets an xattr, not following symlinks +func LSetxattr(path string, attr string, data []byte, flags int) (err error) { + return lsetxattr(path, attr, data, flags) +} + +//sys lgetxattr(path string, attr string, dest []byte) (sz int, err error) + +// LGetxattr gets an xattr, not following symlinks +func LGetxattr(path, attr string) ([]byte, error) { + return getxattrAll(path, attr, lgetxattr) +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_386.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_386.go new file mode 100644 index 0000000000..c3e5c8e385 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_386.go @@ -0,0 +1,111 @@ +// mksyscall.pl -l32 xattr_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lgetxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_amd64.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_amd64.go new file mode 100644 index 0000000000..dec46faaaf --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_amd64.go @@ -0,0 +1,111 @@ +// mksyscall.pl xattr_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lgetxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_arm.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_arm.go new file mode 100644 index 0000000000..c3e5c8e385 --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_arm.go @@ -0,0 +1,111 @@ +// mksyscall.pl -l32 xattr_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lgetxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_arm64.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_arm64.go new file mode 100644 index 0000000000..dec46faaaf --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_arm64.go @@ -0,0 +1,111 @@ +// mksyscall.pl xattr_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lgetxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_ppc64.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_ppc64.go new file mode 100644 index 0000000000..dec46faaaf --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_ppc64.go @@ -0,0 +1,111 @@ +// mksyscall.pl xattr_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lgetxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_ppc64le.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_ppc64le.go new file mode 100644 index 0000000000..dec46faaaf --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_ppc64le.go @@ -0,0 +1,111 @@ +// mksyscall.pl xattr_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lgetxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_s390x.go b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_s390x.go new file mode 100644 index 0000000000..dec46faaaf --- /dev/null +++ b/vendor/github.com/stevvooe/continuity/sysx/xattr_linux_s390x.go @@ -0,0 +1,111 @@ +// mksyscall.pl xattr_linux.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + use(unsafe.Pointer(_p0)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := syscall.Syscall(syscall.SYS_LREMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lgetxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/tonistiigi/fsutil/LICENSE b/vendor/github.com/tonistiigi/fsutil/LICENSE new file mode 100644 index 0000000000..7df441d93e --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/LICENSE @@ -0,0 +1,22 @@ +MIT + +Copyright 2017 Tõnis Tiigi + +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. \ No newline at end of file diff --git a/vendor/github.com/tonistiigi/fsutil/diff.go b/vendor/github.com/tonistiigi/fsutil/diff.go new file mode 100644 index 0000000000..1530973784 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diff.go @@ -0,0 +1,37 @@ +package fsutil + +import ( + "os" + + "golang.org/x/net/context" +) + +type walkerFn func(ctx context.Context, pathC chan<- *currentPath) error + +func Changes(ctx context.Context, a, b walkerFn, changeFn ChangeFunc) error { + return nil +} + +type HandleChangeFn func(ChangeKind, string, os.FileInfo, error) error + +func GetWalkerFn(root string) walkerFn { + return func(ctx context.Context, pathC chan<- *currentPath) error { + return Walk(ctx, root, nil, func(path string, f os.FileInfo, err error) error { + if err != nil { + return err + } + + p := ¤tPath{ + path: path, + f: f, + } + + select { + case <-ctx.Done(): + return ctx.Err() + case pathC <- p: + return nil + } + }) + } +} diff --git a/vendor/github.com/tonistiigi/fsutil/diff_containerd.go b/vendor/github.com/tonistiigi/fsutil/diff_containerd.go new file mode 100644 index 0000000000..c7c9788e85 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diff_containerd.go @@ -0,0 +1,199 @@ +package fsutil + +import ( + "os" + "strings" + + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" +) + +// Everything below is copied from containerd/fs. TODO: remove duplication @dmcgowan + +// Const redefined because containerd/fs doesn't build on !linux + +// ChangeKind is the type of modification that +// a change is making. +type ChangeKind int + +const ( + // ChangeKindAdd represents an addition of + // a file + ChangeKindAdd ChangeKind = iota + + // ChangeKindModify represents a change to + // an existing file + ChangeKindModify + + // ChangeKindDelete represents a delete of + // a file + ChangeKindDelete +) + +// ChangeFunc is the type of function called for each change +// computed during a directory changes calculation. +type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error + +type currentPath struct { + path string + f os.FileInfo + // fullPath string +} + +// doubleWalkDiff walks both directories to create a diff +func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn) (err error) { + g, ctx := errgroup.WithContext(ctx) + + var ( + c1 = make(chan *currentPath, 128) + c2 = make(chan *currentPath, 128) + + f1, f2 *currentPath + rmdir string + ) + g.Go(func() error { + defer close(c1) + return a(ctx, c1) + }) + g.Go(func() error { + defer close(c2) + return b(ctx, c2) + }) + g.Go(func() error { + loop0: + for c1 != nil || c2 != nil { + if f1 == nil && c1 != nil { + f1, err = nextPath(ctx, c1) + if err != nil { + return err + } + if f1 == nil { + c1 = nil + } + } + + if f2 == nil && c2 != nil { + f2, err = nextPath(ctx, c2) + if err != nil { + return err + } + if f2 == nil { + c2 = nil + } + } + if f1 == nil && f2 == nil { + continue + } + + var f os.FileInfo + k, p := pathChange(f1, f2) + switch k { + case ChangeKindAdd: + if rmdir != "" { + rmdir = "" + } + f = f2.f + f2 = nil + case ChangeKindDelete: + // Check if this file is already removed by being + // under of a removed directory + if rmdir != "" && strings.HasPrefix(f1.path, rmdir) { + f1 = nil + continue + } else if rmdir == "" && f1.f.IsDir() { + rmdir = f1.path + string(os.PathSeparator) + } else if rmdir != "" { + rmdir = "" + } + f1 = nil + case ChangeKindModify: + same, err := sameFile(f1, f2) + if err != nil { + return err + } + if f1.f.IsDir() && !f2.f.IsDir() { + rmdir = f1.path + string(os.PathSeparator) + } else if rmdir != "" { + rmdir = "" + } + f = f2.f + f1 = nil + f2 = nil + if same { + continue loop0 + } + } + if err := changeFn(k, p, f, nil); err != nil { + return err + } + } + return nil + }) + + return g.Wait() +} + +func pathChange(lower, upper *currentPath) (ChangeKind, string) { + if lower == nil { + if upper == nil { + panic("cannot compare nil paths") + } + return ChangeKindAdd, upper.path + } + if upper == nil { + return ChangeKindDelete, lower.path + } + + switch i := ComparePath(lower.path, upper.path); { + case i < 0: + // File in lower that is not in upper + return ChangeKindDelete, lower.path + case i > 0: + // File in upper that is not in lower + return ChangeKindAdd, upper.path + default: + return ChangeKindModify, upper.path + } +} + +func sameFile(f1, f2 *currentPath) (same bool, retErr error) { + // If not a directory also check size, modtime, and content + if !f1.f.IsDir() { + if f1.f.Size() != f2.f.Size() { + return false, nil + } + + t1 := f1.f.ModTime() + t2 := f2.f.ModTime() + if t1.UnixNano() != t2.UnixNano() { + return false, nil + } + } + + ls1, ok := f1.f.Sys().(*Stat) + if !ok { + return false, nil + } + ls2, ok := f1.f.Sys().(*Stat) + if !ok { + return false, nil + } + + return compareStat(ls1, ls2) +} + +// compareStat returns whether the stats are equivalent, +// whether the files are considered the same file, and +// an error +func compareStat(ls1, ls2 *Stat) (bool, error) { + return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Devmajor == ls2.Devmajor && ls1.Devminor == ls2.Devminor && ls1.Linkname == ls2.Linkname, nil +} + +func nextPath(ctx context.Context, pathC <-chan *currentPath) (*currentPath, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case p := <-pathC: + return p, nil + } +} diff --git a/vendor/github.com/tonistiigi/fsutil/diff_containerd_linux.go b/vendor/github.com/tonistiigi/fsutil/diff_containerd_linux.go new file mode 100644 index 0000000000..3c9f078f5e --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diff_containerd_linux.go @@ -0,0 +1,37 @@ +package fsutil + +import ( + "bytes" + "syscall" + + "github.com/pkg/errors" + "github.com/stevvooe/continuity/sysx" +) + +// compareSysStat returns whether the stats are equivalent, +// whether the files are considered the same file, and +// an error +func compareSysStat(s1, s2 interface{}) (bool, error) { + ls1, ok := s1.(*syscall.Stat_t) + if !ok { + return false, nil + } + ls2, ok := s2.(*syscall.Stat_t) + if !ok { + return false, nil + } + + return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Rdev == ls2.Rdev, nil +} + +func compareCapabilities(p1, p2 string) (bool, error) { + c1, err := sysx.LGetxattr(p1, "security.capability") + if err != nil && err != syscall.ENODATA { + return false, errors.Wrapf(err, "failed to get xattr for %s", p1) + } + c2, err := sysx.LGetxattr(p2, "security.capability") + if err != nil && err != syscall.ENODATA { + return false, errors.Wrapf(err, "failed to get xattr for %s", p2) + } + return bytes.Equal(c1, c2), nil +} diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter.go b/vendor/github.com/tonistiigi/fsutil/diskwriter.go new file mode 100644 index 0000000000..a54b4a737a --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diskwriter.go @@ -0,0 +1,353 @@ +// +build linux windows + +package fsutil + +import ( + "archive/tar" + "crypto/sha256" + "encoding/hex" + "hash" + "io" + "os" + "path/filepath" + "strconv" + "sync" + "time" + + "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/pkg/tarsum" + "github.com/pkg/errors" + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" +) + +type WriteToFunc func(context.Context, string, io.WriteCloser) error + +type DiskWriterOpt struct { + AsyncDataCb WriteToFunc + SyncDataCb WriteToFunc + NotifyCb func(ChangeKind, string, os.FileInfo, error) error +} + +type DiskWriter struct { + opt DiskWriterOpt + dest string + + wg sync.WaitGroup + ctx context.Context + cancel func() + eg *errgroup.Group +} + +func NewDiskWriter(ctx context.Context, dest string, opt DiskWriterOpt) (*DiskWriter, error) { + if opt.SyncDataCb == nil && opt.AsyncDataCb == nil { + return nil, errors.New("no data callback specified") + } + if opt.SyncDataCb != nil && opt.AsyncDataCb != nil { + return nil, errors.New("can't specify both sync and async data callbacks") + } + + ctx, cancel := context.WithCancel(ctx) + eg, ctx := errgroup.WithContext(ctx) + + return &DiskWriter{ + opt: opt, + dest: dest, + eg: eg, + ctx: ctx, + cancel: cancel, + }, nil +} + +func (dw *DiskWriter) Wait(ctx context.Context) error { + return dw.eg.Wait() +} + +func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, err error) (retErr error) { + if err != nil { + return err + } + + select { + case <-dw.ctx.Done(): + return dw.ctx.Err() + default: + } + + defer func() { + if retErr != nil { + dw.cancel() + } + }() + + p = filepath.FromSlash(p) + + destPath := filepath.Join(dw.dest, p) + + if kind == ChangeKindDelete { + // todo: no need to validate if diff is trusted but is it always? + if err := os.RemoveAll(destPath); err != nil { + return errors.Wrapf(err, "failed to remove: %s", destPath) + } + if dw.opt.NotifyCb != nil { + if err := dw.opt.NotifyCb(kind, p, nil, nil); err != nil { + return err + } + } + return nil + } + + stat, ok := fi.Sys().(*Stat) + if !ok { + return errors.Errorf("%s invalid change without stat information", p) + } + + rename := true + oldFi, err := os.Lstat(destPath) + if err != nil { + if os.IsNotExist(err) { + if kind != ChangeKindAdd { + return errors.Wrapf(err, "invalid addition: %s", destPath) + } + rename = false + } else { + return errors.Wrapf(err, "failed to stat %s", destPath) + } + } + + if oldFi != nil && fi.IsDir() && oldFi.IsDir() { + if err := rewriteMetadata(destPath, stat); err != nil { + return errors.Wrapf(err, "error setting dir metadata for %s", destPath) + } + return nil + } + + newPath := destPath + if rename { + newPath = filepath.Join(filepath.Dir(destPath), ".tmp."+nextSuffix()) + } + + isRegularFile := false + + switch { + case fi.IsDir(): + if err := os.Mkdir(newPath, fi.Mode()); err != nil { + return errors.Wrapf(err, "failed to create dir %s", newPath) + } + case fi.Mode()&os.ModeDevice != 0 || fi.Mode()&os.ModeNamedPipe != 0: + if err := handleTarTypeBlockCharFifo(newPath, stat); err != nil { + return errors.Wrapf(err, "failed to create device %s", newPath) + } + case fi.Mode()&os.ModeSymlink != 0: + if err := os.Symlink(stat.Linkname, newPath); err != nil { + return errors.Wrapf(err, "failed to symlink %s", newPath) + } + case stat.Linkname != "": + if err := os.Link(filepath.Join(dw.dest, stat.Linkname), newPath); err != nil { + return errors.Wrapf(err, "failed to link %s to %s", newPath, stat.Linkname) + } + default: + isRegularFile = true + file, err := os.OpenFile(newPath, os.O_CREATE|os.O_WRONLY, fi.Mode()) //todo: windows + if err != nil { + return errors.Wrapf(err, "failed to create %s", newPath) + } + if dw.opt.SyncDataCb != nil { + if err := dw.processChange(ChangeKindAdd, p, fi, file); err != nil { + file.Close() + return err + } + break + } + if err := file.Close(); err != nil { + return errors.Wrapf(err, "failed to close %s", newPath) + } + } + + if err := rewriteMetadata(newPath, stat); err != nil { + return errors.Wrapf(err, "error setting metadata for %s", newPath) + } + + if rename { + if err := os.Rename(newPath, destPath); err != nil { + return errors.Wrapf(err, "failed to rename %s to %s", newPath, destPath) + } + } + + if isRegularFile { + if dw.opt.AsyncDataCb != nil { + dw.requestAsyncFileData(p, destPath, fi) + } + } else { + return dw.processChange(kind, p, fi, nil) + } + + return nil +} + +func (dw *DiskWriter) requestAsyncFileData(p, dest string, fi os.FileInfo) { + // todo: limit worker threads + dw.eg.Go(func() error { + if err := dw.processChange(ChangeKindAdd, p, fi, &lazyFileWriter{ + dest: dest, + }); err != nil { + return err + } + return chtimes(dest, fi.ModTime().UnixNano()) // TODO: parent dirs + }) +} + +func (dw *DiskWriter) processChange(kind ChangeKind, p string, fi os.FileInfo, w io.WriteCloser) error { + origw := w + var hw *hashedWriter + if dw.opt.NotifyCb != nil { + var err error + if hw, err = newHashWriter(p, fi, w); err != nil { + return err + } + w = hw + } + if origw != nil { + fn := dw.opt.SyncDataCb + if fn == nil && dw.opt.AsyncDataCb != nil { + fn = dw.opt.AsyncDataCb + } + if err := fn(dw.ctx, p, w); err != nil { + return err + } + } else { + if hw != nil { + hw.Close() + } + } + if hw != nil { + return dw.opt.NotifyCb(kind, p, hw, nil) + } + return nil +} + +type hashedWriter struct { + os.FileInfo + io.Writer + h hash.Hash + w io.WriteCloser + sum string +} + +func newHashWriter(p string, fi os.FileInfo, w io.WriteCloser) (*hashedWriter, error) { + h, err := NewTarsumHash(p, fi) + if err != nil { + return nil, err + } + hw := &hashedWriter{ + FileInfo: fi, + Writer: io.MultiWriter(w, h), + h: h, + w: w, + } + return hw, nil +} + +func (hw *hashedWriter) Close() error { + hw.sum = string(hex.EncodeToString(hw.h.Sum(nil))) + if hw.w != nil { + return hw.w.Close() + } + return nil +} + +func (hw *hashedWriter) Hash() string { + return hw.sum +} + +type lazyFileWriter struct { + dest string + ctx context.Context + f *os.File +} + +func (lfw *lazyFileWriter) Write(dt []byte) (int, error) { + if lfw.f == nil { + file, err := os.OpenFile(lfw.dest, os.O_WRONLY, 0) //todo: windows + if err != nil { + return 0, errors.Wrapf(err, "failed to open %s", lfw.dest) + } + lfw.f = file + } + return lfw.f.Write(dt) +} + +func (lfw *lazyFileWriter) Close() error { + if lfw.f != nil { + return lfw.f.Close() + } + return nil +} + +func mkdev(major int64, minor int64) uint32 { + return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff)) +} + +// Random number state. +// We generate random temporary file names so that there's a good +// chance the file doesn't exist yet - keeps the number of tries in +// TempFile to a minimum. +var rand uint32 +var randmu sync.Mutex + +func reseed() uint32 { + return uint32(time.Now().UnixNano() + int64(os.Getpid())) +} + +func nextSuffix() string { + randmu.Lock() + r := rand + if r == 0 { + r = reseed() + } + r = r*1664525 + 1013904223 // constants from Numerical Recipes + rand = r + randmu.Unlock() + return strconv.Itoa(int(1e9 + r%1e9))[1:] +} + +func NewTarsumHash(p string, fi os.FileInfo) (hash.Hash, error) { + stat, ok := fi.Sys().(*Stat) + link := "" + if ok { + link = stat.Linkname + } + if fi.IsDir() { + p += string(os.PathSeparator) + } + h, err := archive.FileInfoHeader(p, fi, link) + if err != nil { + return nil, err + } + h.Name = p + if ok { + h.Uid = int(stat.Uid) + h.Gid = int(stat.Gid) + h.Linkname = stat.Linkname + if stat.Xattrs != nil { + h.Xattrs = make(map[string]string) + for k, v := range stat.Xattrs { + h.Xattrs[k] = string(v) + } + } + } + tsh := &tarsumHash{h: h, Hash: sha256.New()} + tsh.Reset() + return tsh, nil +} + +// Reset resets the Hash to its initial state. +func (tsh *tarsumHash) Reset() { + tsh.Hash.Reset() + tarsum.WriteV1Header(tsh.h, tsh.Hash) +} + +type tarsumHash struct { + hash.Hash + h *tar.Header +} diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_linux.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_linux.go new file mode 100644 index 0000000000..c6d97eb0a6 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_linux.go @@ -0,0 +1,64 @@ +// +build linux + +package fsutil + +import ( + "os" + "syscall" + + "github.com/pkg/errors" + "github.com/stevvooe/continuity/sysx" + "golang.org/x/sys/unix" +) + +func rewriteMetadata(p string, stat *Stat) error { + for key, value := range stat.Xattrs { + sysx.Setxattr(p, key, value, 0) + } + + if err := os.Lchown(p, int(stat.Uid), int(stat.Gid)); err != nil { + return errors.Wrapf(err, "failed to lchown %s", p) + } + + if os.FileMode(stat.Mode)&os.ModeSymlink == 0 { + if err := os.Chmod(p, os.FileMode(stat.Mode)); err != nil { + return errors.Wrapf(err, "failed to chown %s", p) + } + } + + if err := chtimes(p, stat.ModTime); err != nil { + return errors.Wrapf(err, "failed to chtimes %s", p) + } + + return nil +} + +func chtimes(path string, un int64) error { + var utimes [2]unix.Timespec + utimes[0] = unix.NsecToTimespec(un) + utimes[1] = utimes[0] + + if err := unix.UtimesNanoAt(unix.AT_FDCWD, path, utimes[0:], unix.AT_SYMLINK_NOFOLLOW); err != nil { + return errors.Wrap(err, "failed call to UtimesNanoAt") + } + + return nil +} + +// handleTarTypeBlockCharFifo is an OS-specific helper function used by +// createTarFile to handle the following types of header: Block; Char; Fifo +func handleTarTypeBlockCharFifo(path string, stat *Stat) error { + mode := uint32(stat.Mode & 07777) + if os.FileMode(stat.Mode)&os.ModeCharDevice != 0 { + mode |= syscall.S_IFCHR + } else if os.FileMode(stat.Mode)&os.ModeNamedPipe != 0 { + mode |= syscall.S_IFIFO + } else { + mode |= syscall.S_IFBLK + } + + if err := syscall.Mknod(path, mode, int(mkdev(stat.Devmajor, stat.Devminor))); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go new file mode 100644 index 0000000000..16a26f01c5 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_windows.go @@ -0,0 +1,25 @@ +// +build windows + +package fsutil + +import ( + "os" + "time" + + "github.com/pkg/errors" +) + +func rewriteMetadata(p string, stat *Stat) error { + return chtimes(p, stat.ModTime) +} + +func chtimes(path string, un int64) error { + mtime := time.Unix(0, un) + return os.Chtimes(path, mtime, mtime) +} + +// handleTarTypeBlockCharFifo is an OS-specific helper function used by +// createTarFile to handle the following types of header: Block; Char; Fifo +func handleTarTypeBlockCharFifo(path string, stat *Stat) error { + return errors.New("Not implemented on windows") +} diff --git a/vendor/github.com/tonistiigi/fsutil/generate.go b/vendor/github.com/tonistiigi/fsutil/generate.go new file mode 100644 index 0000000000..e433195669 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/generate.go @@ -0,0 +1,3 @@ +package fsutil + +//go:generate protoc --gogoslick_out=. stat.proto wire.proto diff --git a/vendor/github.com/tonistiigi/fsutil/hardlinks.go b/vendor/github.com/tonistiigi/fsutil/hardlinks.go new file mode 100644 index 0000000000..e598ead7e6 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/hardlinks.go @@ -0,0 +1,46 @@ +package fsutil + +import ( + "os" + + "github.com/pkg/errors" +) + +// Hardlinks validates that all targets for links were part of the changes + +type Hardlinks struct { + seenFiles map[string]struct{} +} + +func (v *Hardlinks) HandleChange(kind ChangeKind, p string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + if v.seenFiles == nil { + v.seenFiles = make(map[string]struct{}) + } + + if kind == ChangeKindDelete { + return nil + } + + stat, ok := fi.Sys().(*Stat) + if !ok { + return errors.Errorf("invalid change without stat info: %s", p) + } + + if fi.IsDir() || fi.Mode()&os.ModeSymlink != 0 { + return nil + } + + if len(stat.Linkname) > 0 { + if _, ok := v.seenFiles[stat.Linkname]; !ok { + return errors.Errorf("invalid link %s to unknown path: %q", p, stat.Linkname) + } + } else { + v.seenFiles[p] = struct{}{} + } + + return nil +} diff --git a/vendor/github.com/tonistiigi/fsutil/readme.md b/vendor/github.com/tonistiigi/fsutil/readme.md new file mode 100644 index 0000000000..5ce685b7ed --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/readme.md @@ -0,0 +1,45 @@ +Incremental file directory sync tools in golang. + +``` +BENCH_FILE_SIZE=10000 ./bench.test --test.bench . +BenchmarkCopyWithTar10-4 2000 995242 ns/op +BenchmarkCopyWithTar50-4 300 4710021 ns/op +BenchmarkCopyWithTar200-4 100 16627260 ns/op +BenchmarkCopyWithTar1000-4 20 60031459 ns/op +BenchmarkCPA10-4 1000 1678367 ns/op +BenchmarkCPA50-4 500 3690306 ns/op +BenchmarkCPA200-4 200 9495066 ns/op +BenchmarkCPA1000-4 50 29769289 ns/op +BenchmarkDiffCopy10-4 2000 943889 ns/op +BenchmarkDiffCopy50-4 500 3285950 ns/op +BenchmarkDiffCopy200-4 200 8563792 ns/op +BenchmarkDiffCopy1000-4 50 29511340 ns/op +BenchmarkDiffCopyProto10-4 2000 944615 ns/op +BenchmarkDiffCopyProto50-4 500 3334940 ns/op +BenchmarkDiffCopyProto200-4 200 9420038 ns/op +BenchmarkDiffCopyProto1000-4 50 30632429 ns/op +BenchmarkIncrementalDiffCopy10-4 2000 691993 ns/op +BenchmarkIncrementalDiffCopy50-4 1000 1304253 ns/op +BenchmarkIncrementalDiffCopy200-4 500 3306519 ns/op +BenchmarkIncrementalDiffCopy1000-4 200 10211343 ns/op +BenchmarkIncrementalDiffCopy5000-4 20 55194427 ns/op +BenchmarkIncrementalDiffCopy10000-4 20 91759289 ns/op +BenchmarkIncrementalCopyWithTar10-4 2000 1020258 ns/op +BenchmarkIncrementalCopyWithTar50-4 300 5348786 ns/op +BenchmarkIncrementalCopyWithTar200-4 100 19495000 ns/op +BenchmarkIncrementalCopyWithTar1000-4 20 70338507 ns/op +BenchmarkIncrementalRsync10-4 30 45215754 ns/op +BenchmarkIncrementalRsync50-4 30 45837260 ns/op +BenchmarkIncrementalRsync200-4 30 48780614 ns/op +BenchmarkIncrementalRsync1000-4 20 54801892 ns/op +BenchmarkIncrementalRsync5000-4 20 84782542 ns/op +BenchmarkIncrementalRsync10000-4 10 103355108 ns/op +BenchmarkRsync10-4 30 46776470 ns/op +BenchmarkRsync50-4 30 48601555 ns/op +BenchmarkRsync200-4 20 59642691 ns/op +BenchmarkRsync1000-4 20 101343010 ns/op +BenchmarkGnuTar10-4 500 3171448 ns/op +BenchmarkGnuTar50-4 300 5030296 ns/op +BenchmarkGnuTar200-4 100 10464313 ns/op +BenchmarkGnuTar1000-4 50 30375257 ns/op +``` \ No newline at end of file diff --git a/vendor/github.com/tonistiigi/fsutil/receive.go b/vendor/github.com/tonistiigi/fsutil/receive.go new file mode 100644 index 0000000000..e7cee2b7ce --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/receive.go @@ -0,0 +1,210 @@ +// +build linux windows + +package fsutil + +import ( + "io" + "os" + "sync" + + "github.com/pkg/errors" + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" +) + +func Receive(ctx context.Context, conn Stream, dest string, notifyHashed ChangeFunc) error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + r := &receiver{ + conn: &syncStream{Stream: conn}, + dest: dest, + files: make(map[string]uint32), + pipes: make(map[uint32]io.WriteCloser), + notifyHashed: notifyHashed, + } + return r.run(ctx) +} + +type receiver struct { + dest string + conn Stream + files map[string]uint32 + pipes map[uint32]io.WriteCloser + mu sync.RWMutex + muPipes sync.RWMutex + + notifyHashed ChangeFunc + orderValidator Validator + hlValidator Hardlinks +} + +type dynamicWalker struct { + walkChan chan *currentPath + closed bool +} + +func newDynamicWalker() *dynamicWalker { + return &dynamicWalker{ + walkChan: make(chan *currentPath, 128), + } +} + +func (w *dynamicWalker) update(p *currentPath) error { + if w.closed { + return errors.New("walker is closed") + } + if p == nil { + close(w.walkChan) + return nil + } + w.walkChan <- p + return nil +} + +func (w *dynamicWalker) fill(ctx context.Context, pathC chan<- *currentPath) error { + for { + select { + case p, ok := <-w.walkChan: + if !ok { + return nil + } + pathC <- p + case <-ctx.Done(): + return ctx.Err() + } + } + return nil +} + +func (r *receiver) run(ctx context.Context) error { + g, ctx := errgroup.WithContext(ctx) + + dw, err := NewDiskWriter(ctx, r.dest, DiskWriterOpt{ + AsyncDataCb: r.asyncDataFunc, + NotifyCb: r.notifyHashed, + }) + if err != nil { + return err + } + + w := newDynamicWalker() + + g.Go(func() error { + err := doubleWalkDiff(ctx, dw.HandleChange, GetWalkerFn(r.dest), w.fill) + if err != nil { + return err + } + if err := dw.Wait(ctx); err != nil { + return err + } + r.conn.SendMsg(&Packet{Type: PACKET_FIN}) + return nil + }) + + g.Go(func() error { + var i uint32 = 0 + + var p Packet + for { + p = Packet{Data: p.Data[:0]} + if err := r.conn.RecvMsg(&p); err != nil { + return err + } + switch p.Type { + case PACKET_STAT: + if p.Stat == nil { + if err := w.update(nil); err != nil { + return err + } + break + } + if fileCanRequestData(os.FileMode(p.Stat.Mode)) { + r.mu.Lock() + r.files[p.Stat.Path] = i + r.mu.Unlock() + } + i++ + cp := ¤tPath{path: p.Stat.Path, f: &StatInfo{p.Stat}} + if err := r.orderValidator.HandleChange(ChangeKindAdd, cp.path, cp.f, nil); err != nil { + return err + } + if err := r.hlValidator.HandleChange(ChangeKindAdd, cp.path, cp.f, nil); err != nil { + return err + } + if err := w.update(cp); err != nil { + return err + } + case PACKET_DATA: + r.muPipes.Lock() + pw, ok := r.pipes[p.ID] + r.muPipes.Unlock() + if !ok { + return errors.Errorf("invalid file request %s", p.ID) + } + if len(p.Data) == 0 { + if err := pw.Close(); err != nil { + return err + } + } else { + if _, err := pw.Write(p.Data); err != nil { + return err + } + } + case PACKET_FIN: + return nil + } + } + }) + return g.Wait() +} + +func (r *receiver) asyncDataFunc(ctx context.Context, p string, wc io.WriteCloser) error { + r.mu.Lock() + id, ok := r.files[p] + if !ok { + r.mu.Unlock() + return errors.Errorf("invalid file request %s", p) + } + delete(r.files, p) + r.mu.Unlock() + + wwc := newWrappedWriteCloser(wc) + r.muPipes.Lock() + r.pipes[id] = wwc + r.muPipes.Unlock() + if err := r.conn.SendMsg(&Packet{Type: PACKET_REQ, ID: id}); err != nil { + return err + } + err := wwc.Wait(ctx) + r.muPipes.Lock() + delete(r.pipes, id) + r.muPipes.Unlock() + return err +} + +type wrappedWriteCloser struct { + io.WriteCloser + err error + once sync.Once + done chan struct{} +} + +func newWrappedWriteCloser(wc io.WriteCloser) *wrappedWriteCloser { + return &wrappedWriteCloser{WriteCloser: wc, done: make(chan struct{})} +} + +func (w *wrappedWriteCloser) Close() error { + w.err = w.WriteCloser.Close() + w.once.Do(func() { close(w.done) }) + return w.err +} + +func (w *wrappedWriteCloser) Wait(ctx context.Context) error { + select { + case <-ctx.Done(): + return ctx.Err() + case <-w.done: + return w.err + } +} diff --git a/vendor/github.com/tonistiigi/fsutil/receive_unsupported.go b/vendor/github.com/tonistiigi/fsutil/receive_unsupported.go new file mode 100644 index 0000000000..8e83342374 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/receive_unsupported.go @@ -0,0 +1,14 @@ +// +build !linux,!windows + +package fsutil + +import ( + "runtime" + + "github.com/pkg/errors" + "golang.org/x/net/context" +) + +func Receive(ctx context.Context, conn Stream, dest string, notifyHashed ChangeFunc) error { + return errors.Errorf("receive is unsupported in %s", runtime.GOOS) +} diff --git a/vendor/github.com/tonistiigi/fsutil/send.go b/vendor/github.com/tonistiigi/fsutil/send.go new file mode 100644 index 0000000000..c7b6382c6c --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/send.go @@ -0,0 +1,201 @@ +package fsutil + +import ( + "io" + "os" + "path/filepath" + "sync" + + "github.com/pkg/errors" + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" +) + +var bufPool = sync.Pool{ + New: func() interface{} { + return make([]byte, 32*1<<10) + }, +} + +type Stream interface { + RecvMsg(interface{}) error + SendMsg(m interface{}) error + Context() context.Context +} + +func Send(ctx context.Context, conn Stream, root string, opt *WalkOpt, progressCb func(int, bool)) error { + s := &sender{ + conn: &syncStream{Stream: conn}, + root: root, + opt: opt, + files: make(map[uint32]string), + progressCb: progressCb, + sendpipeline: make(chan *sendHandle, 128), + } + return s.run(ctx) +} + +type sendHandle struct { + id uint32 + path string +} + +type sender struct { + conn Stream + opt *WalkOpt + root string + files map[uint32]string + mu sync.RWMutex + progressCb func(int, bool) + progressCurrent int + sendpipeline chan *sendHandle +} + +func (s *sender) run(ctx context.Context) error { + g, ctx := errgroup.WithContext(ctx) + + defer s.updateProgress(0, true) + + g.Go(func() error { + return s.walk(ctx) + }) + + for i := 0; i < 4; i++ { + g.Go(func() error { + for h := range s.sendpipeline { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if err := s.sendFile(h); err != nil { + return err + } + } + return nil + }) + } + + g.Go(func() error { + defer close(s.sendpipeline) + + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + var p Packet + if err := s.conn.RecvMsg(&p); err != nil { + return err + } + switch p.Type { + case PACKET_REQ: + if err := s.queue(p.ID); err != nil { + return err + } + case PACKET_FIN: + return s.conn.SendMsg(&Packet{Type: PACKET_FIN}) + } + } + }) + + return g.Wait() +} + +func (s *sender) updateProgress(size int, last bool) { + if s.progressCb != nil { + s.progressCurrent += size + s.progressCb(s.progressCurrent, last) + } +} + +func (s *sender) queue(id uint32) error { + s.mu.Lock() + p, ok := s.files[id] + if !ok { + s.mu.Unlock() + return errors.Errorf("invalid file id %d", id) + } + delete(s.files, id) + s.mu.Unlock() + s.sendpipeline <- &sendHandle{id, p} + return nil +} + +func (s *sender) sendFile(h *sendHandle) error { + f, err := os.Open(filepath.Join(s.root, h.path)) + if err == nil { + buf := bufPool.Get().([]byte) + defer bufPool.Put(buf) + if _, err := io.CopyBuffer(&fileSender{sender: s, id: h.id}, f, buf); err != nil { + return err + } + } + return s.conn.SendMsg(&Packet{ID: h.id, Type: PACKET_DATA}) +} + +func (s *sender) walk(ctx context.Context) error { + var i uint32 = 0 + err := Walk(ctx, s.root, s.opt, func(path string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + stat, ok := fi.Sys().(*Stat) + if !ok { + return errors.Wrapf(err, "invalid fileinfo without stat info: %s", path) + } + + p := &Packet{ + Type: PACKET_STAT, + Stat: stat, + } + if fileCanRequestData(os.FileMode(stat.Mode)) { + s.mu.Lock() + s.files[i] = stat.Path + s.mu.Unlock() + } + i++ + s.updateProgress(p.Size(), false) + return errors.Wrapf(s.conn.SendMsg(p), "failed to send stat %s", path) + }) + if err != nil { + return err + } + return errors.Wrapf(s.conn.SendMsg(&Packet{Type: PACKET_STAT}), "failed to send last stat") +} + +func fileCanRequestData(m os.FileMode) bool { + // avoid updating this function as it needs to match between sender/receiver. + // version if needed + return m&os.ModeType == 0 +} + +type fileSender struct { + sender *sender + id uint32 +} + +func (fs *fileSender) Write(dt []byte) (int, error) { + if len(dt) == 0 { + return 0, nil + } + p := &Packet{Type: PACKET_DATA, ID: fs.id, Data: dt} + if err := fs.sender.conn.SendMsg(p); err != nil { + return 0, err + } + fs.sender.updateProgress(p.Size(), false) + return len(dt), nil +} + +type syncStream struct { + Stream + mu sync.Mutex +} + +func (ss *syncStream) SendMsg(m interface{}) error { + ss.mu.Lock() + err := ss.Stream.SendMsg(m) + ss.mu.Unlock() + return err +} diff --git a/vendor/github.com/tonistiigi/fsutil/stat.pb.go b/vendor/github.com/tonistiigi/fsutil/stat.pb.go new file mode 100644 index 0000000000..3f6925e4b0 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/stat.pb.go @@ -0,0 +1,931 @@ +// Code generated by protoc-gen-gogo. +// source: stat.proto +// DO NOT EDIT! + +/* + Package fsutil is a generated protocol buffer package. + + It is generated from these files: + stat.proto + wire.proto + + It has these top-level messages: + Stat + Packet +*/ +package fsutil + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" + +import bytes "bytes" + +import strings "strings" +import reflect "reflect" +import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type Stat struct { + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + Mode uint32 `protobuf:"varint,2,opt,name=mode,proto3" json:"mode,omitempty"` + Uid uint32 `protobuf:"varint,3,opt,name=uid,proto3" json:"uid,omitempty"` + Gid uint32 `protobuf:"varint,4,opt,name=gid,proto3" json:"gid,omitempty"` + Size_ int64 `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"` + ModTime int64 `protobuf:"varint,6,opt,name=modTime,proto3" json:"modTime,omitempty"` + // int32 typeflag = 7; + Linkname string `protobuf:"bytes,7,opt,name=linkname,proto3" json:"linkname,omitempty"` + Devmajor int64 `protobuf:"varint,8,opt,name=devmajor,proto3" json:"devmajor,omitempty"` + Devminor int64 `protobuf:"varint,9,opt,name=devminor,proto3" json:"devminor,omitempty"` + Xattrs map[string][]byte `protobuf:"bytes,10,rep,name=xattrs" json:"xattrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (m *Stat) Reset() { *m = Stat{} } +func (*Stat) ProtoMessage() {} +func (*Stat) Descriptor() ([]byte, []int) { return fileDescriptorStat, []int{0} } + +func (m *Stat) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *Stat) GetMode() uint32 { + if m != nil { + return m.Mode + } + return 0 +} + +func (m *Stat) GetUid() uint32 { + if m != nil { + return m.Uid + } + return 0 +} + +func (m *Stat) GetGid() uint32 { + if m != nil { + return m.Gid + } + return 0 +} + +func (m *Stat) GetSize_() int64 { + if m != nil { + return m.Size_ + } + return 0 +} + +func (m *Stat) GetModTime() int64 { + if m != nil { + return m.ModTime + } + return 0 +} + +func (m *Stat) GetLinkname() string { + if m != nil { + return m.Linkname + } + return "" +} + +func (m *Stat) GetDevmajor() int64 { + if m != nil { + return m.Devmajor + } + return 0 +} + +func (m *Stat) GetDevminor() int64 { + if m != nil { + return m.Devminor + } + return 0 +} + +func (m *Stat) GetXattrs() map[string][]byte { + if m != nil { + return m.Xattrs + } + return nil +} + +func init() { + proto.RegisterType((*Stat)(nil), "fsutil.Stat") +} +func (this *Stat) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*Stat) + if !ok { + that2, ok := that.(Stat) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if this.Path != that1.Path { + return false + } + if this.Mode != that1.Mode { + return false + } + if this.Uid != that1.Uid { + return false + } + if this.Gid != that1.Gid { + return false + } + if this.Size_ != that1.Size_ { + return false + } + if this.ModTime != that1.ModTime { + return false + } + if this.Linkname != that1.Linkname { + return false + } + if this.Devmajor != that1.Devmajor { + return false + } + if this.Devminor != that1.Devminor { + return false + } + if len(this.Xattrs) != len(that1.Xattrs) { + return false + } + for i := range this.Xattrs { + if !bytes.Equal(this.Xattrs[i], that1.Xattrs[i]) { + return false + } + } + return true +} +func (this *Stat) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 14) + s = append(s, "&fsutil.Stat{") + s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n") + s = append(s, "Mode: "+fmt.Sprintf("%#v", this.Mode)+",\n") + s = append(s, "Uid: "+fmt.Sprintf("%#v", this.Uid)+",\n") + s = append(s, "Gid: "+fmt.Sprintf("%#v", this.Gid)+",\n") + s = append(s, "Size_: "+fmt.Sprintf("%#v", this.Size_)+",\n") + s = append(s, "ModTime: "+fmt.Sprintf("%#v", this.ModTime)+",\n") + s = append(s, "Linkname: "+fmt.Sprintf("%#v", this.Linkname)+",\n") + s = append(s, "Devmajor: "+fmt.Sprintf("%#v", this.Devmajor)+",\n") + s = append(s, "Devminor: "+fmt.Sprintf("%#v", this.Devminor)+",\n") + keysForXattrs := make([]string, 0, len(this.Xattrs)) + for k, _ := range this.Xattrs { + keysForXattrs = append(keysForXattrs, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForXattrs) + mapStringForXattrs := "map[string][]byte{" + for _, k := range keysForXattrs { + mapStringForXattrs += fmt.Sprintf("%#v: %#v,", k, this.Xattrs[k]) + } + mapStringForXattrs += "}" + if this.Xattrs != nil { + s = append(s, "Xattrs: "+mapStringForXattrs+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringStat(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} +func (m *Stat) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Stat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Path) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintStat(dAtA, i, uint64(len(m.Path))) + i += copy(dAtA[i:], m.Path) + } + if m.Mode != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintStat(dAtA, i, uint64(m.Mode)) + } + if m.Uid != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintStat(dAtA, i, uint64(m.Uid)) + } + if m.Gid != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintStat(dAtA, i, uint64(m.Gid)) + } + if m.Size_ != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintStat(dAtA, i, uint64(m.Size_)) + } + if m.ModTime != 0 { + dAtA[i] = 0x30 + i++ + i = encodeVarintStat(dAtA, i, uint64(m.ModTime)) + } + if len(m.Linkname) > 0 { + dAtA[i] = 0x3a + i++ + i = encodeVarintStat(dAtA, i, uint64(len(m.Linkname))) + i += copy(dAtA[i:], m.Linkname) + } + if m.Devmajor != 0 { + dAtA[i] = 0x40 + i++ + i = encodeVarintStat(dAtA, i, uint64(m.Devmajor)) + } + if m.Devminor != 0 { + dAtA[i] = 0x48 + i++ + i = encodeVarintStat(dAtA, i, uint64(m.Devminor)) + } + if len(m.Xattrs) > 0 { + for k, _ := range m.Xattrs { + dAtA[i] = 0x52 + i++ + v := m.Xattrs[k] + byteSize := 0 + if len(v) > 0 { + byteSize = 1 + len(v) + sovStat(uint64(len(v))) + } + mapSize := 1 + len(k) + sovStat(uint64(len(k))) + byteSize + i = encodeVarintStat(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintStat(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + if len(v) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintStat(dAtA, i, uint64(len(v))) + i += copy(dAtA[i:], v) + } + } + } + return i, nil +} + +func encodeFixed64Stat(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Stat(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintStat(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Stat) Size() (n int) { + var l int + _ = l + l = len(m.Path) + if l > 0 { + n += 1 + l + sovStat(uint64(l)) + } + if m.Mode != 0 { + n += 1 + sovStat(uint64(m.Mode)) + } + if m.Uid != 0 { + n += 1 + sovStat(uint64(m.Uid)) + } + if m.Gid != 0 { + n += 1 + sovStat(uint64(m.Gid)) + } + if m.Size_ != 0 { + n += 1 + sovStat(uint64(m.Size_)) + } + if m.ModTime != 0 { + n += 1 + sovStat(uint64(m.ModTime)) + } + l = len(m.Linkname) + if l > 0 { + n += 1 + l + sovStat(uint64(l)) + } + if m.Devmajor != 0 { + n += 1 + sovStat(uint64(m.Devmajor)) + } + if m.Devminor != 0 { + n += 1 + sovStat(uint64(m.Devminor)) + } + if len(m.Xattrs) > 0 { + for k, v := range m.Xattrs { + _ = k + _ = v + l = 0 + if len(v) > 0 { + l = 1 + len(v) + sovStat(uint64(len(v))) + } + mapEntrySize := 1 + len(k) + sovStat(uint64(len(k))) + l + n += mapEntrySize + 1 + sovStat(uint64(mapEntrySize)) + } + } + return n +} + +func sovStat(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozStat(x uint64) (n int) { + return sovStat(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *Stat) String() string { + if this == nil { + return "nil" + } + keysForXattrs := make([]string, 0, len(this.Xattrs)) + for k, _ := range this.Xattrs { + keysForXattrs = append(keysForXattrs, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForXattrs) + mapStringForXattrs := "map[string][]byte{" + for _, k := range keysForXattrs { + mapStringForXattrs += fmt.Sprintf("%v: %v,", k, this.Xattrs[k]) + } + mapStringForXattrs += "}" + s := strings.Join([]string{`&Stat{`, + `Path:` + fmt.Sprintf("%v", this.Path) + `,`, + `Mode:` + fmt.Sprintf("%v", this.Mode) + `,`, + `Uid:` + fmt.Sprintf("%v", this.Uid) + `,`, + `Gid:` + fmt.Sprintf("%v", this.Gid) + `,`, + `Size_:` + fmt.Sprintf("%v", this.Size_) + `,`, + `ModTime:` + fmt.Sprintf("%v", this.ModTime) + `,`, + `Linkname:` + fmt.Sprintf("%v", this.Linkname) + `,`, + `Devmajor:` + fmt.Sprintf("%v", this.Devmajor) + `,`, + `Devminor:` + fmt.Sprintf("%v", this.Devminor) + `,`, + `Xattrs:` + mapStringForXattrs + `,`, + `}`, + }, "") + return s +} +func valueToStringStat(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *Stat) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Stat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Stat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStat + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Path = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + m.Mode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Mode |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Uid", wireType) + } + m.Uid = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Uid |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Gid", wireType) + } + m.Gid = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Gid |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Size_", wireType) + } + m.Size_ = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Size_ |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ModTime", wireType) + } + m.ModTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ModTime |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Linkname", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStat + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Linkname = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Devmajor", wireType) + } + m.Devmajor = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Devmajor |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Devminor", wireType) + } + m.Devminor = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Devminor |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Xattrs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthStat + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthStat + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + if m.Xattrs == nil { + m.Xattrs = make(map[string][]byte) + } + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var mapbyteLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStat + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapbyteLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intMapbyteLen := int(mapbyteLen) + if intMapbyteLen < 0 { + return ErrInvalidLengthStat + } + postbytesIndex := iNdEx + intMapbyteLen + if postbytesIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue := make([]byte, mapbyteLen) + copy(mapvalue, dAtA[iNdEx:postbytesIndex]) + iNdEx = postbytesIndex + m.Xattrs[mapkey] = mapvalue + } else { + var mapvalue []byte + m.Xattrs[mapkey] = mapvalue + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStat(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthStat + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipStat(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowStat + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowStat + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowStat + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthStat + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowStat + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipStat(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthStat = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowStat = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("stat.proto", fileDescriptorStat) } + +var fileDescriptorStat = []byte{ + // 303 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x91, 0xb1, 0x4e, 0xf3, 0x30, + 0x14, 0x85, 0x73, 0x9b, 0x36, 0x6d, 0xdd, 0xff, 0x97, 0x90, 0xc5, 0x70, 0xd5, 0xc1, 0x8a, 0x98, + 0x32, 0xa0, 0x08, 0xc1, 0x02, 0x8c, 0x48, 0xbc, 0x40, 0x60, 0x60, 0x35, 0xb2, 0x29, 0xa6, 0x4d, + 0x5c, 0x25, 0x4e, 0x45, 0x99, 0x78, 0x04, 0x1e, 0x83, 0xd7, 0x60, 0x63, 0xec, 0xc8, 0x48, 0xcc, + 0xc2, 0xd8, 0x47, 0x40, 0x76, 0xda, 0xc2, 0x76, 0xce, 0x77, 0x7c, 0x65, 0x9d, 0x7b, 0x09, 0xa9, + 0x0c, 0x37, 0xe9, 0xbc, 0xd4, 0x46, 0xd3, 0xe8, 0xae, 0xaa, 0x8d, 0x9a, 0x1d, 0xbc, 0x75, 0x48, + 0xf7, 0xca, 0x70, 0x43, 0x29, 0xe9, 0xce, 0xb9, 0xb9, 0x47, 0x88, 0x21, 0x19, 0x66, 0x5e, 0x3b, + 0x96, 0x6b, 0x21, 0xb1, 0x13, 0x43, 0xf2, 0x3f, 0xf3, 0x9a, 0xee, 0x91, 0xb0, 0x56, 0x02, 0x43, + 0x8f, 0x9c, 0x74, 0x64, 0xa2, 0x04, 0x76, 0x5b, 0x32, 0x51, 0xc2, 0xcd, 0x55, 0xea, 0x49, 0x62, + 0x2f, 0x86, 0x24, 0xcc, 0xbc, 0xa6, 0x48, 0xfa, 0xb9, 0x16, 0xd7, 0x2a, 0x97, 0x18, 0x79, 0xbc, + 0xb5, 0x74, 0x4c, 0x06, 0x33, 0x55, 0x4c, 0x0b, 0x9e, 0x4b, 0xec, 0xfb, 0xdf, 0x77, 0xde, 0x65, + 0x42, 0x2e, 0x72, 0xfe, 0xa0, 0x4b, 0x1c, 0xf8, 0xb1, 0x9d, 0xdf, 0x66, 0xaa, 0xd0, 0x25, 0x0e, + 0x7f, 0x33, 0xe7, 0xe9, 0x11, 0x89, 0x1e, 0xb9, 0x31, 0x65, 0x85, 0x24, 0x0e, 0x93, 0xd1, 0x31, + 0xa6, 0x6d, 0xdf, 0xd4, 0x75, 0x4d, 0x6f, 0x7c, 0x74, 0x59, 0x98, 0x72, 0x99, 0x6d, 0xde, 0x8d, + 0xcf, 0xc8, 0xe8, 0x0f, 0x76, 0xa5, 0xa6, 0x72, 0xb9, 0xd9, 0x86, 0x93, 0x74, 0x9f, 0xf4, 0x16, + 0x7c, 0x56, 0xb7, 0xdb, 0xf8, 0x97, 0xb5, 0xe6, 0xbc, 0x73, 0x0a, 0x17, 0x87, 0xab, 0x86, 0x05, + 0x1f, 0x0d, 0x0b, 0xd6, 0x0d, 0x83, 0x67, 0xcb, 0xe0, 0xd5, 0x32, 0x78, 0xb7, 0x0c, 0x56, 0x96, + 0xc1, 0xa7, 0x65, 0xf0, 0x6d, 0x59, 0xb0, 0xb6, 0x0c, 0x5e, 0xbe, 0x58, 0x70, 0x1b, 0xf9, 0x03, + 0x9c, 0xfc, 0x04, 0x00, 0x00, 0xff, 0xff, 0x19, 0x97, 0x14, 0xf4, 0x8e, 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/tonistiigi/fsutil/stat.proto b/vendor/github.com/tonistiigi/fsutil/stat.proto new file mode 100644 index 0000000000..e279413074 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/stat.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package fsutil; + +message Stat { + string path = 1; + uint32 mode = 2; + uint32 uid = 3; + uint32 gid = 4; + int64 size = 5; + int64 modTime = 6; + // int32 typeflag = 7; + string linkname = 7; + int64 devmajor = 8; + int64 devminor = 9; + map xattrs = 10; +} \ No newline at end of file diff --git a/vendor/github.com/tonistiigi/fsutil/validator.go b/vendor/github.com/tonistiigi/fsutil/validator.go new file mode 100644 index 0000000000..e4a5eba66b --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/validator.go @@ -0,0 +1,88 @@ +package fsutil + +import ( + "os" + "path/filepath" + "sort" + "strings" + + "github.com/pkg/errors" +) + +type parent struct { + dir string + last string +} + +type Validator struct { + parentDirs []parent +} + +func (v *Validator) HandleChange(kind ChangeKind, p string, fi os.FileInfo, err error) (retErr error) { + if err != nil { + return err + } + // test that all paths are in order and all parent dirs were present + if v.parentDirs == nil { + v.parentDirs = make([]parent, 1, 10) + } + if p != filepath.Clean(p) { + return errors.Errorf("invalid unclean path %s", p) + } + if filepath.IsAbs(p) { + return errors.Errorf("abolute path %s not allowed", p) + } + dir := filepath.Dir(p) + base := filepath.Base(p) + if dir == "." { + dir = "" + } + if dir == ".." || strings.HasPrefix(p, "../") { + return errors.Errorf("invalid path: %s", p) + } + + // find a parent dir from saved records + i := sort.Search(len(v.parentDirs), func(i int) bool { + return ComparePath(v.parentDirs[len(v.parentDirs)-1-i].dir, dir) <= 0 + }) + i = len(v.parentDirs) - 1 - i + if i != len(v.parentDirs)-1 { // skipping back to grandparent + v.parentDirs = v.parentDirs[:i+1] + } + + if dir != v.parentDirs[len(v.parentDirs)-1].dir || v.parentDirs[i].last >= base { + return errors.Errorf("changes out of order: %q %q", p, filepath.Join(v.parentDirs[i].dir, v.parentDirs[i].last)) + } + v.parentDirs[i].last = base + if kind != ChangeKindDelete && fi.IsDir() { + v.parentDirs = append(v.parentDirs, parent{ + dir: filepath.Join(dir, base), + last: "", + }) + } + // todo: validate invalid mode combinations + return err +} + +func ComparePath(p1, p2 string) int { + // byte-by-byte comparison to be compatible with str<>str + min := min(len(p1), len(p2)) + for i := 0; i < min; i++ { + switch { + case p1[i] == p2[i]: + continue + case p2[i] != '/' && p1[i] < p2[i] || p1[i] == '/': + return -1 + default: + return 1 + } + } + return len(p1) - len(p2) +} + +func min(x, y int) int { + if x < y { + return x + } + return y +} diff --git a/vendor/github.com/tonistiigi/fsutil/walker.go b/vendor/github.com/tonistiigi/fsutil/walker.go new file mode 100644 index 0000000000..bfec609b5a --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/walker.go @@ -0,0 +1,170 @@ +package fsutil + +import ( + "os" + "path/filepath" + "runtime" + "strings" + "time" + + "github.com/docker/docker/pkg/fileutils" + "github.com/pkg/errors" + "golang.org/x/net/context" +) + +type WalkOpt struct { + IncludePaths []string // todo: remove? + ExcludePatterns []string +} + +func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) error { + root, err := filepath.EvalSymlinks(p) + if err != nil { + return errors.Wrapf(err, "failed to resolve %s", root) + } + fi, err := os.Stat(root) + if err != nil { + return errors.Wrapf(err, "failed to stat: %s", root) + } + if !fi.IsDir() { + return errors.Errorf("%s is not a directory", root) + } + + var pm *fileutils.PatternMatcher + if opt != nil && opt.ExcludePatterns != nil { + pm, err = fileutils.NewPatternMatcher(opt.ExcludePatterns) + if err != nil { + return errors.Wrapf(err, "invalid excludepaths %s", opt.ExcludePatterns) + } + } + + seenFiles := make(map[uint64]string) + return filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil { + if os.IsNotExist(err) { + return filepath.SkipDir + } + return err + } + origpath := path + path, err = filepath.Rel(root, path) + if err != nil { + return err + } + // Skip root + if path == "." { + return nil + } + + if opt != nil { + if opt.IncludePaths != nil { + matched := false + for _, p := range opt.IncludePaths { + if m, _ := filepath.Match(p, path); m { + matched = true + break + } + } + if !matched { + if fi.IsDir() { + return filepath.SkipDir + } + return nil + } + } + if pm != nil { + m, err := pm.Matches(path) + if err != nil { + return errors.Wrap(err, "failed to match excludepatterns") + } + + if m { + if fi.IsDir() { + if !pm.Exclusions() { + return filepath.SkipDir + } + dirSlash := path + string(filepath.Separator) + for _, pat := range pm.Patterns() { + if !pat.Exclusion() { + continue + } + patStr := pat.String() + string(filepath.Separator) + if strings.HasPrefix(patStr, dirSlash) { + goto passedFilter + } + } + return filepath.SkipDir + } + return nil + } + } + } + + passedFilter: + path = filepath.ToSlash(path) + + stat := &Stat{ + Path: path, + Mode: uint32(fi.Mode()), + Size_: fi.Size(), + ModTime: fi.ModTime().UnixNano(), + } + + setUnixOpt(fi, stat, path, seenFiles) + + if !fi.IsDir() { + if fi.Mode()&os.ModeSymlink != 0 { + link, err := os.Readlink(origpath) + if err != nil { + return errors.Wrapf(err, "failed to readlink %s", origpath) + } + stat.Linkname = link + } + } + if err := loadXattr(origpath, stat); err != nil { + return errors.Wrapf(err, "failed to xattr %s", path) + } + + if runtime.GOOS == "windows" { + permPart := stat.Mode & uint32(os.ModePerm) + noPermPart := stat.Mode &^ uint32(os.ModePerm) + // Add the x bit: make everything +x from windows + permPart |= 0111 + permPart &= 0755 + stat.Mode = noPermPart | permPart + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + if err := fn(path, &StatInfo{stat}, nil); err != nil { + return err + } + } + return nil + }) +} + +type StatInfo struct { + *Stat +} + +func (s *StatInfo) Name() string { + return filepath.Base(s.Stat.Path) +} +func (s *StatInfo) Size() int64 { + return s.Stat.Size_ +} +func (s *StatInfo) Mode() os.FileMode { + return os.FileMode(s.Stat.Mode) +} +func (s *StatInfo) ModTime() time.Time { + return time.Unix(s.Stat.ModTime/1e9, s.Stat.ModTime%1e9) +} +func (s *StatInfo) IsDir() bool { + return s.Mode().IsDir() +} +func (s *StatInfo) Sys() interface{} { + return s.Stat +} diff --git a/vendor/github.com/tonistiigi/fsutil/walker_unix.go b/vendor/github.com/tonistiigi/fsutil/walker_unix.go new file mode 100644 index 0000000000..6f13c956cb --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/walker_unix.go @@ -0,0 +1,61 @@ +// +build !windows + +package fsutil + +import ( + "os" + "syscall" + + "github.com/pkg/errors" + "github.com/stevvooe/continuity/sysx" +) + +func loadXattr(origpath string, stat *Stat) error { + xattrs, err := sysx.LListxattr(origpath) + if err != nil { + return errors.Wrapf(err, "failed to xattr %s", origpath) + } + if len(xattrs) > 0 { + m := make(map[string][]byte) + for _, key := range xattrs { + v, err := sysx.LGetxattr(origpath, key) + if err == nil { + m[key] = v + } + } + stat.Xattrs = m + } + return nil +} + +func setUnixOpt(fi os.FileInfo, stat *Stat, path string, seenFiles map[uint64]string) { + s := fi.Sys().(*syscall.Stat_t) + + stat.Uid = s.Uid + stat.Gid = s.Gid + + if !fi.IsDir() { + if s.Mode&syscall.S_IFBLK != 0 || + s.Mode&syscall.S_IFCHR != 0 { + stat.Devmajor = int64(major(uint64(s.Rdev))) + stat.Devminor = int64(minor(uint64(s.Rdev))) + } + + ino := s.Ino + if s.Nlink > 1 { + if oldpath, ok := seenFiles[ino]; ok { + stat.Linkname = oldpath + stat.Size_ = 0 + } + } + seenFiles[ino] = path + } +} + +func major(device uint64) uint64 { + return (device >> 8) & 0xfff +} + +func minor(device uint64) uint64 { + return (device & 0xff) | ((device >> 12) & 0xfff00) +} diff --git a/vendor/github.com/tonistiigi/fsutil/walker_windows.go b/vendor/github.com/tonistiigi/fsutil/walker_windows.go new file mode 100644 index 0000000000..a1a2b45569 --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/walker_windows.go @@ -0,0 +1,14 @@ +// +build windows + +package fsutil + +import ( + "os" +) + +func loadXattr(_ string, _ *Stat) error { + return nil +} + +func setUnixOpt(_ os.FileInfo, _ *Stat, _ string, _ map[uint64]string) { +} diff --git a/vendor/github.com/tonistiigi/fsutil/wire.pb.go b/vendor/github.com/tonistiigi/fsutil/wire.pb.go new file mode 100644 index 0000000000..263fb126be --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/wire.pb.go @@ -0,0 +1,563 @@ +// Code generated by protoc-gen-gogo. +// source: wire.proto +// DO NOT EDIT! + +package fsutil + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" + +import strconv "strconv" + +import bytes "bytes" + +import strings "strings" +import reflect "reflect" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type Packet_PacketType int32 + +const ( + PACKET_STAT Packet_PacketType = 0 + PACKET_REQ Packet_PacketType = 1 + PACKET_DATA Packet_PacketType = 2 + PACKET_FIN Packet_PacketType = 3 +) + +var Packet_PacketType_name = map[int32]string{ + 0: "PACKET_STAT", + 1: "PACKET_REQ", + 2: "PACKET_DATA", + 3: "PACKET_FIN", +} +var Packet_PacketType_value = map[string]int32{ + "PACKET_STAT": 0, + "PACKET_REQ": 1, + "PACKET_DATA": 2, + "PACKET_FIN": 3, +} + +func (Packet_PacketType) EnumDescriptor() ([]byte, []int) { return fileDescriptorWire, []int{0, 0} } + +type Packet struct { + Type Packet_PacketType `protobuf:"varint,1,opt,name=type,proto3,enum=fsutil.Packet_PacketType" json:"type,omitempty"` + Stat *Stat `protobuf:"bytes,2,opt,name=stat" json:"stat,omitempty"` + ID uint32 `protobuf:"varint,3,opt,name=ID,proto3" json:"ID,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *Packet) Reset() { *m = Packet{} } +func (*Packet) ProtoMessage() {} +func (*Packet) Descriptor() ([]byte, []int) { return fileDescriptorWire, []int{0} } + +func (m *Packet) GetType() Packet_PacketType { + if m != nil { + return m.Type + } + return PACKET_STAT +} + +func (m *Packet) GetStat() *Stat { + if m != nil { + return m.Stat + } + return nil +} + +func (m *Packet) GetID() uint32 { + if m != nil { + return m.ID + } + return 0 +} + +func (m *Packet) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func init() { + proto.RegisterType((*Packet)(nil), "fsutil.Packet") + proto.RegisterEnum("fsutil.Packet_PacketType", Packet_PacketType_name, Packet_PacketType_value) +} +func (x Packet_PacketType) String() string { + s, ok := Packet_PacketType_name[int32(x)] + if ok { + return s + } + return strconv.Itoa(int(x)) +} +func (this *Packet) Equal(that interface{}) bool { + if that == nil { + if this == nil { + return true + } + return false + } + + that1, ok := that.(*Packet) + if !ok { + that2, ok := that.(Packet) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + if this == nil { + return true + } + return false + } else if this == nil { + return false + } + if this.Type != that1.Type { + return false + } + if !this.Stat.Equal(that1.Stat) { + return false + } + if this.ID != that1.ID { + return false + } + if !bytes.Equal(this.Data, that1.Data) { + return false + } + return true +} +func (this *Packet) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 8) + s = append(s, "&fsutil.Packet{") + s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n") + if this.Stat != nil { + s = append(s, "Stat: "+fmt.Sprintf("%#v", this.Stat)+",\n") + } + s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") + s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringWire(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} +func (m *Packet) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Packet) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Type != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintWire(dAtA, i, uint64(m.Type)) + } + if m.Stat != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintWire(dAtA, i, uint64(m.Stat.Size())) + n1, err := m.Stat.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } + if m.ID != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintWire(dAtA, i, uint64(m.ID)) + } + if len(m.Data) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintWire(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + return i, nil +} + +func encodeFixed64Wire(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Wire(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} +func encodeVarintWire(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Packet) Size() (n int) { + var l int + _ = l + if m.Type != 0 { + n += 1 + sovWire(uint64(m.Type)) + } + if m.Stat != nil { + l = m.Stat.Size() + n += 1 + l + sovWire(uint64(l)) + } + if m.ID != 0 { + n += 1 + sovWire(uint64(m.ID)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovWire(uint64(l)) + } + return n +} + +func sovWire(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozWire(x uint64) (n int) { + return sovWire(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *Packet) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Packet{`, + `Type:` + fmt.Sprintf("%v", this.Type) + `,`, + `Stat:` + strings.Replace(fmt.Sprintf("%v", this.Stat), "Stat", "Stat", 1) + `,`, + `ID:` + fmt.Sprintf("%v", this.ID) + `,`, + `Data:` + fmt.Sprintf("%v", this.Data) + `,`, + `}`, + }, "") + return s +} +func valueToStringWire(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *Packet) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWire + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Packet: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Packet: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWire + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= (Packet_PacketType(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Stat", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWire + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWire + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Stat == nil { + m.Stat = &Stat{} + } + if err := m.Stat.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWire + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ID |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWire + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthWire + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipWire(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthWire + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipWire(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowWire + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowWire + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowWire + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthWire + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowWire + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipWire(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthWire = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowWire = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("wire.proto", fileDescriptorWire) } + +var fileDescriptorWire = []byte{ + // 253 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xcf, 0x2c, 0x4a, + 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4b, 0x2b, 0x2e, 0x2d, 0xc9, 0xcc, 0x91, 0xe2, + 0x2a, 0x2e, 0x49, 0x2c, 0x81, 0x88, 0x29, 0x9d, 0x65, 0xe4, 0x62, 0x0b, 0x48, 0x4c, 0xce, 0x4e, + 0x2d, 0x11, 0xd2, 0xe5, 0x62, 0x29, 0xa9, 0x2c, 0x48, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x33, + 0x92, 0xd4, 0x83, 0xa8, 0xd6, 0x83, 0xc8, 0x42, 0xa9, 0x90, 0xca, 0x82, 0xd4, 0x20, 0xb0, 0x32, + 0x21, 0x05, 0x2e, 0x16, 0x90, 0x39, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x3c, 0x30, 0xe5, + 0xc1, 0x25, 0x89, 0x25, 0x41, 0x60, 0x19, 0x21, 0x3e, 0x2e, 0x26, 0x4f, 0x17, 0x09, 0x66, 0x05, + 0x46, 0x0d, 0xde, 0x20, 0x26, 0x4f, 0x17, 0x21, 0x21, 0x2e, 0x96, 0x94, 0xc4, 0x92, 0x44, 0x09, + 0x16, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x30, 0x5b, 0xc9, 0x8f, 0x8b, 0x0b, 0x61, 0xb2, 0x10, 0x3f, + 0x17, 0x77, 0x80, 0xa3, 0xb3, 0xb7, 0x6b, 0x48, 0x7c, 0x70, 0x88, 0x63, 0x88, 0x00, 0x83, 0x10, + 0x1f, 0x17, 0x17, 0x54, 0x20, 0xc8, 0x35, 0x50, 0x80, 0x11, 0x49, 0x81, 0x8b, 0x63, 0x88, 0xa3, + 0x00, 0x13, 0x92, 0x02, 0x37, 0x4f, 0x3f, 0x01, 0x66, 0x27, 0x9d, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, + 0x3c, 0x94, 0x63, 0xf8, 0xf0, 0x50, 0x8e, 0xb1, 0xe1, 0x91, 0x1c, 0xe3, 0x8a, 0x47, 0x72, 0x8c, + 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x8b, 0x47, 0x72, + 0x0c, 0x1f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x90, 0xc4, 0x06, 0x0e, 0x04, 0x63, 0x40, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xda, 0x30, 0x43, 0x22, 0x26, 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/tonistiigi/fsutil/wire.proto b/vendor/github.com/tonistiigi/fsutil/wire.proto new file mode 100644 index 0000000000..d19432093f --- /dev/null +++ b/vendor/github.com/tonistiigi/fsutil/wire.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package fsutil; + +import "stat.proto"; + +message Packet { + enum PacketType { + PACKET_STAT = 0; + PACKET_REQ = 1; + PACKET_DATA = 2; + PACKET_FIN = 3; + } + PacketType type = 1; + Stat stat = 2; + uint32 ID = 3; + bytes data = 4; +} diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go new file mode 100644 index 0000000000..533438d91c --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -0,0 +1,67 @@ +// 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. + +// Package errgroup provides synchronization, error propagation, and Context +// cancelation for groups of goroutines working on subtasks of a common task. +package errgroup + +import ( + "sync" + + "golang.org/x/net/context" +) + +// A Group is a collection of goroutines working on subtasks that are part of +// the same overall task. +// +// A zero Group is valid and does not cancel on error. +type Group struct { + cancel func() + + wg sync.WaitGroup + + errOnce sync.Once + err error +} + +// WithContext returns a new Group and an associated Context derived from ctx. +// +// The derived Context is canceled the first time a function passed to Go +// returns a non-nil error or the first time Wait returns, whichever occurs +// first. +func WithContext(ctx context.Context) (*Group, context.Context) { + ctx, cancel := context.WithCancel(ctx) + return &Group{cancel: cancel}, ctx +} + +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. +func (g *Group) Wait() error { + g.wg.Wait() + if g.cancel != nil { + g.cancel() + } + return g.err +} + +// Go calls the given function in a new goroutine. +// +// The first call to return a non-nil error cancels the group; its error will be +// returned by Wait. +func (g *Group) Go(f func() error) { + g.wg.Add(1) + + go func() { + defer g.wg.Done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel() + } + }) + } + }() +} diff --git a/vendor/golang.org/x/sync/singleflight/singleflight.go b/vendor/golang.org/x/sync/singleflight/singleflight.go new file mode 100644 index 0000000000..9a4f8d59e0 --- /dev/null +++ b/vendor/golang.org/x/sync/singleflight/singleflight.go @@ -0,0 +1,111 @@ +// Copyright 2013 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 singleflight provides a duplicate function call suppression +// mechanism. +package singleflight // import "golang.org/x/sync/singleflight" + +import "sync" + +// call is an in-flight or completed singleflight.Do call +type call struct { + wg sync.WaitGroup + + // These fields are written once before the WaitGroup is done + // and are only read after the WaitGroup is done. + val interface{} + err error + + // These fields are read and written with the singleflight + // mutex held before the WaitGroup is done, and are read but + // not written after the WaitGroup is done. + dups int + chans []chan<- Result +} + +// Group represents a class of work and forms a namespace in +// which units of work can be executed with duplicate suppression. +type Group struct { + mu sync.Mutex // protects m + m map[string]*call // lazily initialized +} + +// Result holds the results of Do, so they can be passed +// on a channel. +type Result struct { + Val interface{} + Err error + Shared bool +} + +// Do executes and returns the results of the given function, making +// sure that only one execution is in-flight for a given key at a +// time. If a duplicate comes in, the duplicate caller waits for the +// original to complete and receives the same results. +// The return value shared indicates whether v was given to multiple callers. +func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) { + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + g.mu.Unlock() + c.wg.Wait() + return c.val, c.err, true + } + c := new(call) + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + g.doCall(c, key, fn) + return c.val, c.err, c.dups > 0 +} + +// DoChan is like Do but returns a channel that will receive the +// results when they are ready. +func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result { + ch := make(chan Result, 1) + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + c.chans = append(c.chans, ch) + g.mu.Unlock() + return ch + } + c := &call{chans: []chan<- Result{ch}} + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + go g.doCall(c, key, fn) + + return ch +} + +// doCall handles the single call for a key. +func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { + c.val, c.err = fn() + c.wg.Done() + + g.mu.Lock() + delete(g.m, key) + for _, ch := range c.chans { + ch <- Result{c.val, c.err, c.dups > 0} + } + g.mu.Unlock() +} + +// Forget tells the singleflight to forget about a key. Future calls +// to Do for this key will call the function rather than waiting for +// an earlier call to complete. +func (g *Group) Forget(key string) { + g.mu.Lock() + delete(g.m, key) + g.mu.Unlock() +}