Source file
src/syscall/dir_plan9.go
Documentation: syscall
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
189 func gbit16(b []byte) (uint16, []byte) {
190 return uint16(b[0]) | uint16(b[1])<<8, b[2:]
191 }
192
193
194 func gbit32(b []byte) (uint32, []byte) {
195 return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
196 }
197
198
199 func gbit64(b []byte) (uint64, []byte) {
200 lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
201 hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
202 return uint64(lo) | uint64(hi)<<32, b[8:]
203 }
204
205
206
207
208 func gstring(b []byte) (string, []byte, bool) {
209 n, b := gbit16(b)
210 if int(n) > len(b) {
211 return "", b, false
212 }
213 return string(b[:n]), b[n:], true
214 }
215
View as plain text