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