Adds /mnt/ to #r
[akaros.git] / kern / drivers / dev / root.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 /* courtesy of the inferno mkroot script. */
17 int rootmaxq = 13;
18 struct dirtab roottab[13] = {
19         {"",    {0, 0, QTDIR},   0,     0555},
20         {"chan",        {1, 0, QTDIR},   0,     0555},
21         {"dev", {2, 0, QTDIR},   0,     0555},
22         {"fd",  {3, 0, QTDIR},   0,     0555},
23         {"prog",        {4, 0, QTDIR},   0,     0555},
24         {"prof",        {5, 0, QTDIR},   0,     0555},
25         {"net", {6, 0, QTDIR},   0,     0555},
26         {"net.alt",     {7, 0, QTDIR},   0,     0555},
27         {"nvfs",        {8, 0, QTDIR},   0,     0555},
28         {"env", {9, 0, QTDIR},   0,     0555},
29         {"root",        {10, 0, QTDIR},  0,     0555},
30         {"srv", {11, 0, QTDIR},  0,     0555},
31         /* not courtesy of mkroot */
32         {"mnt", {12, 0, QTDIR},  0,     0555},
33 };
34 struct rootdata rootdata[13] = {
35         {0,      &roottab[1],    12,    NULL},
36         {0,      NULL,   0,      NULL},
37         {0,      NULL,   0,      NULL},
38         {0,      NULL,   0,      NULL},
39         {0,      NULL,   0,      NULL},
40         {0,      NULL,   0,      NULL},
41         {0,      NULL,   0,      NULL},
42         {0,      NULL,   0,      NULL},
43         {0,      NULL,   0,      NULL},
44         {0,      NULL,   0,      NULL},
45         {0,      NULL,   0,      NULL},
46         {0,      NULL,   0,      NULL},
47         {0,      NULL,   0,      NULL},
48 };
49
50 static struct chan*
51 rootattach(char *spec)
52 {
53         int i;
54         uint32_t len;
55         struct rootdata *r;
56
57         if(*spec)
58                 error(Ebadspec);
59         for (i = 0; i < rootmaxq; i++){
60                 r = &rootdata[i];
61                 if (r->sizep){
62                         len = *r->sizep;
63                         r->size = len;
64                         roottab[i].length = len;
65                 }
66         }
67         return devattach('r', spec);
68 }
69
70 static int
71 rootgen(struct chan *c, char *name,
72         struct dirtab *tab, int nd, int s, struct dir *dp)
73 {
74         int p, i;
75         struct rootdata *r;
76
77         if(s == DEVDOTDOT){
78                 p = rootdata[c->qid.path].dotdot;
79                 c->qid.path = p;
80                 c->qid.type = QTDIR;
81                 name = "#r";
82                 if(p != 0){
83                         for(i = 0; i < rootmaxq; i++)
84                                 if(roottab[i].qid.path == c->qid.path){
85                                         name = roottab[i].name;
86                                         break;
87                                 }
88                 }
89                 devdir(c, c->qid, name, 0, eve, 0555, dp);
90                 return 1;
91         }
92         if(name != NULL){
93                 isdir(c);
94                 r = &rootdata[(int)c->qid.path];
95                 tab = r->ptr;
96                 for(i=0; i<r->size; i++, tab++)
97                         if(strcmp(tab->name, name) == 0){
98                                 devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
99                                 return 1;
100                         }
101                 return -1;
102         }
103         if(s >= nd)
104                 return -1;
105         tab += s;
106         devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
107         return 1;
108 }
109
110 static struct walkqid*
111 rootwalk(struct chan *c, struct chan *nc, char **name, int nname)
112 {
113         uint32_t p;
114
115         p = c->qid.path;
116         if(nname == 0)
117                 p = rootdata[p].dotdot;
118         return devwalk(c, nc, name, nname, rootdata[p].ptr, rootdata[p].size, rootgen);
119 }
120
121 static int
122 rootstat(struct chan *c, uint8_t *dp, int n)
123 {
124         int p;
125
126         p = rootdata[c->qid.path].dotdot;
127         return devstat(c, dp, n, rootdata[p].ptr, rootdata[p].size, rootgen);
128 }
129
130 static struct chan*
131 rootopen(struct chan *c, int omode)
132 {
133         int p;
134
135         p = rootdata[c->qid.path].dotdot;
136         return devopen(c, omode, rootdata[p].ptr, rootdata[p].size, rootgen);
137 }
138
139 /*
140  * sysremove() knows this is a nop
141  */
142 static void      
143 rootclose(struct chan *c)
144 {
145 }
146
147 static long      
148 rootread(struct chan *c, void *buf, long n, int64_t offset)
149 {
150         uint32_t p, len;
151         uint8_t *data;
152
153         p = c->qid.path;
154         if(c->qid.type & QTDIR)
155                 return devdirread(c, buf, n, rootdata[p].ptr, rootdata[p].size, rootgen);
156         len = rootdata[p].size;
157         if(offset < 0 || offset >= len)
158                 return 0;
159         if(offset+n > len)
160                 n = len - offset;
161         data = rootdata[p].ptr;
162         memmove(buf, data+offset, n);
163         return n;
164 }
165
166 static long      
167 rootwrite(struct chan *c, void *a, long n, int64_t off)
168 {
169         error(Eperm);
170         return 0;
171 }
172
173 struct dev rootdevtab __devtab = {
174         'r',
175         "root",
176         devreset,
177         devinit,
178         devshutdown,
179         rootattach,
180         rootwalk,
181         rootstat,
182         rootopen,
183         devcreate,
184         rootclose,
185         rootread,
186         devbread,
187         rootwrite,
188         devbwrite,
189         devremove,
190         devwstat,
191 };