OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / sys / plan9 / dir_plan9.go
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.
4
5 // Plan 9 directory marshalling. See intro(5).
6
7 package plan9
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 // A Qid represents a 9P server's unique identification for a file.
18 type Qid struct {
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 (plan9.QTDIR for example)
22 }
23
24 // A Dir contains the metadata for a file.
25 type Dir struct {
26         // system-modified data
27         Type uint16 // server type
28         Dev  uint32 // server subtype
29
30         // file data
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
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 // Null assigns special "don't touch" values to members of d to
57 // avoid modifying them during plan9.Wstat.
58 func (d *Dir) Null() { *d = nullDir }
59
60 // Marshal encodes a 9P stat message corresponding to d into b
61 //
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)
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 // UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
94 //
95 // If b is too small to hold a valid stat message, ErrShortStat is returned.
96 //
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
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 // pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
139 func pbit8(b []byte, v uint8) []byte {
140         b[0] = byte(v)
141         return b[1:]
142 }
143
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 {
146         b[0] = byte(v)
147         b[1] = byte(v >> 8)
148         return b[2:]
149 }
150
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 {
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 // 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 {
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 // 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)))
177         n := copy(b, s)
178         return b[n:]
179 }
180
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:]
184 }
185
186 // gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
187 func gbit16(b []byte) (uint16, []byte) {
188         return uint16(b[0]) | uint16(b[1])<<8, b[2:]
189 }
190
191 // gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
192 func gbit32(b []byte) (uint32, []byte) {
193         return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
194 }
195
196 // gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
197 func gbit64(b []byte) (uint64, []byte) {
198         lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
199         hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
200         return uint64(lo) | uint64(hi)<<32, b[8:]
201 }
202
203 // gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
204 // It returns the string with the remaining slice of b and a boolean. If the length is
205 // greater than the number of bytes in b, the boolean will be false.
206 func gstring(b []byte) (string, []byte, bool) {
207         n, b := gbit16(b)
208         if int(n) > len(b) {
209                 return "", b, false
210         }
211         return string(b[:n]), b[n:], true
212 }