podman

Форк
0
212 строк · 5.6 Кб
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
}
213

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.