github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/syscall/syscall_windows.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Windows system calls. 6 7 package syscall 8 9 import ( 10 errorspkg "errors" 11 "github.com/c12o16h1/go/src/internal/oserror" 12 "github.com/c12o16h1/go/src/internal/race" 13 "runtime" 14 "sync" 15 "unicode/utf16" 16 "unsafe" 17 ) 18 19 type Handle uintptr 20 21 const InvalidHandle = ^Handle(0) 22 23 // StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s, 24 // with a terminating NUL added. If s contains a NUL byte this 25 // function panics instead of returning an error. 26 // 27 // Deprecated: Use UTF16FromString instead. 28 func StringToUTF16(s string) []uint16 { 29 a, err := UTF16FromString(s) 30 if err != nil { 31 panic("syscall: string with NUL passed to StringToUTF16") 32 } 33 return a 34 } 35 36 // UTF16FromString returns the UTF-16 encoding of the UTF-8 string 37 // s, with a terminating NUL added. If s contains a NUL byte at any 38 // location, it returns (nil, EINVAL). 39 func UTF16FromString(s string) ([]uint16, error) { 40 for i := 0; i < len(s); i++ { 41 if s[i] == 0 { 42 return nil, EINVAL 43 } 44 } 45 return utf16.Encode([]rune(s + "\x00")), nil 46 } 47 48 // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, 49 // with a terminating NUL removed. 50 func UTF16ToString(s []uint16) string { 51 for i, v := range s { 52 if v == 0 { 53 s = s[0:i] 54 break 55 } 56 } 57 return string(utf16.Decode(s)) 58 } 59 60 // utf16PtrToString is like UTF16ToString, but takes *uint16 61 // as a parameter instead of []uint16. 62 // max is how many times p can be advanced looking for the null terminator. 63 // If max is hit, the string is truncated at that point. 64 func utf16PtrToString(p *uint16, max int) string { 65 if p == nil { 66 return "" 67 } 68 // Find NUL terminator. 69 end := unsafe.Pointer(p) 70 n := 0 71 for *(*uint16)(end) != 0 && n < max { 72 end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p)) 73 n++ 74 } 75 s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n] 76 return string(utf16.Decode(s)) 77 } 78 79 // StringToUTF16Ptr returns pointer to the UTF-16 encoding of 80 // the UTF-8 string s, with a terminating NUL added. If s 81 // contains a NUL byte this function panics instead of 82 // returning an error. 83 // 84 // Deprecated: Use UTF16PtrFromString instead. 85 func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] } 86 87 // UTF16PtrFromString returns pointer to the UTF-16 encoding of 88 // the UTF-8 string s, with a terminating NUL added. If s 89 // contains a NUL byte at any location, it returns (nil, EINVAL). 90 func UTF16PtrFromString(s string) (*uint16, error) { 91 a, err := UTF16FromString(s) 92 if err != nil { 93 return nil, err 94 } 95 return &a[0], nil 96 } 97 98 // Errno is the Windows error number. 99 // 100 // Errno values can be tested against error values from the os package 101 // using errors.Is. For example: 102 // 103 // _, _, err := syscall.Syscall(...) 104 // if errors.Is(err, os.ErrNotExist) ... 105 type Errno uintptr 106 107 func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) } 108 109 // FormatMessage is deprecated (msgsrc should be uintptr, not uint32, but can 110 // not be changed due to the Go 1 compatibility guarantee). 111 // 112 // Deprecated: Use FormatMessage from golang.org/x/sys/windows instead. 113 func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { 114 return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args) 115 } 116 117 func (e Errno) Error() string { 118 // deal with special go errors 119 idx := int(e - APPLICATION_ERROR) 120 if 0 <= idx && idx < len(errors) { 121 return errors[idx] 122 } 123 // ask windows for the remaining errors 124 var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS 125 b := make([]uint16, 300) 126 n, err := formatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil) 127 if err != nil { 128 n, err = formatMessage(flags, 0, uint32(e), 0, b, nil) 129 if err != nil { 130 return "winapi error #" + itoa(int(e)) 131 } 132 } 133 // trim terminating \r and \n 134 for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { 135 } 136 return string(utf16.Decode(b[:n])) 137 } 138 139 const _ERROR_BAD_NETPATH = Errno(53) 140 141 func (e Errno) Is(target error) bool { 142 switch target { 143 case oserror.ErrPermission: 144 return e == ERROR_ACCESS_DENIED 145 case oserror.ErrExist: 146 return e == ERROR_ALREADY_EXISTS || 147 e == ERROR_DIR_NOT_EMPTY || 148 e == ERROR_FILE_EXISTS 149 case oserror.ErrNotExist: 150 return e == ERROR_FILE_NOT_FOUND || 151 e == _ERROR_BAD_NETPATH || 152 e == ERROR_PATH_NOT_FOUND 153 } 154 return false 155 } 156 157 func (e Errno) Temporary() bool { 158 return e == EINTR || e == EMFILE || e.Timeout() 159 } 160 161 func (e Errno) Timeout() bool { 162 return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT 163 } 164 165 // Implemented in runtime/syscall_windows.go. 166 func compileCallback(fn interface{}, cleanstack bool) uintptr 167 168 // NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. 169 // This is useful when interoperating with Windows code requiring callbacks. 170 // The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. 171 func NewCallback(fn interface{}) uintptr { 172 return compileCallback(fn, true) 173 } 174 175 // NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention. 176 // This is useful when interoperating with Windows code requiring callbacks. 177 // The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. 178 func NewCallbackCDecl(fn interface{}) uintptr { 179 return compileCallback(fn, false) 180 } 181 182 // windows api calls 183 184 //sys GetLastError() (lasterr error) 185 //sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW 186 //sys FreeLibrary(handle Handle) (err error) 187 //sys GetProcAddress(module Handle, procname string) (proc uintptr, err error) 188 //sys GetVersion() (ver uint32, err error) 189 //sys formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW 190 //sys ExitProcess(exitcode uint32) 191 //sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW 192 //sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) 193 //sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) 194 //sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff] 195 //sys CloseHandle(handle Handle) (err error) 196 //sys GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle] 197 //sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW 198 //sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW 199 //sys FindClose(handle Handle) (err error) 200 //sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) 201 //sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW 202 //sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW 203 //sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW 204 //sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW 205 //sys DeleteFile(path *uint16) (err error) = DeleteFileW 206 //sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW 207 //sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW 208 //sys SetEndOfFile(handle Handle) (err error) 209 //sys GetSystemTimeAsFileTime(time *Filetime) 210 //sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] 211 //sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) 212 //sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) 213 //sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) 214 //sys CancelIo(s Handle) (err error) 215 //sys CancelIoEx(s Handle, o *Overlapped) (err error) 216 //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW 217 //sys CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = advapi32.CreateProcessAsUserW 218 //sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) 219 //sys TerminateProcess(handle Handle, exitcode uint32) (err error) 220 //sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) 221 //sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW 222 //sys GetCurrentProcess() (pseudoHandle Handle, err error) 223 //sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) 224 //sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) 225 //sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff] 226 //sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW 227 //sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) 228 //sys GetFileType(filehandle Handle) (n uint32, err error) 229 //sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW 230 //sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext 231 //sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom 232 //sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW 233 //sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW 234 //sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW 235 //sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW 236 //sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) 237 //sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW 238 //sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW 239 //sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW 240 //sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW 241 //sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW 242 //sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0] 243 //sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) 244 //sys FlushFileBuffers(handle Handle) (err error) 245 //sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW 246 //sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW 247 //sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW 248 //sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW 249 //sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) 250 //sys UnmapViewOfFile(addr uintptr) (err error) 251 //sys FlushViewOfFile(addr uintptr, length uintptr) (err error) 252 //sys VirtualLock(addr uintptr, length uintptr) (err error) 253 //sys VirtualUnlock(addr uintptr, length uintptr) (err error) 254 //sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile 255 //sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW 256 //sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW 257 //sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore 258 //sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore 259 //sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore 260 //sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore 261 //sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain 262 //sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain 263 //sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext 264 //sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext 265 //sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy 266 //sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW 267 //sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey 268 //sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW 269 //sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW 270 //sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW 271 //sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId 272 //sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode 273 //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW 274 //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW 275 //sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot 276 //sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW 277 //sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW 278 //sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) 279 // This function returns 1 byte BOOLEAN rather than the 4 byte BOOL. 280 //sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW 281 //sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW 282 283 // syscall interface implementation for other packages 284 285 func makeInheritSa() *SecurityAttributes { 286 var sa SecurityAttributes 287 sa.Length = uint32(unsafe.Sizeof(sa)) 288 sa.InheritHandle = 1 289 return &sa 290 } 291 292 func Open(path string, mode int, perm uint32) (fd Handle, err error) { 293 if len(path) == 0 { 294 return InvalidHandle, ERROR_FILE_NOT_FOUND 295 } 296 pathp, err := UTF16PtrFromString(path) 297 if err != nil { 298 return InvalidHandle, err 299 } 300 var access uint32 301 switch mode & (O_RDONLY | O_WRONLY | O_RDWR) { 302 case O_RDONLY: 303 access = GENERIC_READ 304 case O_WRONLY: 305 access = GENERIC_WRITE 306 case O_RDWR: 307 access = GENERIC_READ | GENERIC_WRITE 308 } 309 if mode&O_CREAT != 0 { 310 access |= GENERIC_WRITE 311 } 312 if mode&O_APPEND != 0 { 313 access &^= GENERIC_WRITE 314 access |= FILE_APPEND_DATA 315 } 316 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE) 317 var sa *SecurityAttributes 318 if mode&O_CLOEXEC == 0 { 319 sa = makeInheritSa() 320 } 321 var createmode uint32 322 switch { 323 case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): 324 createmode = CREATE_NEW 325 case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): 326 createmode = CREATE_ALWAYS 327 case mode&O_CREAT == O_CREAT: 328 createmode = OPEN_ALWAYS 329 case mode&O_TRUNC == O_TRUNC: 330 createmode = TRUNCATE_EXISTING 331 default: 332 createmode = OPEN_EXISTING 333 } 334 var attrs uint32 = FILE_ATTRIBUTE_NORMAL 335 if perm&S_IWRITE == 0 { 336 attrs = FILE_ATTRIBUTE_READONLY 337 } 338 h, e := CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) 339 return h, e 340 } 341 342 func Read(fd Handle, p []byte) (n int, err error) { 343 var done uint32 344 e := ReadFile(fd, p, &done, nil) 345 if e != nil { 346 if e == ERROR_BROKEN_PIPE { 347 // NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin 348 return 0, nil 349 } 350 return 0, e 351 } 352 if race.Enabled { 353 if done > 0 { 354 race.WriteRange(unsafe.Pointer(&p[0]), int(done)) 355 } 356 race.Acquire(unsafe.Pointer(&ioSync)) 357 } 358 if msanenabled && done > 0 { 359 msanWrite(unsafe.Pointer(&p[0]), int(done)) 360 } 361 return int(done), nil 362 } 363 364 func Write(fd Handle, p []byte) (n int, err error) { 365 if race.Enabled { 366 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 367 } 368 var done uint32 369 e := WriteFile(fd, p, &done, nil) 370 if e != nil { 371 return 0, e 372 } 373 if race.Enabled && done > 0 { 374 race.ReadRange(unsafe.Pointer(&p[0]), int(done)) 375 } 376 if msanenabled && done > 0 { 377 msanRead(unsafe.Pointer(&p[0]), int(done)) 378 } 379 return int(done), nil 380 } 381 382 var ioSync int64 383 384 var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx") 385 386 const ptrSize = unsafe.Sizeof(uintptr(0)) 387 388 // setFilePointerEx calls SetFilePointerEx. 389 // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365542(v=vs.85).aspx 390 func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error { 391 var e1 Errno 392 switch runtime.GOARCH { 393 default: 394 panic("unsupported architecture") 395 case "amd64": 396 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0) 397 case "386": 398 // distToMove is a LARGE_INTEGER: 399 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa383713(v=vs.85).aspx 400 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0) 401 case "arm": 402 // distToMove must be 8-byte aligned per ARM calling convention 403 // https://msdn.microsoft.com/en-us/library/dn736986.aspx#Anchor_7 404 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 6, uintptr(handle), 0, uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence)) 405 } 406 if e1 != 0 { 407 return errnoErr(e1) 408 } 409 return nil 410 } 411 412 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) { 413 var w uint32 414 switch whence { 415 case 0: 416 w = FILE_BEGIN 417 case 1: 418 w = FILE_CURRENT 419 case 2: 420 w = FILE_END 421 } 422 // use GetFileType to check pipe, pipe can't do seek 423 ft, _ := GetFileType(fd) 424 if ft == FILE_TYPE_PIPE { 425 return 0, ESPIPE 426 } 427 err = setFilePointerEx(fd, offset, &newoffset, w) 428 return 429 } 430 431 func Close(fd Handle) (err error) { 432 return CloseHandle(fd) 433 } 434 435 var ( 436 Stdin = getStdHandle(STD_INPUT_HANDLE) 437 Stdout = getStdHandle(STD_OUTPUT_HANDLE) 438 Stderr = getStdHandle(STD_ERROR_HANDLE) 439 ) 440 441 func getStdHandle(h int) (fd Handle) { 442 r, _ := GetStdHandle(h) 443 CloseOnExec(r) 444 return r 445 } 446 447 const ImplementsGetwd = true 448 449 func Getwd() (wd string, err error) { 450 b := make([]uint16, 300) 451 n, e := GetCurrentDirectory(uint32(len(b)), &b[0]) 452 if e != nil { 453 return "", e 454 } 455 return string(utf16.Decode(b[0:n])), nil 456 } 457 458 func Chdir(path string) (err error) { 459 pathp, err := UTF16PtrFromString(path) 460 if err != nil { 461 return err 462 } 463 return SetCurrentDirectory(pathp) 464 } 465 466 func Mkdir(path string, mode uint32) (err error) { 467 pathp, err := UTF16PtrFromString(path) 468 if err != nil { 469 return err 470 } 471 return CreateDirectory(pathp, nil) 472 } 473 474 func Rmdir(path string) (err error) { 475 pathp, err := UTF16PtrFromString(path) 476 if err != nil { 477 return err 478 } 479 return RemoveDirectory(pathp) 480 } 481 482 func Unlink(path string) (err error) { 483 pathp, err := UTF16PtrFromString(path) 484 if err != nil { 485 return err 486 } 487 return DeleteFile(pathp) 488 } 489 490 func Rename(oldpath, newpath string) (err error) { 491 from, err := UTF16PtrFromString(oldpath) 492 if err != nil { 493 return err 494 } 495 to, err := UTF16PtrFromString(newpath) 496 if err != nil { 497 return err 498 } 499 return MoveFile(from, to) 500 } 501 502 func ComputerName() (name string, err error) { 503 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1 504 b := make([]uint16, n) 505 e := GetComputerName(&b[0], &n) 506 if e != nil { 507 return "", e 508 } 509 return string(utf16.Decode(b[0:n])), nil 510 } 511 512 func Ftruncate(fd Handle, length int64) (err error) { 513 curoffset, e := Seek(fd, 0, 1) 514 if e != nil { 515 return e 516 } 517 defer Seek(fd, curoffset, 0) 518 _, e = Seek(fd, length, 0) 519 if e != nil { 520 return e 521 } 522 e = SetEndOfFile(fd) 523 if e != nil { 524 return e 525 } 526 return nil 527 } 528 529 func Gettimeofday(tv *Timeval) (err error) { 530 var ft Filetime 531 GetSystemTimeAsFileTime(&ft) 532 *tv = NsecToTimeval(ft.Nanoseconds()) 533 return nil 534 } 535 536 func Pipe(p []Handle) (err error) { 537 if len(p) != 2 { 538 return EINVAL 539 } 540 var r, w Handle 541 e := CreatePipe(&r, &w, makeInheritSa(), 0) 542 if e != nil { 543 return e 544 } 545 p[0] = r 546 p[1] = w 547 return nil 548 } 549 550 func Utimes(path string, tv []Timeval) (err error) { 551 if len(tv) != 2 { 552 return EINVAL 553 } 554 pathp, e := UTF16PtrFromString(path) 555 if e != nil { 556 return e 557 } 558 h, e := CreateFile(pathp, 559 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 560 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) 561 if e != nil { 562 return e 563 } 564 defer Close(h) 565 a := NsecToFiletime(tv[0].Nanoseconds()) 566 w := NsecToFiletime(tv[1].Nanoseconds()) 567 return SetFileTime(h, nil, &a, &w) 568 } 569 570 func UtimesNano(path string, ts []Timespec) (err error) { 571 if len(ts) != 2 { 572 return EINVAL 573 } 574 pathp, e := UTF16PtrFromString(path) 575 if e != nil { 576 return e 577 } 578 h, e := CreateFile(pathp, 579 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil, 580 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) 581 if e != nil { 582 return e 583 } 584 defer Close(h) 585 a := NsecToFiletime(TimespecToNsec(ts[0])) 586 w := NsecToFiletime(TimespecToNsec(ts[1])) 587 return SetFileTime(h, nil, &a, &w) 588 } 589 590 func Fsync(fd Handle) (err error) { 591 return FlushFileBuffers(fd) 592 } 593 594 func Chmod(path string, mode uint32) (err error) { 595 p, e := UTF16PtrFromString(path) 596 if e != nil { 597 return e 598 } 599 attrs, e := GetFileAttributes(p) 600 if e != nil { 601 return e 602 } 603 if mode&S_IWRITE != 0 { 604 attrs &^= FILE_ATTRIBUTE_READONLY 605 } else { 606 attrs |= FILE_ATTRIBUTE_READONLY 607 } 608 return SetFileAttributes(p, attrs) 609 } 610 611 func LoadCancelIoEx() error { 612 return procCancelIoEx.Find() 613 } 614 615 func LoadSetFileCompletionNotificationModes() error { 616 return procSetFileCompletionNotificationModes.Find() 617 } 618 619 // net api calls 620 621 const socket_error = uintptr(^uint32(0)) 622 623 //sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup 624 //sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup 625 //sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl 626 //sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket 627 //sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt 628 //sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt 629 //sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind 630 //sys connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect 631 //sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname 632 //sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername 633 //sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen 634 //sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown 635 //sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket 636 //sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx 637 //sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs 638 //sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv 639 //sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend 640 //sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom 641 //sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo 642 //sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname 643 //sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname 644 //sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs 645 //sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname 646 //sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W 647 //sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree 648 //sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W 649 //sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW 650 //sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW 651 //sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry 652 //sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo 653 //sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes 654 //sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW 655 656 // For testing: clients can set this flag to force 657 // creation of IPv6 sockets to return EAFNOSUPPORT. 658 var SocketDisableIPv6 bool 659 660 type RawSockaddrInet4 struct { 661 Family uint16 662 Port uint16 663 Addr [4]byte /* in_addr */ 664 Zero [8]uint8 665 } 666 667 type RawSockaddrInet6 struct { 668 Family uint16 669 Port uint16 670 Flowinfo uint32 671 Addr [16]byte /* in6_addr */ 672 Scope_id uint32 673 } 674 675 type RawSockaddr struct { 676 Family uint16 677 Data [14]int8 678 } 679 680 type RawSockaddrAny struct { 681 Addr RawSockaddr 682 Pad [100]int8 683 } 684 685 type Sockaddr interface { 686 sockaddr() (ptr unsafe.Pointer, len int32, err error) // lowercase; only we can define Sockaddrs 687 } 688 689 type SockaddrInet4 struct { 690 Port int 691 Addr [4]byte 692 raw RawSockaddrInet4 693 } 694 695 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { 696 if sa.Port < 0 || sa.Port > 0xFFFF { 697 return nil, 0, EINVAL 698 } 699 sa.raw.Family = AF_INET 700 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 701 p[0] = byte(sa.Port >> 8) 702 p[1] = byte(sa.Port) 703 for i := 0; i < len(sa.Addr); i++ { 704 sa.raw.Addr[i] = sa.Addr[i] 705 } 706 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil 707 } 708 709 type SockaddrInet6 struct { 710 Port int 711 ZoneId uint32 712 Addr [16]byte 713 raw RawSockaddrInet6 714 } 715 716 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { 717 if sa.Port < 0 || sa.Port > 0xFFFF { 718 return nil, 0, EINVAL 719 } 720 sa.raw.Family = AF_INET6 721 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 722 p[0] = byte(sa.Port >> 8) 723 p[1] = byte(sa.Port) 724 sa.raw.Scope_id = sa.ZoneId 725 for i := 0; i < len(sa.Addr); i++ { 726 sa.raw.Addr[i] = sa.Addr[i] 727 } 728 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil 729 } 730 731 type RawSockaddrUnix struct { 732 Family uint16 733 Path [UNIX_PATH_MAX]int8 734 } 735 736 type SockaddrUnix struct { 737 Name string 738 raw RawSockaddrUnix 739 } 740 741 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { 742 name := sa.Name 743 n := len(name) 744 if n > len(sa.raw.Path) { 745 return nil, 0, EINVAL 746 } 747 if n == len(sa.raw.Path) && name[0] != '@' { 748 return nil, 0, EINVAL 749 } 750 sa.raw.Family = AF_UNIX 751 for i := 0; i < n; i++ { 752 sa.raw.Path[i] = int8(name[i]) 753 } 754 // length is family (uint16), name, NUL. 755 sl := int32(2) 756 if n > 0 { 757 sl += int32(n) + 1 758 } 759 if sa.raw.Path[0] == '@' { 760 sa.raw.Path[0] = 0 761 // Don't count trailing NUL for abstract address. 762 sl-- 763 } 764 765 return unsafe.Pointer(&sa.raw), sl, nil 766 } 767 768 func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { 769 switch rsa.Addr.Family { 770 case AF_UNIX: 771 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 772 sa := new(SockaddrUnix) 773 if pp.Path[0] == 0 { 774 // "Abstract" Unix domain socket. 775 // Rewrite leading NUL as @ for textual display. 776 // (This is the standard convention.) 777 // Not friendly to overwrite in place, 778 // but the callers below don't care. 779 pp.Path[0] = '@' 780 } 781 782 // Assume path ends at NUL. 783 // This is not technically the Linux semantics for 784 // abstract Unix domain sockets--they are supposed 785 // to be uninterpreted fixed-size binary blobs--but 786 // everyone uses this convention. 787 n := 0 788 for n < len(pp.Path) && pp.Path[n] != 0 { 789 n++ 790 } 791 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n:n] 792 sa.Name = string(bytes) 793 return sa, nil 794 795 case AF_INET: 796 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 797 sa := new(SockaddrInet4) 798 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 799 sa.Port = int(p[0])<<8 + int(p[1]) 800 for i := 0; i < len(sa.Addr); i++ { 801 sa.Addr[i] = pp.Addr[i] 802 } 803 return sa, nil 804 805 case AF_INET6: 806 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 807 sa := new(SockaddrInet6) 808 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 809 sa.Port = int(p[0])<<8 + int(p[1]) 810 sa.ZoneId = pp.Scope_id 811 for i := 0; i < len(sa.Addr); i++ { 812 sa.Addr[i] = pp.Addr[i] 813 } 814 return sa, nil 815 } 816 return nil, EAFNOSUPPORT 817 } 818 819 func Socket(domain, typ, proto int) (fd Handle, err error) { 820 if domain == AF_INET6 && SocketDisableIPv6 { 821 return InvalidHandle, EAFNOSUPPORT 822 } 823 return socket(int32(domain), int32(typ), int32(proto)) 824 } 825 826 func SetsockoptInt(fd Handle, level, opt int, value int) (err error) { 827 v := int32(value) 828 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v))) 829 } 830 831 func Bind(fd Handle, sa Sockaddr) (err error) { 832 ptr, n, err := sa.sockaddr() 833 if err != nil { 834 return err 835 } 836 return bind(fd, ptr, n) 837 } 838 839 func Connect(fd Handle, sa Sockaddr) (err error) { 840 ptr, n, err := sa.sockaddr() 841 if err != nil { 842 return err 843 } 844 return connect(fd, ptr, n) 845 } 846 847 func Getsockname(fd Handle) (sa Sockaddr, err error) { 848 var rsa RawSockaddrAny 849 l := int32(unsafe.Sizeof(rsa)) 850 if err = getsockname(fd, &rsa, &l); err != nil { 851 return 852 } 853 return rsa.Sockaddr() 854 } 855 856 func Getpeername(fd Handle) (sa Sockaddr, err error) { 857 var rsa RawSockaddrAny 858 l := int32(unsafe.Sizeof(rsa)) 859 if err = getpeername(fd, &rsa, &l); err != nil { 860 return 861 } 862 return rsa.Sockaddr() 863 } 864 865 func Listen(s Handle, n int) (err error) { 866 return listen(s, int32(n)) 867 } 868 869 func Shutdown(fd Handle, how int) (err error) { 870 return shutdown(fd, int32(how)) 871 } 872 873 func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) { 874 rsa, l, err := to.sockaddr() 875 if err != nil { 876 return err 877 } 878 return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine) 879 } 880 881 func LoadGetAddrInfo() error { 882 return procGetAddrInfoW.Find() 883 } 884 885 var connectExFunc struct { 886 once sync.Once 887 addr uintptr 888 err error 889 } 890 891 func LoadConnectEx() error { 892 connectExFunc.once.Do(func() { 893 var s Handle 894 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 895 if connectExFunc.err != nil { 896 return 897 } 898 defer CloseHandle(s) 899 var n uint32 900 connectExFunc.err = WSAIoctl(s, 901 SIO_GET_EXTENSION_FUNCTION_POINTER, 902 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)), 903 uint32(unsafe.Sizeof(WSAID_CONNECTEX)), 904 (*byte)(unsafe.Pointer(&connectExFunc.addr)), 905 uint32(unsafe.Sizeof(connectExFunc.addr)), 906 &n, nil, 0) 907 }) 908 return connectExFunc.err 909 } 910 911 func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) { 912 r1, _, e1 := Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0) 913 if r1 == 0 { 914 if e1 != 0 { 915 err = error(e1) 916 } else { 917 err = EINVAL 918 } 919 } 920 return 921 } 922 923 func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error { 924 err := LoadConnectEx() 925 if err != nil { 926 return errorspkg.New("failed to find ConnectEx: " + err.Error()) 927 } 928 ptr, n, err := sa.sockaddr() 929 if err != nil { 930 return err 931 } 932 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) 933 } 934 935 // Invented structures to support what package os expects. 936 type Rusage struct { 937 CreationTime Filetime 938 ExitTime Filetime 939 KernelTime Filetime 940 UserTime Filetime 941 } 942 943 type WaitStatus struct { 944 ExitCode uint32 945 } 946 947 func (w WaitStatus) Exited() bool { return true } 948 949 func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) } 950 951 func (w WaitStatus) Signal() Signal { return -1 } 952 953 func (w WaitStatus) CoreDump() bool { return false } 954 955 func (w WaitStatus) Stopped() bool { return false } 956 957 func (w WaitStatus) Continued() bool { return false } 958 959 func (w WaitStatus) StopSignal() Signal { return -1 } 960 961 func (w WaitStatus) Signaled() bool { return false } 962 963 func (w WaitStatus) TrapCause() int { return -1 } 964 965 // Timespec is an invented structure on Windows, but here for 966 // consistency with the syscall package for other operating systems. 967 type Timespec struct { 968 Sec int64 969 Nsec int64 970 } 971 972 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } 973 974 func NsecToTimespec(nsec int64) (ts Timespec) { 975 ts.Sec = nsec / 1e9 976 ts.Nsec = nsec % 1e9 977 return 978 } 979 980 // TODO(brainman): fix all needed for net 981 982 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS } 983 func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) { 984 return 0, nil, EWINDOWS 985 } 986 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS } 987 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS } 988 989 // The Linger struct is wrong but we only noticed after Go 1. 990 // sysLinger is the real system call structure. 991 992 // BUG(brainman): The definition of Linger is not appropriate for direct use 993 // with Setsockopt and Getsockopt. 994 // Use SetsockoptLinger instead. 995 996 type Linger struct { 997 Onoff int32 998 Linger int32 999 } 1000 1001 type sysLinger struct { 1002 Onoff uint16 1003 Linger uint16 1004 } 1005 1006 type IPMreq struct { 1007 Multiaddr [4]byte /* in_addr */ 1008 Interface [4]byte /* in_addr */ 1009 } 1010 1011 type IPv6Mreq struct { 1012 Multiaddr [16]byte /* in6_addr */ 1013 Interface uint32 1014 } 1015 1016 func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, EWINDOWS } 1017 1018 func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { 1019 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)} 1020 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys))) 1021 } 1022 1023 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { 1024 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) 1025 } 1026 func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { 1027 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) 1028 } 1029 func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS } 1030 1031 func Getpid() (pid int) { return int(getCurrentProcessId()) } 1032 1033 func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) { 1034 // NOTE(rsc): The Win32finddata struct is wrong for the system call: 1035 // the two paths are each one uint16 short. Use the correct struct, 1036 // a win32finddata1, and then copy the results out. 1037 // There is no loss of expressivity here, because the final 1038 // uint16, if it is used, is supposed to be a NUL, and Go doesn't need that. 1039 // For Go 1.1, we might avoid the allocation of win32finddata1 here 1040 // by adding a final Bug [2]uint16 field to the struct and then 1041 // adjusting the fields in the result directly. 1042 var data1 win32finddata1 1043 handle, err = findFirstFile1(name, &data1) 1044 if err == nil { 1045 copyFindData(data, &data1) 1046 } 1047 return 1048 } 1049 1050 func FindNextFile(handle Handle, data *Win32finddata) (err error) { 1051 var data1 win32finddata1 1052 err = findNextFile1(handle, &data1) 1053 if err == nil { 1054 copyFindData(data, &data1) 1055 } 1056 return 1057 } 1058 1059 func getProcessEntry(pid int) (*ProcessEntry32, error) { 1060 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 1061 if err != nil { 1062 return nil, err 1063 } 1064 defer CloseHandle(snapshot) 1065 var procEntry ProcessEntry32 1066 procEntry.Size = uint32(unsafe.Sizeof(procEntry)) 1067 if err = Process32First(snapshot, &procEntry); err != nil { 1068 return nil, err 1069 } 1070 for { 1071 if procEntry.ProcessID == uint32(pid) { 1072 return &procEntry, nil 1073 } 1074 err = Process32Next(snapshot, &procEntry) 1075 if err != nil { 1076 return nil, err 1077 } 1078 } 1079 } 1080 1081 func Getppid() (ppid int) { 1082 pe, err := getProcessEntry(Getpid()) 1083 if err != nil { 1084 return -1 1085 } 1086 return int(pe.ParentProcessID) 1087 } 1088 1089 // TODO(brainman): fix all needed for os 1090 func Fchdir(fd Handle) (err error) { return EWINDOWS } 1091 func Link(oldpath, newpath string) (err error) { return EWINDOWS } 1092 func Symlink(path, link string) (err error) { return EWINDOWS } 1093 1094 func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS } 1095 func Chown(path string, uid int, gid int) (err error) { return EWINDOWS } 1096 func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS } 1097 func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS } 1098 1099 func Getuid() (uid int) { return -1 } 1100 func Geteuid() (euid int) { return -1 } 1101 func Getgid() (gid int) { return -1 } 1102 func Getegid() (egid int) { return -1 } 1103 func Getgroups() (gids []int, err error) { return nil, EWINDOWS } 1104 1105 type Signal int 1106 1107 func (s Signal) Signal() {} 1108 1109 func (s Signal) String() string { 1110 if 0 <= s && int(s) < len(signals) { 1111 str := signals[s] 1112 if str != "" { 1113 return str 1114 } 1115 } 1116 return "signal " + itoa(int(s)) 1117 } 1118 1119 func LoadCreateSymbolicLink() error { 1120 return procCreateSymbolicLinkW.Find() 1121 } 1122 1123 // Readlink returns the destination of the named symbolic link. 1124 func Readlink(path string, buf []byte) (n int, err error) { 1125 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING, 1126 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0) 1127 if err != nil { 1128 return -1, err 1129 } 1130 defer CloseHandle(fd) 1131 1132 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE) 1133 var bytesReturned uint32 1134 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil) 1135 if err != nil { 1136 return -1, err 1137 } 1138 1139 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0])) 1140 var s string 1141 switch rdb.ReparseTag { 1142 case IO_REPARSE_TAG_SYMLINK: 1143 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) 1144 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) 1145 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2]) 1146 if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 { 1147 if len(s) >= 4 && s[:4] == `\??\` { 1148 s = s[4:] 1149 switch { 1150 case len(s) >= 2 && s[1] == ':': // \??\C:\foo\bar 1151 // do nothing 1152 case len(s) >= 4 && s[:4] == `UNC\`: // \??\UNC\foo\bar 1153 s = `\\` + s[4:] 1154 default: 1155 // unexpected; do nothing 1156 } 1157 } else { 1158 // unexpected; do nothing 1159 } 1160 } 1161 case _IO_REPARSE_TAG_MOUNT_POINT: 1162 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) 1163 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) 1164 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2]) 1165 if len(s) >= 4 && s[:4] == `\??\` { // \??\C:\foo\bar 1166 s = s[4:] 1167 } else { 1168 // unexpected; do nothing 1169 } 1170 default: 1171 // the path is not a symlink or junction but another type of reparse 1172 // point 1173 return -1, ENOENT 1174 } 1175 n = copy(buf, []byte(s)) 1176 1177 return n, nil 1178 }