Signed-off-by: Sébastien HOUZÉ <cto@verylastroom.com>
| ... | ... |
@@ -382,6 +382,7 @@ type tarAppender struct {
|
| 382 | 382 |
// for hardlink mapping |
| 383 | 383 |
SeenFiles map[uint64]string |
| 384 | 384 |
IDMappings *idtools.IDMappings |
| 385 |
+ ChownOpts *idtools.IDPair |
|
| 385 | 386 |
|
| 386 | 387 |
// For packing and unpacking whiteout files in the |
| 387 | 388 |
// non standard format. The whiteout files defined |
| ... | ... |
@@ -390,12 +391,13 @@ type tarAppender struct {
|
| 390 | 390 |
WhiteoutConverter tarWhiteoutConverter |
| 391 | 391 |
} |
| 392 | 392 |
|
| 393 |
-func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer) *tarAppender {
|
|
| 393 |
+func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair) *tarAppender {
|
|
| 394 | 394 |
return &tarAppender{
|
| 395 | 395 |
SeenFiles: make(map[uint64]string), |
| 396 | 396 |
TarWriter: tar.NewWriter(writer), |
| 397 | 397 |
Buffer: pools.BufioWriter32KPool.Get(nil), |
| 398 | 398 |
IDMappings: idMapping, |
| 399 |
+ ChownOpts: chownOpts, |
|
| 399 | 400 |
} |
| 400 | 401 |
} |
| 401 | 402 |
|
| ... | ... |
@@ -470,6 +472,12 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
| 470 | 470 |
} |
| 471 | 471 |
} |
| 472 | 472 |
|
| 473 |
+ // explicitly override with ChownOpts |
|
| 474 |
+ if ta.ChownOpts != nil {
|
|
| 475 |
+ hdr.Uid = ta.ChownOpts.UID |
|
| 476 |
+ hdr.Gid = ta.ChownOpts.GID |
|
| 477 |
+ } |
|
| 478 |
+ |
|
| 473 | 479 |
if ta.WhiteoutConverter != nil {
|
| 474 | 480 |
wo, err := ta.WhiteoutConverter.ConvertWrite(hdr, path, fi) |
| 475 | 481 |
if err != nil {
|
| ... | ... |
@@ -692,6 +700,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) |
| 692 | 692 |
ta := newTarAppender( |
| 693 | 693 |
idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), |
| 694 | 694 |
compressWriter, |
| 695 |
+ options.ChownOpts, |
|
| 695 | 696 |
) |
| 696 | 697 |
ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat) |
| 697 | 698 |
|
| ... | ... |
@@ -14,6 +14,7 @@ import ( |
| 14 | 14 |
"testing" |
| 15 | 15 |
"time" |
| 16 | 16 |
|
| 17 |
+ "github.com/docker/docker/pkg/idtools" |
|
| 17 | 18 |
"github.com/stretchr/testify/assert" |
| 18 | 19 |
"github.com/stretchr/testify/require" |
| 19 | 20 |
) |
| ... | ... |
@@ -724,6 +725,57 @@ func TestTarUntar(t *testing.T) {
|
| 724 | 724 |
} |
| 725 | 725 |
} |
| 726 | 726 |
|
| 727 |
+func TestTarWithOptionsChownOptsAlwaysOverridesIdPair(t *testing.T) {
|
|
| 728 |
+ origin, err := ioutil.TempDir("", "docker-test-tar-chown-opt")
|
|
| 729 |
+ require.NoError(t, err) |
|
| 730 |
+ |
|
| 731 |
+ defer os.RemoveAll(origin) |
|
| 732 |
+ filePath := filepath.Join(origin, "1") |
|
| 733 |
+ err = ioutil.WriteFile(filePath, []byte("hello world"), 0700)
|
|
| 734 |
+ require.NoError(t, err) |
|
| 735 |
+ |
|
| 736 |
+ idMaps := []idtools.IDMap{
|
|
| 737 |
+ 0: {
|
|
| 738 |
+ ContainerID: 0, |
|
| 739 |
+ HostID: 0, |
|
| 740 |
+ Size: 65536, |
|
| 741 |
+ }, |
|
| 742 |
+ 1: {
|
|
| 743 |
+ ContainerID: 0, |
|
| 744 |
+ HostID: 100000, |
|
| 745 |
+ Size: 65536, |
|
| 746 |
+ }, |
|
| 747 |
+ } |
|
| 748 |
+ |
|
| 749 |
+ cases := []struct {
|
|
| 750 |
+ opts *TarOptions |
|
| 751 |
+ expectedUID int |
|
| 752 |
+ expectedGID int |
|
| 753 |
+ }{
|
|
| 754 |
+ {&TarOptions{ChownOpts: &idtools.IDPair{UID: 1337, GID: 42}}, 1337, 42},
|
|
| 755 |
+ {&TarOptions{ChownOpts: &idtools.IDPair{UID: 100001, GID: 100001}, UIDMaps: idMaps, GIDMaps: idMaps}, 100001, 100001},
|
|
| 756 |
+ {&TarOptions{ChownOpts: &idtools.IDPair{UID: 0, GID: 0}, NoLchown: false}, 0, 0},
|
|
| 757 |
+ {&TarOptions{ChownOpts: &idtools.IDPair{UID: 1, GID: 1}, NoLchown: true}, 1, 1},
|
|
| 758 |
+ {&TarOptions{ChownOpts: &idtools.IDPair{UID: 1000, GID: 1000}, NoLchown: true}, 1000, 1000},
|
|
| 759 |
+ } |
|
| 760 |
+ for _, testCase := range cases {
|
|
| 761 |
+ reader, err := TarWithOptions(filePath, testCase.opts) |
|
| 762 |
+ require.NoError(t, err) |
|
| 763 |
+ tr := tar.NewReader(reader) |
|
| 764 |
+ defer reader.Close() |
|
| 765 |
+ for {
|
|
| 766 |
+ hdr, err := tr.Next() |
|
| 767 |
+ if err == io.EOF {
|
|
| 768 |
+ // end of tar archive |
|
| 769 |
+ break |
|
| 770 |
+ } |
|
| 771 |
+ require.NoError(t, err) |
|
| 772 |
+ assert.Equal(t, hdr.Uid, testCase.expectedUID, "Uid equals expected value") |
|
| 773 |
+ assert.Equal(t, hdr.Gid, testCase.expectedGID, "Gid equals expected value") |
|
| 774 |
+ } |
|
| 775 |
+ } |
|
| 776 |
+} |
|
| 777 |
+ |
|
| 727 | 778 |
func TestTarWithOptions(t *testing.T) {
|
| 728 | 779 |
// TODO Windows: Figure out how to fix this test. |
| 729 | 780 |
if runtime.GOOS == "windows" {
|
| ... | ... |
@@ -394,7 +394,7 @@ func ChangesSize(newDir string, changes []Change) int64 {
|
| 394 | 394 |
func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (io.ReadCloser, error) {
|
| 395 | 395 |
reader, writer := io.Pipe() |
| 396 | 396 |
go func() {
|
| 397 |
- ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer) |
|
| 397 |
+ ta := newTarAppender(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer, nil) |
|
| 398 | 398 |
|
| 399 | 399 |
// this buffer is needed for the duration of this piped stream |
| 400 | 400 |
defer pools.BufioWriter32KPool.Put(ta.Buffer) |