aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/protocol.c')
-rw-r--r--net/9p/protocol.c85
1 files changed, 82 insertions, 3 deletions
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 43e98220e9a4..4ebeffd21d3d 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -27,6 +27,7 @@
27 27
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/uaccess.h>
30#include <net/9p/9p.h> 31#include <net/9p/9p.h>
31#include <net/9p/client.h> 32#include <net/9p/client.h>
32#include "protocol.h" 33#include "protocol.h"
@@ -51,6 +52,38 @@
51static int 52static int
52p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...); 53p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...);
53 54
55#define PACKET_DEBUG 0
56
57void
58p9pdu_dump(int way, struct p9_fcall *pdu)
59{
60 int i, n;
61 u8 *data = pdu->sdata;
62 int datalen = pdu->size;
63 char buf[255];
64 int buflen = 255;
65
66 i = n = 0;
67 if (datalen > (buflen-16))
68 datalen = buflen-16;
69 while (i < datalen) {
70 n += scnprintf(buf + n, buflen - n, "%02x ", data[i]);
71 if (i%4 == 3)
72 n += scnprintf(buf + n, buflen - n, " ");
73 if (i%32 == 31)
74 n += scnprintf(buf + n, buflen - n, "\n");
75
76 i++;
77 }
78 n += scnprintf(buf + n, buflen - n, "\n");
79
80 if (way)
81 printk(KERN_NOTICE "[[(%d)[ %s\n", datalen, buf);
82 else
83 printk(KERN_NOTICE "]](%d)] %s\n", datalen, buf);
84}
85EXPORT_SYMBOL(p9pdu_dump);
86
54void p9stat_free(struct p9_wstat *stbuf) 87void p9stat_free(struct p9_wstat *stbuf)
55{ 88{
56 kfree(stbuf->name); 89 kfree(stbuf->name);
@@ -77,6 +110,18 @@ static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size)
77 return size - len; 110 return size - len;
78} 111}
79 112
113static size_t
114pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
115{
116 size_t len = MIN(pdu->capacity - pdu->size, size);
117 int err = copy_from_user(&pdu->sdata[pdu->size], udata, len);
118 if (err)
119 printk(KERN_WARNING "pdu_write_u returning: %d\n", err);
120
121 pdu->size += len;
122 return size - len;
123}
124
80/* 125/*
81 b - int8_t 126 b - int8_t
82 w - int16_t 127 w - int16_t
@@ -174,7 +219,6 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
174 stbuf->extension = NULL; 219 stbuf->extension = NULL;
175 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = 220 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
176 -1; 221 -1;
177
178 errcode = 222 errcode =
179 p9pdu_readf(pdu, optional, 223 p9pdu_readf(pdu, optional,
180 "wwdQdddqssss?sddd", 224 "wwdQdddqssss?sddd",
@@ -332,7 +376,6 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
332 case 's':{ 376 case 's':{
333 const char *ptr = va_arg(ap, const char *); 377 const char *ptr = va_arg(ap, const char *);
334 int16_t len = 0; 378 int16_t len = 0;
335
336 if (ptr) 379 if (ptr)
337 len = MIN(strlen(ptr), USHORT_MAX); 380 len = MIN(strlen(ptr), USHORT_MAX);
338 381
@@ -356,7 +399,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
356 p9pdu_writef(pdu, optional, 399 p9pdu_writef(pdu, optional,
357 "wwdQdddqssss?sddd", 400 "wwdQdddqssss?sddd",
358 stbuf->size, stbuf->type, 401 stbuf->size, stbuf->type,
359 stbuf->dev, stbuf->qid, 402 stbuf->dev, &stbuf->qid,
360 stbuf->mode, stbuf->atime, 403 stbuf->mode, stbuf->atime,
361 stbuf->mtime, stbuf->length, 404 stbuf->mtime, stbuf->length,
362 stbuf->name, stbuf->uid, 405 stbuf->name, stbuf->uid,
@@ -374,6 +417,16 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
374 errcode = -EFAULT; 417 errcode = -EFAULT;
375 } 418 }
376 break; 419 break;
420 case 'U':{
421 int32_t count = va_arg(ap, int32_t);
422 const char __user *udata =
423 va_arg(ap, const void *);
424 errcode =
425 p9pdu_writef(pdu, optional, "d", count);
426 if (!errcode && pdu_write_u(pdu, udata, count))
427 errcode = -EFAULT;
428 }
429 break;
377 case 'T':{ 430 case 'T':{
378 int16_t nwname = va_arg(ap, int); 431 int16_t nwname = va_arg(ap, int);
379 const char **wnames = va_arg(ap, const char **); 432 const char **wnames = va_arg(ap, const char **);
@@ -455,3 +508,29 @@ p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...)
455 508
456 return ret; 509 return ret;
457} 510}
511
512int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
513{
514 return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
515}
516
517int p9pdu_finalize(struct p9_fcall *pdu)
518{
519 int size = pdu->size;
520 int err;
521
522 pdu->size = 0;
523 err = p9pdu_writef(pdu, 0, "d", size);
524 pdu->size = size;
525
526 if (PACKET_DEBUG)
527 p9pdu_dump(0, pdu);
528
529 return err;
530}
531
532void p9pdu_reset(struct p9_fcall *pdu)
533{
534 pdu->offset = 0;
535 pdu->size = 0;
536}