diff --git a/client/client_test.go b/client/client_test.go index af5bc722c8bb..c90274dc398a 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -101,6 +101,7 @@ var allTests = []func(t *testing.T, sb integration.Sandbox){ testFileOpCopyAlwaysReplaceExistingDestPaths, testFileOpRmWildcard, testFileOpCopyUIDCache, + testFileOpCopyChmodText, testCallDiskUsage, testBuildMultiMount, testBuildHTTPSource, @@ -1705,6 +1706,48 @@ func testFileOpCopyRm(t *testing.T, sb integration.Sandbox) { require.Equal(t, []byte("file2"), dt) } +func testFileOpCopyChmodText(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + c, err := New(sb.Context(), sb.Address()) + require.NoError(t, err) + defer c.Close() + + tcases := []struct { + src string + dest string + mode string + }{ + {"file", "f1", "go-w"}, + {"file", "f2", "o-rwx,g+x"}, + {"file", "f3", "u=rwx,g=,o="}, + {"file", "f4", "u+rw,g+r,o-x,o+w"}, + {"dir", "d1", "a+X"}, + {"dir", "d2", "g+rw,o+rw"}, + } + + st := llb.Image("alpine"). + Run(llb.Shlex(`sh -c "mkdir /input && touch /input/file && mkdir /input/dir && chmod 0400 /input/dir && mkdir /expected"`)) + + for _, tc := range tcases { + st = st.Run(llb.Shlex(`sh -c "cp -a /input/` + tc.src + ` /expected/` + tc.dest + ` && chmod ` + tc.mode + ` /expected/` + tc.dest + `"`)) + } + cp := llb.Scratch() + + for _, tc := range tcases { + cp = cp.File(llb.Copy(st.Root(), "/input/"+tc.src, "/"+tc.dest, llb.ChmodOpt{ModeStr: tc.mode})) + } + + for _, tc := range tcases { + st = st.Run(llb.Shlex(`sh -c '[ "$(stat -c '%A' /expected/`+tc.dest+`)" == "$(stat -c '%A' /actual/`+tc.dest+`)" ]'`), llb.AddMount("/actual", cp, llb.Readonly)) + } + + def, err := st.Marshal(sb.Context()) + require.NoError(t, err) + + _, err = c.Solve(sb.Context(), def, SolveOpt{}, nil) + require.NoError(t, err) +} + // moby/buildkit#3291 func testFileOpCopyUIDCache(t *testing.T, sb integration.Sandbox) { requiresLinux(t) diff --git a/client/llb/fileop.go b/client/llb/fileop.go index 85af57e093c1..193536e9d2bb 100644 --- a/client/llb/fileop.go +++ b/client/llb/fileop.go @@ -264,6 +264,15 @@ func WithUIDGID(uid, gid int) ChownOption { } } +type ChmodOpt struct { + Mode os.FileMode + ModeStr string +} + +func (co ChmodOpt) SetCopyOption(mi *CopyInfo) { + mi.Mode = &co +} + type ChownOpt struct { User *UserOpt Group *UserOpt @@ -492,7 +501,7 @@ type CopyOption interface { } type CopyInfo struct { - Mode *os.FileMode + Mode *ChmodOpt FollowSymlinks bool CopyDirContentsOnly bool IncludePatterns []string @@ -541,7 +550,11 @@ func (a *fileActionCopy) toProtoAction(ctx context.Context, parent string, base AlwaysReplaceExistingDestPaths: a.info.AlwaysReplaceExistingDestPaths, } if a.info.Mode != nil { - c.Mode = int32(*a.info.Mode) + if a.info.Mode.ModeStr != "" { + c.ModeStr = a.info.Mode.ModeStr + } else { + c.Mode = int32(a.info.Mode.Mode) + } } else { c.Mode = -1 } @@ -574,6 +587,9 @@ func (a *fileActionCopy) addCaps(f *FileOp) { if a.info.AlwaysReplaceExistingDestPaths { addCap(&f.constraints, pb.CapFileCopyAlwaysReplaceExistingDestPaths) } + if a.info.Mode.ModeStr != "" { + addCap(&f.constraints, pb.CapFileCopyModeStringFormat) + } } type CreatedTime time.Time diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index 17e6024d163f..5a6e20112753 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -1359,14 +1359,14 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error { copyOpt = append(copyOpt, llb.WithExcludePatterns(cfg.excludePatterns)) } - var mode *os.FileMode + var mode *llb.ChmodOpt if cfg.chmod != "" { p, err := strconv.ParseUint(cfg.chmod, 8, 32) if err != nil || p > 0o7777 { return errors.Errorf("invalid chmod parameter: '%v'. it should be octal string and between 0 and 07777", cfg.chmod) } perm := os.FileMode(p) - mode = &perm + mode = &llb.ChmodOpt{Mode: perm} } if cfg.checksum != "" { diff --git a/go.mod b/go.mod index 69c71a9e7af7..4053511d8503 100644 --- a/go.mod +++ b/go.mod @@ -68,7 +68,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spdx/tools-golang v0.5.3 github.com/stretchr/testify v1.9.0 - github.com/tonistiigi/fsutil v0.0.0-20240926161958-8754824c3c4f + github.com/tonistiigi/fsutil v0.0.0-20241001141129-e98dfb603c6f github.com/tonistiigi/go-actions-cache v0.0.0-20240327122527-58651d5e11d6 github.com/tonistiigi/go-archvariant v1.0.0 github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 @@ -166,6 +166,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect github.com/shibumi/go-pathspec v1.3.0 // indirect + github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/vishvananda/netns v0.0.4 // indirect go.opencensus.io v0.24.0 // indirect diff --git a/go.sum b/go.sum index 41f32d27e81b..119f3e0c53de 100644 --- a/go.sum +++ b/go.sum @@ -379,8 +379,10 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tonistiigi/fsutil v0.0.0-20240926161958-8754824c3c4f h1:scejvzjNA30X9ufWPUH/a2MhWg1sQPxeC6N6wm7nWEE= -github.com/tonistiigi/fsutil v0.0.0-20240926161958-8754824c3c4f/go.mod h1:xnG7rCC28GVN8efEm5ijNp56TnNtrYCv75EtTH42yz4= +github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 h1:eUk79E1w8yMtXeHSzjKorxuC8qJOnyXQnLaJehxpJaI= +github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY= +github.com/tonistiigi/fsutil v0.0.0-20241001141129-e98dfb603c6f h1:LuAOoRH31KqSNuYFl1grkcl3Sr3+Rv4uQ+e65P0SFLA= +github.com/tonistiigi/fsutil v0.0.0-20241001141129-e98dfb603c6f/go.mod h1:BwWj5HZxE1/r8WnLfSLIMDNyXE9y/XKwQwRqmgx4nKY= github.com/tonistiigi/go-actions-cache v0.0.0-20240327122527-58651d5e11d6 h1:XFG/Wmm5dFYoqUiVChLumRjRzJm0P9k/qDMhxLqdupU= github.com/tonistiigi/go-actions-cache v0.0.0-20240327122527-58651d5e11d6/go.mod h1:anhKd3mnC1shAbQj1Q4IJ+w6xqezxnyDYlx/yKa7IXM= github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0= diff --git a/solver/llbsolver/file/backend.go b/solver/llbsolver/file/backend.go index 7f22a1a1616d..2c529a43a22d 100644 --- a/solver/llbsolver/file/backend.go +++ b/solver/llbsolver/file/backend.go @@ -190,7 +190,9 @@ func docopy(ctx context.Context, src, dest string, action *pb.FileActionCopy, u ci.ExcludePatterns = action.ExcludePatterns ci.Chown = ch ci.Utime = timestampToTime(action.Timestamp) - if m := int(action.Mode); m != -1 { + if action.ModeStr != "" { + ci.ModeStr = action.ModeStr + } else if m := int(action.Mode); m != -1 { ci.Mode = &m } ci.CopyDirContents = action.DirCopyContents diff --git a/solver/pb/caps.go b/solver/pb/caps.go index 2ef56039e598..e8e66ad0f6e1 100644 --- a/solver/pb/caps.go +++ b/solver/pb/caps.go @@ -67,6 +67,7 @@ const ( CapFileCopyIncludeExcludePatterns apicaps.CapID = "file.copy.includeexcludepatterns" CapFileRmNoFollowSymlink apicaps.CapID = "file.rm.nofollowsymlink" CapFileCopyAlwaysReplaceExistingDestPaths apicaps.CapID = "file.copy.alwaysreplaceexistingdestpaths" + CapFileCopyModeStringFormat apicaps.CapID = "file.copy.modestring" CapConstraints apicaps.CapID = "constraints" CapPlatform apicaps.CapID = "platform" diff --git a/solver/pb/ops.pb.go b/solver/pb/ops.pb.go index dc09f31f27a1..ea2e39512ce7 100644 --- a/solver/pb/ops.pb.go +++ b/solver/pb/ops.pb.go @@ -2517,6 +2517,8 @@ type FileActionCopy struct { ExcludePatterns []string `protobuf:"bytes,13,rep,name=exclude_patterns,json=excludePatterns,proto3" json:"exclude_patterns,omitempty"` // alwaysReplaceExistingDestPaths results in an existing dest path that differs in type from the src path being replaced rather than the default of returning an error AlwaysReplaceExistingDestPaths bool `protobuf:"varint,14,opt,name=alwaysReplaceExistingDestPaths,proto3" json:"alwaysReplaceExistingDestPaths,omitempty"` + // mode in non-octal format + ModeStr string `protobuf:"bytes,15,opt,name=modeStr,proto3" json:"modeStr,omitempty"` } func (x *FileActionCopy) Reset() { @@ -2649,6 +2651,13 @@ func (x *FileActionCopy) GetAlwaysReplaceExistingDestPaths() bool { return false } +func (x *FileActionCopy) GetModeStr() string { + if x != nil { + return x.ModeStr + } + return "" +} + type FileActionMkFile struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3600,7 +3609,7 @@ var file_ops_proto_rawDesc = []byte{ 0x05, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x12, 0x22, 0x0a, 0x02, 0x72, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x48, 0x00, 0x52, 0x02, 0x72, 0x6d, 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xc4, 0x04, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xde, 0x04, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x72, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x72, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, @@ -3636,83 +3645,84 @@ var file_ops_proto_rawDesc = []byte{ 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, - 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0x90, 0x01, 0x0a, 0x10, - 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, 0x6c, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, - 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9d, - 0x01, 0x0a, 0x0f, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, - 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, - 0x6b, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, - 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x6e, - 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, - 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x4e, - 0x0a, 0x08, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x75, 0x73, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x4f, 0x70, 0x74, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x53, - 0x0a, 0x07, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x4e, - 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x48, 0x00, 0x52, 0x06, 0x62, - 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x04, 0x62, 0x79, 0x49, 0x44, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x04, 0x62, 0x79, 0x49, 0x44, 0x42, 0x06, 0x0a, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x22, 0x38, 0x0a, 0x0c, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, - 0x4f, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x22, 0x0a, - 0x0a, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x22, 0x31, 0x0a, 0x07, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4f, 0x70, 0x12, 0x26, 0x0a, 0x06, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, - 0x62, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x73, 0x22, 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, - 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x26, 0x0a, 0x0e, - 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x22, 0x5c, 0x0a, 0x06, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x12, 0x28, - 0x0a, 0x05, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, - 0x74, 0x52, 0x05, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x05, 0x75, 0x70, 0x70, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x70, - 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x75, 0x70, 0x70, - 0x65, 0x72, 0x2a, 0x28, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, - 0x05, 0x55, 0x4e, 0x53, 0x45, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, - 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x2a, 0x29, 0x0a, 0x0c, - 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, - 0x53, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x58, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x53, - 0x45, 0x43, 0x55, 0x52, 0x45, 0x10, 0x01, 0x2a, 0x40, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x49, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, - 0x0a, 0x06, 0x53, 0x45, 0x43, 0x52, 0x45, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, - 0x48, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x03, 0x12, 0x09, - 0x0a, 0x05, 0x54, 0x4d, 0x50, 0x46, 0x53, 0x10, 0x04, 0x2a, 0x31, 0x0a, 0x11, 0x4d, 0x6f, 0x75, - 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0b, - 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, - 0x4e, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x46, 0x46, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0f, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, 0x74, 0x12, - 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, - 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, - 0x45, 0x44, 0x10, 0x02, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, - 0x2f, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, + 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, + 0x64, 0x65, 0x53, 0x74, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x10, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, + 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, + 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, + 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9d, 0x01, 0x0a, 0x0f, 0x46, 0x69, 0x6c, + 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, + 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, + 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x6e, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, + 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, + 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x4e, 0x0a, 0x08, 0x43, 0x68, 0x6f, 0x77, + 0x6e, 0x4f, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x52, + 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, + 0x74, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x53, 0x0a, 0x07, 0x55, 0x73, 0x65, 0x72, + 0x4f, 0x70, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x4f, 0x70, 0x74, 0x48, 0x00, 0x52, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x14, 0x0a, 0x04, 0x62, 0x79, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, + 0x04, 0x62, 0x79, 0x49, 0x44, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x38, 0x0a, + 0x0c, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x22, 0x0a, 0x0a, 0x4d, 0x65, 0x72, 0x67, 0x65, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x31, 0x0a, 0x07, 0x4d, + 0x65, 0x72, 0x67, 0x65, 0x4f, 0x70, 0x12, 0x26, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x72, 0x67, + 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x22, 0x26, + 0x0a, 0x0e, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x26, 0x0a, 0x0e, 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, + 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x5c, + 0x0a, 0x06, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x6f, 0x77, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x77, + 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x6c, 0x6f, 0x77, + 0x65, 0x72, 0x12, 0x28, 0x0a, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x2a, 0x28, 0x0a, 0x07, + 0x4e, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x53, 0x45, 0x54, + 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, + 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x2a, 0x29, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x41, 0x4e, 0x44, 0x42, 0x4f, + 0x58, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x53, 0x45, 0x43, 0x55, 0x52, 0x45, 0x10, + 0x01, 0x2a, 0x40, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, + 0x0a, 0x04, 0x42, 0x49, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x43, 0x52, + 0x45, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x10, 0x02, 0x12, 0x09, 0x0a, + 0x05, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x4d, 0x50, 0x46, + 0x53, 0x10, 0x04, 0x2a, 0x31, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x07, 0x0a, + 0x03, 0x4f, 0x46, 0x46, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0f, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, + 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, + 0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, + 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x02, 0x42, 0x24, + 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, + 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/solver/pb/ops.proto b/solver/pb/ops.proto index 32435bb86ecc..f1432af65bcb 100644 --- a/solver/pb/ops.proto +++ b/solver/pb/ops.proto @@ -341,6 +341,8 @@ message FileActionCopy { repeated string exclude_patterns = 13; // alwaysReplaceExistingDestPaths results in an existing dest path that differs in type from the src path being replaced rather than the default of returning an error bool alwaysReplaceExistingDestPaths = 14; + // mode in non-octal format + string modeStr = 15; } message FileActionMkFile { diff --git a/vendor/github.com/tonistiigi/dchapes-mode/.hgignore b/vendor/github.com/tonistiigi/dchapes-mode/.hgignore new file mode 100644 index 000000000000..be8f61dd1540 --- /dev/null +++ b/vendor/github.com/tonistiigi/dchapes-mode/.hgignore @@ -0,0 +1,5 @@ +syntax: glob +bench*.out* +cmode +coverage.out +coverage.txt diff --git a/vendor/github.com/tonistiigi/dchapes-mode/Dockerfile b/vendor/github.com/tonistiigi/dchapes-mode/Dockerfile new file mode 100644 index 000000000000..b295c4fb8ea1 --- /dev/null +++ b/vendor/github.com/tonistiigi/dchapes-mode/Dockerfile @@ -0,0 +1,29 @@ + +# syntax=docker/dockerfile:1 + +ARG GO_VERSION=1.23 +ARG XX_VERSION=1.5.0 + +FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx + +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS base +RUN apk add --no-cache git +COPY --from=xx / / +WORKDIR /src + +FROM base AS build +ARG TARGETPLATFORM +RUN --mount=target=. --mount=target=/go/pkg/mod,type=cache \ + --mount=target=/root/.cache,type=cache \ + xx-go build ./... + +FROM base AS test +ARG TESTFLAGS +RUN --mount=target=. --mount=target=/go/pkg/mod,type=cache \ + --mount=target=/root/.cache,type=cache \ + xx-go test -v -coverprofile=/tmp/coverage.txt -covermode=atomic ${TESTFLAGS} ./... + +FROM scratch AS test-coverage +COPY --from=test /tmp/coverage.txt /coverage-root.txt + +FROM build \ No newline at end of file diff --git a/vendor/github.com/tonistiigi/dchapes-mode/LICENSE b/vendor/github.com/tonistiigi/dchapes-mode/LICENSE new file mode 100644 index 000000000000..a8743fb2d8b1 --- /dev/null +++ b/vendor/github.com/tonistiigi/dchapes-mode/LICENSE @@ -0,0 +1,22 @@ +Copyright © 2016-2018, Dave Chapeskie +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/tonistiigi/dchapes-mode/README.md b/vendor/github.com/tonistiigi/dchapes-mode/README.md new file mode 100644 index 000000000000..dca34f9fcc21 --- /dev/null +++ b/vendor/github.com/tonistiigi/dchapes-mode/README.md @@ -0,0 +1,26 @@ +Mode +======== + +This is a fork of [hg.sr.ht/~dchapes/mode](https://hg.sr.ht/~dchapes/mode) with minimal patches and basic CI. + +[Mode](https://hg.sr.ht/~dchapes/mode) +is a [Go](http://golang.org/) package that provides +a native Go implementation of BSD's +[`setmode`](https://www.freebsd.org/cgi/man.cgi?query=setmode&sektion=3) +and `getmode` which can be used to modify the mode bits of +an [`os.FileMode`](https://golang.org/pkg/os#FileMode) value +based on a symbolic value as described by the +Unix [`chmod`](https://www.freebsd.org/cgi/man.cgi?query=chmod&sektion=1) command. + +[![Go Reference](https://pkg.go.dev/badge/hg.sr.ht/~dchapes/mode.svg)](https://pkg.go.dev/hg.sr.ht/~dchapes/mode) + +Online package documentation is available via +[pkg.go.dev](https://pkg.go.dev/hg.sr.ht/~dchapes/mode). + +To install: + + go get hg.sr.ht/~dchapes/mode + +or `go build` any Go code that imports it: + + import "hg.sr.ht/~dchapes/mode" diff --git a/vendor/github.com/tonistiigi/dchapes-mode/bits.go b/vendor/github.com/tonistiigi/dchapes-mode/bits.go new file mode 100644 index 000000000000..4dbb08ad7869 --- /dev/null +++ b/vendor/github.com/tonistiigi/dchapes-mode/bits.go @@ -0,0 +1,76 @@ +package mode + +import "os" + +type modet uint16 + +// Although many of these can be found in the syscall package +// we don't use those to avoid the dependency, add some more +// values, use non-exported Go names, and use octal for better clarity. +// +// Note that Go only uses the the nine least significant bits as "Unix +// permission bits" (os.ModePerm == 0777). We use chmod(1)'s octal +// definitions that include three further bits: isUID, isGID, and +// isTXT (07000). Go has os.ModeSetuid=1<<23, os.ModeSetgid=1<<22, +// and os.ModeSticy=1<<20 for these. We do this so that absolute +// octal values can include those bits as defined by chmod(1). +const ( + //ifDir = 040000 // directory + isUID = 04000 // set user id on execution + isGID = 02000 // set group id on execution + isTXT = 01000 // sticky bit + iRWXU = 00700 // RWX mask for owner + iRUser = 00400 // R for owner + iWUser = 00200 // W for owner + iXUser = 00100 // X for owner + iRWXG = 00070 // RWX mask for group + iRGroup = 00040 // R for group + iWGroup = 00020 // W for group + iXGroup = 00010 // X for group + iRWXO = 00007 // RWX mask for other + iROther = 00004 // R for other + iWOther = 00002 // W for other + iXOther = 00001 // X for other + + standardBits = isUID | isGID | iRWXU | iRWXG | iRWXO + + // os.FileMode bits we touch + fmBits = os.ModeSetuid | os.ModeSetgid | os.ModeSticky | os.ModePerm +) + +func fileModeToBits(fm os.FileMode) modet { + m := modet(fm.Perm()) + /* + if fm&os.ModeSetuid != 0 { + m |= isUID + } + if fm&os.ModeSetgid != 0 { + m |= isGID + } + if fm&os.ModeSticky != 0 { + m |= isTXT + } + */ + m |= modet(fm & (os.ModeSetuid | os.ModeSetgid) >> 12) + m |= modet(fm & os.ModeSticky >> 11) + return m +} + +func bitsToFileMode(old os.FileMode, m modet) os.FileMode { + fm := old &^ fmBits + fm |= os.FileMode(m) & os.ModePerm + /* + if m&isUID != 0 { + fm |= os.ModeSetuid + } + if m&isGID != 0 { + fm |= os.ModeSetgid + } + if m&isTXT != 0 { + fm |= os.ModeSticky + } + */ + fm |= os.FileMode(m&(isUID|isGID)) << 12 + fm |= os.FileMode(m&isTXT) << 11 + return fm +} diff --git a/vendor/github.com/tonistiigi/dchapes-mode/docker-bake.hcl b/vendor/github.com/tonistiigi/dchapes-mode/docker-bake.hcl new file mode 100644 index 000000000000..1220e9096962 --- /dev/null +++ b/vendor/github.com/tonistiigi/dchapes-mode/docker-bake.hcl @@ -0,0 +1,24 @@ +variable "GO_VERSION" { + default = null +} + +group "default" { + targets = ["build"] +} + +target "build" { + args = { + GO_VERSION = GO_VERSION + } + output = ["type=cacheonly"] +} + +target "test" { + inherits = ["build"] + target = "test" +} + +target "cross" { + inherits = ["build"] + platforms = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x", "darwin/amd64", "darwin/arm64", "windows/amd64", "windows/arm64", "freebsd/amd64", "freebsd/arm64"] +} \ No newline at end of file diff --git a/vendor/github.com/tonistiigi/dchapes-mode/mode.go b/vendor/github.com/tonistiigi/dchapes-mode/mode.go new file mode 100644 index 000000000000..01d3444f9142 --- /dev/null +++ b/vendor/github.com/tonistiigi/dchapes-mode/mode.go @@ -0,0 +1,546 @@ +/* + +Parts of this file are a heavily modified C to Go +translation of BSD's /usr/src/lib/libc/gen/setmode.c +that contains the following copyright notice: + + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Dave Borman at Cray Research, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + +*/ + +// Package mode provides a native Go implementation of BSD's setmode and getmode +// which can be used to modify the mode bits of an os.FileMode value based on +// a symbolic value as described by the Unix chmod command. +// +// For a full description of the mode string see chmod(1). +// Some examples include: +// +// 644 make a file readable by anyone and writable by the owner +// only. +// +// go-w deny write permission to group and others. +// +// =rw,+X set the read and write permissions to the usual defaults, +// but retain any execute permissions that are currently set. +// +// +X make a directory or file searchable/executable by everyone +// if it is already searchable/executable by anyone. +// +// 755 +// u=rwx,go=rx +// u=rwx,go=u-w make a file readable/executable by everyone and writable by +// the owner only. +// +// go= clear all mode bits for group and others. +// +// go=u-w set the group bits equal to the user bits, but clear the +// group write bit. +// +// See Also: +// +// setmode(3): https://www.freebsd.org/cgi/man.cgi?query=setmode&sektion=3 +// chmod(1): https://www.freebsd.org/cgi/man.cgi?query=chmod&sektion=1 +package mode + +import ( + "errors" + "fmt" + "os" + "strconv" + "strings" +) + +// Set is a set of changes to apply to an os.FileMode. +// Changes include setting or clearing specific bits, copying bits from one +// user class to another (e.g. "u=go" sets the user permissions to a copy of +// the group and other permsissions), etc. +type Set struct { + cmds []bitcmd +} + +type bitcmd struct { + cmd byte + cmd2 byte + bits modet +} + +const ( + cmd2Clear byte = 1 << iota + cmd2Set + cmd2GBits + cmd2OBits + cmd2UBits +) + +func (c bitcmd) String() string { + c2 := "" + if c.cmd2 != 0 { + c2 = " cmd2:" + if c.cmd2&cmd2Clear != 0 { + c2 += " CLR" + } + if c.cmd2&cmd2Set != 0 { + c2 += " SET" + } + if c.cmd2&cmd2UBits != 0 { + c2 += " UBITS" + } + if c.cmd2&cmd2GBits != 0 { + c2 += " GBITS" + } + if c.cmd2&cmd2OBits != 0 { + c2 += " OBITS" + } + } + return fmt.Sprintf("cmd: %q bits %#05o%s", c.cmd, c.bits, c2) +} + +// The String method will likely only be useful when testing. +func (s Set) String() string { + var buf strings.Builder + buf.Grow(21*len(s.cmds) + 10) + _, _ = buf.WriteString("set: {\n") + for _, c := range s.cmds { + _, _ = buf.WriteString(c.String()) + _ = buf.WriteByte('\n') + } + _, _ = buf.WriteString("}") + return buf.String() +} + +// ErrSyntax indicates an argument does not represent a valid mode. +var ErrSyntax = errors.New("invalid syntax") + +// Apply changes the provided os.FileMode based on the given umask and +// absolute or symbolic mode value. +// +// Apply is a convience to calling ParseWithUmask followed by Apply. +// Since it needs to parse the mode value string on each call it +// should only be used when mode value string will not be reapplied. +func Apply(s string, perm os.FileMode, umask uint) (os.FileMode, error) { + set, err := ParseWithUmask(s, umask) + if err != nil { + return 0, err + } + return set.Apply(perm), nil +} + +// Parse takes an absolute (octal) or symbolic mode value, +// as described in chmod(1), as an argument and returns +// the set of bit operations representing the mode value +// that can be applied to specific os.FileMode values. +// +// Same as ParseWithUmask(s, 0). +func Parse(s string) (Set, error) { + return ParseWithUmask(s, 0) +} + +// TODO(dchapes): A Set.Parse method that reuses existing memory. + +// TODO(dchapes): Only call syscall.Umask when abosolutely necessary and +// provide a Set method to query if set is umask dependant (and perhaps +// the umask that was in effect when parsed). + +// ParseWithUmask is like Parse but uses the provided +// file creation mask instead of calling syscall.Umask. +func ParseWithUmask(s string, umask uint) (Set, error) { + var m Set + if s == "" { + return m, ErrSyntax + } + + // If an absolute number, get it and return; + // disallow non-octal digits or illegal bits. + if d := s[0]; '0' <= d && d <= '9' { + v, err := strconv.ParseInt(s, 8, 16) + if err != nil { + return m, err + } + if v&^(standardBits|isTXT) != 0 { + return m, ErrSyntax + } + // We know this takes exactly two bitcmds. + m.cmds = make([]bitcmd, 0, 2) + m.addcmd('=', standardBits|isTXT, modet(v), 0) + return m, nil + } + + // Get a copy of the mask for the permissions that are mask relative. + // Flip the bits, we want what's not set. + var mask modet = ^modet(umask) + + // Pre-allocate room for several commands. + //m.cmds = make([]bitcmd, 0, 8) + + // Build list of bitcmd structs to set/clear/copy bits as described by + // each clause of the symbolic mode. + equalOpDone := false + for { + // First, find out which bits might be modified. + var who modet + whoLoop: + for { + if len(s) == 0 { + return Set{}, ErrSyntax + } + switch s[0] { + case 'a': + who |= standardBits + case 'u': + who |= isUID | iRWXU + case 'g': + who |= isGID | iRWXG + case 'o': + who |= iRWXO + default: + break whoLoop + } + s = s[1:] + } + + var op byte + getop: + op, s = s[0], s[1:] + switch op { + case '+', '-': + // Nothing. + case '=': + equalOpDone = false + default: + return Set{}, ErrSyntax + } + + who &^= isTXT + permLoop: + for perm, permX := modet(0), modet(0); ; s = s[1:] { + var b byte + if len(s) > 0 { + b = s[0] + } + switch b { + case 'r': + perm |= iRUser | iRGroup | iROther + case 's': + // If only "other" bits ignore set-id. + if who == 0 || who&^iRWXO != 0 { + perm |= isUID | isGID + } + case 't': + // If only "other bits ignore sticky. + if who == 0 || who&^iRWXO != 0 { + who |= isTXT + perm |= isTXT + } + case 'w': + perm |= iWUser | iWGroup | iWOther + case 'X': + if op == '+' { + permX = iXUser | iXGroup | iXOther + } + case 'x': + perm |= iXUser | iXGroup | iXOther + case 'u', 'g', 'o': + // Whenever we hit 'u', 'g', or 'o', we have + // to flush out any partial mode that we have, + // and then do the copying of the mode bits. + if perm != 0 { + m.addcmd(op, who, perm, mask) + perm = 0 + } + if op == '=' { + equalOpDone = true + } + if permX != 0 { + m.addcmd('X', who, permX, mask) + permX = 0 + } + m.addcmd(b, who, modet(op), mask) + default: + // Add any permissions that we haven't alread done. + if perm != 0 || op == '=' && !equalOpDone { + if op == '=' { + equalOpDone = true + } + m.addcmd(op, who, perm, mask) + //perm = 0 + } + if permX != 0 { + m.addcmd('X', who, permX, mask) + //permX = 0 + } + break permLoop + } + } + + if s == "" { + break + } + if s[0] != ',' { + goto getop + } + s = s[1:] + } + + m.compress() + return m, nil +} + +// Apply returns the os.FileMode after applying the set of changes. +func (s Set) Apply(perm os.FileMode) os.FileMode { + omode := fileModeToBits(perm) + newmode := omode + + // When copying the user, group or other bits around, we "know" + // where the bits are in the mode so that we can do shifts to + // copy them around. If we don't use shifts, it gets real + // grundgy with lots of single bit checks and bit sets. + common := func(c bitcmd, value modet) { + if c.cmd2&cmd2Clear != 0 { + var clrval modet + if c.cmd2&cmd2Set != 0 { + clrval = iRWXO + } else { + clrval = value + } + if c.cmd2&cmd2UBits != 0 { + newmode &^= clrval << 6 & c.bits + } + if c.cmd2&cmd2GBits != 0 { + newmode &^= clrval << 3 & c.bits + } + if c.cmd2&cmd2OBits != 0 { + newmode &^= clrval & c.bits + } + } + if c.cmd2&cmd2Set != 0 { + if c.cmd2&cmd2UBits != 0 { + newmode |= value << 6 & c.bits + } + if c.cmd2&cmd2GBits != 0 { + newmode |= value << 3 & c.bits + } + if c.cmd2&cmd2OBits != 0 { + newmode |= value & c.bits + } + } + } + + for _, c := range s.cmds { + switch c.cmd { + case 'u': + common(c, newmode&iRWXU>>6) + case 'g': + common(c, newmode&iRWXG>>3) + case 'o': + common(c, newmode&iRWXO) + + case '+': + newmode |= c.bits + case '-': + newmode &^= c.bits + + case 'X': + if omode&(iXUser|iXGroup|iXOther) != 0 || perm.IsDir() { + newmode |= c.bits + } + } + } + + return bitsToFileMode(perm, newmode) +} + +// Chmod is a convience routine that applies the changes in +// Set to the named file. To avoid some race conditions, +// it opens the file and uses os.File.Stat and +// os.File.Chmod rather than os.Stat and os.Chmod if possible. +func (s *Set) Chmod(name string) (old, new os.FileMode, err error) { + if f, err := os.Open(name); err == nil { // nolint: vetshadow + defer f.Close() // nolint: errcheck + return s.ChmodFile(f) + } + // Fallback to os.Stat and os.Chmod if we + // don't have permission to open the file. + fi, err := os.Stat(name) + if err != nil { + return 0, 0, err + } + old = fi.Mode() + new = s.Apply(old) + if new != old { + err = os.Chmod(name, new) + } + return old, new, err + +} + +// ChmodFile is a convience routine that applies +// the changes in Set to the open file f. +func (s *Set) ChmodFile(f *os.File) (old, new os.FileMode, err error) { + fi, err := f.Stat() + if err != nil { + return 0, 0, err + } + old = fi.Mode() + new = s.Apply(old) + if new != old { + err = f.Chmod(new) + } + return old, new, err +} + +func (s *Set) addcmd(op byte, who, oparg, mask modet) { + c := bitcmd{} + switch op { + case '=': + c.cmd = '-' + if who != 0 { + c.bits = who + } else { + c.bits = standardBits + } + + s.cmds = append(s.cmds, c) + //c = bitcmd{} // reset, not actually needed + op = '+' + fallthrough + case '+', '-', 'X': + c.cmd = op + if who != 0 { + c.bits = who & oparg + } else { + c.bits = mask & oparg + } + + case 'u', 'g', 'o': + c.cmd = op + if who != 0 { + if who&iRUser != 0 { + c.cmd2 |= cmd2UBits + } + if who&iRGroup != 0 { + c.cmd2 |= cmd2GBits + } + if who&iROther != 0 { + c.cmd2 |= cmd2OBits + } + c.bits = ^modet(0) + } else { + c.cmd2 = cmd2UBits | cmd2GBits | cmd2OBits + c.bits = mask + } + + switch oparg { + case '+': + c.cmd2 |= cmd2Set + case '-': + c.cmd2 |= cmd2Clear + case '=': + c.cmd2 |= cmd2Set | cmd2Clear + } + default: + panic("unreachable") + } + s.cmds = append(s.cmds, c) +} + +// compress by compacting consecutive '+', '-' and 'X' +// commands into at most 3 commands, one of each. The 'u', +// 'g' and 'o' commands continue to be separate. They could +// probably be compacted, but it's not worth the effort. +func (s *Set) compress() { + //log.Println("before:", *m) + //log.Println("Start compress:") + j := 0 + for i := 0; i < len(s.cmds); i++ { + c := s.cmds[i] + //log.Println(" read", i, c) + if strings.IndexByte("+-X", c.cmd) < 0 { + // Copy over any 'u', 'g', and 'o' commands. + if i != j { + s.cmds[j] = c + } + //log.Println(" wrote", j, "from", i) + j++ + continue + } + var setbits, clrbits, Xbits modet + for ; i < len(s.cmds); i++ { + c = s.cmds[i] + //log.Println(" scan", i, c) + switch c.cmd { + case '-': + clrbits |= c.bits + setbits &^= c.bits + Xbits &^= c.bits + continue + case '+': + setbits |= c.bits + clrbits &^= c.bits + Xbits &^= c.bits + continue + case 'X': + Xbits |= c.bits &^ setbits + continue + default: + i-- + } + break + } + if clrbits != 0 { + s.cmds[j].cmd = '-' + s.cmds[j].cmd2 = 0 + s.cmds[j].bits = clrbits + //log.Println(" wrote", j, "clrbits") + j++ + } + if setbits != 0 { + s.cmds[j].cmd = '+' + s.cmds[j].cmd2 = 0 + s.cmds[j].bits = setbits + //log.Println(" wrote", j, "setbits") + j++ + } + if Xbits != 0 { + s.cmds[j].cmd = 'X' + s.cmds[j].cmd2 = 0 + s.cmds[j].bits = Xbits + //log.Println(" wrote", j, "Xbits") + j++ + } + } + /* + if len(m.cmds) != j { + log.Println("compressed", len(m.cmds), "down to", j) + } + */ + s.cmds = s.cmds[:j] + //log.Println("after:", *m) +} diff --git a/vendor/github.com/tonistiigi/fsutil/Dockerfile b/vendor/github.com/tonistiigi/fsutil/Dockerfile index 21c1f39f6082..3a76d341fb45 100644 --- a/vendor/github.com/tonistiigi/fsutil/Dockerfile +++ b/vendor/github.com/tonistiigi/fsutil/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 -ARG GO_VERSION=1.21 -ARG XX_VERSION=1.4.0 +ARG GO_VERSION=1.23 +ARG XX_VERSION=1.5.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy.go b/vendor/github.com/tonistiigi/fsutil/copy/copy.go index f8cc0a4331f7..c2b1ab97d080 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy.go @@ -13,6 +13,7 @@ import ( "github.com/containerd/continuity/fs" "github.com/moby/patternmatcher" "github.com/pkg/errors" + mode "github.com/tonistiigi/dchapes-mode" "github.com/tonistiigi/fsutil" ) @@ -83,12 +84,21 @@ func Copy(ctx context.Context, srcRoot, src, dstRoot, dst string, opts ...Opt) e } } + var modeSet *mode.Set + if ci.ModeStr != "" { + ms, err := mode.ParseWithUmask(ci.ModeStr, 0) + if err != nil { + return err + } + modeSet = &ms + } + dst, err := fs.RootPath(dstRoot, filepath.Clean(dst)) if err != nil { return err } - c, err := newCopier(dstRoot, ci.Chown, ci.Utime, ci.Mode, ci.XAttrErrorHandler, ci.IncludePatterns, ci.ExcludePatterns, ci.AlwaysReplaceExistingDestPaths, ci.ChangeFunc) + c, err := newCopier(dstRoot, ci.Chown, ci.Utime, ci.Mode, modeSet, ci.XAttrErrorHandler, ci.IncludePatterns, ci.ExcludePatterns, ci.AlwaysReplaceExistingDestPaths, ci.ChangeFunc) if err != nil { return err } @@ -161,10 +171,12 @@ type Chowner func(*User) (*User, error) type XAttrErrorHandler func(dst, src, xattrKey string, err error) error type CopyInfo struct { - Chown Chowner - Utime *time.Time - AllowWildcards bool - Mode *int + Chown Chowner + Utime *time.Time + AllowWildcards bool + Mode *int + // ModeStr is mode in non-octal format. Overrides Mode if non-empty. + ModeStr string XAttrErrorHandler XAttrErrorHandler CopyDirContents bool FollowLinks bool @@ -234,6 +246,7 @@ type copier struct { chown Chowner utime *time.Time mode *int + modeSet *mode.Set inodes map[uint64]string xattrErrorHandler XAttrErrorHandler includePatternMatcher *patternmatcher.PatternMatcher @@ -250,7 +263,7 @@ type parentDir struct { copied bool } -func newCopier(root string, chown Chowner, tm *time.Time, mode *int, xeh XAttrErrorHandler, includePatterns, excludePatterns []string, alwaysReplaceExistingDestPaths bool, changeFunc fsutil.ChangeFunc) (*copier, error) { +func newCopier(root string, chown Chowner, tm *time.Time, mode *int, modeSet *mode.Set, xeh XAttrErrorHandler, includePatterns, excludePatterns []string, alwaysReplaceExistingDestPaths bool, changeFunc fsutil.ChangeFunc) (*copier, error) { if xeh == nil { xeh = func(dst, src, key string, err error) error { return err @@ -282,6 +295,7 @@ func newCopier(root string, chown Chowner, tm *time.Time, mode *int, xeh XAttrEr utime: tm, xattrErrorHandler: xeh, mode: mode, + modeSet: modeSet, includePatternMatcher: includePatternMatcher, excludePatternMatcher: excludePatternMatcher, changefn: changeFunc, diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go index 6d9b490c66c0..9b046c539733 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go @@ -29,7 +29,9 @@ func (c *copier) copyFileInfo(fi os.FileInfo, src, name string) error { } m := fi.Mode() - if c.mode != nil { + if c.modeSet != nil { + m = c.modeSet.Apply(m) + } else if c.mode != nil { m = os.FileMode(*c.mode).Perm() if *c.mode&syscall.S_ISGID != 0 { m |= os.ModeSetgid diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go index 4a7d0c86b1bb..e90a41d3563a 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go @@ -30,7 +30,9 @@ func (c *copier) copyFileInfo(fi os.FileInfo, src, name string) error { } m := fi.Mode() - if c.mode != nil { + if c.modeSet != nil { + m = c.modeSet.Apply(m) + } else if c.mode != nil { m = os.FileMode(*c.mode).Perm() if *c.mode&syscall.S_ISGID != 0 { m |= os.ModeSetgid diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go index 58f822d0cf82..a049565e0b89 100644 --- a/vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go +++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_windows.go @@ -37,6 +37,10 @@ func getFileSecurityInfo(name string) (*windows.SID, *windows.ACL, error) { } func (c *copier) copyFileInfo(fi os.FileInfo, src, name string) error { + if c.modeSet != nil { + return errors.Errorf("non-octal mode not supported on windows") + } + if err := os.Chmod(name, fi.Mode()); err != nil { return errors.Wrapf(err, "failed to chmod %s", name) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 916d428e61b9..51fd94242f9d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -733,8 +733,11 @@ github.com/spdx/tools-golang/spdx/v2/v2_3 ## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/require -# github.com/tonistiigi/fsutil v0.0.0-20240926161958-8754824c3c4f -## explicit; go 1.20 +# github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 +## explicit; go 1.21 +github.com/tonistiigi/dchapes-mode +# github.com/tonistiigi/fsutil v0.0.0-20241001141129-e98dfb603c6f +## explicit; go 1.21 github.com/tonistiigi/fsutil github.com/tonistiigi/fsutil/copy github.com/tonistiigi/fsutil/types