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