ajhahn.de
← eeco
Go 38 lines
//go:build !windows

package selfupdate

import (
	"os"
	"path/filepath"
)

// swap atomically replaces target with newPath. The temp file is written
// in the same directory as target so the rename is a same-filesystem
// move (POSIX guarantees atomicity for those).
func swap(newPath, target string) error {
	info, err := os.Stat(target)
	if err != nil {
		return err
	}
	dir := filepath.Dir(target)
	tmp, err := os.CreateTemp(dir, ".eeco-new-*")
	if err != nil {
		return err
	}
	tmpName := tmp.Name()
	if err := tmp.Close(); err != nil {
		os.Remove(tmpName)
		return err
	}
	if err := copyFile(newPath, tmpName); err != nil {
		os.Remove(tmpName)
		return err
	}
	if err := os.Chmod(tmpName, info.Mode()); err != nil {
		os.Remove(tmpName)
		return err
	}
	return os.Rename(tmpName, target)
}