func Unpack(buf []byte, dotu bool) (fc *Fcall, err error, fcsz int) {
	var m uint16
	if len(buf) < 7 {
		return nil, &Error{"buffer too short", EINVAL}, 0
	}
	fc = new(Fcall)
	fc.Fid = NOFID
	fc.Afid = NOFID
	fc.Newfid = NOFID
	p := buf
	fc.Size, p = gint32(p)
	fc.Type, p = gint8(p)
	fc.Tag, p = gint16(p)
	if int(fc.Size) > len(buf) || fc.Size < 7 {
		return nil, &Error{fmt.Sprintf("buffer too short: %d expected %d",
				len(buf), fc.Size),
				EINVAL},
			0
	}
	p = p[0 : fc.Size-7]
	fc.Pkt = buf[0:fc.Size]
	fcsz = int(fc.Size)
	if fc.Type < Tversion || fc.Type >= Tlast {
		return nil, &Error{"invalid id", EINVAL}, 0
	}
	var sz uint32
	if dotu {
		sz = minFcusize[fc.Type-Tversion]
	} else {
		sz = minFcsize[fc.Type-Tversion]
	}
	if fc.Size < sz {
		goto szerror
	}
	err = nil
	switch fc.Type {
	default:
		return nil, &Error{"invalid message id", EINVAL}, 0
	case Tversion, Rversion:
		fc.Msize, p = gint32(p)
		fc.Version, p = gstr(p)
		if p == nil {
			goto szerror
		}
	case Tauth:
		fc.Afid, p = gint32(p)
		fc.Uname, p = gstr(p)
		if p == nil {
			goto szerror
		}
		fc.Aname, p = gstr(p)
		if p == nil {
			goto szerror
		}
		fc.Unamenum = NOUID
		if dotu && len(p) > 0 {
			fc.Unamenum, p = gint32(p)
		}
	case Rauth, Rattach:
		p = gqid(p, &fc.Qid)
	case Tflush:
		fc.Oldtag, p = gint16(p)
	case Tattach:
		fc.Fid, p = gint32(p)
		fc.Afid, p = gint32(p)
		fc.Uname, p = gstr(p)
		if p == nil {
			goto szerror
		}
		fc.Aname, p = gstr(p)
		if p == nil {
			goto szerror
		}
		fc.Unamenum = NOUID
		if dotu && len(p) > 0 {
			fc.Unamenum, p = gint32(p)
		}
	case Rerror:
		fc.Error, p = gstr(p)
		if p == nil {
			goto szerror
		}
		if dotu {
			fc.Errornum, p = gint32(p)
		} else {
			fc.Errornum = 0
		}
	case Twalk:
		fc.Fid, p = gint32(p)
		fc.Newfid, p = gint32(p)
		m, p = gint16(p)
		fc.Wname = make([]string, m)
		for i := 0; i < int(m); i++ {
			fc.Wname[i], p = gstr(p)
			if p == nil {
				goto szerror
			}
		}
	case Rwalk:
		m, p = gint16(p)
		fc.Wqid = make([]Qid, m)
		for i := 0; i < int(m); i++ {
			p = gqid(p, &fc.Wqid[i])
		}
	case Topen:
		fc.Fid, p = gint32(p)
		fc.Mode, p = gint8(p)
	case Ropen, Rcreate:
		p = gqid(p, &fc.Qid)
		fc.Iounit, p = gint32(p)
	case Tcreate:
		fc.Fid, p = gint32(p)
		fc.Name, p = gstr(p)
		if p == nil {
			goto szerror
		}
		fc.Perm, p = gint32(p)
		fc.Mode, p = gint8(p)
		if dotu {
			fc.Ext, p = gstr(p)
			if p == nil {
				goto szerror
			}
		}
	case Tread:
		fc.Fid, p = gint32(p)
		fc.Offset, p = gint64(p)
		fc.Count, p = gint32(p)
	case Rread:
		fc.Count, p = gint32(p)
		if len(p) < int(fc.Count) {
			goto szerror
		}
		fc.Data = p
		p = p[fc.Count:]
	case Twrite:
		fc.Fid, p = gint32(p)
		fc.Offset, p = gint64(p)
		fc.Count, p = gint32(p)
		if len(p) != int(fc.Count) {
			fc.Data = make([]byte, fc.Count)
			copy(fc.Data, p)
			p = p[len(p):]
		} else {
			fc.Data = p
			p = p[fc.Count:]
		}
	case Rwrite:
		fc.Count, p = gint32(p)
	case Tclunk, Tremove, Tstat:
		fc.Fid, p = gint32(p)
	case Rstat:
		m, p = gint16(p)
		p, err = gstat(p, &fc.Dir, dotu)
		if err != nil {
			return nil, err, 0
		}
	case Twstat:
		fc.Fid, p = gint32(p)
		m, p = gint16(p)
		p, _ = gstat(p, &fc.Dir, dotu)
	case Rflush, Rclunk, Rremove, Rwstat:
	}
	if len(p) > 0 {
		goto szerror
	}
	return
szerror:
	return nil, &Error{"invalid size", EINVAL}, 0
}
Creates a Fcall value from the on-the-wire representation. If
dotu is true, reads 9P2000.u messages. Returns the unpacked message,
error and how many bytes from the buffer were used by the message.
package p
import (
	"fmt"
)