rename_windows.go raw

   1  package rename
   2  
   3  // The following is adapted from goleveldb
   4  // (https://github.com/syndtr/goleveldb) under the following license:
   5  //
   6  // Copyright 2012 Suryandaru Triandana <syndtr@gmail.com> All rights reserved.
   7  //
   8  // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
   9  // following conditions are met:
  10  //
  11  //     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
  12  //     disclaimer.
  13  //
  14  //     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
  15  //     disclaimer in the documentation and/or other materials provided with the distribution.
  16  //
  17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  18  // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22  // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.import (
  24  import (
  25  	"syscall"
  26  	"unsafe"
  27  )
  28  
  29  var (
  30  	modkernel32     = syscall.NewLazyDLL("kernel32.dll")
  31  	procMoveFileExW = modkernel32.NewProc("MoveFileExW")
  32  )
  33  
  34  const (
  35  	_MOVEFILE_REPLACE_EXISTING = 1
  36  )
  37  
  38  func moveFileEx(from *uint16, to *uint16, flags uint32) (e error) {
  39  	r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3,
  40  		uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)),
  41  		uintptr(flags),
  42  	)
  43  	if r1 == 0 {
  44  		if e1 != 0 {
  45  			return error(e1)
  46  		} else {
  47  			return syscall.EINVAL
  48  		}
  49  	}
  50  	return nil
  51  }
  52  
  53  // Atomic provides an atomic file rename. newpath is replaced if it already exists.
  54  func Atomic(oldpath, newpath string) (e error) {
  55  	from, e := syscall.UTF16PtrFromString(oldpath)
  56  	if e != nil {
  57  		E.Ln(e)
  58  		return e
  59  	}
  60  	to, e := syscall.UTF16PtrFromString(newpath)
  61  	if e != nil {
  62  		E.Ln(e)
  63  		return e
  64  	}
  65  	return moveFileEx(from, to, _MOVEFILE_REPLACE_EXISTING)
  66  }
  67