You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.6 KiB

  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. // Plan 9 directory marshalling. See intro(5).
  5. package plan9
  6. import "errors"
  7. var (
  8. ErrShortStat = errors.New("stat buffer too short")
  9. ErrBadStat = errors.New("malformed stat buffer")
  10. ErrBadName = errors.New("bad character in file name")
  11. )
  12. // A Qid represents a 9P server's unique identification for a file.
  13. type Qid struct {
  14. Path uint64 // the file server's unique identification for the file
  15. Vers uint32 // version number for given Path
  16. Type uint8 // the type of the file (plan9.QTDIR for example)
  17. }
  18. // A Dir contains the metadata for a file.
  19. type Dir struct {
  20. // system-modified data
  21. Type uint16 // server type
  22. Dev uint32 // server subtype
  23. // file data
  24. Qid Qid // unique id from server
  25. Mode uint32 // permissions
  26. Atime uint32 // last read time
  27. Mtime uint32 // last write time
  28. Length int64 // file length
  29. Name string // last element of path
  30. Uid string // owner name
  31. Gid string // group name
  32. Muid string // last modifier name
  33. }
  34. var nullDir = Dir{
  35. Type: ^uint16(0),
  36. Dev: ^uint32(0),
  37. Qid: Qid{
  38. Path: ^uint64(0),
  39. Vers: ^uint32(0),
  40. Type: ^uint8(0),
  41. },
  42. Mode: ^uint32(0),
  43. Atime: ^uint32(0),
  44. Mtime: ^uint32(0),
  45. Length: ^int64(0),
  46. }
  47. // Null assigns special "don't touch" values to members of d to
  48. // avoid modifying them during plan9.Wstat.
  49. func (d *Dir) Null() { *d = nullDir }
  50. // Marshal encodes a 9P stat message corresponding to d into b
  51. //
  52. // If there isn't enough space in b for a stat message, ErrShortStat is returned.
  53. func (d *Dir) Marshal(b []byte) (n int, err error) {
  54. n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
  55. if n > len(b) {
  56. return n, ErrShortStat
  57. }
  58. for _, c := range d.Name {
  59. if c == '/' {
  60. return n, ErrBadName
  61. }
  62. }
  63. b = pbit16(b, uint16(n)-2)
  64. b = pbit16(b, d.Type)
  65. b = pbit32(b, d.Dev)
  66. b = pbit8(b, d.Qid.Type)
  67. b = pbit32(b, d.Qid.Vers)
  68. b = pbit64(b, d.Qid.Path)
  69. b = pbit32(b, d.Mode)
  70. b = pbit32(b, d.Atime)
  71. b = pbit32(b, d.Mtime)
  72. b = pbit64(b, uint64(d.Length))
  73. b = pstring(b, d.Name)
  74. b = pstring(b, d.Uid)
  75. b = pstring(b, d.Gid)
  76. b = pstring(b, d.Muid)
  77. return n, nil
  78. }
  79. // UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
  80. //
  81. // If b is too small to hold a valid stat message, ErrShortStat is returned.
  82. //
  83. // If the stat message itself is invalid, ErrBadStat is returned.
  84. func UnmarshalDir(b []byte) (*Dir, error) {
  85. if len(b) < STATFIXLEN {
  86. return nil, ErrShortStat
  87. }
  88. size, buf := gbit16(b)
  89. if len(b) != int(size)+2 {
  90. return nil, ErrBadStat
  91. }
  92. b = buf
  93. var d Dir
  94. d.Type, b = gbit16(b)
  95. d.Dev, b = gbit32(b)
  96. d.Qid.Type, b = gbit8(b)
  97. d.Qid.Vers, b = gbit32(b)
  98. d.Qid.Path, b = gbit64(b)
  99. d.Mode, b = gbit32(b)
  100. d.Atime, b = gbit32(b)
  101. d.Mtime, b = gbit32(b)
  102. n, b := gbit64(b)
  103. d.Length = int64(n)
  104. var ok bool
  105. if d.Name, b, ok = gstring(b); !ok {
  106. return nil, ErrBadStat
  107. }
  108. if d.Uid, b, ok = gstring(b); !ok {
  109. return nil, ErrBadStat
  110. }
  111. if d.Gid, b, ok = gstring(b); !ok {
  112. return nil, ErrBadStat
  113. }
  114. if d.Muid, b, ok = gstring(b); !ok {
  115. return nil, ErrBadStat
  116. }
  117. return &d, nil
  118. }
  119. // pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
  120. func pbit8(b []byte, v uint8) []byte {
  121. b[0] = byte(v)
  122. return b[1:]
  123. }
  124. // pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
  125. func pbit16(b []byte, v uint16) []byte {
  126. b[0] = byte(v)
  127. b[1] = byte(v >> 8)
  128. return b[2:]
  129. }
  130. // pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
  131. func pbit32(b []byte, v uint32) []byte {
  132. b[0] = byte(v)
  133. b[1] = byte(v >> 8)
  134. b[2] = byte(v >> 16)
  135. b[3] = byte(v >> 24)
  136. return b[4:]
  137. }
  138. // pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
  139. func pbit64(b []byte, v uint64) []byte {
  140. b[0] = byte(v)
  141. b[1] = byte(v >> 8)
  142. b[2] = byte(v >> 16)
  143. b[3] = byte(v >> 24)
  144. b[4] = byte(v >> 32)
  145. b[5] = byte(v >> 40)
  146. b[6] = byte(v >> 48)
  147. b[7] = byte(v >> 56)
  148. return b[8:]
  149. }
  150. // pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
  151. // returning the remaining slice of b..
  152. func pstring(b []byte, s string) []byte {
  153. b = pbit16(b, uint16(len(s)))
  154. n := copy(b, s)
  155. return b[n:]
  156. }
  157. // gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
  158. func gbit8(b []byte) (uint8, []byte) {
  159. return uint8(b[0]), b[1:]
  160. }
  161. // gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
  162. func gbit16(b []byte) (uint16, []byte) {
  163. return uint16(b[0]) | uint16(b[1])<<8, b[2:]
  164. }
  165. // gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
  166. func gbit32(b []byte) (uint32, []byte) {
  167. return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
  168. }
  169. // gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
  170. func gbit64(b []byte) (uint64, []byte) {
  171. lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
  172. hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
  173. return uint64(lo) | uint64(hi)<<32, b[8:]
  174. }
  175. // gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
  176. // It returns the string with the remaining slice of b and a boolean. If the length is
  177. // greater than the number of bytes in b, the boolean will be false.
  178. func gstring(b []byte) (string, []byte, bool) {
  179. n, b := gbit16(b)
  180. if int(n) > len(b) {
  181. return "", b, false
  182. }
  183. return string(b[:n]), b[n:], true
  184. }