72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
// +build windows
|
|
|
|
package cliconfig
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
var (
|
|
shell = syscall.MustLoadDLL("Shell32.dll")
|
|
getFolderPath = shell.MustFindProc("SHGetFolderPathW")
|
|
)
|
|
|
|
const CSIDL_APPDATA = 26
|
|
|
|
func configFile() (string, error) {
|
|
dir, err := homeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return filepath.Join(dir, "terraform.rc"), nil
|
|
}
|
|
|
|
func configDir() (string, error) {
|
|
dir, err := homeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return filepath.Join(dir, "terraform.d"), nil
|
|
}
|
|
|
|
func homeDir() (string, error) {
|
|
b := make([]uint16, syscall.MAX_PATH)
|
|
|
|
// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx
|
|
r, _, err := getFolderPath.Call(0, CSIDL_APPDATA, 0, 0, uintptr(unsafe.Pointer(&b[0])))
|
|
if uint32(r) != 0 {
|
|
return "", err
|
|
}
|
|
|
|
return syscall.UTF16ToString(b), nil
|
|
}
|
|
|
|
func replaceFileAtomic(source, destination string) error {
|
|
// On Windows, renaming one file over another is not atomic and certain
|
|
// error conditions can result in having only the source file and nothing
|
|
// at the destination file. Instead, we need to call into the MoveFileEx
|
|
// Windows API function.
|
|
srcPtr, err := syscall.UTF16PtrFromString(source)
|
|
if err != nil {
|
|
return &os.LinkError{"replace", source, destination, err}
|
|
}
|
|
destPtr, err := syscall.UTF16PtrFromString(destination)
|
|
if err != nil {
|
|
return &os.LinkError{"replace", source, destination, err}
|
|
}
|
|
|
|
flags := uint32(windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH)
|
|
err = windows.MoveFileEx(srcPtr, destPtr, flags)
|
|
if err != nil {
|
|
return &os.LinkError{"replace", source, destination, err}
|
|
}
|
|
return nil
|
|
}
|