github.com/unikumab/tail@v1.0.1-0.20180514194441-a1dbeea552b7/winfile/winfile.go (about)

     1  // +build windows
     2  
     3  package winfile
     4  
     5  import (
     6  	"os"
     7  	"syscall"
     8  	"unsafe"
     9  )
    10  
    11  // issue also described here
    12  //https://codereview.appspot.com/8203043/
    13  
    14  // https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L218
    15  func Open(path string, mode int, perm uint32) (fd syscall.Handle, err error) {
    16  	if len(path) == 0 {
    17  		return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND
    18  	}
    19  	pathp, err := syscall.UTF16PtrFromString(path)
    20  	if err != nil {
    21  		return syscall.InvalidHandle, err
    22  	}
    23  	var access uint32
    24  	switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) {
    25  	case syscall.O_RDONLY:
    26  		access = syscall.GENERIC_READ
    27  	case syscall.O_WRONLY:
    28  		access = syscall.GENERIC_WRITE
    29  	case syscall.O_RDWR:
    30  		access = syscall.GENERIC_READ | syscall.GENERIC_WRITE
    31  	}
    32  	if mode&syscall.O_CREAT != 0 {
    33  		access |= syscall.GENERIC_WRITE
    34  	}
    35  	if mode&syscall.O_APPEND != 0 {
    36  		access &^= syscall.GENERIC_WRITE
    37  		access |= syscall.FILE_APPEND_DATA
    38  	}
    39  	sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE)
    40  	var sa *syscall.SecurityAttributes
    41  	if mode&syscall.O_CLOEXEC == 0 {
    42  		sa = makeInheritSa()
    43  	}
    44  	var createmode uint32
    45  	switch {
    46  	case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL):
    47  		createmode = syscall.CREATE_NEW
    48  	case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC):
    49  		createmode = syscall.CREATE_ALWAYS
    50  	case mode&syscall.O_CREAT == syscall.O_CREAT:
    51  		createmode = syscall.OPEN_ALWAYS
    52  	case mode&syscall.O_TRUNC == syscall.O_TRUNC:
    53  		createmode = syscall.TRUNCATE_EXISTING
    54  	default:
    55  		createmode = syscall.OPEN_EXISTING
    56  	}
    57  	h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0)
    58  	return h, e
    59  }
    60  
    61  // https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L211
    62  func makeInheritSa() *syscall.SecurityAttributes {
    63  	var sa syscall.SecurityAttributes
    64  	sa.Length = uint32(unsafe.Sizeof(sa))
    65  	sa.InheritHandle = 1
    66  	return &sa
    67  }
    68  
    69  // https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_windows.go#L133
    70  func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) {
    71  	r, e := Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
    72  	if e != nil {
    73  		return nil, e
    74  	}
    75  	return os.NewFile(uintptr(r), name), nil
    76  }
    77  
    78  // https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_posix.go#L61
    79  func syscallMode(i os.FileMode) (o uint32) {
    80  	o |= uint32(i.Perm())
    81  	if i&os.ModeSetuid != 0 {
    82  		o |= syscall.S_ISUID
    83  	}
    84  	if i&os.ModeSetgid != 0 {
    85  		o |= syscall.S_ISGID
    86  	}
    87  	if i&os.ModeSticky != 0 {
    88  		o |= syscall.S_ISVTX
    89  	}
    90  	// No mapping for Go's ModeTemporary (plan9 only).
    91  	return
    92  }