From b78c736356cb2142e66bd8c8020f6f355c565917 Mon Sep 17 00:00:00 2001 From: Daehyeok Mun Date: Sun, 13 Dec 2015 18:25:28 -0700 Subject: [PATCH] Remove output file when save/export fail Signed-off-by: Daehyeok Mun --- api/client/export.go | 21 ++++++++------------- api/client/save.go | 20 +++++++------------- api/client/utils.go | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/api/client/export.go b/api/client/export.go index ec94f6728e..45ddc2052f 100644 --- a/api/client/export.go +++ b/api/client/export.go @@ -3,7 +3,6 @@ package client import ( "errors" "io" - "os" Cli "github.com/docker/docker/cli" flag "github.com/docker/docker/pkg/mflag" @@ -21,16 +20,7 @@ func (cli *DockerCli) CmdExport(args ...string) error { cmd.ParseFlags(args, true) - var ( - output = cli.out - err error - ) - if *outfile != "" { - output, err = os.Create(*outfile) - if err != nil { - return err - } - } else if cli.isTerminalOut { + if *outfile == "" && cli.isTerminalOut { return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.") } @@ -40,6 +30,11 @@ func (cli *DockerCli) CmdExport(args ...string) error { } defer responseBody.Close() - _, err = io.Copy(output, responseBody) - return err + if *outfile == "" { + _, err := io.Copy(cli.out, responseBody) + return err + } + + return copyToFile(*outfile, responseBody) + } diff --git a/api/client/save.go b/api/client/save.go index e7e0166d6f..5c16180e3d 100644 --- a/api/client/save.go +++ b/api/client/save.go @@ -3,7 +3,6 @@ package client import ( "errors" "io" - "os" Cli "github.com/docker/docker/cli" flag "github.com/docker/docker/pkg/mflag" @@ -21,19 +20,9 @@ func (cli *DockerCli) CmdSave(args ...string) error { cmd.ParseFlags(args, true) - var ( - output = cli.out - err error - ) - if *outfile == "" && cli.isTerminalOut { return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.") } - if *outfile != "" { - if output, err = os.Create(*outfile); err != nil { - return err - } - } responseBody, err := cli.client.ImageSave(cmd.Args()) if err != nil { @@ -41,6 +30,11 @@ func (cli *DockerCli) CmdSave(args ...string) error { } defer responseBody.Close() - _, err = io.Copy(output, responseBody) - return err + if *outfile == "" { + _, err := io.Copy(cli.out, responseBody) + return err + } + + return copyToFile(*outfile, responseBody) + } diff --git a/api/client/utils.go b/api/client/utils.go index 687add5bc2..f22c38e9fc 100644 --- a/api/client/utils.go +++ b/api/client/utils.go @@ -4,8 +4,11 @@ import ( "encoding/base64" "encoding/json" "fmt" + "io" + "io/ioutil" "os" gosignal "os/signal" + "path/filepath" "runtime" "time" @@ -138,3 +141,27 @@ func (cli *DockerCli) getTtySize() (int, int) { } return int(ws.Height), int(ws.Width) } + +func copyToFile(outfile string, r io.Reader) error { + tmpFile, err := ioutil.TempFile(filepath.Dir(outfile), ".docker_temp_") + if err != nil { + return err + } + + tmpPath := tmpFile.Name() + + _, err = io.Copy(tmpFile, r) + tmpFile.Close() + + if err != nil { + os.Remove(tmpPath) + return err + } + + if err = os.Rename(tmpPath, outfile); err != nil { + os.Remove(tmpPath) + return err + } + + return nil +}