From 084400464d5765e90e79f804f6b4c0f66c1c9f27 Mon Sep 17 00:00:00 2001 From: Xiaoxuan Wang <103478229+wangxiaoxuan273@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:13:39 +0800 Subject: [PATCH] fix: handle errors returned by `Close()` in write paths (#1581) Signed-off-by: Xiaoxuan Wang --- cmd/oras/internal/display/content/manifest_fetch.go | 8 ++++++-- cmd/oras/internal/display/content/manifest_index.go | 8 ++++++-- cmd/oras/root/pull.go | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/cmd/oras/internal/display/content/manifest_fetch.go b/cmd/oras/internal/display/content/manifest_fetch.go index 9dcf7347b..de8f06772 100644 --- a/cmd/oras/internal/display/content/manifest_fetch.go +++ b/cmd/oras/internal/display/content/manifest_fetch.go @@ -31,14 +31,18 @@ type manifestFetch struct { outputPath string } -func (h *manifestFetch) OnContentFetched(desc ocispec.Descriptor, manifest []byte) error { +func (h *manifestFetch) OnContentFetched(desc ocispec.Descriptor, manifest []byte) (eventErr error) { out := h.stdout if h.outputPath != "-" && h.outputPath != "" { f, err := os.Create(h.outputPath) if err != nil { return fmt.Errorf("failed to open %q: %w", h.outputPath, err) } - defer f.Close() + defer func() { + if err := f.Close(); eventErr == nil { + eventErr = err + } + }() out = f } return output.PrintJSON(out, manifest, h.pretty) diff --git a/cmd/oras/internal/display/content/manifest_index.go b/cmd/oras/internal/display/content/manifest_index.go index b040aa998..6c07506fe 100644 --- a/cmd/oras/internal/display/content/manifest_index.go +++ b/cmd/oras/internal/display/content/manifest_index.go @@ -44,14 +44,18 @@ func NewManifestIndexCreateHandler(out io.Writer, pretty bool, outputPath string } // OnContentCreated is called after index content is created. -func (h *manifestIndexCreate) OnContentCreated(manifest []byte) error { +func (h *manifestIndexCreate) OnContentCreated(manifest []byte) (eventErr error) { out := h.stdout if h.outputPath != "" && h.outputPath != "-" { f, err := os.Create(h.outputPath) if err != nil { return fmt.Errorf("failed to open %q: %w", h.outputPath, err) } - defer f.Close() + defer func() { + if err := f.Close(); eventErr == nil { + eventErr = err + } + }() out = f } return output.PrintJSON(out, manifest, h.pretty) diff --git a/cmd/oras/root/pull.go b/cmd/oras/root/pull.go index e7b558fc3..60bd60a32 100644 --- a/cmd/oras/root/pull.go +++ b/cmd/oras/root/pull.go @@ -121,7 +121,7 @@ Example - Pull artifact files from an OCI layout archive 'layout.tar': return oerrors.Command(cmd, &opts.Target) } -func runPull(cmd *cobra.Command, opts *pullOptions) error { +func runPull(cmd *cobra.Command, opts *pullOptions) (pullError error) { ctx, logger := command.GetLogger(cmd, &opts.Common) statusHandler, metadataHandler, err := display.NewPullHandler(opts.Printer, opts.Format, opts.Path, opts.TTY) if err != nil { @@ -148,7 +148,11 @@ func runPull(cmd *cobra.Command, opts *pullOptions) error { if err != nil { return err } - defer dst.Close() + defer func() { + if err := dst.Close(); pullError == nil { + pullError = err + } + }() dst.AllowPathTraversalOnWrite = opts.PathTraversal dst.DisableOverwrite = opts.KeepOldFiles