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