mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
vendor: update fsutil 0f039a052ca1da01626278199624b62aed9b3729
full diff: 3bbb99cdbd...0f039a052c
- tonistiigi/fsutil#66 copy: add fast copy path for darwin
- tonistiigi/fsutil#67 Treat Unix sockets as regular files
- relates to moby/buildkit#1144 Fix socket handling
- tonistiigi/fsutil#68 fix gocrypto commit
- tonistiigi/fsutil#69 receive: use filter on receive diff
- prevents incremental transfers with userns because the metadata
on disk is always different than the one being transferred.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
67a0695e8b
commit
94a8c8b3c0
13 changed files with 162 additions and 59 deletions
|
@ -27,7 +27,7 @@ golang.org/x/sync e225da77a7e68af35c70ccbf71af
|
||||||
|
|
||||||
# buildkit
|
# buildkit
|
||||||
github.com/moby/buildkit 4f4e03067523b2fc5ca2f17514a5e75ad63e02fb
|
github.com/moby/buildkit 4f4e03067523b2fc5ca2f17514a5e75ad63e02fb
|
||||||
github.com/tonistiigi/fsutil 3bbb99cdbd76619ab717299830c60f6f2a533a6b
|
github.com/tonistiigi/fsutil 0f039a052ca1da01626278199624b62aed9b3729
|
||||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||||
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
||||||
github.com/google/shlex 6f45313302b9c56850fc17f99e40caebce98c716
|
github.com/google/shlex 6f45313302b9c56850fc17f99e40caebce98c716
|
||||||
|
|
15
vendor/github.com/tonistiigi/fsutil/copy/copy.go
generated
vendored
15
vendor/github.com/tonistiigi/fsutil/copy/copy.go
generated
vendored
|
@ -329,21 +329,6 @@ func ensureEmptyFileTarget(dst string) error {
|
||||||
return os.Remove(dst)
|
return os.Remove(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFile(source, target string) error {
|
|
||||||
src, err := os.Open(source)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to open source %s", source)
|
|
||||||
}
|
|
||||||
defer src.Close()
|
|
||||||
tgt, err := os.Create(target)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to open target %s", target)
|
|
||||||
}
|
|
||||||
defer tgt.Close()
|
|
||||||
|
|
||||||
return copyFileContent(tgt, src)
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsWildcards(name string) bool {
|
func containsWildcards(name string) bool {
|
||||||
isWindows := runtime.GOOS == "windows"
|
isWindows := runtime.GOOS == "windows"
|
||||||
for i := 0; i < len(name); i++ {
|
for i := 0; i < len(name); i++ {
|
||||||
|
|
84
vendor/github.com/tonistiigi/fsutil/copy/copy_darwin.go
generated
vendored
Normal file
84
vendor/github.com/tonistiigi/fsutil/copy/copy_darwin.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// <sys/clonefile.h
|
||||||
|
// int clonefileat(int, const char *, int, const char *, uint32_t) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);
|
||||||
|
|
||||||
|
const CLONE_NOFOLLOW = 0x0001 /* Don't follow symbolic links */
|
||||||
|
const CLONE_NOOWNERCOPY = 0x0002 /* Don't copy ownership information from */
|
||||||
|
|
||||||
|
func copyFile(source, target string) error {
|
||||||
|
if err := clonefile(source, target); err != nil {
|
||||||
|
if err != unix.EINVAL {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
src, err := os.Open(source)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open source %s", source)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
tgt, err := os.Create(target)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open target %s", target)
|
||||||
|
}
|
||||||
|
defer tgt.Close()
|
||||||
|
|
||||||
|
return copyFileContent(tgt, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFileContent(dst, src *os.File) error {
|
||||||
|
buf := bufferPool.Get().(*[]byte)
|
||||||
|
_, err := io.CopyBuffer(dst, src, *buf)
|
||||||
|
bufferPool.Put(buf)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// errnoErr returns common boxed Errno values, to prevent
|
||||||
|
// allocations at runtime.
|
||||||
|
func errnoErr(e syscall.Errno) error {
|
||||||
|
switch e {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case unix.EAGAIN:
|
||||||
|
return syscall.EAGAIN
|
||||||
|
case unix.EINVAL:
|
||||||
|
return syscall.EINVAL
|
||||||
|
case unix.ENOENT:
|
||||||
|
return syscall.ENOENT
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func clonefile(src, dst string) (err error) {
|
||||||
|
var _p0, _p1 *byte
|
||||||
|
_p0, err = unix.BytePtrFromString(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_p1, err = unix.BytePtrFromString(dst)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fdcwd := unix.AT_FDCWD
|
||||||
|
_, _, e1 := unix.Syscall6(unix.SYS_CLONEFILEAT, uintptr(fdcwd), uintptr(unsafe.Pointer(_p0)), uintptr(fdcwd), uintptr(unsafe.Pointer(_p1)), uintptr(CLONE_NOFOLLOW), 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
15
vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go
generated
vendored
15
vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go
generated
vendored
|
@ -52,6 +52,21 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyFile(source, target string) error {
|
||||||
|
src, err := os.Open(source)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open source %s", source)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
tgt, err := os.Create(target)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open target %s", target)
|
||||||
|
}
|
||||||
|
defer tgt.Close()
|
||||||
|
|
||||||
|
return copyFileContent(tgt, src)
|
||||||
|
}
|
||||||
|
|
||||||
func copyFileContent(dst, src *os.File) error {
|
func copyFileContent(dst, src *os.File) error {
|
||||||
st, err := src.Stat()
|
st, err := src.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
9
vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go
generated
vendored
9
vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go
generated
vendored
|
@ -3,7 +3,6 @@
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
@ -51,14 +50,6 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFileContent(dst, src *os.File) error {
|
|
||||||
buf := bufferPool.Get().(*[]byte)
|
|
||||||
_, err := io.CopyBuffer(dst, src, *buf)
|
|
||||||
bufferPool.Put(buf)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyDevice(dst string, fi os.FileInfo) error {
|
func copyDevice(dst string, fi os.FileInfo) error {
|
||||||
st, ok := fi.Sys().(*syscall.Stat_t)
|
st, ok := fi.Sys().(*syscall.Stat_t)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
15
vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go
generated
vendored
15
vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go
generated
vendored
|
@ -17,6 +17,21 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyFile(source, target string) error {
|
||||||
|
src, err := os.Open(source)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open source %s", source)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
tgt, err := os.Create(target)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to open target %s", target)
|
||||||
|
}
|
||||||
|
defer tgt.Close()
|
||||||
|
|
||||||
|
return copyFileContent(tgt, src)
|
||||||
|
}
|
||||||
|
|
||||||
func copyFileContent(dst, src *os.File) error {
|
func copyFileContent(dst, src *os.File) error {
|
||||||
buf := bufferPool.Get().(*[]byte)
|
buf := bufferPool.Get().(*[]byte)
|
||||||
_, err := io.CopyBuffer(dst, src, *buf)
|
_, err := io.CopyBuffer(dst, src, *buf)
|
||||||
|
|
8
vendor/github.com/tonistiigi/fsutil/diff.go
generated
vendored
8
vendor/github.com/tonistiigi/fsutil/diff.go
generated
vendored
|
@ -5,6 +5,7 @@ import (
|
||||||
"hash"
|
"hash"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/tonistiigi/fsutil/types"
|
"github.com/tonistiigi/fsutil/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,9 +26,14 @@ func GetWalkerFn(root string) walkerFn {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stat, ok := f.Sys().(*types.Stat)
|
||||||
|
if !ok {
|
||||||
|
return errors.Errorf("%T invalid file without stat information", f.Sys())
|
||||||
|
}
|
||||||
|
|
||||||
p := ¤tPath{
|
p := ¤tPath{
|
||||||
path: path,
|
path: path,
|
||||||
f: f,
|
stat: stat,
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
|
47
vendor/github.com/tonistiigi/fsutil/diff_containerd.go
generated
vendored
47
vendor/github.com/tonistiigi/fsutil/diff_containerd.go
generated
vendored
|
@ -37,12 +37,12 @@ type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
|
||||||
|
|
||||||
type currentPath struct {
|
type currentPath struct {
|
||||||
path string
|
path string
|
||||||
f os.FileInfo
|
stat *types.Stat
|
||||||
// fullPath string
|
// fullPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// doubleWalkDiff walks both directories to create a diff
|
// doubleWalkDiff walks both directories to create a diff
|
||||||
func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn) (err error) {
|
func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn, filter FilterFunc) (err error) {
|
||||||
g, ctx := errgroup.WithContext(ctx)
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -86,14 +86,22 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn) (er
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var f os.FileInfo
|
var f *types.Stat
|
||||||
k, p := pathChange(f1, f2)
|
var f2copy *currentPath
|
||||||
|
if f2 != nil {
|
||||||
|
statCopy := *f2.stat
|
||||||
|
if filter != nil {
|
||||||
|
filter(f2.path, &statCopy)
|
||||||
|
}
|
||||||
|
f2copy = ¤tPath{path: f2.path, stat: &statCopy}
|
||||||
|
}
|
||||||
|
k, p := pathChange(f1, f2copy)
|
||||||
switch k {
|
switch k {
|
||||||
case ChangeKindAdd:
|
case ChangeKindAdd:
|
||||||
if rmdir != "" {
|
if rmdir != "" {
|
||||||
rmdir = ""
|
rmdir = ""
|
||||||
}
|
}
|
||||||
f = f2.f
|
f = f2.stat
|
||||||
f2 = nil
|
f2 = nil
|
||||||
case ChangeKindDelete:
|
case ChangeKindDelete:
|
||||||
// Check if this file is already removed by being
|
// Check if this file is already removed by being
|
||||||
|
@ -101,30 +109,30 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn) (er
|
||||||
if rmdir != "" && strings.HasPrefix(f1.path, rmdir) {
|
if rmdir != "" && strings.HasPrefix(f1.path, rmdir) {
|
||||||
f1 = nil
|
f1 = nil
|
||||||
continue
|
continue
|
||||||
} else if rmdir == "" && f1.f.IsDir() {
|
} else if rmdir == "" && f1.stat.IsDir() {
|
||||||
rmdir = f1.path + string(os.PathSeparator)
|
rmdir = f1.path + string(os.PathSeparator)
|
||||||
} else if rmdir != "" {
|
} else if rmdir != "" {
|
||||||
rmdir = ""
|
rmdir = ""
|
||||||
}
|
}
|
||||||
f1 = nil
|
f1 = nil
|
||||||
case ChangeKindModify:
|
case ChangeKindModify:
|
||||||
same, err := sameFile(f1, f2)
|
same, err := sameFile(f1, f2copy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if f1.f.IsDir() && !f2.f.IsDir() {
|
if f1.stat.IsDir() && !f2copy.stat.IsDir() {
|
||||||
rmdir = f1.path + string(os.PathSeparator)
|
rmdir = f1.path + string(os.PathSeparator)
|
||||||
} else if rmdir != "" {
|
} else if rmdir != "" {
|
||||||
rmdir = ""
|
rmdir = ""
|
||||||
}
|
}
|
||||||
f = f2.f
|
f = f2.stat
|
||||||
f1 = nil
|
f1 = nil
|
||||||
f2 = nil
|
f2 = nil
|
||||||
if same {
|
if same {
|
||||||
continue loop0
|
continue loop0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := changeFn(k, p, f, nil); err != nil {
|
if err := changeFn(k, p, &StatInfo{f}, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,28 +167,17 @@ func pathChange(lower, upper *currentPath) (ChangeKind, string) {
|
||||||
|
|
||||||
func sameFile(f1, f2 *currentPath) (same bool, retErr error) {
|
func sameFile(f1, f2 *currentPath) (same bool, retErr error) {
|
||||||
// If not a directory also check size, modtime, and content
|
// If not a directory also check size, modtime, and content
|
||||||
if !f1.f.IsDir() {
|
if !f1.stat.IsDir() {
|
||||||
if f1.f.Size() != f2.f.Size() {
|
if f1.stat.Size_ != f2.stat.Size_ {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
t1 := f1.f.ModTime()
|
if f1.stat.ModTime != f2.stat.ModTime {
|
||||||
t2 := f2.f.ModTime()
|
|
||||||
if t1.UnixNano() != t2.UnixNano() {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ls1, ok := f1.f.Sys().(*types.Stat)
|
return compareStat(f1.stat, f2.stat)
|
||||||
if !ok {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
ls2, ok := f2.f.Sys().(*types.Stat)
|
|
||||||
if !ok {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return compareStat(ls1, ls2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compareStat returns whether the stats are equivalent,
|
// compareStat returns whether the stats are equivalent,
|
||||||
|
|
6
vendor/github.com/tonistiigi/fsutil/diskwriter.go
generated
vendored
6
vendor/github.com/tonistiigi/fsutil/diskwriter.go
generated
vendored
|
@ -194,7 +194,7 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
|
||||||
|
|
||||||
if isRegularFile {
|
if isRegularFile {
|
||||||
if dw.opt.AsyncDataCb != nil {
|
if dw.opt.AsyncDataCb != nil {
|
||||||
dw.requestAsyncFileData(p, destPath, fi)
|
dw.requestAsyncFileData(p, destPath, fi, &statCopy)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return dw.processChange(kind, p, fi, nil)
|
return dw.processChange(kind, p, fi, nil)
|
||||||
|
@ -203,7 +203,7 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dw *DiskWriter) requestAsyncFileData(p, dest string, fi os.FileInfo) {
|
func (dw *DiskWriter) requestAsyncFileData(p, dest string, fi os.FileInfo, st *types.Stat) {
|
||||||
// todo: limit worker threads
|
// todo: limit worker threads
|
||||||
dw.eg.Go(func() error {
|
dw.eg.Go(func() error {
|
||||||
if err := dw.processChange(ChangeKindAdd, p, fi, &lazyFileWriter{
|
if err := dw.processChange(ChangeKindAdd, p, fi, &lazyFileWriter{
|
||||||
|
@ -211,7 +211,7 @@ func (dw *DiskWriter) requestAsyncFileData(p, dest string, fi os.FileInfo) {
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return chtimes(dest, fi.ModTime().UnixNano()) // TODO: parent dirs
|
return chtimes(dest, st.ModTime) // TODO: parent dirs
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
vendor/github.com/tonistiigi/fsutil/go.mod
generated
vendored
2
vendor/github.com/tonistiigi/fsutil/go.mod
generated
vendored
|
@ -19,7 +19,7 @@ require (
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/sirupsen/logrus v1.0.3 // indirect
|
github.com/sirupsen/logrus v1.0.3 // indirect
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
golang.org/x/crypto v0.0.0-20190129210102-0709b304e793 // indirect
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 // indirect
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
|
||||||
|
|
8
vendor/github.com/tonistiigi/fsutil/receive.go
generated
vendored
8
vendor/github.com/tonistiigi/fsutil/receive.go
generated
vendored
|
@ -133,7 +133,7 @@ func (r *receiver) run(ctx context.Context) error {
|
||||||
if !r.merge {
|
if !r.merge {
|
||||||
destWalker = GetWalkerFn(r.dest)
|
destWalker = GetWalkerFn(r.dest)
|
||||||
}
|
}
|
||||||
err := doubleWalkDiff(ctx, dw.HandleChange, destWalker, w.fill)
|
err := doubleWalkDiff(ctx, dw.HandleChange, destWalker, w.fill, r.filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -180,11 +180,11 @@ func (r *receiver) run(ctx context.Context) error {
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
cp := ¤tPath{path: p.Stat.Path, f: &StatInfo{p.Stat}}
|
cp := ¤tPath{path: p.Stat.Path, stat: p.Stat}
|
||||||
if err := r.orderValidator.HandleChange(ChangeKindAdd, cp.path, cp.f, nil); err != nil {
|
if err := r.orderValidator.HandleChange(ChangeKindAdd, cp.path, &StatInfo{cp.stat}, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.hlValidator.HandleChange(ChangeKindAdd, cp.path, cp.f, nil); err != nil {
|
if err := r.hlValidator.HandleChange(ChangeKindAdd, cp.path, &StatInfo{cp.stat}, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := w.update(cp); err != nil {
|
if err := w.update(cp); err != nil {
|
||||||
|
|
3
vendor/github.com/tonistiigi/fsutil/stat.go
generated
vendored
3
vendor/github.com/tonistiigi/fsutil/stat.go
generated
vendored
|
@ -49,6 +49,9 @@ func mkstat(path, relpath string, fi os.FileInfo, inodemap map[uint64]string) (*
|
||||||
stat.Mode = noPermPart | permPart
|
stat.Mode = noPermPart | permPart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the socket bit since archive/tar.FileInfoHeader does not handle it
|
||||||
|
stat.Mode &^= uint32(os.ModeSocket)
|
||||||
|
|
||||||
return stat, nil
|
return stat, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
vendor/github.com/tonistiigi/fsutil/types/stat.go
generated
vendored
Normal file
7
vendor/github.com/tonistiigi/fsutil/types/stat.go
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
func (s Stat) IsDir() bool {
|
||||||
|
return os.FileMode(s.Mode).IsDir()
|
||||||
|
}
|
Loading…
Reference in a new issue