func (fd *netFD) Write(p []byte) (n int, err os.Error) { if fd == nil { return 0, os.EINVAL } fd.wio.Lock() defer fd.wio.Unlock() fd.incref() defer fd.decref() if fd.sysfile == nil { return 0, os.EINVAL } // Submit send request. var pckt ioPacket pckt.c = fd.cw var done uint32 e := syscall.WSASend(uint32(fd.sysfd), newWSABuf(p), 1, &done, uint32(0), &pckt.o, nil) switch e { case 0: // IO completed immediately, but we need to get our completion message anyway. case syscall.ERROR_IO_PENDING: // IO started, and we have to wait for it's completion. default: return 0, &OpError{"WSASend", fd.net, fd.laddr, os.Errno(e)} } // Wait for our request to complete. r := <-pckt.c if r.errno != 0 { err = &OpError{"WSASend", fd.net, fd.laddr, os.Errno(r.errno)} } n = int(r.qty) return }
func (p *pollster) StopWaiting(fd int, bits uint) { events, already := p.events[fd] if !already { print("Epoll unexpected fd=", fd, "\n") return } // If syscall.EPOLLONESHOT is not set, the wait // is a repeating wait, so don't change it. if events&syscall.EPOLLONESHOT == 0 { return } // Disable the given bits. // If we're still waiting for other events, modify the fd // event in the kernel. Otherwise, delete it. events &= ^uint32(bits) if int32(events)&^syscall.EPOLLONESHOT != 0 { var ev syscall.EpollEvent ev.Fd = int32(fd) ev.Events = events if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 { print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n") } p.events[fd] = events } else { if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 { print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n") } p.events[fd] = 0, false } }
// Generic socket creation. func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(f, p, t) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Allow reuse of recently-used addresses. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) // Allow broadcast. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) if f == syscall.AF_INET6 { // using ip, tcp, udp, etc. // allow both protocols even if the OS default is otherwise. syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) } if la != nil { e = syscall.Bind(s, la) if e != 0 { closesocket(s) return nil, os.Errno(e) } } if ra != nil { e = syscall.Connect(s, ra) for e == syscall.EINTR { e = syscall.Connect(s, ra) } if e != 0 { closesocket(s) return nil, os.Errno(e) } } sa, _ := syscall.Getsockname(s) laddr := toAddr(sa) sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd, err = newFD(s, f, p, net, laddr, raddr) if err != nil { closesocket(s) return nil, err } return fd, nil }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) { if fd == nil || fd.sysfd == syscall.InvalidHandle { return nil, os.EINVAL } fd.incref() defer fd.decref() // Get new socket. // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(fd.family, fd.proto, 0) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Associate our new socket with IOCP. onceStartServer.Do(startServer) if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != 0 { return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)} } // Submit accept request. var o acceptOp o.Init(fd, 'r') o.newsock = s _, err = iosrv.ExecIO(&o, 0) if err != nil { closesocket(s) return nil, err } // Inherit properties of the listening socket. e = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) if e != 0 { closesocket(s) return nil, err } // Get local and peer addr out of AcceptEx buffer. var lrsa, rrsa *syscall.RawSockaddrAny var llen, rlen int32 l := uint32(unsafe.Sizeof(*lrsa)) syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &lrsa, &llen, &rrsa, &rlen) lsa, _ := lrsa.Sockaddr() rsa, _ := rrsa.Sockaddr() nfd = allocFD(s, fd.family, fd.proto, fd.net) nfd.setAddr(toAddr(lsa), toAddr(rsa)) return nfd, nil }
func (fd *netFD) dup() (f *os.File, err error) { ns, e := syscall.Dup(fd.sysfd) if e != 0 { return nil, &OpError{"dup", fd.net, fd.laddr, os.Errno(e)} } // We want blocking mode for the new fd, hence the double negative. if e = syscall.SetNonblock(ns, false); e != 0 { return nil, &OpError{"setnonblock", fd.net, fd.laddr, os.Errno(e)} } return os.NewFile(ns, fd.sysfile.Name()), nil }
// MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. func MakeRaw(fd int) (*State, error) { var oldState State if e := syscall.Tcgetattr(fd, &oldState.termios); e != 0 { return nil, os.Errno(e) } newState := oldState.termios newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG if e := syscall.Tcsetattr(fd, syscall.TCSANOW, &newState); e != 0 { return nil, os.Errno(e) } return &oldState, nil }
func lookup(uid int, username string, lookupByName bool) (*User, os.Error) { var pwd syscall.Passwd var result *syscall.Passwd // FIXME: Should let buf grow if necessary. const bufSize = 1024 buf := make([]byte, bufSize) if lookupByName { rv := libc_getpwnam_r(syscall.StringBytePtr(username), &pwd, &buf[0], bufSize, &result) if rv != 0 { return nil, fmt.Errorf("user: lookup username %s: %s", username, os.Errno(syscall.GetErrno())) } if result == nil { return nil, UnknownUserError(username) } } else { rv := libc_getpwuid_r(syscall.Uid_t(uid), &pwd, &buf[0], bufSize, &result) if rv != 0 { return nil, fmt.Errorf("user: lookup userid %d: %s", uid, os.Errno(syscall.GetErrno())) } if result == nil { return nil, UnknownUserIdError(uid) } } u := &User{ Uid: int(pwd.Pw_uid), Gid: int(pwd.Pw_gid), Username: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))), Name: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))), HomeDir: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))), } // The pw_gecos field isn't quite standardized. Some docs // say: "It is expected to be a comma separated list of // personal data where the first item is the full name of the // user." if i := strings.Index(u.Name, ","); i >= 0 { u.Name = u.Name[:i] } return u, nil }
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err os.Error) { if fd == nil || fd.sysfile == nil { return 0, 0, 0, nil, os.EINVAL } fd.rio.Lock() defer fd.rio.Unlock() fd.incref() defer fd.decref() if fd.rdeadline_delta > 0 { fd.rdeadline = pollserver.Now() + fd.rdeadline_delta } else { fd.rdeadline = 0 } var oserr os.Error for { var errno int n, oobn, flags, sa, errno = syscall.Recvmsg(fd.sysfd, p, oob, 0) if (errno == syscall.EAGAIN || errno == syscall.EINTR) && fd.rdeadline >= 0 { pollserver.WaitRead(fd) continue } if errno != 0 { oserr = os.Errno(errno) } if n == 0 { oserr = os.EOF } break } if oserr != nil { err = &OpError{"read", fd.net, fd.laddr, oserr} return } return }
func flush(addr, len uintptr) os.Error { _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, addr, syscall.MS_SYNC, 0) if errno != 0 { return os.Errno(errno) } return nil }
func lock(addr, len uintptr) os.Error { _, _, errno := syscall.Syscall(syscall.SYS_MLOCK, addr, len, 0) if errno != 0 { return os.Errno(errno) } return nil }
func unmap(addr, len uintptr) os.Error { _, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, addr, len, 0) if errno != 0 { return os.Errno(errno) } return nil }
func newPollServer() (s *pollServer, err os.Error) { s = new(pollServer) s.cr = make(chan *netFD, 1) s.cw = make(chan *netFD, 1) // s.pr and s.pw are indistinguishable. if s.pr, s.pw, err = selfConnectedTCPSocket(); err != nil { return nil, err } var e int if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 { Errno: err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)} Error: s.pr.Close() return nil, err } if s.poll, err = newpollster(); err != nil { goto Error } if _, err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { s.poll.Close() goto Error } s.pending = make(map[int]*netFD) go s.Run() return s, nil }
func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) { if fd == nil || fd.sysfile == nil { return 0, os.EINVAL } fd.wio.Lock() defer fd.wio.Unlock() fd.incref() defer fd.decref() if fd.wdeadline_delta > 0 { fd.wdeadline = pollserver.Now() + fd.wdeadline_delta } else { fd.wdeadline = 0 } var oserr os.Error for { errno := syscall.Sendto(fd.sysfd, p, 0, sa) if errno == syscall.EAGAIN && fd.wdeadline >= 0 { pollserver.WaitWrite(fd) continue } if errno != 0 { oserr = os.Errno(errno) } break } if oserr == nil { n = len(p) } else { err = &OpError{"write", fd.net, fd.raddr, oserr} } return }
func (fd *netFD) Read(p []byte) (n int, err os.Error) { if fd == nil || fd.sysfile == nil { return 0, os.EINVAL } fd.rio.Lock() defer fd.rio.Unlock() fd.incref() defer fd.decref() if fd.rdeadline_delta > 0 { fd.rdeadline = pollserver.Now() + fd.rdeadline_delta } else { fd.rdeadline = 0 } var oserr os.Error for { var errno int n, errno = syscall.Read(fd.sysfile.Fd(), p) if errno == syscall.EAGAIN && fd.rdeadline >= 0 { pollserver.WaitRead(fd) continue } if errno != 0 { n = 0 oserr = os.Errno(errno) } else if n == 0 && errno == 0 && fd.proto != syscall.SOCK_DGRAM { err = os.EOF } break } if oserr != nil { err = &OpError{"read", fd.net, fd.raddr, oserr} } return }
func Open() (PacketReader, error) { fd, e := syscall.Open(device, os.O_RDONLY|syscall.O_CLOEXEC, 0666) if e != 0 { return nil, &os.PathError{"open", device, os.Errno(e)} } var data [16]byte data[0] = 'e' data[1] = 'n' data[2] = '0' var len uint32 var immediate uint32 = 1 var promisc uint32 = 1 if err := ioctl(fd, syscall.BIOCGBLEN, uintptr(unsafe.Pointer(&len))); err != nil { return nil, err } if err := ioctl(fd, syscall.BIOCSBLEN, uintptr(unsafe.Pointer(&len))); err != nil { return nil, err } if err := ioctl(fd, syscall.BIOCIMMEDIATE, uintptr(unsafe.Pointer(&immediate))); err != nil { return nil, err } if err := ioctl(fd, syscall.BIOCSETIF, uintptr(unsafe.Pointer(&data[0]))); err != nil { return nil, err } if err := ioctl(fd, syscall.BIOCPROMISC, uintptr(unsafe.Pointer(&promisc))); err != nil { return nil, err } return &reader{fd, int(len)}, nil }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) { if fd == nil || fd.file == nil { return nil, os.EINVAL } // See ../syscall/exec.go for description of ForkLock. // It is okay to hold the lock across syscall.Accept // because we have put fd.fd into non-blocking mode. syscall.ForkLock.RLock() var s, e int var sa syscall.Sockaddr for { s, sa, e = syscall.Accept(fd.fd) if e != syscall.EAGAIN { break } syscall.ForkLock.RUnlock() pollserver.WaitRead(fd) syscall.ForkLock.RLock() } if e != 0 { syscall.ForkLock.RUnlock() return nil, &OpError{"accept", fd.net, fd.laddr, os.Errno(e)} } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() if nfd, err = newFD(s, fd.family, fd.proto, fd.net, fd.laddr, toAddr(sa)); err != nil { syscall.Close(s) return nil, err } return nfd, nil }
func movePkg(pkg *archPkg) os.Error { filename := fmt.Sprintf("%s-%s-%s.%s", pkg.Name, pkg.Version, pkg.Arch, pkg.Ext) srcPath := fmt.Sprintf("%s/%s", *cachePath, filename) /* try to rename, first */ errno := syscall.Rename(srcPath, fmt.Sprintf("%s/%s", *destPath, filename)) switch errno { case syscall.EXDEV: src, err := os.Open(srcPath, os.O_RDONLY, 0666) if err != nil { fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err.String()) os.Exit(1) } defer src.Close() sfi, err := src.Stat() dst, err := os.Open(fmt.Sprintf("%s/%s", *destPath, filename), os.O_WRONLY|os.O_CREAT|os.O_TRUNC, sfi.Permission()) if err != nil { fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err.String()) os.Exit(1) } defer dst.Close() err = copyFile(src, bufio.NewWriter(dst)) if err == nil { return os.Remove(srcPath) } return err /* different from err outside if */ } return os.Errno(errno) }
func newFD(fd, family, proto int, net string, laddr, raddr Addr) (f *netFD, err os.Error) { once.Do(startServer) if e := syscall.SetNonblock(fd, true); e != 0 { return nil, &OpError{"setnonblock", net, laddr, os.Errno(e)} } f = &netFD{ sysfd: fd, family: family, proto: proto, net: net, laddr: laddr, raddr: raddr, } var ls, rs string if laddr != nil { ls = laddr.String() } if raddr != nil { rs = raddr.String() } f.sysfile = os.NewFile(fd, net+":"+ls+"->"+rs) f.cr = make(chan bool, 1) f.cw = make(chan bool, 1) return f, nil }
func newFD(fd, family, proto int, net string, laddr, raddr Addr) (f *netFD, err os.Error) { if initErr != nil { return nil, initErr } onceStartServer.Do(startServer) // Associate our socket with pollserver.iocp. if _, e := syscall.CreateIoCompletionPort(int32(fd), pollserver.iocp, 0, 0); e != 0 { return nil, &OpError{"CreateIoCompletionPort", net, laddr, os.Errno(e)} } f = &netFD{ sysfd: fd, family: family, proto: proto, cr: make(chan *ioResult), cw: make(chan *ioResult), net: net, laddr: laddr, raddr: raddr, } var ls, rs string if laddr != nil { ls = laddr.String() } if raddr != nil { rs = raddr.String() } f.sysfile = os.NewFile(fd, net+":"+ls+"->"+rs) return f, nil }
func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) { if fd == nil || fd.sysfile == nil { return 0, nil, os.EINVAL } fd.rio.Lock() defer fd.rio.Unlock() fd.incref() defer fd.decref() if fd.rdeadline_delta > 0 { fd.rdeadline = pollserver.Now() + fd.rdeadline_delta } else { fd.rdeadline = 0 } var oserr os.Error for { var errno int n, sa, errno = syscall.Recvfrom(fd.sysfd, p, 0) if errno == syscall.EAGAIN && fd.rdeadline >= 0 { pollserver.WaitRead(fd) continue } if errno != 0 { n = 0 oserr = os.Errno(errno) } break } if oserr != nil { err = &OpError{"read", fd.net, fd.laddr, oserr} } return }
func (fd *netFD) connect(ra syscall.Sockaddr) (err os.Error) { e := syscall.Connect(fd.sysfd, ra) if e != 0 { return os.Errno(e) } return nil }
func newPollServer() (s *pollServer, err os.Error) { s = new(pollServer) s.cr = make(chan *netFD, 1) s.cw = make(chan *netFD, 1) if s.pr, s.pw, err = os.Pipe(); err != nil { return nil, err } var e int if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 { goto Errno } if e = syscall.SetNonblock(s.pw.Fd(), true); e != 0 { goto Errno } if s.poll, err = newpollster(); err != nil { goto Error } if _, err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { s.poll.Close() goto Error } s.pending = make(map[int]*netFD) go s.Run() return s, nil Errno: err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)} Error: s.pr.Close() s.pw.Close() return nil, err }
// enable raw mode and gather metrics, like number of columns func (l *LineReader) raw() { // STD_OUTPUT_HANDLE h, errno := syscall.GetStdHandle(-11) t.h = uintptr(h) if int32(t.h) == -1 { err := os.Errno(errno) panic(err) } ok, _, e := syscall.Syscall(procGetConsoleMode, 2, t.h, uintptr(unsafe.Pointer(&t.origTerm)), 0) if ok == 0 { err := os.NewSyscallError("GetConsoleMode", int(e)) panic(err) } raw := t.origTerm raw &^= _ENABLE_LINE_INPUT | _ENABLE_ECHO_INPUT | _ENABLE_PROCESSED_INPUT | _ENABLE_WINDOW_INPUT ok, _, e = syscall.Syscall(procSetConsoleMode, 2, t.h, uintptr(raw), 0) if ok == 0 { err := os.NewSyscallError("SetConsoleMode", int(e)) panic(err) } win := t.getConsoleInfo() t.cols = int(win.dwSize.x) t.rows = int(win.dwSize.y) t.buf = new(buffer) }
func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) { // pollServer is locked. var kmode int if mode == 'r' { kmode = syscall.EVFILT_READ } else { kmode = syscall.EVFILT_WRITE } ev := &p.kbuf[0] // EV_ADD - add event to kqueue list // EV_ONESHOT - delete the event the first time it triggers flags := syscall.EV_ADD if !repeat { flags |= syscall.EV_ONESHOT } syscall.SetKevent(ev, fd, kmode, flags) n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil) if e != 0 { return false, os.NewSyscallError("kevent", e) } if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode { return false, os.NewSyscallError("kqueue phase error", e) } if ev.Data != 0 { return false, os.Errno(int(ev.Data)) } return false, nil }
func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) { r, e := syscall.Open(name, mode, perm) if e != 0 { err = os.Errno(e) } return newFile(r, name), err }
// ForkExec forks the current process and execs argv0, stopping the // new process after the exec syscall. See os.ForkExec for additional // details. func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) { p := newProcess(-1) // Create array of integer (system) fds. intfd := make([]int, len(fd)) for i, f := range fd { if f == nil { intfd[i] = -1 } else { intfd[i] = f.Fd() } } // Fork from the monitor thread so we get the right tracer pid. err := p.do(func() os.Error { pid, errno := syscall.PtraceForkExec(argv0, argv, envv, dir, intfd) if errno != 0 { return &os.PathError{"fork/exec", argv0, os.Errno(errno)} } p.pid = pid // The process will raise SIGTRAP when it reaches execve. _, err := p.newThread(pid, syscall.SIGTRAP, false) return err }) if err != nil { p.stopMonitor(err) return nil, err } return p, nil }
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error { var kmode int if mode == 'r' { kmode = syscall.EVFILT_READ } else { kmode = syscall.EVFILT_WRITE } var events [1]syscall.Kevent_t ev := &events[0] // EV_ADD - add event to kqueue list // EV_RECEIPT - generate fake EV_ERROR as result of add, // rather than waiting for real event // EV_ONESHOT - delete the event the first time it triggers flags := syscall.EV_ADD | syscall.EV_RECEIPT if !repeat { flags |= syscall.EV_ONESHOT } syscall.SetKevent(ev, fd, kmode, flags) n, e := syscall.Kevent(p.kq, &events, &events, nil) if e != 0 { return os.NewSyscallError("kevent", e) } if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode { return os.ErrorString("kqueue phase error") } if ev.Data != 0 { return os.Errno(int(ev.Data)) } return nil }
func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) { if fd == nil { return 0, nil, os.EINVAL } if len(p) == 0 { return 0, nil, nil } fd.rio.Lock() defer fd.rio.Unlock() fd.incref() defer fd.decref() if fd.sysfd == -1 { return 0, nil, os.EINVAL } // Submit receive request. var pckt ioPacket pckt.c = fd.cr pckt.w = newWSABuf(p) var done uint32 flags := uint32(0) var rsa syscall.RawSockaddrAny l := int32(unsafe.Sizeof(rsa)) var e int if fd.rdeadline_delta > 0 { a := &arg{f: readfrom, fd: fd, pckt: &pckt, done: &done, flags: &flags, rsa: &rsa, size: &l, c: make(chan int)} ioChan <- a e = <-a.c } else { e = syscall.WSARecvFrom(uint32(fd.sysfd), pckt.w, 1, &done, &flags, &rsa, &l, &pckt.o, nil) } switch e { case 0: // IO completed immediately, but we need to get our completion message anyway. case syscall.ERROR_IO_PENDING: // IO started, and we have to wait for it's completion. default: return 0, nil, &OpError{"WSARecvFrom", fd.net, fd.laddr, os.Errno(e)} } // Wait for our request to complete. r := waitPacket(fd, &pckt, 'r') if r.errno != 0 { err = &OpError{"WSARecvFrom", fd.net, fd.laddr, os.Errno(r.errno)} } n = int(r.qty) sa, _ = rsa.Sockaddr() return }
// Accept blocks until a new connection is available on our fd // returns a fileConn as a net.Conn for Listener interface func (l *fdListener) Accept() (c net.Conn, err os.Error) { if nfd, _, errno := syscall.Accept(l.fd); errno == 0 { c = fileConn{os.NewFile(nfd, "<fd:"+strconv.Itoa(l.fd)+">")} } else { err = os.Errno(errno) } return }
// Generic socket creation. func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(f, p, t) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Allow reuse of recently-used addresses. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) // Allow broadcast. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) if la != nil { e = syscall.Bind(s, la) if e != 0 { syscall.Close(s) return nil, os.Errno(e) } } if ra != nil { e = syscall.Connect(s, ra) if e != 0 { syscall.Close(s) return nil, os.Errno(e) } } sa, _ := syscall.Getsockname(s) laddr := toAddr(sa) sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd, err = newFD(s, f, p, net, laddr, raddr) if err != nil { syscall.Close(s) return nil, err } return fd, nil }