1 // Copyright 2011 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.
14 func (fd
*netFD
) status(ln
int) (string, error
) {
16 return "", syscall
.EINVAL
19 status
, err
:= os
.Open(fd
.dir
+ "/status")
24 buf
:= make([]byte, ln
)
25 n
, err
:= io
.ReadFull(status
, buf
[:])
29 return string(buf
[:n
]), nil
32 func newFileFD(f
*os
.File
) (net
*netFD
, err error
) {
34 close := func(fd
int) {
40 path
, err
:= syscall
.Fd2path(int(f
.Fd()))
42 return nil, os
.NewSyscallError("fd2path", err
)
44 comp
:= splitAtBytes(path
, "/")
46 if n
< 3 || comp
[0][0:3] != "net" {
47 return nil, syscall
.EPLAN9
51 switch file
:= comp
[n
-1]; file
{
53 syscall
.ForkLock
.RLock()
54 fd
, err
:= syscall
.Dup(int(f
.Fd()), -1)
55 syscall
.ForkLock
.RUnlock()
57 return nil, os
.NewSyscallError("dup", err
)
61 dir
:= netdir
+ "/" + comp
[n
-2]
62 ctl
= os
.NewFile(uintptr(fd
), dir
+"/"+file
)
65 n
, err
:= ctl
.Read(buf
[:])
69 name
= string(buf
[:n
])
72 return nil, errors
.New("could not find control file for connection")
74 dir
:= netdir
+ "/" + comp
[1] + "/" + name
75 ctl
, err
= os
.OpenFile(dir
+"/ctl", os
.O_RDWR
, 0)
79 defer close(int(ctl
.Fd()))
81 dir
:= netdir
+ "/" + comp
[1] + "/" + name
82 laddr
, err
:= readPlan9Addr(comp
[1], dir
+"/local")
86 return newFD(comp
[1], name
, ctl
, nil, laddr
, nil)
89 func newFileConn(f
*os
.File
) (c Conn
, err error
) {
90 fd
, err
:= newFileFD(f
)
95 return nil, syscall
.EINVAL
98 fd
.data
, err
= os
.OpenFile(fd
.dir
+"/data", os
.O_RDWR
, 0)
103 switch fd
.laddr
.(type) {
105 return newTCPConn(fd
), nil
107 return newUDPConn(fd
), nil
109 return nil, syscall
.EPLAN9
112 func newFileListener(f
*os
.File
) (l Listener
, err error
) {
113 fd
, err
:= newFileFD(f
)
117 switch fd
.laddr
.(type) {
120 return nil, syscall
.EPLAN9
123 // check that file corresponds to a listener
124 s
, err
:= fd
.status(len("Listen"))
129 return nil, errors
.New("file does not represent a listener")
132 return &TCPListener
{fd
}, nil
135 // FileConn returns a copy of the network connection corresponding to
136 // the open file f. It is the caller's responsibility to close f when
137 // finished. Closing c does not affect f, and closing f does not
139 func FileConn(f
*os
.File
) (c Conn
, err error
) {
140 return newFileConn(f
)
143 // FileListener returns a copy of the network listener corresponding
144 // to the open file f. It is the caller's responsibility to close l
145 // when finished. Closing l does not affect f, and closing f does not
147 func FileListener(f
*os
.File
) (l Listener
, err error
) {
148 return newFileListener(f
)
151 // FilePacketConn returns a copy of the packet network connection
152 // corresponding to the open file f. It is the caller's
153 // responsibility to close f when finished. Closing c does not affect
154 // f, and closing f does not affect c.
155 func FilePacketConn(f
*os
.File
) (c PacketConn
, err error
) {
156 return nil, syscall
.EPLAN9