Ver Fonte

Merge pull request #167 from thaJeztah/18.09_backport_cp_longname

[18.09 backport] pkg/archive:CopyTo(): fix for long dest filename
Andrew Hsu há 6 anos atrás
pai
commit
2f867e6b4c
2 ficheiros alterados com 32 adições e 0 exclusões
  1. 8 0
      pkg/archive/copy.go
  2. 24 0
      pkg/archive/copy_unix_test.go

+ 8 - 0
pkg/archive/copy.go

@@ -336,6 +336,14 @@ func RebaseArchiveEntries(srcContent io.Reader, oldBase, newBase string) io.Read
 				return
 			}
 
+			// srcContent tar stream, as served by TarWithOptions(), is
+			// definitely in PAX format, but tar.Next() mistakenly guesses it
+			// as USTAR, which creates a problem: if the newBase is >100
+			// characters long, WriteHeader() returns an error like
+			// "archive/tar: cannot encode header: Format specifies USTAR; and USTAR cannot encode Name=...".
+			//
+			// To fix, set the format to PAX here. See docker/for-linux issue #484.
+			hdr.Format = tar.FormatPAX
 			hdr.Name = strings.Replace(hdr.Name, oldBase, newBase, 1)
 			if hdr.Typeflag == tar.TypeLink {
 				hdr.Linkname = strings.Replace(hdr.Linkname, oldBase, newBase, 1)

+ 24 - 0
pkg/archive/copy_unix_test.go

@@ -257,6 +257,30 @@ func TestCopyErrDstNotDir(t *testing.T) {
 	}
 }
 
+// Test to check if CopyTo works with a long (>100 characters) destination file name.
+// This is a regression (see https://github.com/docker/for-linux/issues/484).
+func TestCopyLongDstFilename(t *testing.T) {
+	const longName = "a_very_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_long_filename_that_is_101_characters"
+	tmpDirA, tmpDirB := getTestTempDirs(t)
+	defer removeAllPaths(tmpDirA, tmpDirB)
+
+	// Load A with some sample files and directories.
+	createSampleDir(t, tmpDirA)
+
+	srcInfo := CopyInfo{Path: filepath.Join(tmpDirA, "file1"), Exists: true, IsDir: false}
+
+	content, err := TarResource(srcInfo)
+	if err != nil {
+		t.Fatalf("unexpected error %T: %s", err, err)
+	}
+	defer content.Close()
+
+	err = CopyTo(content, srcInfo, filepath.Join(tmpDirB, longName))
+	if err != nil {
+		t.Fatalf("unexpected error %T: %s", err, err)
+	}
+}
+
 // Possibilities are reduced to the remaining 10 cases:
 //
 //  case | srcIsDir | onlyDirContents | dstExists | dstIsDir | dstTrSep | action