1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Plan 9 directory marshaling. See intro(5).
12 ErrShortStat
= errors
.New("stat buffer too short")
13 ErrBadStat
= errors
.New("malformed stat buffer")
14 ErrBadName
= errors
.New("bad character in file name")
17 // A Qid represents a 9P server's unique identification for a file.
19 Path
uint64 // the file server's unique identification for the file
20 Vers
uint32 // version number for given Path
21 Type
uint8 // the type of the file (syscall.QTDIR for example)
24 // A Dir contains the metadata for a file.
26 // system-modified data
27 Type
uint16 // server type
28 Dev
uint32 // server subtype
31 Qid Qid
// unique id from server
32 Mode
uint32 // permissions
33 Atime
uint32 // last read time
34 Mtime
uint32 // last write time
35 Length
int64 // file length
36 Name
string // last element of path
37 Uid
string // owner name
38 Gid
string // group name
39 Muid
string // last modifier name
56 // Null assigns special "don't touch" values to members of d to
57 // avoid modifying them during syscall.Wstat.
58 func (d
*Dir
) Null() { *d
= nullDir
}
60 // Marshal encodes a 9P stat message corresponding to d into b
62 // If there isn't enough space in b for a stat message, ErrShortStat is returned.
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
)
66 return n
, ErrShortStat
69 for _
, c
:= range d
.Name
{
75 b
= pbit16(b
, uint16(n
)-2)
78 b
= pbit8(b
, d
.Qid
.Type
)
79 b
= pbit32(b
, d
.Qid
.Vers
)
80 b
= pbit64(b
, d
.Qid
.Path
)
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
)
88 b
= pstring(b
, d
.Muid
)
93 // UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
95 // If b is too small to hold a valid stat message, ErrShortStat is returned.
97 // If the stat message itself is invalid, ErrBadStat is returned.
98 func UnmarshalDir(b
[]byte) (*Dir
, error
) {
99 if len(b
) < STATFIXLEN
{
100 return nil, ErrShortStat
102 size
, buf
:= gbit16(b
)
103 if len(b
) != int(size
)+2 {
104 return nil, ErrBadStat
109 d
.Type
, b
= gbit16(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
)
122 if d
.Name
, b
, ok
= gstring(b
); !ok
{
123 return nil, ErrBadStat
125 if d
.Uid
, b
, ok
= gstring(b
); !ok
{
126 return nil, ErrBadStat
128 if d
.Gid
, b
, ok
= gstring(b
); !ok
{
129 return nil, ErrBadStat
131 if d
.Muid
, b
, ok
= gstring(b
); !ok
{
132 return nil, ErrBadStat
138 // pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
139 func pbit8(b
[]byte, v
uint8) []byte {
144 // pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
145 func pbit16(b
[]byte, v
uint16) []byte {
151 // pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
152 func pbit32(b
[]byte, v
uint32) []byte {
160 // pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
161 func pbit64(b
[]byte, v
uint64) []byte {
173 // pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
174 // returning the remaining slice of b..
175 func pstring(b
[]byte, s
string) []byte {
176 b
= pbit16(b
, uint16(len(s
)))
181 // gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
182 func gbit8(b
[]byte) (uint8, []byte) {
183 return uint8(b
[0]), b
[1:]
186 // gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
188 func gbit16(b
[]byte) (uint16, []byte) {
189 return uint16(b
[0]) |
uint16(b
[1])<<8, b
[2:]
192 // gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
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:]
197 // gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
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:]
204 // gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
205 // It returns the string with the remaining slice of b and a boolean. If the length is
206 // greater than the number of bytes in b, the boolean will be false.
207 func gstring(b
[]byte) (string, []byte, bool) {
212 return string(b
[:n
]), b
[n
:], true