)
//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizeOfPointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
-
//sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
+//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
const (
ComputerNameNetBIOS = 0
ComputerNamePhysicalDnsDomain = 6
ComputerNamePhysicalDnsFullyQualified = 7
ComputerNameMax = 8
+
+ MOVEFILE_REPLACE_EXISTING = 0x1
+ MOVEFILE_COPY_ALLOWED = 0x2
+ MOVEFILE_DELAY_UNTIL_REBOOT = 0x4
+ MOVEFILE_WRITE_THROUGH = 0x8
+ MOVEFILE_CREATE_HARDLINK = 0x10
+ MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20
)
+
+func Rename(oldpath, newpath string) error {
+ from, err := syscall.UTF16PtrFromString(oldpath)
+ if err != nil {
+ return err
+ }
+ to, err := syscall.UTF16PtrFromString(newpath)
+ if err != nil {
+ return err
+ }
+ return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
+}
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
+ procMoveFileExW = modkernel32.NewProc("MoveFileExW")
)
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizeOfPointer *uint32) (errcode error) {
}
return
}
+
+func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+++ /dev/null
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package os_test
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
- "testing"
-)
-
-func TestErrIsExistAfterRename(t *testing.T) {
- dir, err := ioutil.TempDir("", "go-build")
- if err != nil {
- t.Fatalf("Create temp directory: %v", err)
- }
- defer os.RemoveAll(dir)
-
- src := filepath.Join(dir, "src")
- dest := filepath.Join(dir, "dest")
-
- f, err := os.Create(src)
- if err != nil {
- t.Fatalf("Create file %v: %v", src, err)
- }
- f.Close()
- err = os.Rename(src, dest)
- if err != nil {
- t.Fatalf("Rename %v to %v: %v", src, dest, err)
- }
-
- f, err = os.Create(src)
- if err != nil {
- t.Fatalf("Create file %v: %v", src, err)
- }
- f.Close()
- err = os.Rename(src, dest)
- if err == nil {
- t.Fatal("Rename should have failed")
- }
- if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" {
- t.Fatal(s)
- return
- }
-}
}
}
-func rename(oldname, newname string) error {
- e := syscall.Rename(oldname, newname)
- if e != nil {
- return &LinkError{"rename", oldname, newname, e}
- }
- return nil
-}
-
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
func syscallMode(i FileMode) (o uint32) {
o |= uint32(i.Perm())
"syscall"
)
+func rename(oldname, newname string) error {
+ e := syscall.Rename(oldname, newname)
+ if e != nil {
+ return &LinkError{"rename", oldname, newname, e}
+ }
+ return nil
+}
+
// File represents an open file descriptor.
type File struct {
*file
package os
import (
+ "internal/syscall/windows"
"io"
"runtime"
"sync"
return &PathError{"remove", name, e}
}
+func rename(oldname, newname string) error {
+ e := windows.Rename(oldname, newname)
+ if e != nil {
+ return &LinkError{"rename", oldname, newname, e}
+ }
+ return nil
+}
+
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) {
defer chtmpdir(t)()
}
from, to := "renamefrom", "renameto"
- Remove(to) // Just in case.
+ // Ensure we are not testing the overwrite case here.
+ Remove(from)
+ Remove(to)
+
file, err := Create(from)
if err != nil {
- t.Fatalf("open %q failed: %v", to, err)
+ t.Fatalf("open %q failed: %v", from, err)
}
if err = file.Close(); err != nil {
- t.Errorf("close %q failed: %v", to, err)
+ t.Errorf("close %q failed: %v", from, err)
}
err = Rename(from, to)
if err != nil {
}
}
+func TestRenameOverwriteDest(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("skipping on plan9")
+ }
+ if runtime.GOOS == "darwin" && runtime.GOARCH == "arm" {
+ defer chtmpdir(t)()
+ }
+ from, to := "renamefrom", "renameto"
+ // Just in case.
+ Remove(from)
+ Remove(to)
+
+ toData := []byte("to")
+ fromData := []byte("from")
+
+ err := ioutil.WriteFile(to, toData, 0777)
+ if err != nil {
+ t.Fatalf("write file %q failed: %v", to, err)
+ }
+
+ err = ioutil.WriteFile(from, fromData, 0777)
+ if err != nil {
+ t.Fatalf("write file %q failed: %v", from, err)
+ }
+ err = Rename(from, to)
+ if err != nil {
+ t.Fatalf("rename %q, %q failed: %v", to, from, err)
+ }
+ defer Remove(to)
+
+ _, err = Stat(from)
+ if err == nil {
+ t.Errorf("from file %q still exists", from)
+ }
+ if err != nil && !IsNotExist(err) {
+ t.Fatalf("stat from: %v", err)
+ }
+ toFi, err := Stat(to)
+ if err != nil {
+ t.Fatalf("stat %q failed: %v", to, err)
+ }
+ if toFi.Size() != int64(len(fromData)) {
+ t.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi.Size(), len(fromData))
+ }
+}
+
func exec(t *testing.T, dir, cmd string, args []string, expect string) {
r, w, err := Pipe()
if err != nil {