diff --git a/pkg/fileutil/fileutil.go b/pkg/fileutil/fileutil.go index a2e5aa95cf6..47d917734f6 100644 --- a/pkg/fileutil/fileutil.go +++ b/pkg/fileutil/fileutil.go @@ -84,7 +84,7 @@ func ValidatePathWithinBase(base, candidate string) error { return fmt.Errorf("failed to resolve base path %q: %w", base, err) } } - absCand, err := resolveWithAncestorSymlinks(candidate) + absCand, err := resolvePathWithExistingAncestorSymlinks(candidate) if err != nil { return fmt.Errorf("failed to resolve candidate path %q: %w", candidate, err) } @@ -97,13 +97,13 @@ func ValidatePathWithinBase(base, candidate string) error { return nil } -// resolveWithAncestorSymlinks resolves a path to its absolute real form, following +// resolvePathWithExistingAncestorSymlinks resolves a path to its absolute real form, following // symlinks for every existing component. For paths whose final component does not // yet exist on disk, it walks up to the longest existing ancestor, resolves that // through filepath.EvalSymlinks (catching any symlinked directories along the way), // and then re-appends the non-existing suffix. This prevents a symlinked directory // inside base from being used to escape the boundary when the target file is new. -func resolveWithAncestorSymlinks(p string) (string, error) { +func resolvePathWithExistingAncestorSymlinks(p string) (string, error) { // Fast path: path exists — EvalSymlinks fully resolves it. if resolved, err := filepath.EvalSymlinks(p); err == nil { return resolved, nil @@ -188,7 +188,7 @@ type syncWriteCloser interface { Close() error } -func copyFileContents(in io.Reader, out syncWriteCloser, dst string) (err error) { +func copyToFileAndSync(in io.Reader, out syncWriteCloser, dst string) (err error) { removePartial := false defer func() { @@ -225,7 +225,7 @@ func CopyFile(src, dst string) error { fileutilLog.Printf("Failed to create destination file: %s", err) return err } - err = copyFileContents(in, out, dst) + err = copyToFileAndSync(in, out, dst) if err != nil { return err } diff --git a/pkg/fileutil/fileutil_test.go b/pkg/fileutil/fileutil_test.go index f8e56aaaf17..51a8299695b 100644 --- a/pkg/fileutil/fileutil_test.go +++ b/pkg/fileutil/fileutil_test.go @@ -438,14 +438,14 @@ func TestCopyFile(t *testing.T) { }) } -func TestCopyFileContents(t *testing.T) { +func TestCopyToFileAndSync(t *testing.T) { t.Parallel() t.Run("returns close error after successful sync", func(t *testing.T) { t.Parallel() closeErr := errors.New("close failed") out := &stubSyncWriteCloser{closeErr: closeErr} - err := copyFileContents(strings.NewReader("hello"), out, filepath.Join(t.TempDir(), "dst.txt")) + err := copyToFileAndSync(strings.NewReader("hello"), out, filepath.Join(t.TempDir(), "dst.txt")) require.ErrorIs(t, err, closeErr) assert.Equal(t, 1, out.closeCalls, "destination should be closed once") @@ -464,7 +464,7 @@ func TestCopyFileContents(t *testing.T) { dst := filepath.Join(t.TempDir(), "dst.txt") require.NoError(t, os.WriteFile(dst, []byte("partial"), 0600), "Should create destination placeholder") - err := copyFileContents(strings.NewReader("hello"), out, dst) + err := copyToFileAndSync(strings.NewReader("hello"), out, dst) require.ErrorIs(t, err, writeErr) assert.Equal(t, 1, out.closeCalls, "destination should be closed once during cleanup")