kconfig: use pkg-config for ncurses detection
[akaros.git] / kern / src / ns / convM2D.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-2018 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 /* It looks like the intent of this code is to check any stat that we, the
42  * kernel or our userspace, send out.
43  *
44  * Throws on error. */
45 void statcheck(uint8_t *buf, size_t nbuf)
46 {
47         uint8_t *ebuf;
48         int i;
49
50         ebuf = buf + nbuf;
51
52         if (nbuf < STAT_FIX_LEN_9P)
53                 error(EINVAL, "%s: legacy chunk too short (%lu < %u)", __func__,
54                       nbuf, STAT_FIX_LEN_9P);
55         if (nbuf != BIT16SZ + GBIT16(buf))
56                 error(EINVAL, "%s: size mismatch (%lu != %u)", __func__, nbuf,
57                       BIT16SZ + GBIT16(buf));
58
59         buf += STAT_FIX_LEN_9P - STAT_NR_STRINGS_9P * BIT16SZ;
60
61         /* Check the legacy strings that all stats have. */
62         for (i = 0; i < STAT_NR_STRINGS_9P; i++) {
63                 if (buf + BIT16SZ > ebuf)
64                         error(EINVAL, "%s: string %d (legacy) out of range",
65                               __func__, i);
66                 buf += BIT16SZ + GBIT16(buf);
67         }
68         /* Legacy 9p stats are OK
69          * TODO: consider removing this.  We get them from userspace, e.g.
70          * mkdir. */
71         if (buf == ebuf)
72                 return;
73
74         for (i = STAT_NR_STRINGS_9P; i < STAT_NR_STRINGS_AK; i++) {
75                 if (buf + BIT16SZ > ebuf)
76                         error(EINVAL, "%s: string %d (akaros) out of range",
77                               __func__, i);
78                 buf += BIT16SZ + GBIT16(buf);
79         }
80
81         if (buf + __STAT_FIX_LEN_AK_NONSTRING > ebuf)
82                 error(EINVAL, "%s: akaros chunk too short (%ld < %u)", __func__,
83                       ebuf - buf, __STAT_FIX_LEN_AK_NONSTRING);
84         buf += __STAT_FIX_LEN_AK_NONSTRING;
85         if (buf != ebuf)
86                 error(EINVAL, "%s: %lu extra bytes", __func__, ebuf - buf);
87 }
88
89 static char nullstring[] = "";
90
91 unsigned int
92 convM2D(uint8_t * buf, unsigned int nbuf, struct dir *d, char *strs)
93 {
94         uint8_t *p, *ebuf;
95         char *sv[STAT_NR_STRINGS_AK] = {nullstring};
96         int i, ns;
97         bool good_stat = false;
98         size_t msg_sz = 0;
99
100         if (nbuf < STAT_FIX_LEN_9P)
101                 return 0;
102
103         /* This M might not have all the fields we expect.  We'll ensure the
104          * strings have the right values later.  We still need to initialize all
105          * of the non-string extended fields. */
106         init_empty_dir(d);
107
108         p = buf;
109         /* They might have given us more than one M, so we need to use the size
110          * field to determine the real end of this M. */
111         msg_sz = GBIT16(p) + BIT16SZ;
112         ebuf = buf + MIN(nbuf, msg_sz);
113
114         p += BIT16SZ;   /* jump over size */
115         d->type = GBIT16(p);            p += BIT16SZ;
116         d->dev = GBIT32(p);             p += BIT32SZ;
117         d->qid.type = GBIT8(p);         p += BIT8SZ;
118         d->qid.vers = GBIT32(p);        p += BIT32SZ;
119         d->qid.path = GBIT64(p);        p += BIT64SZ;
120         d->mode = GBIT32(p);            p += BIT32SZ;
121         /* Get a first attempt at atime/mtime.  Revisit this in 2038. */
122         d->atime.tv_sec = GBIT32(p);    p += BIT32SZ;
123         d->mtime.tv_sec = GBIT32(p);    p += BIT32SZ;
124         d->length = GBIT64(p);          p += BIT64SZ;
125
126         /* They might have asked for -1, meaning "don't touch".  Need to convert
127          * that to our 64 bit times. */
128         if ((int32_t)d->atime.tv_sec == -1)
129                 d->atime.tv_sec = ~0;
130         if ((int32_t)d->mtime.tv_sec == -1)
131                 d->mtime.tv_sec = ~0;
132
133         /* Anything beyond the legacy 9p strings might not be supported.  Though
134          * if you have more, you probably have at least EVH's 9p2000.u
135          * extensions.  Once we get all of the legacy strings, we have a good
136          * stat. */
137         for (i = 0; i < STAT_NR_STRINGS_AK; i++) {
138                 if (i == STAT_NR_STRINGS_9P)
139                         good_stat = true;
140                 if (p + BIT16SZ > ebuf)
141                         goto out;
142                 ns = GBIT16(p); p += BIT16SZ;
143                 if (p + ns > ebuf)
144                         goto out;
145                 if (strs) {
146                         sv[i] = strs;
147                         memmove(strs, p, ns);
148                         strs += ns;
149                         *strs++ = '\0';
150                 }
151                 p += ns;
152         }
153
154         /* Check for 9p2000.u */
155         if (p + 3 * BIT32SZ > ebuf)
156                 goto out;
157         d->n_uid = GBIT32(p);           p += BIT32SZ;
158         d->n_gid = GBIT32(p);           p += BIT32SZ;
159         d->n_muid = GBIT32(p);          p += BIT32SZ;
160
161         /* Check for extended timespecs */
162         if (p + 4 * (2 * BIT64SZ) > ebuf)
163                 goto out;
164         d->atime.tv_sec = GBIT64(p);    p += BIT64SZ;
165         d->atime.tv_nsec = GBIT64(p);   p += BIT64SZ;
166         d->btime.tv_sec = GBIT64(p);    p += BIT64SZ;
167         d->btime.tv_nsec = GBIT64(p);   p += BIT64SZ;
168         d->ctime.tv_sec = GBIT64(p);    p += BIT64SZ;
169         d->ctime.tv_nsec = GBIT64(p);   p += BIT64SZ;
170         d->mtime.tv_sec = GBIT64(p);    p += BIT64SZ;
171         d->mtime.tv_nsec = GBIT64(p);   p += BIT64SZ;
172
173         /* Fall-through */
174 out:
175         if (!good_stat)
176                 return 0;
177         d->name = sv[0];
178         d->uid = sv[1];
179         d->gid = sv[2];
180         d->muid = sv[3];
181         d->ext = sv[4];
182         return p - buf;
183 }