Browse Source

Merge pull request #10439 from estesp/10426-fix-arg-list-too-long

Pass excludes/options to tar unarchiver via environment versus cmd line
Alexander Morozov 10 years ago
parent
commit
f207dd5e7c
1 changed files with 20 additions and 14 deletions
  1. 20 14
      pkg/chrootarchive/archive.go

+ 20 - 14
pkg/chrootarchive/archive.go

@@ -1,7 +1,6 @@
 package chrootarchive
 package chrootarchive
 
 
 import (
 import (
-	"bytes"
 	"encoding/json"
 	"encoding/json"
 	"flag"
 	"flag"
 	"fmt"
 	"fmt"
@@ -9,7 +8,6 @@ import (
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"runtime"
 	"runtime"
-	"strings"
 	"syscall"
 	"syscall"
 
 
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/archive"
@@ -28,11 +26,14 @@ func chroot(path string) error {
 func untar() {
 func untar() {
 	runtime.LockOSThread()
 	runtime.LockOSThread()
 	flag.Parse()
 	flag.Parse()
-	if err := chroot(flag.Arg(0)); err != nil {
+
+	var options *archive.TarOptions
+
+	if err := json.Unmarshal([]byte(os.Getenv("OPT")), &options); err != nil {
 		fatal(err)
 		fatal(err)
 	}
 	}
-	var options *archive.TarOptions
-	if err := json.NewDecoder(strings.NewReader(flag.Arg(1))).Decode(&options); err != nil {
+
+	if err := chroot(flag.Arg(0)); err != nil {
 		fatal(err)
 		fatal(err)
 	}
 	}
 	if err := archive.Unpack(os.Stdin, "/", options); err != nil {
 	if err := archive.Unpack(os.Stdin, "/", options); err != nil {
@@ -54,27 +55,32 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error
 		options.ExcludePatterns = []string{}
 		options.ExcludePatterns = []string{}
 	}
 	}
 
 
-	var (
-		buf bytes.Buffer
-		enc = json.NewEncoder(&buf)
-	)
-	if err := enc.Encode(options); err != nil {
-		return fmt.Errorf("Untar json encode: %v", err)
-	}
+	dest = filepath.Clean(dest)
 	if _, err := os.Stat(dest); os.IsNotExist(err) {
 	if _, err := os.Stat(dest); os.IsNotExist(err) {
 		if err := os.MkdirAll(dest, 0777); err != nil {
 		if err := os.MkdirAll(dest, 0777); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
-	dest = filepath.Clean(dest)
+
+	// We can't pass the exclude list directly via cmd line
+	// because we easily overrun the shell max argument list length
+	// when the full image list is passed (e.g. when this is used
+	// by `docker load`). Instead we will add the JSON marshalled
+	// and placed in the env, which has significantly larger
+	// max size
+	data, err := json.Marshal(options)
+	if err != nil {
+		return fmt.Errorf("Untar json encode: %v", err)
+	}
 	decompressedArchive, err := archive.DecompressStream(tarArchive)
 	decompressedArchive, err := archive.DecompressStream(tarArchive)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 	defer decompressedArchive.Close()
 	defer decompressedArchive.Close()
 
 
-	cmd := reexec.Command("docker-untar", dest, buf.String())
+	cmd := reexec.Command("docker-untar", dest)
 	cmd.Stdin = decompressedArchive
 	cmd.Stdin = decompressedArchive
+	cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))
 	out, err := cmd.CombinedOutput()
 	out, err := cmd.CombinedOutput()
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Untar %s %s", err, out)
 		return fmt.Errorf("Untar %s %s", err, out)