github.com/nxadm/tail@v1.4.12-0.20231010141446-ba755e4d73b6/winfile/winfile.go (about)

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