2018-23-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / net / fd_plan9.go
blob46ee5d97400f91a7894c171e621f1345127f0ca8
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.
5 package net
7 import (
8 "internal/poll"
9 "io"
10 "os"
11 "syscall"
14 // Network file descriptor.
15 type netFD struct {
16 pfd poll.FD
18 // immutable until Close
19 net string
20 n string
21 dir string
22 listen, ctl, data *os.File
23 laddr, raddr Addr
24 isStream bool
27 var netdir = "/net" // default network
29 func newFD(net, name string, listen, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
30 ret := &netFD{
31 net: net,
32 n: name,
33 dir: netdir + "/" + net + "/" + name,
34 listen: listen,
35 ctl: ctl, data: data,
36 laddr: laddr,
37 raddr: raddr,
39 ret.pfd.Destroy = ret.destroy
40 return ret, nil
43 func (fd *netFD) init() error {
44 // stub for future fd.pd.Init(fd)
45 return nil
48 func (fd *netFD) name() string {
49 var ls, rs string
50 if fd.laddr != nil {
51 ls = fd.laddr.String()
53 if fd.raddr != nil {
54 rs = fd.raddr.String()
56 return fd.net + ":" + ls + "->" + rs
59 func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }
61 func (fd *netFD) destroy() {
62 if !fd.ok() {
63 return
65 err := fd.ctl.Close()
66 if fd.data != nil {
67 if err1 := fd.data.Close(); err1 != nil && err == nil {
68 err = err1
71 if fd.listen != nil {
72 if err1 := fd.listen.Close(); err1 != nil && err == nil {
73 err = err1
76 fd.ctl = nil
77 fd.data = nil
78 fd.listen = nil
81 func (fd *netFD) Read(b []byte) (n int, err error) {
82 if !fd.ok() || fd.data == nil {
83 return 0, syscall.EINVAL
85 n, err = fd.pfd.Read(fd.data.Read, b)
86 if fd.net == "udp" && err == io.EOF {
87 n = 0
88 err = nil
90 return
93 func (fd *netFD) Write(b []byte) (n int, err error) {
94 if !fd.ok() || fd.data == nil {
95 return 0, syscall.EINVAL
97 return fd.pfd.Write(fd.data.Write, b)
100 func (fd *netFD) closeRead() error {
101 if !fd.ok() {
102 return syscall.EINVAL
104 return syscall.EPLAN9
107 func (fd *netFD) closeWrite() error {
108 if !fd.ok() {
109 return syscall.EINVAL
111 return syscall.EPLAN9
114 func (fd *netFD) Close() error {
115 if err := fd.pfd.Close(); err != nil {
116 return err
118 if !fd.ok() {
119 return syscall.EINVAL
121 if fd.net == "tcp" {
122 // The following line is required to unblock Reads.
123 _, err := fd.ctl.WriteString("close")
124 if err != nil {
125 return err
128 err := fd.ctl.Close()
129 if fd.data != nil {
130 if err1 := fd.data.Close(); err1 != nil && err == nil {
131 err = err1
134 if fd.listen != nil {
135 if err1 := fd.listen.Close(); err1 != nil && err == nil {
136 err = err1
139 fd.ctl = nil
140 fd.data = nil
141 fd.listen = nil
142 return err
145 // This method is only called via Conn.
146 func (fd *netFD) dup() (*os.File, error) {
147 if !fd.ok() || fd.data == nil {
148 return nil, syscall.EINVAL
150 return fd.file(fd.data, fd.dir+"/data")
153 func (l *TCPListener) dup() (*os.File, error) {
154 if !l.fd.ok() {
155 return nil, syscall.EINVAL
157 return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
160 func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
161 dfd, err := syscall.Dup(int(f.Fd()), -1)
162 if err != nil {
163 return nil, os.NewSyscallError("dup", err)
165 return os.NewFile(uintptr(dfd), s), nil
168 func setReadBuffer(fd *netFD, bytes int) error {
169 return syscall.EPLAN9
172 func setWriteBuffer(fd *netFD, bytes int) error {
173 return syscall.EPLAN9