-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstat.go
138 lines (131 loc) · 3.09 KB
/
stat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package ninep
import (
"errors"
"io"
)
// TODO: Rename Stat to 'Dir', to be in sync with Plan9 structs.
// Stat represents a directory entry in 9p.
type Stat struct {
Type uint16 // for kernel use
Dev uint32 // for kernel use
// The type of the file (directory etc.) represented as a bit
// vector corresponding to the high 8 bits of the file's mode
// word.
QID QID
Mode uint32 // permissions and flags
Atime uint32 // last access time
Mtime uint32 // last modification time
Length uint64 // length of file in bytes
Name string // file name; must be / if the file is the root
UID string // owner's name
GID string // group's name
MUID string // name of the user who last modified the file
}
func readStat(r io.Reader, s *Stat) error {
var size uint16
if err := readUint16(r, &size); err != nil {
return err
}
lr := &io.LimitedReader{R: r, N: int64(size)}
if err := readUint16(lr, &s.Type); err != nil {
return err
}
if err := readUint32(lr, &s.Dev); err != nil {
return err
}
if err := readUint8(lr, &s.QID.Kind); err != nil {
return err
}
if err := readUint32(lr, &s.QID.Vers); err != nil {
return err
}
if err := readUint64(lr, &s.QID.Path); err != nil {
return err
}
if err := readUint32(lr, &s.Mode); err != nil {
return err
}
if err := readUint32(lr, &s.Atime); err != nil {
return err
}
if err := readUint32(lr, &s.Mtime); err != nil {
return err
}
if err := readUint64(lr, &s.Length); err != nil {
return err
}
if err := readString(lr, &s.Name); err != nil {
return err
}
if err := readString(lr, &s.UID); err != nil {
return err
}
if err := readString(lr, &s.GID); err != nil {
return err
}
if err := readString(lr, &s.MUID); err != nil {
return err
}
if lr.N > 0 {
return errors.New("stat is shorter than allocated size")
}
return nil
}
func stringSize(s string) uint16 {
return uint16(2 + len(s))
}
// Size of the given stat struct serialized,
// not including the 2-byte size field.
func statSize(s Stat) (size uint16) {
size += 39 // fixed part
size += stringSize(s.Name)
size += stringSize(s.UID)
size += stringSize(s.GID)
size += stringSize(s.MUID)
return size
}
func writeStat(w io.Writer, s Stat) error {
if err := writeUint16(w, statSize(s)); err != nil {
return err
}
if err := writeUint16(w, s.Type); err != nil {
return err
}
if err := writeUint32(w, s.Dev); err != nil {
return err
}
if err := writeUint8(w, s.QID.Kind); err != nil {
return err
}
if err := writeUint32(w, s.QID.Vers); err != nil {
return err
}
if err := writeUint64(w, s.QID.Path); err != nil {
return err
}
if err := writeUint32(w, s.Mode); err != nil {
return err
}
if err := writeUint32(w, s.Atime); err != nil {
return err
}
if err := writeUint32(w, s.Mtime); err != nil {
return err
}
if err := writeUint64(w, s.Length); err != nil {
return err
}
if err := writeString(w, s.Name); err != nil {
return err
}
if err := writeString(w, s.UID); err != nil {
return err
}
if err := writeString(w, s.GID); err != nil {
return err
}
if err := writeString(w, s.MUID); err != nil {
return err
}
return nil
}