/go9p/g9p/unpack.go

https://code.google.com/p/rog-go/ · Go · 224 lines · 182 code · 36 blank · 6 comment · 46 complexity · 77237de4bad971213a139e67ecf9659e MD5 · raw file

  1. // Copyright 2009 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. package g9p
  5. import (
  6. "fmt"
  7. "syscall"
  8. )
  9. // Creates a Fcall value from the on-the-wire representation. If
  10. // dotu is true, reads 9P2000.u messages. Returns the unpacked message,
  11. // error and how many bytes from the buffer were used by the message.
  12. func Unpack(buf []byte, dotu bool) (fc *Fcall, err error, fcsz int) {
  13. var m uint16
  14. if len(buf) < 7 {
  15. return nil, &Error{"buffer too short", syscall.EINVAL}, 0
  16. }
  17. fc = new(Fcall)
  18. fc.Fid = NOFID
  19. fc.Afid = NOFID
  20. fc.Newfid = NOFID
  21. p := buf
  22. fc.Size, p = gint32(p)
  23. fc.Type, p = gint8(p)
  24. fc.Tag, p = gint16(p)
  25. if int(fc.Size) > len(buf) || fc.Size < 7 {
  26. return nil, &Error{fmt.Sprintf("buffer too short: %d expected %d",
  27. len(buf), fc.Size),
  28. syscall.EINVAL},
  29. 0
  30. }
  31. p = p[0 : fc.Size-7]
  32. fc.Pkt = buf[0:fc.Size]
  33. fcsz = int(fc.Size)
  34. if fc.Type < Tversion || fc.Type >= Tlast {
  35. return nil, &Error{"invalid id", syscall.EINVAL}, 0
  36. }
  37. var sz uint32
  38. if dotu {
  39. sz = minFcsize[fc.Type-Tversion]
  40. } else {
  41. sz = minFcusize[fc.Type-Tversion]
  42. }
  43. if fc.Size < sz {
  44. szerror:
  45. return nil, &Error{"invalid size", syscall.EINVAL}, 0
  46. }
  47. err = nil
  48. switch fc.Type {
  49. default:
  50. return nil, &Error{"invalid message id", syscall.EINVAL}, 0
  51. case Tversion, Rversion:
  52. fc.Msize, p = gint32(p)
  53. fc.Version, p = gstr(p)
  54. if p == nil {
  55. goto szerror
  56. }
  57. case Tauth:
  58. fc.Afid, p = gint32(p)
  59. fc.Uname, p = gstr(p)
  60. if p == nil {
  61. goto szerror
  62. }
  63. fc.Aname, p = gstr(p)
  64. if p == nil {
  65. goto szerror
  66. }
  67. if dotu {
  68. if len(p) > 0 {
  69. fc.Unamenum, p = gint32(p)
  70. } else {
  71. fc.Unamenum = NOUID
  72. }
  73. } else {
  74. fc.Unamenum = NOUID
  75. }
  76. case Rauth, Rattach:
  77. p = gqid(p, &fc.Qid)
  78. case Tflush:
  79. fc.Oldtag, p = gint16(p)
  80. case Tattach:
  81. fc.Fid, p = gint32(p)
  82. fc.Afid, p = gint32(p)
  83. fc.Uname, p = gstr(p)
  84. if p == nil {
  85. goto szerror
  86. }
  87. fc.Aname, p = gstr(p)
  88. if p == nil {
  89. goto szerror
  90. }
  91. if dotu {
  92. if len(p) > 0 {
  93. fc.Unamenum, p = gint32(p)
  94. } else {
  95. fc.Unamenum = NOUID
  96. }
  97. }
  98. case Rerror:
  99. fc.Error, p = gstr(p)
  100. if p == nil {
  101. goto szerror
  102. }
  103. if dotu {
  104. fc.Errornum, p = gint32(p)
  105. } else {
  106. fc.Errornum = 0
  107. }
  108. case Twalk:
  109. fc.Fid, p = gint32(p)
  110. fc.Newfid, p = gint32(p)
  111. m, p = gint16(p)
  112. fc.Wname = make([]string, m)
  113. for i := 0; i < int(m); i++ {
  114. fc.Wname[i], p = gstr(p)
  115. if p == nil {
  116. goto szerror
  117. }
  118. }
  119. case Rwalk:
  120. m, p = gint16(p)
  121. fc.Wqid = make([]Qid, m)
  122. for i := 0; i < int(m); i++ {
  123. p = gqid(p, &fc.Wqid[i])
  124. }
  125. case Topen:
  126. fc.Fid, p = gint32(p)
  127. fc.Mode, p = gint8(p)
  128. case Ropen, Rcreate:
  129. p = gqid(p, &fc.Qid)
  130. fc.Iounit, p = gint32(p)
  131. case Tcreate:
  132. fc.Fid, p = gint32(p)
  133. fc.Name, p = gstr(p)
  134. if p == nil {
  135. goto szerror
  136. }
  137. fc.Perm, p = gint32(p)
  138. fc.Mode, p = gint8(p)
  139. if dotu {
  140. fc.Ext, p = gstr(p)
  141. if p == nil {
  142. goto szerror
  143. }
  144. }
  145. case Tread:
  146. fc.Fid, p = gint32(p)
  147. fc.Offset, p = gint64(p)
  148. fc.Count, p = gint32(p)
  149. case Rread:
  150. fc.Count, p = gint32(p)
  151. if len(p) < int(fc.Count) {
  152. goto szerror
  153. }
  154. fc.Data = p
  155. p = p[fc.Count:len(p)]
  156. case Twrite:
  157. fc.Fid, p = gint32(p)
  158. fc.Offset, p = gint64(p)
  159. fc.Count, p = gint32(p)
  160. if len(p) != int(fc.Count) {
  161. fc.Data = make([]byte, fc.Count)
  162. copy(fc.Data, p)
  163. p = p[len(p):]
  164. } else {
  165. fc.Data = p
  166. p = p[fc.Count:len(p)]
  167. }
  168. case Rwrite:
  169. fc.Count, p = gint32(p)
  170. case Tclunk, Tremove, Tstat:
  171. fc.Fid, p = gint32(p)
  172. case Rstat:
  173. m, p = gint16(p)
  174. p = gstat(p, &fc.Dir, dotu)
  175. if p == nil {
  176. goto szerror
  177. }
  178. case Twstat:
  179. fc.Fid, p = gint32(p)
  180. m, p = gint16(p)
  181. p = gstat(p, &fc.Dir, dotu)
  182. case Rflush, Rclunk, Rremove, Rwstat:
  183. }
  184. if len(p) > 0 {
  185. goto szerror
  186. }
  187. return
  188. }