fix: clean up temp files after atomic write failures

Signed-off-by: Bojun Chai <bojunchai@microsoft.com>
pull/32058/head
Bojun Chai 6 months ago
parent 29d309e56b
commit d607e742a4

@ -26,12 +26,17 @@ import (
// AtomicWriteFile atomically (as atomic as os.Rename allows) writes a file to a
// disk.
func AtomicWriteFile(filename string, reader io.Reader, mode os.FileMode) error {
func AtomicWriteFile(filename string, reader io.Reader, mode os.FileMode) (err error) {
tempFile, err := os.CreateTemp(filepath.Split(filename))
if err != nil {
return err
}
tempName := tempFile.Name()
defer func() {
if err != nil {
_ = os.Remove(tempName)
}
}()
if _, err := io.Copy(tempFile, reader); err != nil {
tempFile.Close() // return value is ignored as we are already on error path

@ -120,6 +120,30 @@ func TestAtomicWriteFile_LargeContent(t *testing.T) {
}
}
// TestAtomicWriteFile_CleansUpTempFileOnRenameError verifies that temporary
// files are removed when the final rename step fails.
func TestAtomicWriteFile_CleansUpTempFileOnRenameError(t *testing.T) {
dir := t.TempDir()
target := filepath.Join(dir, "existing-dir")
if err := os.Mkdir(target, 0755); err != nil {
t.Fatal(err)
}
err := AtomicWriteFile(target, bytes.NewReader([]byte("content")), 0644)
if err == nil {
t.Fatal("expected rename error, got nil")
}
entries, err := os.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
if len(entries) != 1 || entries[0].Name() != "existing-dir" {
t.Fatalf("expected only existing-dir to remain, found %v entries", len(entries))
}
}
// TestPlatformAtomicWriteFile_OverwritesExisting verifies that the platform
// helper replaces existing files instead of silently skipping them.
func TestPlatformAtomicWriteFile_OverwritesExisting(t *testing.T) {

Loading…
Cancel
Save