Merge pull request #1342 from tonistiigi/userns-chown
fileop: keep correct user for parent dir on usernsv0.7
commit
fac9c1b402
5
go.mod
5
go.mod
|
@ -1,10 +1,11 @@
|
||||||
module github.com/moby/buildkit
|
module github.com/moby/buildkit
|
||||||
|
|
||||||
go 1.11
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/Microsoft/go-winio v0.4.14
|
github.com/Microsoft/go-winio v0.4.14
|
||||||
|
github.com/Microsoft/hcsshim v0.8.5 // indirect
|
||||||
github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect
|
github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect
|
||||||
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58 // indirect
|
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58 // indirect
|
||||||
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601 // indirect
|
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601 // indirect
|
||||||
|
@ -56,7 +57,7 @@ require (
|
||||||
github.com/sirupsen/logrus v1.4.1
|
github.com/sirupsen/logrus v1.4.1
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
|
||||||
github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1
|
github.com/tonistiigi/fsutil v0.0.0-20200128191323-6c909ab392c1
|
||||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
|
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
|
||||||
github.com/uber/jaeger-client-go v0.0.0-20180103221425-e02c85f9069e
|
github.com/uber/jaeger-client-go v0.0.0-20180103221425-e02c85f9069e
|
||||||
github.com/uber/jaeger-lib v1.2.1 // indirect
|
github.com/uber/jaeger-lib v1.2.1 // indirect
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -16,7 +16,6 @@ github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601 h1:6xW3ogNpFIly
|
||||||
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
||||||
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 h1:WMpHmC6AxwWb9hMqhudkqG7A/p14KiMnl6d3r1iUMjU=
|
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 h1:WMpHmC6AxwWb9hMqhudkqG7A/p14KiMnl6d3r1iUMjU=
|
||||||
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||||
github.com/containerd/containerd v1.2.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
|
||||||
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf h1:phUfu9w7+g1Vp149t3FThX2BmW+DkKkHj613PzZrQuU=
|
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf h1:phUfu9w7+g1Vp149t3FThX2BmW+DkKkHj613PzZrQuU=
|
||||||
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
|
@ -157,8 +156,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1 h1:WRlNtJ2whFMKo95/e6uaNuAnn5TxLcMzczqMcfbIDxo=
|
github.com/tonistiigi/fsutil v0.0.0-20200128191323-6c909ab392c1 h1:mGr3EjIwJQQMv8RSHatpbAPX4oK3R09XfjKcuNP2nv0=
|
||||||
github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1/go.mod h1:hP47OZfgT1aNVDJj28EnEKaKg6mjPEoS5Tb4BsWCTPs=
|
github.com/tonistiigi/fsutil v0.0.0-20200128191323-6c909ab392c1/go.mod h1:0kCXd/oIZJyFcSuTTh68iZpVnczpc2Y1/c/XSIC4IHo=
|
||||||
github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe h1:pd7hrFSqUPxYS9IB+UMG1AB/8EXGXo17ssx0bSQ5L6Y=
|
github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe h1:pd7hrFSqUPxYS9IB+UMG1AB/8EXGXo17ssx0bSQ5L6Y=
|
||||||
github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe/go.mod h1:/+MCh11CJf2oz0BXmlmqyopK/ad1rKkcOXPoYuPCJYU=
|
github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe/go.mod h1:/+MCh11CJf2oz0BXmlmqyopK/ad1rKkcOXPoYuPCJYU=
|
||||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
|
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
|
||||||
|
|
|
@ -26,33 +26,58 @@ func timestampToTime(ts int64) *time.Time {
|
||||||
return &tm
|
return &tm
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapUser(user *copy.ChownOpt, idmap *idtools.IdentityMapping) (*copy.ChownOpt, error) {
|
func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Chowner, error) {
|
||||||
if idmap == nil || user == nil {
|
if user == nil {
|
||||||
return user, nil
|
return func(old *copy.User) (*copy.User, error) {
|
||||||
|
if old == nil {
|
||||||
|
if idmap == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
old = ©.User{} // root
|
||||||
|
}
|
||||||
|
if idmap != nil {
|
||||||
|
identity, err := idmap.ToHost(idtools.Identity{
|
||||||
|
UID: old.Uid,
|
||||||
|
GID: old.Gid,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ©.User{Uid: identity.UID, Gid: identity.GID}, nil
|
||||||
|
}
|
||||||
|
return old, nil
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
identity, err := idmap.ToHost(idtools.Identity{
|
u := *user
|
||||||
UID: user.Uid,
|
if idmap != nil {
|
||||||
GID: user.Gid,
|
identity, err := idmap.ToHost(idtools.Identity{
|
||||||
})
|
UID: user.Uid,
|
||||||
if err != nil {
|
GID: user.Gid,
|
||||||
return nil, err
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
u.Uid = identity.UID
|
||||||
|
u.Gid = identity.GID
|
||||||
}
|
}
|
||||||
return ©.ChownOpt{Uid: identity.UID, Gid: identity.GID}, nil
|
return func(*copy.User) (*copy.User, error) {
|
||||||
|
return &u, nil
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
|
func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.User, idmap *idtools.IdentityMapping) error {
|
||||||
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
|
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err = mapUser(user, idmap)
|
ch, err := mapUserToChowner(user, idmap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if action.MakeParents {
|
if action.MakeParents {
|
||||||
if err := copy.MkdirAll(p, os.FileMode(action.Mode)&0777, user, timestampToTime(action.Timestamp)); err != nil {
|
if err := copy.MkdirAll(p, os.FileMode(action.Mode)&0777, ch, timestampToTime(action.Timestamp)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,7 +87,7 @@ func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := copy.Chown(p, user); err != nil {
|
if err := copy.Chown(p, nil, ch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := copy.Utimes(p, timestampToTime(action.Timestamp)); err != nil {
|
if err := copy.Utimes(p, timestampToTime(action.Timestamp)); err != nil {
|
||||||
|
@ -73,13 +98,13 @@ func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
|
func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *copy.User, idmap *idtools.IdentityMapping) error {
|
||||||
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
|
p, err := fs.RootPath(d, filepath.Join(filepath.Join("/", action.Path)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err = mapUser(user, idmap)
|
ch, err := mapUserToChowner(user, idmap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -88,7 +113,7 @@ func mkfile(ctx context.Context, d string, action pb.FileActionMkFile, user *cop
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := copy.Chown(p, user); err != nil {
|
if err := copy.Chown(p, nil, ch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +160,7 @@ func rmPath(root, src string, allowNotFound bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *copy.ChownOpt, idmap *idtools.IdentityMapping) error {
|
func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *copy.User, idmap *idtools.IdentityMapping) error {
|
||||||
srcPath := cleanPath(action.Src)
|
srcPath := cleanPath(action.Src)
|
||||||
destPath := cleanPath(action.Dest)
|
destPath := cleanPath(action.Dest)
|
||||||
|
|
||||||
|
@ -154,14 +179,14 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := mapUser(u, idmap)
|
ch, err := mapUserToChowner(u, idmap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
opt := []copy.Opt{
|
opt := []copy.Opt{
|
||||||
func(ci *copy.CopyInfo) {
|
func(ci *copy.CopyInfo) {
|
||||||
ci.Chown = u
|
ci.Chown = ch
|
||||||
ci.Utime = timestampToTime(action.Timestamp)
|
ci.Utime = timestampToTime(action.Timestamp)
|
||||||
if m := int(action.Mode); m != -1 {
|
if m := int(action.Mode); m != -1 {
|
||||||
ci.Mode = &m
|
ci.Mode = &m
|
||||||
|
@ -174,7 +199,7 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
|
||||||
|
|
||||||
if !action.AllowWildcard {
|
if !action.AllowWildcard {
|
||||||
if action.AttemptUnpackDockerCompatibility {
|
if action.AttemptUnpackDockerCompatibility {
|
||||||
if ok, err := unpack(ctx, src, srcPath, dest, destPath, u, timestampToTime(action.Timestamp)); err != nil {
|
if ok, err := unpack(ctx, src, srcPath, dest, destPath, ch, timestampToTime(action.Timestamp)); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if ok {
|
} else if ok {
|
||||||
return nil
|
return nil
|
||||||
|
@ -197,7 +222,7 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
|
||||||
|
|
||||||
for _, s := range m {
|
for _, s := range m {
|
||||||
if action.AttemptUnpackDockerCompatibility {
|
if action.AttemptUnpackDockerCompatibility {
|
||||||
if ok, err := unpack(ctx, src, s, dest, destPath, u, timestampToTime(action.Timestamp)); err != nil {
|
if ok, err := unpack(ctx, src, s, dest, destPath, ch, timestampToTime(action.Timestamp)); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if ok {
|
} else if ok {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
copy "github.com/tonistiigi/fsutil/copy"
|
copy "github.com/tonistiigi/fsutil/copy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func unpack(ctx context.Context, srcRoot string, src string, destRoot string, dest string, user *copy.ChownOpt, tm *time.Time) (bool, error) {
|
func unpack(ctx context.Context, srcRoot string, src string, destRoot string, dest string, ch copy.Chowner, tm *time.Time) (bool, error) {
|
||||||
src, err := fs.RootPath(srcRoot, src)
|
src, err := fs.RootPath(srcRoot, src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -25,7 +25,7 @@ func unpack(ctx context.Context, srcRoot string, src string, destRoot string, de
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if err := copy.MkdirAll(dest, 0755, user, tm); err != nil {
|
if err := copy.MkdirAll(dest, 0755, ch, tm); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,11 @@ import (
|
||||||
copy "github.com/tonistiigi/fsutil/copy"
|
copy "github.com/tonistiigi/fsutil/copy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.ChownOpt, error) {
|
func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.User, error) {
|
||||||
if chopt == nil {
|
if chopt == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
var us copy.ChownOpt
|
var us copy.User
|
||||||
if chopt.User != nil {
|
if chopt.User != nil {
|
||||||
switch u := chopt.User.User.(type) {
|
switch u := chopt.User.User.(type) {
|
||||||
case *pb.UserOpt_ByName:
|
case *pb.UserOpt_ByName:
|
||||||
|
|
|
@ -7,8 +7,7 @@ services:
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- "1.11.x"
|
- "1.12.x"
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- export GO111MODULE=on
|
- export GO111MODULE=on
|
||||||
|
@ -19,3 +18,6 @@ script:
|
||||||
- sudo ./test -test.v
|
- sudo ./test -test.v
|
||||||
- go test -c -o test ./copy
|
- go test -c -o test ./copy
|
||||||
- sudo ./test -test.v
|
- sudo ./test -test.v
|
||||||
|
- GOOS=darwin go build ./...
|
||||||
|
- GOOS=windows go build ./...
|
||||||
|
- GOARCH=arm GOARM=7 go build ./...
|
||||||
|
|
|
@ -146,14 +146,16 @@ func (c *copier) prepareTargetDir(srcFollowed, src, destPath string, copyDirCont
|
||||||
return destPath, nil
|
return destPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChownOpt struct {
|
type User struct {
|
||||||
Uid, Gid int
|
Uid, Gid int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Chowner func(*User) (*User, error)
|
||||||
|
|
||||||
type XAttrErrorHandler func(dst, src, xattrKey string, err error) error
|
type XAttrErrorHandler func(dst, src, xattrKey string, err error) error
|
||||||
|
|
||||||
type CopyInfo struct {
|
type CopyInfo struct {
|
||||||
Chown *ChownOpt
|
Chown Chowner
|
||||||
Utime *time.Time
|
Utime *time.Time
|
||||||
AllowWildcards bool
|
AllowWildcards bool
|
||||||
Mode *int
|
Mode *int
|
||||||
|
@ -172,7 +174,9 @@ func WithCopyInfo(ci CopyInfo) func(*CopyInfo) {
|
||||||
|
|
||||||
func WithChown(uid, gid int) Opt {
|
func WithChown(uid, gid int) Opt {
|
||||||
return func(ci *CopyInfo) {
|
return func(ci *CopyInfo) {
|
||||||
ci.Chown = &ChownOpt{Uid: uid, Gid: gid}
|
ci.Chown = func(*User) (*User, error) {
|
||||||
|
return &User{Uid: uid, Gid: gid}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,14 +198,14 @@ func AllowXAttrErrors(ci *CopyInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type copier struct {
|
type copier struct {
|
||||||
chown *ChownOpt
|
chown Chowner
|
||||||
utime *time.Time
|
utime *time.Time
|
||||||
mode *int
|
mode *int
|
||||||
inodes map[uint64]string
|
inodes map[uint64]string
|
||||||
xattrErrorHandler XAttrErrorHandler
|
xattrErrorHandler XAttrErrorHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCopier(chown *ChownOpt, tm *time.Time, mode *int, xeh XAttrErrorHandler) *copier {
|
func newCopier(chown Chowner, tm *time.Time, mode *int, xeh XAttrErrorHandler) *copier {
|
||||||
if xeh == nil {
|
if xeh == nil {
|
||||||
xeh = func(dst, src, key string, err error) error {
|
xeh = func(dst, src, key string, err error) error {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containerd/containerd/sys"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -20,11 +19,14 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
st := fi.Sys().(*syscall.Stat_t)
|
st := fi.Sys().(*syscall.Stat_t)
|
||||||
|
|
||||||
chown := c.chown
|
chown := c.chown
|
||||||
|
uid, gid := getUidGid(fi)
|
||||||
|
old := &User{Uid: uid, Gid: gid}
|
||||||
if chown == nil {
|
if chown == nil {
|
||||||
uid, gid := getUidGid(fi)
|
chown = func(u *User) (*User, error) {
|
||||||
chown = &ChownOpt{Uid: uid, Gid: gid}
|
return u, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := Chown(name, chown); err != nil {
|
if err := Chown(name, old, chown); err != nil {
|
||||||
return errors.Wrapf(err, "failed to chown %s", name)
|
return errors.Wrapf(err, "failed to chown %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
timespec := []unix.Timespec{unix.Timespec(sys.StatAtime(st)), unix.Timespec(sys.StatMtime(st))}
|
timespec := []unix.Timespec{unix.Timespec(StatAtime(st)), unix.Timespec(StatMtime(st))}
|
||||||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
||||||
return errors.Wrapf(err, "failed to utime %s", name)
|
return errors.Wrapf(err, "failed to utime %s", name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containerd/containerd/sys"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -19,11 +18,14 @@ func getUidGid(fi os.FileInfo) (uid, gid int) {
|
||||||
func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
st := fi.Sys().(*syscall.Stat_t)
|
st := fi.Sys().(*syscall.Stat_t)
|
||||||
chown := c.chown
|
chown := c.chown
|
||||||
|
uid, gid := getUidGid(fi)
|
||||||
|
old := &User{Uid: uid, Gid: gid}
|
||||||
if chown == nil {
|
if chown == nil {
|
||||||
uid, gid := getUidGid(fi)
|
chown = func(u *User) (*User, error) {
|
||||||
chown = &ChownOpt{Uid: uid, Gid: gid}
|
return u, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := Chown(name, chown); err != nil {
|
if err := Chown(name, old, chown); err != nil {
|
||||||
return errors.Wrapf(err, "failed to chown %s", name)
|
return errors.Wrapf(err, "failed to chown %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
timespec := []unix.Timespec{unix.Timespec(sys.StatAtime(st)), unix.Timespec(sys.StatMtime(st))}
|
timespec := []unix.Timespec{unix.Timespec(StatAtime(st)), unix.Timespec(StatMtime(st))}
|
||||||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
||||||
return errors.Wrapf(err, "failed to utime %s", name)
|
return errors.Wrapf(err, "failed to utime %s", name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,18 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Chown(p string, user *ChownOpt) error {
|
func Chown(p string, old *User, fn Chowner) error {
|
||||||
|
if fn == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
user, err := fn(old)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
if user != nil {
|
if user != nil {
|
||||||
if err := os.Lchown(p, user.Uid, user.Gid); err != nil {
|
if err := os.Lchown(p, user.Uid, user.Gid); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -16,7 +25,7 @@ func Chown(p string, user *ChownOpt) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MkdirAll is forked os.MkdirAll
|
// MkdirAll is forked os.MkdirAll
|
||||||
func MkdirAll(path string, perm os.FileMode, user *ChownOpt, tm *time.Time) error {
|
func MkdirAll(path string, perm os.FileMode, user Chowner, tm *time.Time) error {
|
||||||
// Fast path: if we can tell whether path is a directory or file, stop with success or error.
|
// Fast path: if we can tell whether path is a directory or file, stop with success or error.
|
||||||
dir, err := os.Stat(path)
|
dir, err := os.Stat(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -62,7 +71,7 @@ func MkdirAll(path string, perm os.FileMode, user *ChownOpt, tm *time.Time) erro
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Chown(path, user); err != nil {
|
if err := Chown(path, nil, user); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// +build darwin freebsd netbsd openbsd
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Returns the last-accessed time
|
||||||
|
func StatAtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Atimespec
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the last-modified time
|
||||||
|
func StatMtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Mtimespec
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
// +build dragonfly linux solaris
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Returns the last-accessed time
|
||||||
|
func StatAtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Atim
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the last-modified time
|
||||||
|
func StatMtime(st *syscall.Stat_t) syscall.Timespec {
|
||||||
|
return st.Mtim
|
||||||
|
}
|
|
@ -2,8 +2,6 @@ module github.com/tonistiigi/fsutil
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.4.11 // indirect
|
github.com/Microsoft/go-winio v0.4.11 // indirect
|
||||||
github.com/Microsoft/hcsshim v0.8.5 // indirect
|
|
||||||
github.com/containerd/containerd v1.2.4
|
|
||||||
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352
|
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/docker v0.0.0-20180531152204-71cd53e4a197
|
github.com/docker/docker v0.0.0-20180531152204-71cd53e4a197
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
|
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
|
||||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
github.com/Microsoft/hcsshim v0.8.5 h1:kg/pore5Yyf4DXQ5nelSqfaYQG54YIdNeFRKJaPnFiM=
|
|
||||||
github.com/Microsoft/hcsshim v0.8.5/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
|
||||||
github.com/containerd/containerd v1.2.4 h1:qN8LCvw+KA5wVCOnHspD/n2K9cJ34+YOs05qBBWhHiw=
|
|
||||||
github.com/containerd/containerd v1.2.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
|
||||||
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352 h1:CdBoaTKPl60tksFVWYc5QnLWwXBcU+XcLiXx8+NcZ9o=
|
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352 h1:CdBoaTKPl60tksFVWYc5QnLWwXBcU+XcLiXx8+NcZ9o=
|
||||||
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
|
|
@ -234,7 +234,7 @@ github.com/stretchr/testify/require
|
||||||
github.com/stretchr/testify/assert
|
github.com/stretchr/testify/assert
|
||||||
# github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
# github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
||||||
github.com/syndtr/gocapability/capability
|
github.com/syndtr/gocapability/capability
|
||||||
# github.com/tonistiigi/fsutil v0.0.0-20191018213012-0f039a052ca1
|
# github.com/tonistiigi/fsutil v0.0.0-20200128191323-6c909ab392c1
|
||||||
github.com/tonistiigi/fsutil
|
github.com/tonistiigi/fsutil
|
||||||
github.com/tonistiigi/fsutil/types
|
github.com/tonistiigi/fsutil/types
|
||||||
github.com/tonistiigi/fsutil/copy
|
github.com/tonistiigi/fsutil/copy
|
||||||
|
|
Loading…
Reference in New Issue