Source file
src/syscall/dir_plan9.go
1
2
3
4
5
6
7 package syscall
8
9 import "errors"
10
11 var (
12 ErrShortStat = errors.New("stat buffer too short")
13 ErrBadStat = errors.New("malformed stat buffer")
14 ErrBadName = errors.New("bad character in file name")
15 )
16
17
18 type Qid struct {
19 Path uint64
20 Vers uint32
21 Type uint8
22 }
23
24
25 type Dir struct {
26
27 Type uint16
28 Dev uint32
29
30
31 Qid Qid
32 Mode uint32
33 Atime uint32
34 Mtime uint32
35 Length int64
36 Name string
37 Uid string
38 Gid string
39 Muid string
40 }
41
42 var nullDir = Dir{
43 Type: ^uint16(0),
44 Dev: ^uint32(0),
45 Qid: Qid{
46 Path: ^uint64(0),
47 Vers: ^uint32(0),
48 Type: ^uint8(0),
49 },
50 Mode: ^uint32(0),
51 Atime: ^uint32(0),
52 Mtime: ^uint32(0),
53 Length: ^int64(0),
54 }
55
56
57
58 func (d *Dir) Null() { *d = nullDir }
59
60
61
62
63 func (d *Dir) Marshal(b []byte) (n int, err error) {
64 n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
65 if n > len(b) {
66 return n, ErrShortStat
67 }
68
69 for _, c := range d.Name {
70 if c == '/' {
71 return n, ErrBadName
72 }
73 }
74
75 b = pbit16(b, uint16(n)-2)
76 b = pbit16(b, d.Type)
77 b = pbit32(b, d.Dev)
78 b = pbit8(b, d.Qid.Type)
79 b = pbit32(b, d.Qid.Vers)
80 b = pbit64(b, d.Qid.Path)
81 b = pbit32(b, d.Mode)
82 b = pbit32(b, d.Atime)
83 b = pbit32(b, d.Mtime)
84 b = pbit64(b, uint64(d.Length))
85 b = pstring(b, d.Name)
86 b = pstring(b, d.Uid)
87 b = pstring(b, d.Gid)
88 b = pstring(b, d.Muid)
89
90 return n, nil
91 }
92
93
94
95
96
97
98 func UnmarshalDir(b []byte) (*Dir, error) {
99 if len(b) < STATFIXLEN {
100 return nil, ErrShortStat
101 }
102 size, buf := gbit16(b)
103 if len(b) != int(size)+2 {
104 return nil, ErrBadStat
105 }
106 b = buf
107
108 var d Dir
109 d.Type, b = gbit16(b)
110 d.Dev, b = gbit32(b)
111 d.Qid.Type, b = gbit8(b)
112 d.Qid.Vers, b = gbit32(b)
113 d.Qid.Path, b = gbit64(b)
114 d.Mode, b = gbit32(b)
115 d.Atime, b = gbit32(b)
116 d.Mtime, b = gbit32(b)
117
118 n, b := gbit64(b)
119 d.Length = int64(n)
120
121 var ok bool
122 if d.Name, b, ok = gstring(b); !ok {
123 return nil, ErrBadStat
124 }
125 if d.Uid, b, ok = gstring(b); !ok {
126 return nil, ErrBadStat
127 }
128 if d.Gid, b, ok = gstring(b); !ok {
129 return nil, ErrBadStat
130 }
131 if d.Muid, b, ok = gstring(b); !ok {
132 return nil, ErrBadStat
133 }
134
135 return &d, nil
136 }
137
138
139 func pbit8(b []byte, v uint8) []byte {
140 b[0] = byte(v)
141 return b[1:]
142 }
143
144
145 func pbit16(b []byte, v uint16) []byte {
146 b[0] = byte(v)
147 b[1] = byte(v >> 8)
148 return b[2:]
149 }
150
151
152 func pbit32(b []byte, v uint32) []byte {
153 b[0] = byte(v)
154 b[1] = byte(v >> 8)
155 b[2] = byte(v >> 16)
156 b[3] = byte(v >> 24)
157 return b[4:]
158 }
159
160
161 func pbit64(b []byte, v uint64) []byte {
162 b[0] = byte(v)
163 b[1] = byte(v >> 8)
164 b[2] = byte(v >> 16)
165 b[3] = byte(v >> 24)
166 b[4] = byte(v >> 32)
167 b[5] = byte(v >> 40)
168 b[6] = byte(v >> 48)
169 b[7] = byte(v >> 56)
170 return b[8:]
171 }
172
173
174
175 func pstring(b []byte, s string) []byte {
176 b = pbit16(b, uint16(len(s)))
177 n := copy(b, s)
178 return b[n:]
179 }
180
181
182 func gbit8(b []byte) (uint8, []byte) {
183 return uint8(b[0]), b[1:]
184 }
185
186
187
188 func gbit16(b []byte) (uint16, []byte) {
189 return uint16(b[0]) | uint16(b[1])<<8, b[2:]
190 }
191
192
193 func gbit32(b []byte) (uint32, []byte) {
194 return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
195 }
196
197
198 func gbit64(b []byte) (uint64, []byte) {
199 lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
200 hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
201 return uint64(lo) | uint64(hi)<<32, b[8:]
202 }
203
204
205
206
207 func gstring(b []byte) (string, []byte, bool) {
208 n, b := gbit16(b)
209 if int(n) > len(b) {
210 return "", b, false
211 }
212 return string(b[:n]), b[n:], true
213 }
214
View as plain text