summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go')
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go55
1 files changed, 55 insertions, 0 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go
new file mode 100644
index 000000000..5e8102239
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/internal/sysfs/rename_windows.go
@@ -0,0 +1,55 @@
+package sysfs
+
+import (
+ "os"
+ "syscall"
+
+ "github.com/tetratelabs/wazero/experimental/sys"
+)
+
+func rename(from, to string) sys.Errno {
+ if from == to {
+ return 0
+ }
+
+ var fromIsDir, toIsDir bool
+ if fromStat, errno := stat(from); errno != 0 {
+ return errno // failed to stat from
+ } else {
+ fromIsDir = fromStat.Mode.IsDir()
+ }
+ if toStat, errno := stat(to); errno == sys.ENOENT {
+ return syscallRename(from, to) // file or dir to not-exist is ok
+ } else if errno != 0 {
+ return errno // failed to stat to
+ } else {
+ toIsDir = toStat.Mode.IsDir()
+ }
+
+ // Now, handle known cases
+ switch {
+ case !fromIsDir && toIsDir: // file to dir
+ return sys.EISDIR
+ case !fromIsDir && !toIsDir: // file to file
+ // Use os.Rename instead of syscall.Rename to overwrite a file.
+ // This uses MoveFileEx instead of MoveFile (used by syscall.Rename).
+ return sys.UnwrapOSError(os.Rename(from, to))
+ case fromIsDir && !toIsDir: // dir to file
+ return sys.ENOTDIR
+ default: // dir to dir
+
+ // We can't tell if a directory is empty or not, via stat information.
+ // Reading the directory is expensive, as it can buffer large amounts
+ // of data on fail. Instead, speculatively try to remove the directory.
+ // This is only one syscall and won't buffer anything.
+ if errno := rmdir(to); errno == 0 || errno == sys.ENOENT {
+ return syscallRename(from, to)
+ } else {
+ return errno
+ }
+ }
+}
+
+func syscallRename(from string, to string) sys.Errno {
+ return sys.UnwrapOSError(syscall.Rename(from, to))
+}