github.com/atlassian/git-lob@v0.0.0-20150806085256-2386a5ed291a/core/links_windows.go (about)

     1  // +build windows
     2  
     3  package core
     4  
     5  // Windows-specific dll functions
     6  
     7  import (
     8  	"os"
     9  	"syscall"
    10  	"unsafe"
    11  )
    12  
    13  // Create a hard link to a file
    14  // This link can be deleted like any other file afterwards
    15  func CreateHardLink(target, link string) error {
    16  	kern32 := syscall.NewLazyDLL("kernel32.dll")
    17  	proc := kern32.NewProc("CreateHardLinkW")
    18  	link16, err := syscall.UTF16PtrFromString(link)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	target16, err := syscall.UTF16PtrFromString(target)
    23  	if err != nil {
    24  		return err
    25  	}
    26  	ret, _, err := proc.Call(
    27  		uintptr(unsafe.Pointer(link16)),
    28  		uintptr(unsafe.Pointer(target16)),
    29  		0)
    30  
    31  	if ret == 0 {
    32  		// zero return means failure in Win API
    33  		// err already contains result of GetLastError
    34  		return err
    35  	}
    36  	return nil
    37  }
    38  
    39  // Get the number of hard links to a given file (min 1)
    40  func GetHardLinkCount(target string) (linkCount int, err error) {
    41  	// syscall already has a number of windows calls already, including
    42  	// GetFileInformationByHandle, it just doesn't expose the number of links right
    43  	// now, since they don't support hard links on Windows
    44  	// For this reason we can use Go's file open commands & pass the fd to the Win API
    45  	file, err := os.OpenFile(target, os.O_RDONLY, 0644)
    46  	if err != nil {
    47  		return 0, err
    48  	}
    49  	defer file.Close()
    50  
    51  	var d syscall.ByHandleFileInformation
    52  	err = syscall.GetFileInformationByHandle(syscall.Handle(file.Fd()), &d)
    53  	if err != nil {
    54  		return 0, err
    55  	}
    56  
    57  	return int(d.NumberOfLinks), nil
    58  }