⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conv.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * net/9p/conv.c * * 9P protocol conversion functions * *  Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net> *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 *  as published by the Free Software Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to: *  Free Software Foundation *  51 Franklin Street, Fifth Floor *  Boston, MA  02111-1301  USA * */#include <linux/module.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/idr.h>#include <linux/uaccess.h>#include <net/9p/9p.h>/* * Buffer to help with string parsing */struct cbuf {	unsigned char *sp;	unsigned char *p;	unsigned char *ep;};static inline void buf_init(struct cbuf *buf, void *data, int datalen){	buf->sp = buf->p = data;	buf->ep = data + datalen;}static inline int buf_check_overflow(struct cbuf *buf){	return buf->p > buf->ep;}static int buf_check_size(struct cbuf *buf, int len){	if (buf->p + len > buf->ep) {		if (buf->p < buf->ep) {			P9_EPRINTK(KERN_ERR,				"buffer overflow: want %d has %d\n", len,				(int)(buf->ep - buf->p));			dump_stack();			buf->p = buf->ep + 1;		}		return 0;	}	return 1;}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_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_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_int64(struct cbuf *buf, u64 val){	if (buf_check_size(buf, 8)) {		*(__le64 *)buf->p = cpu_to_le64(val);		buf->p += 8;	}}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;}static inline void buf_put_string(struct cbuf *buf, const char *s){	buf_put_stringn(buf, s, strlen(s));}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 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 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 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 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 void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid){	qid->type = buf_get_int8(bufp);	qid->version = buf_get_int32(bufp);	qid->path = buf_get_int64(bufp);}/** * p9_size_wstat - calculate the size of a variable length stat struct * @stat: metadata (stat) structure * @dotu: non-zero if 9P2000.u * */static int p9_size_wstat(struct p9_wstat *wstat, int dotu){	int size = 0;	if (wstat == NULL) {		P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n");		return 0;	}	size =			/* 2 + *//* size[2] */	    2 +			/* type[2] */	    4 +			/* dev[4] */	    1 +			/* qid.type[1] */	    4 +			/* qid.vers[4] */	    8 +			/* qid.path[8] */	    4 +			/* mode[4] */	    4 +			/* atime[4] */	    4 +			/* mtime[4] */	    8 +			/* length[8] */	    8;			/* minimum sum of string lengths */	if (wstat->name)		size += strlen(wstat->name);	if (wstat->uid)		size += strlen(wstat->uid);	if (wstat->gid)		size += strlen(wstat->gid);	if (wstat->muid)		size += strlen(wstat->muid);	if (dotu) {		size += 4 +	/* n_uid[4] */		    4 +		/* n_gid[4] */		    4 +		/* n_muid[4] */		    2;		/* string length of extension[4] */		if (wstat->extension)			size += strlen(wstat->extension);	}	return size;}/** * buf_get_stat - safely decode a recieved metadata (stat) structure * @bufp: buffer to deserialize * @stat: metadata (stat) structure * @dotu: non-zero if 9P2000.u * */static voidbuf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu){	stat->size = buf_get_int16(bufp);	stat->type = buf_get_int16(bufp);	stat->dev = buf_get_int32(bufp);	stat->qid.type = buf_get_int8(bufp);	stat->qid.version = buf_get_int32(bufp);	stat->qid.path = buf_get_int64(bufp);	stat->mode = buf_get_int32(bufp);	stat->atime = buf_get_int32(bufp);	stat->mtime = buf_get_int32(bufp);	stat->length = buf_get_int64(bufp);	buf_get_str(bufp, &stat->name);	buf_get_str(bufp, &stat->uid);	buf_get_str(bufp, &stat->gid);	buf_get_str(bufp, &stat->muid);	if (dotu) {		buf_get_str(bufp, &stat->extension);		stat->n_uid = buf_get_int32(bufp);		stat->n_gid = buf_get_int32(bufp);		stat->n_muid = buf_get_int32(bufp);	}}/** * p9_deserialize_stat - decode a received metadata structure * @buf: buffer to deserialize * @buflen: length of received buffer * @stat: metadata structure to decode into * @dotu: non-zero if 9P2000.u * * Note: stat will point to the buf region. */intp9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,		int dotu){	struct cbuf buffer;	struct cbuf *bufp = &buffer;	unsigned char *p;	buf_init(bufp, buf, buflen);	p = bufp->p;	buf_get_stat(bufp, stat, dotu);	if (buf_check_overflow(bufp))		return 0;	else		return bufp->p - p;}EXPORT_SYMBOL(p9_deserialize_stat);/** * deserialize_fcall - unmarshal a response * @buf: recieved buffer * @buflen: length of received buffer * @rcall: fcall structure to populate * @rcalllen: length of fcall structure to populate * @dotu: non-zero if 9P2000.u * */intp9_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;}EXPORT_SYMBOL(p9_deserialize_fcall);static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p){	*p = val;	buf_put_int8(bufp, val);}static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p){	*p = val;	buf_put_int16(bufp, val);}static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p){	*p = val;	buf_put_int32(bufp, val);}static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p){	*p = val;	buf_put_int64(bufp, val);}static voidp9_put_str(struct cbuf *bufp, char *data, struct p9_str *str){	int len;	char *s;	if (data)		len = strlen(data);	else		len = 0;	s = buf_put_stringn(bufp, data, len);	if (str) {		str->len = len;		str->str = s;	}}static intp9_put_data(struct cbuf *bufp, const char *data, int count,		   unsigned char **pdata){	*pdata = buf_alloc(bufp, count);	memmove(*pdata, data, count);	return count;}static intp9_put_user_data(struct cbuf *bufp, const char __user *data, int count,		   unsigned char **pdata)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -