Skip to content

Commit fcb571c

Browse files
committed
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. Signed-off-by: Steve Beattie <steve.beattie@chainguard.dev>
1 parent 42306d1 commit fcb571c

1 file changed

Lines changed: 43 additions & 37 deletions

File tree

pkg/archive/rpm.go

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,47 @@ import (
2121
"github.com/ulikunitz/xz"
2222
)
2323

24+
// extractFileFromCPIO extracts a single file from a CPIO archive.
25+
func extractFileFromCPIO(ctx context.Context, cr *cpio.Reader, target string, buf []byte) error {
26+
if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil {
27+
return fmt.Errorf("failed to create parent directory: %w", err)
28+
}
29+
30+
out, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
31+
if err != nil {
32+
return fmt.Errorf("failed to create file: %w", err)
33+
}
34+
defer out.Close()
35+
36+
var written int64
37+
for {
38+
if written > 0 && written%file.ExtractBuffer == 0 && ctx.Err() != nil {
39+
return ctx.Err()
40+
}
41+
42+
n, err := cr.Read(buf)
43+
if n > 0 {
44+
written += int64(n)
45+
if written > file.MaxBytes {
46+
return fmt.Errorf("file exceeds maximum allowed size (%d bytes): %s", file.MaxBytes, target)
47+
}
48+
if _, writeErr := out.Write(buf[:n]); writeErr != nil {
49+
return fmt.Errorf("failed to write file contents: %w", writeErr)
50+
}
51+
}
52+
53+
if errors.Is(err, io.EOF) {
54+
break
55+
}
56+
57+
if err != nil {
58+
return fmt.Errorf("failed to read file contents: %w", err)
59+
}
60+
}
61+
62+
return nil
63+
}
64+
2465
// extractRPM extracts .rpm packages.
2566
//
2667
//nolint:cyclop // ignore complexity of 40
@@ -142,43 +183,8 @@ func ExtractRPM(ctx context.Context, d, f string) error {
142183
continue
143184
}
144185

145-
if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil {
146-
return fmt.Errorf("failed to create parent directory: %w", err)
147-
}
148-
149-
out, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
150-
if err != nil {
151-
return fmt.Errorf("failed to create file: %w", err)
152-
}
153-
154-
var written int64
155-
for {
156-
if written > 0 && written%file.ExtractBuffer == 0 && ctx.Err() != nil {
157-
return ctx.Err()
158-
}
159-
160-
n, err := cr.Read(buf)
161-
if n > 0 {
162-
written += int64(n)
163-
if written > file.MaxBytes {
164-
return fmt.Errorf("file exceeds maximum allowed size (%d bytes): %s", file.MaxBytes, target)
165-
}
166-
if _, writeErr := out.Write(buf[:n]); writeErr != nil {
167-
return fmt.Errorf("failed to write file contents: %w", writeErr)
168-
}
169-
}
170-
171-
if errors.Is(err, io.EOF) {
172-
break
173-
}
174-
175-
if err != nil {
176-
return fmt.Errorf("failed to read file contents: %w", err)
177-
}
178-
}
179-
180-
if err := out.Close(); err != nil {
181-
return fmt.Errorf("failed to close file: %w", err)
186+
if err := extractFileFromCPIO(ctx, cr, target, buf); err != nil {
187+
return err
182188
}
183189
}
184190

0 commit comments

Comments
 (0)