mirror of
https://github.com/restic/restic.git
synced 2024-12-23 00:07:25 +00:00
Better temp file cleanup on Windows.
This commit is contained in:
parent
7d55b4f95e
commit
9e34c791c9
1 changed files with 51 additions and 2 deletions
|
@ -1,10 +1,41 @@
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Random number state.
|
||||||
|
// We generate random temporary file names so that there's a good
|
||||||
|
// chance the file doesn't exist yet - keeps the number of tries in
|
||||||
|
// TempFile to a minimum.
|
||||||
|
var rand uint32
|
||||||
|
var randmu sync.Mutex
|
||||||
|
|
||||||
|
func reseed() uint32 {
|
||||||
|
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextRandom() string {
|
||||||
|
randmu.Lock()
|
||||||
|
r := rand
|
||||||
|
if r == 0 {
|
||||||
|
r = reseed()
|
||||||
|
}
|
||||||
|
r = r*1664525 + 1013904223 // constants from Numerical Recipes
|
||||||
|
rand = r
|
||||||
|
randmu.Unlock()
|
||||||
|
return strconv.Itoa(int(1e9 + r%1e9))[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
|
||||||
|
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
|
||||||
)
|
)
|
||||||
|
|
||||||
// fixpath returns an absolute path on windows, so restic can open long file
|
// fixpath returns an absolute path on windows, so restic can open long file
|
||||||
|
@ -32,7 +63,25 @@ func fixpath(name string) string {
|
||||||
|
|
||||||
// TempFile creates a temporary file.
|
// TempFile creates a temporary file.
|
||||||
func TempFile(dir, prefix string) (f *os.File, err error) {
|
func TempFile(dir, prefix string) (f *os.File, err error) {
|
||||||
return ioutil.TempFile(dir, prefix)
|
if dir == "" {
|
||||||
|
dir = os.TempDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE)
|
||||||
|
creation := uint32(syscall.CREATE_NEW)
|
||||||
|
flags := uint32(FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE)
|
||||||
|
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
path := filepath.Join(dir, prefix+nextRandom())
|
||||||
|
|
||||||
|
h, err := syscall.CreateFile(syscall.StringToUTF16Ptr(path), access, 0, nil, creation, flags, 0)
|
||||||
|
if err == nil {
|
||||||
|
return os.NewFile(uintptr(h), path), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proper error handling is still to do
|
||||||
|
return nil, os.ErrExist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chmod changes the mode of the named file to mode.
|
// Chmod changes the mode of the named file to mode.
|
||||||
|
|
Loading…
Reference in a new issue