Skip to content

Commit

Permalink
Fix file moving to be safe on Windows.
Browse files Browse the repository at this point in the history
Fix file moving to be safe on Windows. A shim was added
that calls into the Win32 API / MoveFileEx that prevents an error
occurring on windows if the destination already exists. This shim might
not be needed once os.Replace lands, possibly in Go 1.5.

See: golang/go#8914

[#88907658]
  • Loading branch information
David Morhovich, David Varvel and John Shahid committed Feb 24, 2015
1 parent 1e59e50 commit 8e2f69d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 3 deletions.
4 changes: 2 additions & 2 deletions cached_downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ type CachedDownloader interface {
Fetch(urlToFetch *url.URL, cacheKey string, transformer CacheTransformer, cancelChan <-chan struct{}) (io.ReadCloser, int64, error)
}

func NoopTransform(source, destination string) (int64, error) {
err := os.Rename(source, destination)
func NoopTransform(source string, destination string) (int64, error) {
err := Replace(source, destination)
if err != nil {
return 0, err
}
Expand Down
2 changes: 1 addition & 1 deletion file_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (c *FileCache) Add(cacheKey string, sourcePath string, size int64, cachingI
uniqueName := fmt.Sprintf("%s-%d-%d", cacheKey, time.Now().UnixNano(), c.seq)
cachePath := filepath.Join(c.cachedPath, uniqueName)

err := os.Rename(sourcePath, cachePath)
err := Replace(sourcePath, cachePath)
if err != nil {
return nil, err
}
Expand Down
9 changes: 9 additions & 0 deletions replace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build !windows

package cacheddownloader

import "os"

func Replace(src, dst string) error {
return os.Rename(src, dst)
}
34 changes: 34 additions & 0 deletions replace_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cacheddownloader

import (
"syscall"
"unsafe"
)

func Replace(src, dst string) error {
kernel32, err := syscall.LoadLibrary("kernel32.dll")
if err != nil {
return err
}
defer syscall.FreeLibrary(kernel32)
moveFileExUnicode, err := syscall.GetProcAddress(kernel32, "MoveFileExW")
if err != nil {
return err
}

srcString := syscall.StringToUTF16Ptr(src)
dstString := syscall.StringToUTF16Ptr(dst)

srcPtr := uintptr(unsafe.Pointer(srcString))
dstPtr := uintptr(unsafe.Pointer(dstString))

MOVEFILE_REPLACE_EXISTING := 0x1
flag := uintptr(MOVEFILE_REPLACE_EXISTING)

_, _, callErr := syscall.Syscall(uintptr(moveFileExUnicode), 3, srcPtr, dstPtr, flag)
if callErr != 0 {
return callErr
}

return nil
}

0 comments on commit 8e2f69d

Please sign in to comment.