static void buf_put_int32(struct cbuf *buf, u32 val) { if (buf_check_size(buf, 4)) { *(__le32 *)buf->p = cpu_to_le32(val); buf->p += 4; } }
static void buf_put_int8(struct cbuf *buf, u8 val) { if (buf_check_size(buf, 1)) { buf->p[0] = val; buf->p++; } }
static void buf_put_int16(struct cbuf *buf, u16 val) { if (buf_check_size(buf, 2)) { *(__le16 *) buf->p = cpu_to_le16(val); buf->p += 2; } }
static void buf_put_int64(struct cbuf *buf, u64 val) { if (buf_check_size(buf, 8)) { *(__le64 *)buf->p = cpu_to_le64(val); buf->p += 8; } }
static inline void buf_put_int8(struct cbuf *buf, u8 val, u8* pval) { if (buf_check_size(buf, 1)) { buf->p[0] = val; buf->p++; if (pval) *pval = val; } }
static void *buf_alloc(struct cbuf *buf, int len) { void *ret = NULL; if (buf_check_size(buf, len)) { ret = buf->p; buf->p += len; } return ret; }
static void buf_get_str(struct cbuf *buf, struct p9_str *vstr) { vstr->len = buf_get_int16(buf); if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { vstr->str = buf->p; buf->p += vstr->len; } else { vstr->len = 0; vstr->str = NULL; } }
static u64 buf_get_int64(struct cbuf *buf) { u64 ret = 0; if (buf_check_size(buf, 8)) { ret = le64_to_cpu(*(__le64 *)buf->p); buf->p += 8; } return ret; }
static u32 buf_get_int32(struct cbuf *buf) { u32 ret = 0; if (buf_check_size(buf, 4)) { ret = le32_to_cpu(*(__le32 *)buf->p); buf->p += 4; } return ret; }
static u16 buf_get_int16(struct cbuf *buf) { u16 ret = 0; if (buf_check_size(buf, 2)) { ret = le16_to_cpu(*(__le16 *)buf->p); buf->p += 2; } return ret; }
static u8 buf_get_int8(struct cbuf *buf) { u8 ret = 0; if (buf_check_size(buf, 1)) { ret = buf->p[0]; buf->p++; } return ret; }
static inline void buf_put_int16(struct cbuf *buf, u16 val, u16 *pval) { if (buf_check_size(buf, 2)) { buf->p[0] = val; buf->p[1] = val >> 8; buf->p += 2; if (pval) *pval = val; }
static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) { char *ret; ret = NULL; if (buf_check_size(buf, slen + 2)) { buf_put_int16(buf, slen); ret = buf->p; memcpy(buf->p, s, slen); buf->p += slen; } return ret; }
int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall, int dotu) { struct cbuf buffer; struct cbuf *bufp = &buffer; int i = 0; buf_init(bufp, buf, buflen); rcall->size = buf_get_int32(bufp); rcall->id = buf_get_int8(bufp); rcall->tag = buf_get_int16(bufp); P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id, rcall->tag); switch (rcall->id) { default: P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id); return -EPROTO; case P9_RVERSION: rcall->params.rversion.msize = buf_get_int32(bufp); buf_get_str(bufp, &rcall->params.rversion.version); break; case P9_RFLUSH: break; case P9_RATTACH: rcall->params.rattach.qid.type = buf_get_int8(bufp); rcall->params.rattach.qid.version = buf_get_int32(bufp); rcall->params.rattach.qid.path = buf_get_int64(bufp); break; case P9_RWALK: rcall->params.rwalk.nwqid = buf_get_int16(bufp); if (rcall->params.rwalk.nwqid > P9_MAXWELEM) { P9_EPRINTK(KERN_ERR, "Rwalk with more than %d qids: %d\n", P9_MAXWELEM, rcall->params.rwalk.nwqid); return -EPROTO; } for (i = 0; i < rcall->params.rwalk.nwqid; i++) buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); break; case P9_ROPEN: buf_get_qid(bufp, &rcall->params.ropen.qid); rcall->params.ropen.iounit = buf_get_int32(bufp); break; case P9_RCREATE: buf_get_qid(bufp, &rcall->params.rcreate.qid); rcall->params.rcreate.iounit = buf_get_int32(bufp); break; case P9_RREAD: rcall->params.rread.count = buf_get_int32(bufp); rcall->params.rread.data = bufp->p; buf_check_size(bufp, rcall->params.rread.count); break; case P9_RWRITE: rcall->params.rwrite.count = buf_get_int32(bufp); break; case P9_RCLUNK: break; case P9_RREMOVE: break; case P9_RSTAT: buf_get_int16(bufp); buf_get_stat(bufp, &rcall->params.rstat.stat, dotu); break; case P9_RWSTAT: break; case P9_RERROR: buf_get_str(bufp, &rcall->params.rerror.error); if (dotu) rcall->params.rerror.errno = buf_get_int16(bufp); break; } if (buf_check_overflow(bufp)) { P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n"); return -EIO; } return bufp->p - bufp->sp; }