Source file
src/runtime/env_plan9.go
1
2
3
4
5 package runtime
6
7 import "unsafe"
8
9 const (
10
11 envDir = "/env/"
12
13 dirBufSize = 4096
14
15 envBufSize = 128
16
17 nameOffset = 39
18 )
19
20
21
22
23
24
25
26
27
28
29
30 func goenvs() {
31 buf := make([]byte, envBufSize)
32 copy(buf, envDir)
33 dirfd := open(&buf[0], _OREAD, 0)
34 if dirfd < 0 {
35 return
36 }
37 defer closefd(dirfd)
38 dofiles(dirfd, func(name []byte) {
39 name = append(name, 0)
40 buf = buf[:len(envDir)]
41 copy(buf, envDir)
42 buf = append(buf, name...)
43 fd := open(&buf[0], _OREAD, 0)
44 if fd < 0 {
45 return
46 }
47 defer closefd(fd)
48 n := len(buf)
49 r := 0
50 for {
51 r = int(pread(fd, unsafe.Pointer(&buf[0]), int32(n), 0))
52 if r < n {
53 break
54 }
55 n = int(seek(fd, 0, 2)) + 1
56 if len(buf) < n {
57 buf = make([]byte, n)
58 }
59 }
60 if r <= 0 {
61 r = 0
62 } else if buf[r-1] == 0 {
63 r--
64 }
65 name[len(name)-1] = '='
66 env := make([]byte, len(name)+r)
67 copy(env, name)
68 copy(env[len(name):], buf[:r])
69 envs = append(envs, string(env))
70 })
71 }
72
73
74
75
76
77 func dofiles(dirfd int32, f func([]byte)) {
78 dirbuf := new([dirBufSize]byte)
79
80 var off int64 = 0
81 for {
82 n := pread(dirfd, unsafe.Pointer(&dirbuf[0]), int32(dirBufSize), off)
83 if n <= 0 {
84 return
85 }
86 for b := dirbuf[:n]; len(b) > 0; {
87 var name []byte
88 name, b = gdirname(b)
89 if name == nil {
90 return
91 }
92 f(name)
93 }
94 off += int64(n)
95 }
96 }
97
98
99
100
101
102
103 func gdirname(buf []byte) (name []byte, rest []byte) {
104 if 2+nameOffset+2 > len(buf) {
105 return
106 }
107 entryLen, buf := gbit16(buf)
108 if entryLen > len(buf) {
109 return
110 }
111 n, b := gbit16(buf[nameOffset:])
112 if n > len(b) {
113 return
114 }
115 name = b[:n]
116 rest = buf[entryLen:]
117 return
118 }
119
120
121
122
123
124 func gbit16(b []byte) (int, []byte) {
125 return int(b[0]) | int(b[1])<<8, b[2:]
126 }
127
View as plain text