kconfig: use pkg-config for ncurses detection
[akaros.git] / kern / src / ns / convM2S.c
1 /* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
2  * Portions Copyright © 1997-1999 Vita Nuova Limited
3  * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
4  *                                (www.vitanuova.com)
5  * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
6  *
7  * Modified for the Akaros operating system:
8  * Copyright (c) 2013-2014 The Regents of the University of California
9  * Copyright (c) 2013-2015 Google Inc.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE. */
28
29 #include <slab.h>
30 #include <kmalloc.h>
31 #include <kref.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <error.h>
36 #include <cpio.h>
37 #include <pmap.h>
38 #include <smp.h>
39 #include <net/ip.h>
40
41 static uint8_t *gstring(uint8_t *p, uint8_t *ep, char **s)
42 {
43         unsigned int n;
44
45         if (p + BIT16SZ > ep)
46                 return NULL;
47         n = GBIT16(p);
48         p += BIT16SZ - 1;
49         if (p + n + 1 > ep)
50                 return NULL;
51         /* move it down, on top of count, to make room for '\0' */
52         memmove(p, p + 1, n);
53         p[n] = '\0';
54         *s = (char *)p;
55         p += n + 1;
56         return p;
57 }
58
59 static uint8_t *gqid(uint8_t *p, uint8_t *ep, struct qid *q)
60 {
61         if (p + QIDSZ > ep)
62                 return NULL;
63         q->type = GBIT8(p);
64         p += BIT8SZ;
65         q->vers = GBIT32(p);
66         p += BIT32SZ;
67         q->path = GBIT64(p);
68         p += BIT64SZ;
69         return p;
70 }
71
72 /* This initializes a dir to "don't touch" values.  These fields are ignored on
73  * a wstat. */
74 void init_empty_dir(struct dir *d)
75 {
76         d->type = ~0;
77         d->dev = ~0;
78         d->qid.path = ~0;
79         d->qid.vers = ~0;
80         d->qid.type = ~0;
81         d->mode = ~0;
82         d->length = ~0;
83         d->name = "";
84         d->uid = "";
85         d->gid = "";
86         d->muid = "";
87         d->ext = "";
88         d->n_uid = ~0;
89         d->n_gid = ~0;
90         d->n_muid = ~0;
91         d->atime.tv_sec = ~0;
92         d->btime.tv_sec = ~0;
93         d->ctime.tv_sec = ~0;
94         d->mtime.tv_sec = ~0;
95         /* We don't look at tv_nsec to determine whether or not the field is
96          * "don't touch".  This way, all nsecs are normal. */
97         d->atime.tv_nsec = 0;
98         d->btime.tv_nsec = 0;
99         d->ctime.tv_nsec = 0;
100         d->mtime.tv_nsec = 0;
101 }
102
103 /*
104  * no syntactic checks.
105  * three causes for error:
106  *  1. message size field is incorrect
107  *  2. input buffer too short for its own data (counts too long, etc.)
108  *  3. too many names or qids
109  * gqid() and gstring() return NULL if they would reach beyond buffer.
110  * main switch statement checks range and also can fall through
111  * to test at end of routine.
112  */
113 unsigned int convM2S(uint8_t *ap, unsigned int nap, struct fcall *f)
114 {
115         uint8_t *p, *ep;
116         unsigned int i, size;
117
118         p = ap;
119         ep = p + nap;
120
121         if (p + BIT32SZ + BIT8SZ + BIT16SZ > ep)
122                 return 0;
123         size = GBIT32(p);
124         p += BIT32SZ;
125
126         if (size < BIT32SZ + BIT8SZ + BIT16SZ)
127                 return 0;
128
129         f->type = GBIT8(p);
130         p += BIT8SZ;
131         f->tag = GBIT16(p);
132         p += BIT16SZ;
133
134         switch (f->type) {
135         default:
136                 return 0;
137
138         case Tversion:
139                 if (p + BIT32SZ > ep)
140                         return 0;
141                 f->msize = GBIT32(p);
142                 p += BIT32SZ;
143                 p = gstring(p, ep, &f->version);
144                 break;
145
146         case Tflush:
147                 if (p + BIT16SZ > ep)
148                         return 0;
149                 f->oldtag = GBIT16(p);
150                 p += BIT16SZ;
151                 break;
152
153         case Tauth:
154                 if (p + BIT32SZ > ep)
155                         return 0;
156                 f->afid = GBIT32(p);
157                 p += BIT32SZ;
158                 p = gstring(p, ep, &f->uname);
159                 if (p == NULL)
160                         break;
161                 p = gstring(p, ep, &f->aname);
162                 if (p == NULL)
163                         break;
164                 break;
165
166         case Tattach:
167                 if (p + BIT32SZ > ep)
168                         return 0;
169                 f->fid = GBIT32(p);
170                 p += BIT32SZ;
171                 if (p + BIT32SZ > ep)
172                         return 0;
173                 f->afid = GBIT32(p);
174                 p += BIT32SZ;
175                 p = gstring(p, ep, &f->uname);
176                 if (p == NULL)
177                         break;
178                 p = gstring(p, ep, &f->aname);
179                 if (p == NULL)
180                         break;
181                 break;
182
183         case Twalk:
184                 if (p + BIT32SZ + BIT32SZ + BIT16SZ > ep)
185                         return 0;
186                 f->fid = GBIT32(p);
187                 p += BIT32SZ;
188                 f->newfid = GBIT32(p);
189                 p += BIT32SZ;
190                 f->nwname = GBIT16(p);
191                 p += BIT16SZ;
192                 if (f->nwname > MAXWELEM)
193                         return 0;
194                 for (i = 0; i < f->nwname; i++) {
195                         p = gstring(p, ep, &f->wname[i]);
196                         if (p == NULL)
197                                 break;
198                 }
199                 break;
200
201         case Topen:
202                 if (p + BIT32SZ + BIT8SZ > ep)
203                         return 0;
204                 f->fid = GBIT32(p);
205                 p += BIT32SZ;
206                 f->mode = GBIT8(p);
207                 p += BIT8SZ;
208                 break;
209
210         case Tcreate:
211                 if (p + BIT32SZ > ep)
212                         return 0;
213                 f->fid = GBIT32(p);
214                 p += BIT32SZ;
215                 p = gstring(p, ep, &f->name);
216                 if (p == NULL)
217                         break;
218                 if (p + BIT32SZ + BIT8SZ > ep)
219                         return 0;
220                 f->perm = GBIT32(p);
221                 p += BIT32SZ;
222                 f->mode = GBIT8(p);
223                 p += BIT8SZ;
224                 break;
225
226         case Tread:
227                 if (p + BIT32SZ + BIT64SZ + BIT32SZ > ep)
228                         return 0;
229                 f->fid = GBIT32(p);
230                 p += BIT32SZ;
231                 f->offset = GBIT64(p);
232                 p += BIT64SZ;
233                 f->count = GBIT32(p);
234                 p += BIT32SZ;
235                 break;
236
237         case Twrite:
238                 if (p + BIT32SZ + BIT64SZ + BIT32SZ > ep)
239                         return 0;
240                 f->fid = GBIT32(p);
241                 p += BIT32SZ;
242                 f->offset = GBIT64(p);
243                 p += BIT64SZ;
244                 f->count = GBIT32(p);
245                 p += BIT32SZ;
246                 if (p + f->count > ep)
247                         return 0;
248                 f->data = (char *)p;
249                 p += f->count;
250                 break;
251
252         case Tclunk:
253         case Tremove:
254                 if (p + BIT32SZ > ep)
255                         return 0;
256                 f->fid = GBIT32(p);
257                 p += BIT32SZ;
258                 break;
259
260         case Tstat:
261                 if (p + BIT32SZ > ep)
262                         return 0;
263                 f->fid = GBIT32(p);
264                 p += BIT32SZ;
265                 break;
266
267         case Twstat:
268                 if (p + BIT32SZ + BIT16SZ > ep)
269                         return 0;
270                 f->fid = GBIT32(p);
271                 p += BIT32SZ;
272                 f->nstat = GBIT16(p);
273                 p += BIT16SZ;
274                 if (p + f->nstat > ep)
275                         return 0;
276                 f->stat = p;
277                 p += f->nstat;
278                 break;
279
280 /*
281  */
282         case Rversion:
283                 if (p + BIT32SZ > ep)
284                         return 0;
285                 f->msize = GBIT32(p);
286                 p += BIT32SZ;
287                 p = gstring(p, ep, &f->version);
288                 break;
289
290         case Rerror:
291                 p = gstring(p, ep, &f->ename);
292                 break;
293
294         case Rflush:
295                 break;
296
297         case Rauth:
298                 p = gqid(p, ep, &f->aqid);
299                 if (p == NULL)
300                         break;
301                 break;
302
303         case Rattach:
304                 p = gqid(p, ep, &f->qid);
305                 if (p == NULL)
306                         break;
307                 break;
308
309         case Rwalk:
310                 if (p + BIT16SZ > ep)
311                         return 0;
312                 f->nwqid = GBIT16(p);
313                 p += BIT16SZ;
314                 if (f->nwqid > MAXWELEM)
315                         return 0;
316                 for (i = 0; i < f->nwqid; i++) {
317                         p = gqid(p, ep, &f->wqid[i]);
318                         if (p == NULL)
319                                 break;
320                 }
321                 break;
322
323         case Ropen:
324         case Rcreate:
325                 p = gqid(p, ep, &f->qid);
326                 if (p == NULL)
327                         break;
328                 if (p + BIT32SZ > ep)
329                         return 0;
330                 f->iounit = GBIT32(p);
331                 p += BIT32SZ;
332                 break;
333
334         case Rread:
335                 if (p + BIT32SZ > ep)
336                         return 0;
337                 f->count = GBIT32(p);
338                 p += BIT32SZ;
339                 if (p + f->count > ep)
340                         return 0;
341                 f->data = (char *)p;
342                 p += f->count;
343                 break;
344
345         case Rwrite:
346                 if (p + BIT32SZ > ep)
347                         return 0;
348                 f->count = GBIT32(p);
349                 p += BIT32SZ;
350                 break;
351
352         case Rclunk:
353         case Rremove:
354                 break;
355
356         case Rstat:
357                 if (p + BIT16SZ > ep)
358                         return 0;
359                 f->nstat = GBIT16(p);
360                 p += BIT16SZ;
361                 if (p + f->nstat > ep)
362                         return 0;
363                 f->stat = p;
364                 p += f->nstat;
365                 break;
366
367         case Rwstat:
368                 break;
369         }
370
371         if (p == NULL || p > ep)
372                 return 0;
373         if (ap + size == p)
374                 return size;
375         return 0;
376 }