91 lines
1.7 KiB
Go
91 lines
1.7 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
func moveFile(src, dst string) error {
|
|
// zuerst Rename (schnell)
|
|
if err := os.Rename(src, dst); err == nil {
|
|
return nil
|
|
} else {
|
|
// Fallback: Copy+Remove (z.B. bei EXDEV)
|
|
in, err2 := os.Open(src)
|
|
if err2 != nil {
|
|
return err
|
|
}
|
|
defer in.Close()
|
|
|
|
out, err2 := os.Create(dst)
|
|
if err2 != nil {
|
|
return err
|
|
}
|
|
if _, err2 := io.Copy(out, in); err2 != nil {
|
|
out.Close()
|
|
return err2
|
|
}
|
|
if err2 := out.Close(); err2 != nil {
|
|
return err2
|
|
}
|
|
return os.Remove(src)
|
|
}
|
|
}
|
|
|
|
const windowsSharingViolation syscall.Errno = 32 // ERROR_SHARING_VIOLATION
|
|
|
|
func isSharingViolation(err error) bool {
|
|
if runtime.GOOS != "windows" {
|
|
return false
|
|
}
|
|
// Windows: ERROR_SHARING_VIOLATION = 32, ERROR_LOCK_VIOLATION = 33
|
|
var pe *os.PathError
|
|
if errors.As(err, &pe) {
|
|
if errno, ok := pe.Err.(syscall.Errno); ok {
|
|
return errno == syscall.Errno(32) || errno == syscall.Errno(33)
|
|
}
|
|
}
|
|
// Fallback über Text
|
|
s := strings.ToLower(err.Error())
|
|
return strings.Contains(s, "sharing violation") ||
|
|
strings.Contains(s, "used by another process") ||
|
|
strings.Contains(s, "wird von einem anderen prozess verwendet")
|
|
}
|
|
|
|
func removeWithRetry(path string) error {
|
|
var err error
|
|
for i := 0; i < 40; i++ { // ~4s bei 100ms
|
|
err = os.Remove(path)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if isSharingViolation(err) {
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
|
|
func renameWithRetry(oldPath, newPath string) error {
|
|
var err error
|
|
for i := 0; i < 40; i++ {
|
|
err = os.Rename(oldPath, newPath)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if isSharingViolation(err) {
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
return err
|
|
}
|
|
return err
|
|
}
|