github.com/cycloidio/terraform@v1.1.10-0.20220513142504-76d5c768dc63/replacefile/replacefile_windows.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package replacefile
     5  
     6  import (
     7  	"os"
     8  	"syscall"
     9  
    10  	"golang.org/x/sys/windows"
    11  )
    12  
    13  // AtomicRename renames from the source path to the destination path,
    14  // atomically replacing any file that might already exist at the destination.
    15  //
    16  // Typically this operation can succeed only if the source and destination
    17  // are within the same physical filesystem, so this function is best reserved
    18  // for cases where the source and destination exist in the same directory and
    19  // only the local filename differs between them.
    20  func AtomicRename(source, destination string) error {
    21  	// On Windows, renaming one file over another is not atomic and certain
    22  	// error conditions can result in having only the source file and nothing
    23  	// at the destination file. Instead, we need to call into the MoveFileEx
    24  	// Windows API function, setting two flags to opt in to replacing an
    25  	// existing file.
    26  	srcPtr, err := syscall.UTF16PtrFromString(source)
    27  	if err != nil {
    28  		return &os.LinkError{"replace", source, destination, err}
    29  	}
    30  	destPtr, err := syscall.UTF16PtrFromString(destination)
    31  	if err != nil {
    32  		return &os.LinkError{"replace", source, destination, err}
    33  	}
    34  
    35  	flags := uint32(windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH)
    36  	err = windows.MoveFileEx(srcPtr, destPtr, flags)
    37  	if err != nil {
    38  		return &os.LinkError{"replace", source, destination, err}
    39  	}
    40  	return nil
    41  }