Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package filemdl
import (
"os"
"syscall"
"unsafe"
)
const (
moveFileReplacExisting = 0x1
moveFileWriteThrough = 0x8
)
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procMoveFileExW = modkernel32.NewProc("MoveFileExW")
)
//sys moveFileEx(lpExistingFileName *uint16, lpNewFileName *uint16, dwFlags uint32) (err error) = MoveFileExW
// AtomicReplaceFile atomically replaces the destination file or directory with the
// source. It is guaranteed to either replace the target file entirely, or not
// change either file.
func AtomicReplaceFile(source, destination string) error {
src, err := syscall.UTF16PtrFromString(source)
if err != nil {
return &os.LinkError{"replace", source, destination, err}
}
dest, err := syscall.UTF16PtrFromString(destination)
if err != nil {
return &os.LinkError{"replace", source, destination, err}
}
// see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365240(v=vs.85).aspx
if err := moveFileEx(src, dest, moveFileReplacExisting|moveFileWriteThrough); err != nil {
return &os.LinkError{"replace", source, destination, err}
}
return nil
}
func moveFileEx(lpExistingFileName *uint16, lpNewFileName *uint16, dwFlags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(lpExistingFileName)), uintptr(unsafe.Pointer(lpNewFileName)), uintptr(dwFlags))
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}