| // +build windows |
| |
| package winfile |
| |
| import ( |
| "os" |
| "syscall" |
| "unsafe" |
| ) |
| |
| // issue also described here |
| //https://codereview.appspot.com/8203043/ |
| |
| // https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L218 |
| func Open(path string, mode int, perm uint32) (fd syscall.Handle, err error) { |
| if len(path) == 0 { |
| return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND |
| } |
| pathp, err := syscall.UTF16PtrFromString(path) |
| if err != nil { |
| return syscall.InvalidHandle, err |
| } |
| var access uint32 |
| switch mode & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) { |
| case syscall.O_RDONLY: |
| access = syscall.GENERIC_READ |
| case syscall.O_WRONLY: |
| access = syscall.GENERIC_WRITE |
| case syscall.O_RDWR: |
| access = syscall.GENERIC_READ | syscall.GENERIC_WRITE |
| } |
| if mode&syscall.O_CREAT != 0 { |
| access |= syscall.GENERIC_WRITE |
| } |
| if mode&syscall.O_APPEND != 0 { |
| access &^= syscall.GENERIC_WRITE |
| access |= syscall.FILE_APPEND_DATA |
| } |
| sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE) |
| var sa *syscall.SecurityAttributes |
| if mode&syscall.O_CLOEXEC == 0 { |
| sa = makeInheritSa() |
| } |
| var createmode uint32 |
| switch { |
| case mode&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL): |
| createmode = syscall.CREATE_NEW |
| case mode&(syscall.O_CREAT|syscall.O_TRUNC) == (syscall.O_CREAT | syscall.O_TRUNC): |
| createmode = syscall.CREATE_ALWAYS |
| case mode&syscall.O_CREAT == syscall.O_CREAT: |
| createmode = syscall.OPEN_ALWAYS |
| case mode&syscall.O_TRUNC == syscall.O_TRUNC: |
| createmode = syscall.TRUNCATE_EXISTING |
| default: |
| createmode = syscall.OPEN_EXISTING |
| } |
| h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0) |
| return h, e |
| } |
| |
| // https://github.com/jnwhiteh/golang/blob/master/src/pkg/syscall/syscall_windows.go#L211 |
| func makeInheritSa() *syscall.SecurityAttributes { |
| var sa syscall.SecurityAttributes |
| sa.Length = uint32(unsafe.Sizeof(sa)) |
| sa.InheritHandle = 1 |
| return &sa |
| } |
| |
| // https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_windows.go#L133 |
| func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) { |
| r, e := Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) |
| if e != nil { |
| return nil, e |
| } |
| return os.NewFile(uintptr(r), name), nil |
| } |
| |
| // https://github.com/jnwhiteh/golang/blob/master/src/pkg/os/file_posix.go#L61 |
| func syscallMode(i os.FileMode) (o uint32) { |
| o |= uint32(i.Perm()) |
| if i&os.ModeSetuid != 0 { |
| o |= syscall.S_ISUID |
| } |
| if i&os.ModeSetgid != 0 { |
| o |= syscall.S_ISGID |
| } |
| if i&os.ModeSticky != 0 { |
| o |= syscall.S_ISVTX |
| } |
| // No mapping for Go's ModeTemporary (plan9 only). |
| return |
| } |