2017-10-04 Petr Ovtchenkov <ptr@void-ptr.info>
[official-gcc.git] / libgo / go / net / file_plan9.go
blobd16e5a166c356635f2fa2e084d30dbcb44339e57
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 fd, err := syscall.Dup(int(f.Fd()), -1)
54 if err != nil {
55 return nil, os.NewSyscallError("dup", err)
57 defer close(fd)
59 dir := netdir + "/" + comp[n-2]
60 ctl = os.NewFile(uintptr(fd), dir+"/"+file)
61 ctl.Seek(0, io.SeekStart)
62 var buf [16]byte
63 n, err := ctl.Read(buf[:])
64 if err != nil {
65 return nil, err
67 name = string(buf[:n])
68 default:
69 if len(comp) < 4 {
70 return nil, errors.New("could not find control file for connection")
72 dir := netdir + "/" + comp[1] + "/" + name
73 ctl, err = os.OpenFile(dir+"/ctl", os.O_RDWR, 0)
74 if err != nil {
75 return nil, err
77 defer close(int(ctl.Fd()))
79 dir := netdir + "/" + comp[1] + "/" + name
80 laddr, err := readPlan9Addr(comp[1], dir+"/local")
81 if err != nil {
82 return nil, err
84 return newFD(comp[1], name, nil, ctl, nil, laddr, nil)
87 func fileConn(f *os.File) (Conn, error) {
88 fd, err := newFileFD(f)
89 if err != nil {
90 return nil, err
92 if !fd.ok() {
93 return nil, syscall.EINVAL
96 fd.data, err = os.OpenFile(fd.dir+"/data", os.O_RDWR, 0)
97 if err != nil {
98 return nil, err
101 switch fd.laddr.(type) {
102 case *TCPAddr:
103 return newTCPConn(fd), nil
104 case *UDPAddr:
105 return newUDPConn(fd), nil
107 return nil, syscall.EPLAN9
110 func fileListener(f *os.File) (Listener, error) {
111 fd, err := newFileFD(f)
112 if err != nil {
113 return nil, err
115 switch fd.laddr.(type) {
116 case *TCPAddr:
117 default:
118 return nil, syscall.EPLAN9
121 // check that file corresponds to a listener
122 s, err := fd.status(len("Listen"))
123 if err != nil {
124 return nil, err
126 if s != "Listen" {
127 return nil, errors.New("file does not represent a listener")
130 return &TCPListener{fd}, nil
133 func filePacketConn(f *os.File) (PacketConn, error) {
134 return nil, syscall.EPLAN9