Revert r215321.
[official-gcc.git] / libgo / go / net / file_plan9.go
blob068f0881dd36dd3f7740d7f24960167a0f16df39
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.
5 package net
7 import (
8 "errors"
9 "io"
10 "os"
11 "syscall"
14 func (fd *netFD) status(ln int) (string, error) {
15 if !fd.ok() {
16 return "", syscall.EINVAL
19 status, err := os.Open(fd.dir + "/status")
20 if err != nil {
21 return "", err
23 defer status.Close()
24 buf := make([]byte, ln)
25 n, err := io.ReadFull(status, buf[:])
26 if err != nil {
27 return "", err
29 return string(buf[:n]), nil
32 func newFileFD(f *os.File) (net *netFD, err error) {
33 var ctl *os.File
34 close := func(fd int) {
35 if err != nil {
36 syscall.Close(fd)
40 path, err := syscall.Fd2path(int(f.Fd()))
41 if err != nil {
42 return nil, os.NewSyscallError("fd2path", err)
44 comp := splitAtBytes(path, "/")
45 n := len(comp)
46 if n < 3 || comp[0][0:3] != "net" {
47 return nil, syscall.EPLAN9
50 name := comp[2]
51 switch file := comp[n-1]; file {
52 case "ctl", "clone":
53 syscall.ForkLock.RLock()
54 fd, err := syscall.Dup(int(f.Fd()), -1)
55 syscall.ForkLock.RUnlock()
56 if err != nil {
57 return nil, os.NewSyscallError("dup", err)
59 defer close(fd)
61 dir := netdir + "/" + comp[n-2]
62 ctl = os.NewFile(uintptr(fd), dir+"/"+file)
63 ctl.Seek(0, 0)
64 var buf [16]byte
65 n, err := ctl.Read(buf[:])
66 if err != nil {
67 return nil, err
69 name = string(buf[:n])
70 default:
71 if len(comp) < 4 {
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)
76 if err != nil {
77 return nil, err
79 defer close(int(ctl.Fd()))
81 dir := netdir + "/" + comp[1] + "/" + name
82 laddr, err := readPlan9Addr(comp[1], dir+"/local")
83 if err != nil {
84 return nil, err
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)
91 if err != nil {
92 return nil, err
94 if !fd.ok() {
95 return nil, syscall.EINVAL
98 fd.data, err = os.OpenFile(fd.dir+"/data", os.O_RDWR, 0)
99 if err != nil {
100 return nil, err
103 switch fd.laddr.(type) {
104 case *TCPAddr:
105 return newTCPConn(fd), nil
106 case *UDPAddr:
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)
114 if err != nil {
115 return nil, err
117 switch fd.laddr.(type) {
118 case *TCPAddr:
119 default:
120 return nil, syscall.EPLAN9
123 // check that file corresponds to a listener
124 s, err := fd.status(len("Listen"))
125 if err != nil {
126 return nil, err
128 if s != "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
138 // affect c.
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
146 // affect l.
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