Fixes stat() #include
[akaros.git] / user / ndblib / convM2S.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <stdlib.h>
10
11 #include <stdio.h>
12 #include <parlib.h>
13 #include <unistd.h>
14 #include <signal.h>
15 #include <fcntl.h>
16 #include <iplib.h>
17 #include <dir.h>
18 #include <ndb.h>
19 #include <fcall.h>
20
21 static
22 uint8_t*
23 gstring(uint8_t *p, uint8_t *ep, char **s)
24 {
25         unsigned int n;
26
27         if(p+BIT16SZ > ep)
28                 return NULL;
29         n = GBIT16(p);
30         p += BIT16SZ - 1;
31         if(p+n+1 > ep)
32                 return NULL;
33         /* move it down, on top of count, to make room for '\0' */
34         memmove(p, p + 1, n);
35         p[n] = '\0';
36         *s = (char*)p;
37         p += n+1;
38         return p;
39 }
40
41 static
42 uint8_t*
43 gqid(uint8_t *p, uint8_t *ep, struct qid *q)
44 {
45         if(p+QIDSZ > ep)
46                 return NULL;
47         q->type = GBIT8(p);
48         p += BIT8SZ;
49         q->vers = GBIT32(p);
50         p += BIT32SZ;
51         q->path = GBIT64(p);
52         p += BIT64SZ;
53         return p;
54 }
55
56 /*
57  * no syntactic checks.
58  * three causes for error:
59  *  1. message size field is incorrect
60  *  2. input buffer too short for its own data (counts too long, etc.)
61  *  3. too many names or qids
62  * gqid() and gstring() return NULL if they would reach beyond buffer.
63  * main switch statement checks range and also can fall through
64  * to test at end of routine.
65  */
66 unsigned int
67 convM2S(uint8_t *ap, unsigned int nap, struct fcall *f)
68 {
69         uint8_t *p, *ep;
70         unsigned int i, size;
71
72         p = ap;
73         ep = p + nap;
74
75         if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
76                 return 0;
77         size = GBIT32(p);
78         p += BIT32SZ;
79
80         if(size < BIT32SZ+BIT8SZ+BIT16SZ)
81                 return 0;
82
83         f->type = GBIT8(p);
84         p += BIT8SZ;
85         f->tag = GBIT16(p);
86         p += BIT16SZ;
87
88         switch(f->type)
89         {
90         default:
91                 return 0;
92
93         case Tversion:
94                 if(p+BIT32SZ > ep)
95                         return 0;
96                 f->msize = GBIT32(p);
97                 p += BIT32SZ;
98                 p = gstring(p, ep, &f->version);
99                 break;
100
101         case Tflush:
102                 if(p+BIT16SZ > ep)
103                         return 0;
104                 f->oldtag = GBIT16(p);
105                 p += BIT16SZ;
106                 break;
107
108         case Tauth:
109                 if(p+BIT32SZ > ep)
110                         return 0;
111                 f->afid = GBIT32(p);
112                 p += BIT32SZ;
113                 p = gstring(p, ep, &f->uname);
114                 if(p == NULL)
115                         break;
116                 p = gstring(p, ep, &f->aname);
117                 if(p == NULL)
118                         break;
119                 break;
120
121         case Tattach:
122                 if(p+BIT32SZ > ep)
123                         return 0;
124                 f->fid = GBIT32(p);
125                 p += BIT32SZ;
126                 if(p+BIT32SZ > ep)
127                         return 0;
128                 f->afid = GBIT32(p);
129                 p += BIT32SZ;
130                 p = gstring(p, ep, &f->uname);
131                 if(p == NULL)
132                         break;
133                 p = gstring(p, ep, &f->aname);
134                 if(p == NULL)
135                         break;
136                 break;
137
138         case Twalk:
139                 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
140                         return 0;
141                 f->fid = GBIT32(p);
142                 p += BIT32SZ;
143                 f->newfid = GBIT32(p);
144                 p += BIT32SZ;
145                 f->nwname = GBIT16(p);
146                 p += BIT16SZ;
147                 if(f->nwname > MAXWELEM)
148                         return 0;
149                 for(i=0; i<f->nwname; i++){
150                         p = gstring(p, ep, &f->wname[i]);
151                         if(p == NULL)
152                                 break;
153                 }
154                 break;
155
156         case Topen:
157                 if(p+BIT32SZ+BIT8SZ > ep)
158                         return 0;
159                 f->fid = GBIT32(p);
160                 p += BIT32SZ;
161                 f->mode = GBIT8(p);
162                 p += BIT8SZ;
163                 break;
164
165         case Tcreate:
166                 if(p+BIT32SZ > ep)
167                         return 0;
168                 f->fid = GBIT32(p);
169                 p += BIT32SZ;
170                 p = gstring(p, ep, &f->name);
171                 if(p == NULL)
172                         break;
173                 if(p+BIT32SZ+BIT8SZ > ep)
174                         return 0;
175                 f->perm = GBIT32(p);
176                 p += BIT32SZ;
177                 f->mode = GBIT8(p);
178                 p += BIT8SZ;
179                 break;
180
181         case Tread:
182                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
183                         return 0;
184                 f->fid = GBIT32(p);
185                 p += BIT32SZ;
186                 f->offset = GBIT64(p);
187                 p += BIT64SZ;
188                 f->count = GBIT32(p);
189                 p += BIT32SZ;
190                 break;
191
192         case Twrite:
193                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
194                         return 0;
195                 f->fid = GBIT32(p);
196                 p += BIT32SZ;
197                 f->offset = GBIT64(p);
198                 p += BIT64SZ;
199                 f->count = GBIT32(p);
200                 p += BIT32SZ;
201                 if(p+f->count > ep)
202                         return 0;
203                 f->data = (char*)p;
204                 p += f->count;
205                 break;
206
207         case Tclunk:
208         case Tremove:
209                 if(p+BIT32SZ > ep)
210                         return 0;
211                 f->fid = GBIT32(p);
212                 p += BIT32SZ;
213                 break;
214
215         case Tstat:
216                 if(p+BIT32SZ > ep)
217                         return 0;
218                 f->fid = GBIT32(p);
219                 p += BIT32SZ;
220                 break;
221
222         case Twstat:
223                 if(p+BIT32SZ+BIT16SZ > ep)
224                         return 0;
225                 f->fid = GBIT32(p);
226                 p += BIT32SZ;
227                 f->nstat = GBIT16(p);
228                 p += BIT16SZ;
229                 if(p+f->nstat > ep)
230                         return 0;
231                 f->stat = p;
232                 p += f->nstat;
233                 break;
234
235 /*
236  */
237         case Rversion:
238                 if(p+BIT32SZ > ep)
239                         return 0;
240                 f->msize = GBIT32(p);
241                 p += BIT32SZ;
242                 p = gstring(p, ep, &f->version);
243                 break;
244
245         case Rerror:
246                 p = gstring(p, ep, &f->ename);
247                 break;
248
249         case Rflush:
250                 break;
251
252         case Rauth:
253                 p = gqid(p, ep, &f->aqid);
254                 if(p == NULL)
255                         break;
256                 break;
257
258         case Rattach:
259                 p = gqid(p, ep, &f->qid);
260                 if(p == NULL)
261                         break;
262                 break;
263
264         case Rwalk:
265                 if(p+BIT16SZ > ep)
266                         return 0;
267                 f->nwqid = GBIT16(p);
268                 p += BIT16SZ;
269                 if(f->nwqid > MAXWELEM)
270                         return 0;
271                 for(i=0; i<f->nwqid; i++){
272                         p = gqid(p, ep, &f->wqid[i]);
273                         if(p == NULL)
274                                 break;
275                 }
276                 break;
277
278         case Ropen:
279         case Rcreate:
280                 p = gqid(p, ep, &f->qid);
281                 if(p == NULL)
282                         break;
283                 if(p+BIT32SZ > ep)
284                         return 0;
285                 f->iounit = GBIT32(p);
286                 p += BIT32SZ;
287                 break;
288
289         case Rread:
290                 if(p+BIT32SZ > ep)
291                         return 0;
292                 f->count = GBIT32(p);
293                 p += BIT32SZ;
294                 if(p+f->count > ep)
295                         return 0;
296                 f->data = (char*)p;
297                 p += f->count;
298                 break;
299
300         case Rwrite:
301                 if(p+BIT32SZ > ep)
302                         return 0;
303                 f->count = GBIT32(p);
304                 p += BIT32SZ;
305                 break;
306
307         case Rclunk:
308         case Rremove:
309                 break;
310
311         case Rstat:
312                 if(p+BIT16SZ > ep)
313                         return 0;
314                 f->nstat = GBIT16(p);
315                 p += BIT16SZ;
316                 if(p+f->nstat > ep)
317                         return 0;
318                 f->stat = p;
319                 p += f->nstat;
320                 break;
321
322         case Rwstat:
323                 break;
324         }
325
326         if(p==NULL || p>ep)
327                 return 0;
328         if(ap+size == p)
329                 return size;
330         return 0;
331 }