PageRenderTime 204ms CodeModel.GetById 111ms app.highlight 19ms RepoModel.GetById 71ms app.codeStats 1ms

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