From 9cfaf8e32ec5419afd94a696a217c8728d586e87 Mon Sep 17 00:00:00 2001 From: Steve Beattie Date: Wed, 4 Feb 2026 18:46:57 -0800 Subject: [PATCH] fix: abstract out cpio operations to helper function This lets us defer the close operation to the end of the helper function and not try to do the closes in all the early exit operations of the loop. v2: drop cyclometric complexity lint silencing comment Signed-off-by: Steve Beattie --- pkg/archive/rpm.go | 82 ++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/pkg/archive/rpm.go b/pkg/archive/rpm.go index 9e64897d5..b9aeadcc5 100644 --- a/pkg/archive/rpm.go +++ b/pkg/archive/rpm.go @@ -21,9 +21,48 @@ import ( "github.com/ulikunitz/xz" ) +// extractFileFromCPIO extracts a single file from a CPIO archive. +func extractFileFromCPIO(ctx context.Context, cr *cpio.Reader, target string, buf []byte) error { + if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil { + return fmt.Errorf("failed to create parent directory: %w", err) + } + + out, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) + if err != nil { + return fmt.Errorf("failed to create file: %w", err) + } + defer out.Close() + + var written int64 + for { + if written > 0 && written%file.ExtractBuffer == 0 && ctx.Err() != nil { + return ctx.Err() + } + + n, err := cr.Read(buf) + if n > 0 { + written += int64(n) + if written > file.MaxBytes { + return fmt.Errorf("file exceeds maximum allowed size (%d bytes): %s", file.MaxBytes, target) + } + if _, writeErr := out.Write(buf[:n]); writeErr != nil { + return fmt.Errorf("failed to write file contents: %w", writeErr) + } + } + + if errors.Is(err, io.EOF) { + break + } + + if err != nil { + return fmt.Errorf("failed to read file contents: %w", err) + } + } + + return nil +} + // extractRPM extracts .rpm packages. -// -//nolint:cyclop // ignore complexity of 40 func ExtractRPM(ctx context.Context, d, f string) error { if ctx.Err() != nil { return ctx.Err() @@ -142,43 +181,8 @@ func ExtractRPM(ctx context.Context, d, f string) error { continue } - if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil { - return fmt.Errorf("failed to create parent directory: %w", err) - } - - out, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) - if err != nil { - return fmt.Errorf("failed to create file: %w", err) - } - - var written int64 - for { - if written > 0 && written%file.ExtractBuffer == 0 && ctx.Err() != nil { - return ctx.Err() - } - - n, err := cr.Read(buf) - if n > 0 { - written += int64(n) - if written > file.MaxBytes { - return fmt.Errorf("file exceeds maximum allowed size (%d bytes): %s", file.MaxBytes, target) - } - if _, writeErr := out.Write(buf[:n]); writeErr != nil { - return fmt.Errorf("failed to write file contents: %w", writeErr) - } - } - - if errors.Is(err, io.EOF) { - break - } - - if err != nil { - return fmt.Errorf("failed to read file contents: %w", err) - } - } - - if err := out.Close(); err != nil { - return fmt.Errorf("failed to close file: %w", err) + if err := extractFileFromCPIO(ctx, cr, target, buf); err != nil { + return err } }