Source file
src/net/file_plan9.go
1
2
3
4
5 package net
6
7 import (
8 "errors"
9 "io"
10 "os"
11 "syscall"
12 )
13
14 func (fd *netFD) status(ln int) (string, error) {
15 if !fd.ok() {
16 return "", syscall.EINVAL
17 }
18
19 status, err := os.Open(fd.dir + "/status")
20 if err != nil {
21 return "", err
22 }
23 defer status.Close()
24 buf := make([]byte, ln)
25 n, err := io.ReadFull(status, buf[:])
26 if err != nil {
27 return "", err
28 }
29 return string(buf[:n]), nil
30 }
31
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)
37 }
38 }
39
40 path, err := syscall.Fd2path(int(f.Fd()))
41 if err != nil {
42 return nil, os.NewSyscallError("fd2path", err)
43 }
44 comp := splitAtBytes(path, "/")
45 n := len(comp)
46 if n < 3 || comp[0][0:3] != "net" {
47 return nil, syscall.EPLAN9
48 }
49
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)
56 }
57 defer close(fd)
58
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
66 }
67 name = string(buf[:n])
68 default:
69 if len(comp) < 4 {
70 return nil, errors.New("could not find control file for connection")
71 }
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
76 }
77 defer close(int(ctl.Fd()))
78 }
79 dir := netdir + "/" + comp[1] + "/" + name
80 laddr, err := readPlan9Addr(comp[1], dir+"/local")
81 if err != nil {
82 return nil, err
83 }
84 return newFD(comp[1], name, nil, ctl, nil, laddr, nil)
85 }
86
87 func fileConn(f *os.File) (Conn, error) {
88 fd, err := newFileFD(f)
89 if err != nil {
90 return nil, err
91 }
92 if !fd.ok() {
93 return nil, syscall.EINVAL
94 }
95
96 fd.data, err = os.OpenFile(fd.dir+"/data", os.O_RDWR, 0)
97 if err != nil {
98 return nil, err
99 }
100
101 switch fd.laddr.(type) {
102 case *TCPAddr:
103 return newTCPConn(fd), nil
104 case *UDPAddr:
105 return newUDPConn(fd), nil
106 }
107 return nil, syscall.EPLAN9
108 }
109
110 func fileListener(f *os.File) (Listener, error) {
111 fd, err := newFileFD(f)
112 if err != nil {
113 return nil, err
114 }
115 switch fd.laddr.(type) {
116 case *TCPAddr:
117 default:
118 return nil, syscall.EPLAN9
119 }
120
121
122 s, err := fd.status(len("Listen"))
123 if err != nil {
124 return nil, err
125 }
126 if s != "Listen" {
127 return nil, errors.New("file does not represent a listener")
128 }
129
130 return &TCPListener{fd: fd}, nil
131 }
132
133 func filePacketConn(f *os.File) (PacketConn, error) {
134 return nil, syscall.EPLAN9
135 }
136
View as plain text