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 }