Revert r215321.
[official-gcc.git] / libgo / go / net / fd_plan9.go
blob5fe8effc2954dc3ebd7ebe965dd253f36aaf9c85
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 "io"
9 "os"
10 "syscall"
11 "time"
14 // Network file descritor.
15 type netFD struct {
16 // locking/lifetime of sysfd + serialize access to Read and Write methods
17 fdmu fdMutex
19 // immutable until Close
20 proto string
21 n string
22 dir string
23 ctl, data *os.File
24 laddr, raddr Addr
27 var (
28 netdir string // default network
31 func sysInit() {
32 netdir = "/net"
35 func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
36 // On plan9, use the relatively inefficient
37 // goroutine-racing implementation.
38 return dialChannel(net, ra, dialer, deadline)
41 func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
42 return &netFD{proto: proto, n: name, dir: netdir + "/" + proto + "/" + name, ctl: ctl, data: data, laddr: laddr, raddr: raddr}, nil
45 func (fd *netFD) init() error {
46 // stub for future fd.pd.Init(fd)
47 return nil
50 func (fd *netFD) name() string {
51 var ls, rs string
52 if fd.laddr != nil {
53 ls = fd.laddr.String()
55 if fd.raddr != nil {
56 rs = fd.raddr.String()
58 return fd.proto + ":" + ls + "->" + rs
61 func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }
63 func (fd *netFD) destroy() {
64 if !fd.ok() {
65 return
67 err := fd.ctl.Close()
68 if fd.data != nil {
69 if err1 := fd.data.Close(); err1 != nil && err == nil {
70 err = err1
73 fd.ctl = nil
74 fd.data = nil
77 // Add a reference to this fd.
78 // Returns an error if the fd cannot be used.
79 func (fd *netFD) incref() error {
80 if !fd.fdmu.Incref() {
81 return errClosing
83 return nil
86 // Remove a reference to this FD and close if we've been asked to do so
87 // (and there are no references left).
88 func (fd *netFD) decref() {
89 if fd.fdmu.Decref() {
90 fd.destroy()
94 // Add a reference to this fd and lock for reading.
95 // Returns an error if the fd cannot be used.
96 func (fd *netFD) readLock() error {
97 if !fd.fdmu.RWLock(true) {
98 return errClosing
100 return nil
103 // Unlock for reading and remove a reference to this FD.
104 func (fd *netFD) readUnlock() {
105 if fd.fdmu.RWUnlock(true) {
106 fd.destroy()
110 // Add a reference to this fd and lock for writing.
111 // Returns an error if the fd cannot be used.
112 func (fd *netFD) writeLock() error {
113 if !fd.fdmu.RWLock(false) {
114 return errClosing
116 return nil
119 // Unlock for writing and remove a reference to this FD.
120 func (fd *netFD) writeUnlock() {
121 if fd.fdmu.RWUnlock(false) {
122 fd.destroy()
126 func (fd *netFD) Read(b []byte) (n int, err error) {
127 if !fd.ok() || fd.data == nil {
128 return 0, syscall.EINVAL
130 if err := fd.readLock(); err != nil {
131 return 0, err
133 defer fd.readUnlock()
134 n, err = fd.data.Read(b)
135 if fd.proto == "udp" && err == io.EOF {
136 n = 0
137 err = nil
139 return
142 func (fd *netFD) Write(b []byte) (n int, err error) {
143 if !fd.ok() || fd.data == nil {
144 return 0, syscall.EINVAL
146 if err := fd.writeLock(); err != nil {
147 return 0, err
149 defer fd.writeUnlock()
150 return fd.data.Write(b)
153 func (fd *netFD) closeRead() error {
154 if !fd.ok() {
155 return syscall.EINVAL
157 return syscall.EPLAN9
160 func (fd *netFD) closeWrite() error {
161 if !fd.ok() {
162 return syscall.EINVAL
164 return syscall.EPLAN9
167 func (fd *netFD) Close() error {
168 if !fd.fdmu.IncrefAndClose() {
169 return errClosing
171 if !fd.ok() {
172 return syscall.EINVAL
174 err := fd.ctl.Close()
175 if fd.data != nil {
176 if err1 := fd.data.Close(); err1 != nil && err == nil {
177 err = err1
180 fd.ctl = nil
181 fd.data = nil
182 return err
185 // This method is only called via Conn.
186 func (fd *netFD) dup() (*os.File, error) {
187 if !fd.ok() || fd.data == nil {
188 return nil, syscall.EINVAL
190 return fd.file(fd.data, fd.dir+"/data")
193 func (l *TCPListener) dup() (*os.File, error) {
194 if !l.fd.ok() {
195 return nil, syscall.EINVAL
197 return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
200 func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
201 syscall.ForkLock.RLock()
202 dfd, err := syscall.Dup(int(f.Fd()), -1)
203 syscall.ForkLock.RUnlock()
204 if err != nil {
205 return nil, &OpError{"dup", s, fd.laddr, err}
207 return os.NewFile(uintptr(dfd), s), nil
210 func (fd *netFD) setDeadline(t time.Time) error {
211 return syscall.EPLAN9
214 func (fd *netFD) setReadDeadline(t time.Time) error {
215 return syscall.EPLAN9
218 func (fd *netFD) setWriteDeadline(t time.Time) error {
219 return syscall.EPLAN9
222 func setReadBuffer(fd *netFD, bytes int) error {
223 return syscall.EPLAN9
226 func setWriteBuffer(fd *netFD, bytes int) error {
227 return syscall.EPLAN9
230 func skipRawSocketTests() (skip bool, skipmsg string, err error) {
231 return true, "skipping test on plan9", nil