Skip to content

Commit

Permalink
podman save use named pipe
Browse files Browse the repository at this point in the history
podman save uses named pipe as output path, not directly using /dev/stdout.
fix containers#7017

Signed-off-by: Qi Wang <qiwan@redhat.com>
  • Loading branch information
QiWang19 committed Aug 10, 2020
1 parent 162625f commit 17c383f
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 3 deletions.
20 changes: 17 additions & 3 deletions cmd/podman/images/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"strings"

"github.com/containers/podman/v2/libpod/define"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal"

"github.com/containers/podman/v2/cmd/podman/parse"
"github.com/containers/podman/v2/cmd/podman/registry"
Expand All @@ -14,7 +16,6 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/crypto/ssh/terminal"
)

var validFormats = []string{define.OCIManifestDir, define.OCIArchive, define.V2s2ManifestDir, define.V2s2Archive}
Expand Down Expand Up @@ -85,7 +86,10 @@ func saveFlags(flags *pflag.FlagSet) {

func save(cmd *cobra.Command, args []string) error {
var (
tags []string
tags []string
pipePath string
cleanup func() <-chan error
err error
)
if cmd.Flag("compress").Changed && (saveOpts.Format != define.OCIManifestDir && saveOpts.Format != define.V2s2ManifestDir && saveOpts.Format == "") {
return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'")
Expand All @@ -95,7 +99,17 @@ func save(cmd *cobra.Command, args []string) error {
if terminal.IsTerminal(int(fi.Fd())) {
return errors.Errorf("refusing to save to terminal. Use -o flag or redirect")
}
saveOpts.Output = "/dev/stdout"
pipePath, cleanup, err = setupPipe()
if err != nil {
return err
}
defer func() {
errc := cleanup()
if err := <-errc; err != nil && err.Error() != "wait canceled" {
logrus.Errorf("error cleaning up named pipe: %q", err)
}
}()
saveOpts.Output = pipePath
}
if err := parse.ValidateFileName(saveOpts.Output); err != nil {
return err
Expand Down
49 changes: 49 additions & 0 deletions cmd/podman/images/utils_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package images

import (
"io"
"io/ioutil"
"os"
"path/filepath"
"syscall"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)

// setupPipe() for fixing https://github.com/containers/podman/issues/7017
// uses named pipe since containers/image EvalSymlinks fails with /dev/stdout
func setupPipe() (string, func() <-chan error, error) {
errc := make(chan error)
pipeDir, err := ioutil.TempDir(os.TempDir(), "pipeDir")
if err != nil {
return "", nil, err
}
pipePath := filepath.Join(pipeDir, "saveio")
err = syscall.Mkfifo(pipePath, 0600)
if err != nil {
if e := os.RemoveAll(pipeDir); e != nil {
logrus.Errorf("error removing named pipe: %q", e)
}
return "", nil, errors.Wrapf(err, "error creating named pipe")
}
go func() {
fpipe, err := os.Open(pipePath)
if err != nil {
errc <- err
return
}
if _, err = io.Copy(os.Stdout, fpipe); err != nil {
errc <- err
return
}
fpipe.Close()
errc <- errors.New("wait canceled")
}()
return pipePath, func() <-chan error {
if e := os.RemoveAll(pipeDir); e != nil {
logrus.Errorf("error removing named pipe: %q", e)
}
return errc
}, nil
}
7 changes: 7 additions & 0 deletions cmd/podman/images/utils_unsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// +build !linux

package images

func setupPipe() (string, func() <-chan error, error) {
return "/dev/stdout", nil, nil
}

0 comments on commit 17c383f

Please sign in to comment.