Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6] / net / 9p / conv.c
1 /*
2  * net/9p/conv.c
3  *
4  * 9P protocol conversion functions
5  *
6  *  Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net>
7  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 2
12  *  as published by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to:
21  *  Free Software Foundation
22  *  51 Franklin Street, Fifth Floor
23  *  Boston, MA  02111-1301  USA
24  *
25  */
26
27 #include <linux/module.h>
28 #include <linux/errno.h>
29 #include <linux/fs.h>
30 #include <linux/sched.h>
31 #include <linux/idr.h>
32 #include <linux/uaccess.h>
33 #include <net/9p/9p.h>
34
35 /*
36  * Buffer to help with string parsing
37  */
38 struct cbuf {
39         unsigned char *sp;
40         unsigned char *p;
41         unsigned char *ep;
42 };
43
44 static inline void buf_init(struct cbuf *buf, void *data, int datalen)
45 {
46         buf->sp = buf->p = data;
47         buf->ep = data + datalen;
48 }
49
50 static inline int buf_check_overflow(struct cbuf *buf)
51 {
52         return buf->p > buf->ep;
53 }
54
55 static int buf_check_size(struct cbuf *buf, int len)
56 {
57         if (buf->p + len > buf->ep) {
58                 if (buf->p < buf->ep) {
59                         P9_EPRINTK(KERN_ERR,
60                                 "buffer overflow: want %d has %d\n", len,
61                                 (int)(buf->ep - buf->p));
62                         dump_stack();
63                         buf->p = buf->ep + 1;
64                 }
65
66                 return 0;
67         }
68
69         return 1;
70 }
71
72 static void *buf_alloc(struct cbuf *buf, int len)
73 {
74         void *ret = NULL;
75
76         if (buf_check_size(buf, len)) {
77                 ret = buf->p;
78                 buf->p += len;
79         }
80
81         return ret;
82 }
83
84 static void buf_put_int8(struct cbuf *buf, u8 val)
85 {
86         if (buf_check_size(buf, 1)) {
87                 buf->p[0] = val;
88                 buf->p++;
89         }
90 }
91
92 static void buf_put_int16(struct cbuf *buf, u16 val)
93 {
94         if (buf_check_size(buf, 2)) {
95                 *(__le16 *) buf->p = cpu_to_le16(val);
96                 buf->p += 2;
97         }
98 }
99
100 static void buf_put_int32(struct cbuf *buf, u32 val)
101 {
102         if (buf_check_size(buf, 4)) {
103                 *(__le32 *)buf->p = cpu_to_le32(val);
104                 buf->p += 4;
105         }
106 }
107
108 static void buf_put_int64(struct cbuf *buf, u64 val)
109 {
110         if (buf_check_size(buf, 8)) {
111                 *(__le64 *)buf->p = cpu_to_le64(val);
112                 buf->p += 8;
113         }
114 }
115
116 static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
117 {
118         char *ret;
119
120         ret = NULL;
121         if (buf_check_size(buf, slen + 2)) {
122                 buf_put_int16(buf, slen);
123                 ret = buf->p;
124                 memcpy(buf->p, s, slen);
125                 buf->p += slen;
126         }
127
128         return ret;
129 }
130
131 static u8 buf_get_int8(struct cbuf *buf)
132 {
133         u8 ret = 0;
134
135         if (buf_check_size(buf, 1)) {
136                 ret = buf->p[0];
137                 buf->p++;
138         }
139
140         return ret;
141 }
142
143 static u16 buf_get_int16(struct cbuf *buf)
144 {
145         u16 ret = 0;
146
147         if (buf_check_size(buf, 2)) {
148                 ret = le16_to_cpu(*(__le16 *)buf->p);
149                 buf->p += 2;
150         }
151
152         return ret;
153 }
154
155 static u32 buf_get_int32(struct cbuf *buf)
156 {
157         u32 ret = 0;
158
159         if (buf_check_size(buf, 4)) {
160                 ret = le32_to_cpu(*(__le32 *)buf->p);
161                 buf->p += 4;
162         }
163
164         return ret;
165 }
166
167 static u64 buf_get_int64(struct cbuf *buf)
168 {
169         u64 ret = 0;
170
171         if (buf_check_size(buf, 8)) {
172                 ret = le64_to_cpu(*(__le64 *)buf->p);
173                 buf->p += 8;
174         }
175
176         return ret;
177 }
178
179 static void buf_get_str(struct cbuf *buf, struct p9_str *vstr)
180 {
181         vstr->len = buf_get_int16(buf);
182         if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
183                 vstr->str = buf->p;
184                 buf->p += vstr->len;
185         } else {
186                 vstr->len = 0;
187                 vstr->str = NULL;
188         }
189 }
190
191 static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid)
192 {
193         qid->type = buf_get_int8(bufp);
194         qid->version = buf_get_int32(bufp);
195         qid->path = buf_get_int64(bufp);
196 }
197
198 /**
199  * p9_size_wstat - calculate the size of a variable length stat struct
200  * @wstat: metadata (stat) structure
201  * @dotu: non-zero if 9P2000.u
202  *
203  */
204
205 static int p9_size_wstat(struct p9_wstat *wstat, int dotu)
206 {
207         int size = 0;
208
209         if (wstat == NULL) {
210                 P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n");
211                 return 0;
212         }
213
214         size =                  /* 2 + *//* size[2] */
215             2 +                 /* type[2] */
216             4 +                 /* dev[4] */
217             1 +                 /* qid.type[1] */
218             4 +                 /* qid.vers[4] */
219             8 +                 /* qid.path[8] */
220             4 +                 /* mode[4] */
221             4 +                 /* atime[4] */
222             4 +                 /* mtime[4] */
223             8 +                 /* length[8] */
224             8;                  /* minimum sum of string lengths */
225
226         if (wstat->name)
227                 size += strlen(wstat->name);
228         if (wstat->uid)
229                 size += strlen(wstat->uid);
230         if (wstat->gid)
231                 size += strlen(wstat->gid);
232         if (wstat->muid)
233                 size += strlen(wstat->muid);
234
235         if (dotu) {
236                 size += 4 +     /* n_uid[4] */
237                     4 +         /* n_gid[4] */
238                     4 +         /* n_muid[4] */
239                     2;          /* string length of extension[4] */
240                 if (wstat->extension)
241                         size += strlen(wstat->extension);
242         }
243
244         return size;
245 }
246
247 /**
248  * buf_get_stat - safely decode a recieved metadata (stat) structure
249  * @bufp: buffer to deserialize
250  * @stat: metadata (stat) structure
251  * @dotu: non-zero if 9P2000.u
252  *
253  */
254
255 static void
256 buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu)
257 {
258         stat->size = buf_get_int16(bufp);
259         stat->type = buf_get_int16(bufp);
260         stat->dev = buf_get_int32(bufp);
261         stat->qid.type = buf_get_int8(bufp);
262         stat->qid.version = buf_get_int32(bufp);
263         stat->qid.path = buf_get_int64(bufp);
264         stat->mode = buf_get_int32(bufp);
265         stat->atime = buf_get_int32(bufp);
266         stat->mtime = buf_get_int32(bufp);
267         stat->length = buf_get_int64(bufp);
268         buf_get_str(bufp, &stat->name);
269         buf_get_str(bufp, &stat->uid);
270         buf_get_str(bufp, &stat->gid);
271         buf_get_str(bufp, &stat->muid);
272
273         if (dotu) {
274                 buf_get_str(bufp, &stat->extension);
275                 stat->n_uid = buf_get_int32(bufp);
276                 stat->n_gid = buf_get_int32(bufp);
277                 stat->n_muid = buf_get_int32(bufp);
278         }
279 }
280
281 /**
282  * p9_deserialize_stat - decode a received metadata structure
283  * @buf: buffer to deserialize
284  * @buflen: length of received buffer
285  * @stat: metadata structure to decode into
286  * @dotu: non-zero if 9P2000.u
287  *
288  * Note: stat will point to the buf region.
289  */
290
291 int
292 p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
293                 int dotu)
294 {
295         struct cbuf buffer;
296         struct cbuf *bufp = &buffer;
297         unsigned char *p;
298
299         buf_init(bufp, buf, buflen);
300         p = bufp->p;
301         buf_get_stat(bufp, stat, dotu);
302
303         if (buf_check_overflow(bufp))
304                 return 0;
305         else
306                 return bufp->p - p;
307 }
308 EXPORT_SYMBOL(p9_deserialize_stat);
309
310 /**
311  * deserialize_fcall - unmarshal a response
312  * @buf: recieved buffer
313  * @buflen: length of received buffer
314  * @rcall: fcall structure to populate
315  * @rcalllen: length of fcall structure to populate
316  * @dotu: non-zero if 9P2000.u
317  *
318  */
319
320 int
321 p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall,
322                        int dotu)
323 {
324
325         struct cbuf buffer;
326         struct cbuf *bufp = &buffer;
327         int i = 0;
328
329         buf_init(bufp, buf, buflen);
330
331         rcall->size = buf_get_int32(bufp);
332         rcall->id = buf_get_int8(bufp);
333         rcall->tag = buf_get_int16(bufp);
334
335         P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size,
336                                                         rcall->id, rcall->tag);
337
338         switch (rcall->id) {
339         default:
340                 P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id);
341                 return -EPROTO;
342         case P9_RVERSION:
343                 rcall->params.rversion.msize = buf_get_int32(bufp);
344                 buf_get_str(bufp, &rcall->params.rversion.version);
345                 break;
346         case P9_RFLUSH:
347                 break;
348         case P9_RATTACH:
349                 rcall->params.rattach.qid.type = buf_get_int8(bufp);
350                 rcall->params.rattach.qid.version = buf_get_int32(bufp);
351                 rcall->params.rattach.qid.path = buf_get_int64(bufp);
352                 break;
353         case P9_RWALK:
354                 rcall->params.rwalk.nwqid = buf_get_int16(bufp);
355                 if (rcall->params.rwalk.nwqid > P9_MAXWELEM) {
356                         P9_EPRINTK(KERN_ERR,
357                                         "Rwalk with more than %d qids: %d\n",
358                                         P9_MAXWELEM, rcall->params.rwalk.nwqid);
359                         return -EPROTO;
360                 }
361
362                 for (i = 0; i < rcall->params.rwalk.nwqid; i++)
363                         buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
364                 break;
365         case P9_ROPEN:
366                 buf_get_qid(bufp, &rcall->params.ropen.qid);
367                 rcall->params.ropen.iounit = buf_get_int32(bufp);
368                 break;
369         case P9_RCREATE:
370                 buf_get_qid(bufp, &rcall->params.rcreate.qid);
371                 rcall->params.rcreate.iounit = buf_get_int32(bufp);
372                 break;
373         case P9_RREAD:
374                 rcall->params.rread.count = buf_get_int32(bufp);
375                 rcall->params.rread.data = bufp->p;
376                 buf_check_size(bufp, rcall->params.rread.count);
377                 break;
378         case P9_RWRITE:
379                 rcall->params.rwrite.count = buf_get_int32(bufp);
380                 break;
381         case P9_RCLUNK:
382                 break;
383         case P9_RREMOVE:
384                 break;
385         case P9_RSTAT:
386                 buf_get_int16(bufp);
387                 buf_get_stat(bufp, &rcall->params.rstat.stat, dotu);
388                 break;
389         case P9_RWSTAT:
390                 break;
391         case P9_RERROR:
392                 buf_get_str(bufp, &rcall->params.rerror.error);
393                 if (dotu)
394                         rcall->params.rerror.errno = buf_get_int16(bufp);
395                 break;
396         }
397
398         if (buf_check_overflow(bufp)) {
399                 P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n");
400                 return -EIO;
401         }
402
403         return bufp->p - bufp->sp;
404 }
405 EXPORT_SYMBOL(p9_deserialize_fcall);
406
407 static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p)
408 {
409         *p = val;
410         buf_put_int8(bufp, val);
411 }
412
413 static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p)
414 {
415         *p = val;
416         buf_put_int16(bufp, val);
417 }
418
419 static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p)
420 {
421         *p = val;
422         buf_put_int32(bufp, val);
423 }
424
425 static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p)
426 {
427         *p = val;
428         buf_put_int64(bufp, val);
429 }
430
431 static void
432 p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str)
433 {
434         int len;
435         char *s;
436
437         if (data)
438                 len = strlen(data);
439         else
440                 len = 0;
441
442         s = buf_put_stringn(bufp, data, len);
443         if (str) {
444                 str->len = len;
445                 str->str = s;
446         }
447 }
448
449 static int
450 p9_put_data(struct cbuf *bufp, const char *data, int count,
451                    unsigned char **pdata)
452 {
453         *pdata = buf_alloc(bufp, count);
454         if (*pdata == NULL)
455                 return -ENOMEM;
456         memmove(*pdata, data, count);
457         return 0;
458 }
459
460 static int
461 p9_put_user_data(struct cbuf *bufp, const char __user *data, int count,
462                    unsigned char **pdata)
463 {
464         *pdata = buf_alloc(bufp, count);
465         if (*pdata == NULL)
466                 return -ENOMEM;
467         return copy_from_user(*pdata, data, count);
468 }
469
470 static void
471 p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat,
472                struct p9_stat *stat, int statsz, int dotu)
473 {
474         p9_put_int16(bufp, statsz, &stat->size);
475         p9_put_int16(bufp, wstat->type, &stat->type);
476         p9_put_int32(bufp, wstat->dev, &stat->dev);
477         p9_put_int8(bufp, wstat->qid.type, &stat->qid.type);
478         p9_put_int32(bufp, wstat->qid.version, &stat->qid.version);
479         p9_put_int64(bufp, wstat->qid.path, &stat->qid.path);
480         p9_put_int32(bufp, wstat->mode, &stat->mode);
481         p9_put_int32(bufp, wstat->atime, &stat->atime);
482         p9_put_int32(bufp, wstat->mtime, &stat->mtime);
483         p9_put_int64(bufp, wstat->length, &stat->length);
484
485         p9_put_str(bufp, wstat->name, &stat->name);
486         p9_put_str(bufp, wstat->uid, &stat->uid);
487         p9_put_str(bufp, wstat->gid, &stat->gid);
488         p9_put_str(bufp, wstat->muid, &stat->muid);
489
490         if (dotu) {
491                 p9_put_str(bufp, wstat->extension, &stat->extension);
492                 p9_put_int32(bufp, wstat->n_uid, &stat->n_uid);
493                 p9_put_int32(bufp, wstat->n_gid, &stat->n_gid);
494                 p9_put_int32(bufp, wstat->n_muid, &stat->n_muid);
495         }
496 }
497
498 static struct p9_fcall *
499 p9_create_common(struct cbuf *bufp, u32 size, u8 id)
500 {
501         struct p9_fcall *fc;
502
503         size += 4 + 1 + 2;      /* size[4] id[1] tag[2] */
504         fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL);
505         if (!fc)
506                 return ERR_PTR(-ENOMEM);
507
508         fc->sdata = (char *)fc + sizeof(*fc);
509
510         buf_init(bufp, (char *)fc->sdata, size);
511         p9_put_int32(bufp, size, &fc->size);
512         p9_put_int8(bufp, id, &fc->id);
513         p9_put_int16(bufp, P9_NOTAG, &fc->tag);
514
515         return fc;
516 }
517
518 /**
519  * p9_set_tag - set the tag field of an &p9_fcall structure
520  * @fc: fcall structure to set tag within
521  * @tag: tag id to set
522  */
523
524 void p9_set_tag(struct p9_fcall *fc, u16 tag)
525 {
526         fc->tag = tag;
527         *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
528 }
529 EXPORT_SYMBOL(p9_set_tag);
530
531 /**
532  * p9_create_tversion - allocates and creates a T_VERSION request
533  * @msize: requested maximum data size
534  * @version: version string to negotiate
535  *
536  */
537 struct p9_fcall *p9_create_tversion(u32 msize, char *version)
538 {
539         int size;
540         struct p9_fcall *fc;
541         struct cbuf buffer;
542         struct cbuf *bufp = &buffer;
543
544         size = 4 + 2 + strlen(version); /* msize[4] version[s] */
545         fc = p9_create_common(bufp, size, P9_TVERSION);
546         if (IS_ERR(fc))
547                 goto error;
548
549         p9_put_int32(bufp, msize, &fc->params.tversion.msize);
550         p9_put_str(bufp, version, &fc->params.tversion.version);
551
552         if (buf_check_overflow(bufp)) {
553                 kfree(fc);
554                 fc = ERR_PTR(-ENOMEM);
555         }
556 error:
557         return fc;
558 }
559 EXPORT_SYMBOL(p9_create_tversion);
560
561 /**
562  * p9_create_tauth - allocates and creates a T_AUTH request
563  * @afid: handle to use for authentication protocol
564  * @uname: user name attempting to authenticate
565  * @aname: mount specifier for remote server
566  * @n_uname: numeric id for user attempting to authneticate
567  * @dotu: 9P2000.u extension flag
568  *
569  */
570
571 struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname,
572         u32 n_uname, int dotu)
573 {
574         int size;
575         struct p9_fcall *fc;
576         struct cbuf buffer;
577         struct cbuf *bufp = &buffer;
578
579         /* afid[4] uname[s] aname[s] */
580         size = 4 + 2 + 2;
581         if (uname)
582                 size += strlen(uname);
583
584         if (aname)
585                 size += strlen(aname);
586
587         if (dotu)
588                 size += 4;      /* n_uname */
589
590         fc = p9_create_common(bufp, size, P9_TAUTH);
591         if (IS_ERR(fc))
592                 goto error;
593
594         p9_put_int32(bufp, afid, &fc->params.tauth.afid);
595         p9_put_str(bufp, uname, &fc->params.tauth.uname);
596         p9_put_str(bufp, aname, &fc->params.tauth.aname);
597         if (dotu)
598                 p9_put_int32(bufp, n_uname, &fc->params.tauth.n_uname);
599
600         if (buf_check_overflow(bufp)) {
601                 kfree(fc);
602                 fc = ERR_PTR(-ENOMEM);
603         }
604 error:
605         return fc;
606 }
607 EXPORT_SYMBOL(p9_create_tauth);
608
609 /**
610  * p9_create_tattach - allocates and creates a T_ATTACH request
611  * @fid: handle to use for the new mount point
612  * @afid: handle to use for authentication protocol
613  * @uname: user name attempting to attach
614  * @aname: mount specifier for remote server
615  * @n_uname: numeric id for user attempting to attach
616  * @n_uname: numeric id for user attempting to attach
617  * @dotu: 9P2000.u extension flag
618  *
619  */
620
621 struct p9_fcall *
622 p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname,
623         u32 n_uname, int dotu)
624 {
625         int size;
626         struct p9_fcall *fc;
627         struct cbuf buffer;
628         struct cbuf *bufp = &buffer;
629
630         /* fid[4] afid[4] uname[s] aname[s] */
631         size = 4 + 4 + 2 + 2;
632         if (uname)
633                 size += strlen(uname);
634
635         if (aname)
636                 size += strlen(aname);
637
638         if (dotu)
639                 size += 4;      /* n_uname */
640
641         fc = p9_create_common(bufp, size, P9_TATTACH);
642         if (IS_ERR(fc))
643                 goto error;
644
645         p9_put_int32(bufp, fid, &fc->params.tattach.fid);
646         p9_put_int32(bufp, afid, &fc->params.tattach.afid);
647         p9_put_str(bufp, uname, &fc->params.tattach.uname);
648         p9_put_str(bufp, aname, &fc->params.tattach.aname);
649         if (dotu)
650                 p9_put_int32(bufp, n_uname, &fc->params.tattach.n_uname);
651
652 error:
653         return fc;
654 }
655 EXPORT_SYMBOL(p9_create_tattach);
656
657 /**
658  * p9_create_tflush - allocates and creates a T_FLUSH request
659  * @oldtag: tag id for the transaction we are attempting to cancel
660  *
661  */
662
663 struct p9_fcall *p9_create_tflush(u16 oldtag)
664 {
665         int size;
666         struct p9_fcall *fc;
667         struct cbuf buffer;
668         struct cbuf *bufp = &buffer;
669
670         size = 2;               /* oldtag[2] */
671         fc = p9_create_common(bufp, size, P9_TFLUSH);
672         if (IS_ERR(fc))
673                 goto error;
674
675         p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
676
677         if (buf_check_overflow(bufp)) {
678                 kfree(fc);
679                 fc = ERR_PTR(-ENOMEM);
680         }
681 error:
682         return fc;
683 }
684 EXPORT_SYMBOL(p9_create_tflush);
685
686 /**
687  * p9_create_twalk - allocates and creates a T_FLUSH request
688  * @fid: handle we are traversing from
689  * @newfid: a new handle for this transaction
690  * @nwname: number of path elements to traverse
691  * @wnames: array of path elements
692  *
693  */
694
695 struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
696                                      char **wnames)
697 {
698         int i, size;
699         struct p9_fcall *fc;
700         struct cbuf buffer;
701         struct cbuf *bufp = &buffer;
702
703         if (nwname > P9_MAXWELEM) {
704                 P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM);
705                 return NULL;
706         }
707
708         size = 4 + 4 + 2;       /* fid[4] newfid[4] nwname[2] ... */
709         for (i = 0; i < nwname; i++) {
710                 size += 2 + strlen(wnames[i]);  /* wname[s] */
711         }
712
713         fc = p9_create_common(bufp, size, P9_TWALK);
714         if (IS_ERR(fc))
715                 goto error;
716
717         p9_put_int32(bufp, fid, &fc->params.twalk.fid);
718         p9_put_int32(bufp, newfid, &fc->params.twalk.newfid);
719         p9_put_int16(bufp, nwname, &fc->params.twalk.nwname);
720         for (i = 0; i < nwname; i++) {
721                 p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
722         }
723
724         if (buf_check_overflow(bufp)) {
725                 kfree(fc);
726                 fc = ERR_PTR(-ENOMEM);
727         }
728 error:
729         return fc;
730 }
731 EXPORT_SYMBOL(p9_create_twalk);
732
733 /**
734  * p9_create_topen - allocates and creates a T_OPEN request
735  * @fid: handle we are trying to open
736  * @mode: what mode we are trying to open the file in
737  *
738  */
739
740 struct p9_fcall *p9_create_topen(u32 fid, u8 mode)
741 {
742         int size;
743         struct p9_fcall *fc;
744         struct cbuf buffer;
745         struct cbuf *bufp = &buffer;
746
747         size = 4 + 1;           /* fid[4] mode[1] */
748         fc = p9_create_common(bufp, size, P9_TOPEN);
749         if (IS_ERR(fc))
750                 goto error;
751
752         p9_put_int32(bufp, fid, &fc->params.topen.fid);
753         p9_put_int8(bufp, mode, &fc->params.topen.mode);
754
755         if (buf_check_overflow(bufp)) {
756                 kfree(fc);
757                 fc = ERR_PTR(-ENOMEM);
758         }
759 error:
760         return fc;
761 }
762 EXPORT_SYMBOL(p9_create_topen);
763
764 /**
765  * p9_create_tcreate - allocates and creates a T_CREATE request
766  * @fid: handle of directory we are trying to create in
767  * @name: name of the file we are trying to create
768  * @perm: permissions for the file we are trying to create
769  * @mode: what mode we are trying to open the file in
770  * @extension: 9p2000.u extension string (for special files)
771  * @dotu: 9p2000.u enabled flag
772  *
773  * Note: Plan 9 create semantics include opening the resulting file
774  * which is why mode is included.
775  */
776
777 struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
778         char *extension, int dotu)
779 {
780         int size;
781         struct p9_fcall *fc;
782         struct cbuf buffer;
783         struct cbuf *bufp = &buffer;
784
785         /* fid[4] name[s] perm[4] mode[1] */
786         size = 4 + 2 + strlen(name) + 4 + 1;
787         if (dotu) {
788                 size += 2 +                     /* extension[s] */
789                     (extension == NULL ? 0 : strlen(extension));
790         }
791
792         fc = p9_create_common(bufp, size, P9_TCREATE);
793         if (IS_ERR(fc))
794                 goto error;
795
796         p9_put_int32(bufp, fid, &fc->params.tcreate.fid);
797         p9_put_str(bufp, name, &fc->params.tcreate.name);
798         p9_put_int32(bufp, perm, &fc->params.tcreate.perm);
799         p9_put_int8(bufp, mode, &fc->params.tcreate.mode);
800         if (dotu)
801                 p9_put_str(bufp, extension, &fc->params.tcreate.extension);
802
803         if (buf_check_overflow(bufp)) {
804                 kfree(fc);
805                 fc = ERR_PTR(-ENOMEM);
806         }
807 error:
808         return fc;
809 }
810 EXPORT_SYMBOL(p9_create_tcreate);
811
812 /**
813  * p9_create_tread - allocates and creates a T_READ request
814  * @fid: handle of the file we are trying to read
815  * @offset: offset to start reading from
816  * @count: how many bytes to read
817  */
818
819 struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count)
820 {
821         int size;
822         struct p9_fcall *fc;
823         struct cbuf buffer;
824         struct cbuf *bufp = &buffer;
825
826         size = 4 + 8 + 4;       /* fid[4] offset[8] count[4] */
827         fc = p9_create_common(bufp, size, P9_TREAD);
828         if (IS_ERR(fc))
829                 goto error;
830
831         p9_put_int32(bufp, fid, &fc->params.tread.fid);
832         p9_put_int64(bufp, offset, &fc->params.tread.offset);
833         p9_put_int32(bufp, count, &fc->params.tread.count);
834
835         if (buf_check_overflow(bufp)) {
836                 kfree(fc);
837                 fc = ERR_PTR(-ENOMEM);
838         }
839 error:
840         return fc;
841 }
842 EXPORT_SYMBOL(p9_create_tread);
843
844 /**
845  * p9_create_twrite - allocates and creates a T_WRITE request from the kernel
846  * @fid: handle of the file we are trying to write
847  * @offset: offset to start writing at
848  * @count: how many bytes to write
849  * @data: data to write
850  *
851  * This function will create a requst with data buffers from the kernel
852  * such as the page cache.
853  */
854
855 struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
856                                       const char *data)
857 {
858         int size, err;
859         struct p9_fcall *fc;
860         struct cbuf buffer;
861         struct cbuf *bufp = &buffer;
862
863         /* fid[4] offset[8] count[4] data[count] */
864         size = 4 + 8 + 4 + count;
865         fc = p9_create_common(bufp, size, P9_TWRITE);
866         if (IS_ERR(fc))
867                 goto error;
868
869         p9_put_int32(bufp, fid, &fc->params.twrite.fid);
870         p9_put_int64(bufp, offset, &fc->params.twrite.offset);
871         p9_put_int32(bufp, count, &fc->params.twrite.count);
872         err = p9_put_data(bufp, data, count, &fc->params.twrite.data);
873         if (err) {
874                 kfree(fc);
875                 fc = ERR_PTR(err);
876                 goto error;
877         }
878
879         if (buf_check_overflow(bufp)) {
880                 kfree(fc);
881                 fc = ERR_PTR(-ENOMEM);
882         }
883 error:
884         return fc;
885 }
886 EXPORT_SYMBOL(p9_create_twrite);
887
888 /**
889  * p9_create_twrite_u - allocates and creates a T_WRITE request from userspace
890  * @fid: handle of the file we are trying to write
891  * @offset: offset to start writing at
892  * @count: how many bytes to write
893  * @data: data to write
894  *
895  * This function will create a request with data buffers from userspace
896  */
897
898 struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
899                                       const char __user *data)
900 {
901         int size, err;
902         struct p9_fcall *fc;
903         struct cbuf buffer;
904         struct cbuf *bufp = &buffer;
905
906         /* fid[4] offset[8] count[4] data[count] */
907         size = 4 + 8 + 4 + count;
908         fc = p9_create_common(bufp, size, P9_TWRITE);
909         if (IS_ERR(fc))
910                 goto error;
911
912         p9_put_int32(bufp, fid, &fc->params.twrite.fid);
913         p9_put_int64(bufp, offset, &fc->params.twrite.offset);
914         p9_put_int32(bufp, count, &fc->params.twrite.count);
915         err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data);
916         if (err) {
917                 kfree(fc);
918                 fc = ERR_PTR(err);
919                 goto error;
920         }
921
922         if (buf_check_overflow(bufp)) {
923                 kfree(fc);
924                 fc = ERR_PTR(-ENOMEM);
925         }
926 error:
927         return fc;
928 }
929 EXPORT_SYMBOL(p9_create_twrite_u);
930
931 /**
932  * p9_create_tclunk - allocate a request to forget about a file handle
933  * @fid: handle of the file we closing or forgetting about
934  *
935  * clunk is used both to close open files and to discard transient handles
936  * which may be created during meta-data operations and hierarchy traversal.
937  */
938
939 struct p9_fcall *p9_create_tclunk(u32 fid)
940 {
941         int size;
942         struct p9_fcall *fc;
943         struct cbuf buffer;
944         struct cbuf *bufp = &buffer;
945
946         size = 4;               /* fid[4] */
947         fc = p9_create_common(bufp, size, P9_TCLUNK);
948         if (IS_ERR(fc))
949                 goto error;
950
951         p9_put_int32(bufp, fid, &fc->params.tclunk.fid);
952
953         if (buf_check_overflow(bufp)) {
954                 kfree(fc);
955                 fc = ERR_PTR(-ENOMEM);
956         }
957 error:
958         return fc;
959 }
960 EXPORT_SYMBOL(p9_create_tclunk);
961
962 /**
963  * p9_create_tremove - allocate and create a request to remove a file
964  * @fid: handle of the file or directory we are removing
965  *
966  */
967
968 struct p9_fcall *p9_create_tremove(u32 fid)
969 {
970         int size;
971         struct p9_fcall *fc;
972         struct cbuf buffer;
973         struct cbuf *bufp = &buffer;
974
975         size = 4;               /* fid[4] */
976         fc = p9_create_common(bufp, size, P9_TREMOVE);
977         if (IS_ERR(fc))
978                 goto error;
979
980         p9_put_int32(bufp, fid, &fc->params.tremove.fid);
981
982         if (buf_check_overflow(bufp)) {
983                 kfree(fc);
984                 fc = ERR_PTR(-ENOMEM);
985         }
986 error:
987         return fc;
988 }
989 EXPORT_SYMBOL(p9_create_tremove);
990
991 /**
992  * p9_create_tstat - allocate and populate a request for attributes
993  * @fid: handle of the file or directory we are trying to get the attributes of
994  *
995  */
996
997 struct p9_fcall *p9_create_tstat(u32 fid)
998 {
999         int size;
1000         struct p9_fcall *fc;
1001         struct cbuf buffer;
1002         struct cbuf *bufp = &buffer;
1003
1004         size = 4;               /* fid[4] */
1005         fc = p9_create_common(bufp, size, P9_TSTAT);
1006         if (IS_ERR(fc))
1007                 goto error;
1008
1009         p9_put_int32(bufp, fid, &fc->params.tstat.fid);
1010
1011         if (buf_check_overflow(bufp)) {
1012                 kfree(fc);
1013                 fc = ERR_PTR(-ENOMEM);
1014         }
1015 error:
1016         return fc;
1017 }
1018 EXPORT_SYMBOL(p9_create_tstat);
1019
1020 /**
1021  * p9_create_tstat - allocate and populate a request to change attributes
1022  * @fid: handle of the file or directory we are trying to change
1023  * @wstat: &p9_stat structure with attributes we wish to set
1024  * @dotu: 9p2000.u enabled flag
1025  *
1026  */
1027
1028 struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
1029                                       int dotu)
1030 {
1031         int size, statsz;
1032         struct p9_fcall *fc;
1033         struct cbuf buffer;
1034         struct cbuf *bufp = &buffer;
1035
1036         statsz = p9_size_wstat(wstat, dotu);
1037         size = 4 + 2 + 2 + statsz;      /* fid[4] stat[n] */
1038         fc = p9_create_common(bufp, size, P9_TWSTAT);
1039         if (IS_ERR(fc))
1040                 goto error;
1041
1042         p9_put_int32(bufp, fid, &fc->params.twstat.fid);
1043         buf_put_int16(bufp, statsz + 2);
1044         p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu);
1045
1046         if (buf_check_overflow(bufp)) {
1047                 kfree(fc);
1048                 fc = ERR_PTR(-ENOMEM);
1049         }
1050 error:
1051         return fc;
1052 }
1053 EXPORT_SYMBOL(p9_create_twstat);
1054