]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/devroot.c
kernel: try to catch some (rare) mistakes
[plan9front.git] / sys / src / 9 / port / devroot.c
1 #include        "u.h"
2 #include        "../port/lib.h"
3 #include        "mem.h"
4 #include        "dat.h"
5 #include        "fns.h"
6 #include        "../port/error.h"
7
8 enum
9 {
10         Qdir = 0,
11         Qboot = 0x1000,
12
13         Nrootfiles = 32,
14         Nbootfiles = 32,
15 };
16
17 typedef struct Dirlist Dirlist;
18 struct Dirlist
19 {
20         uint base;
21         Dirtab *dir;
22         uchar **data;
23         int ndir;
24         int mdir;
25 };
26
27 static Dirtab rootdir[Nrootfiles] = {
28         "#/",           {Qdir, 0, QTDIR},       0,              DMDIR|0555,
29         "boot", {Qboot, 0, QTDIR},      0,              DMDIR|0555,
30 };
31 static uchar *rootdata[Nrootfiles];
32 static Dirlist rootlist = 
33 {
34         0,
35         rootdir,
36         rootdata,
37         2,
38         Nrootfiles
39 };
40
41 static Dirtab bootdir[Nbootfiles] = {
42         "boot", {Qboot, 0, QTDIR},      0,              DMDIR|0555,
43 };
44 static uchar *bootdata[Nbootfiles];
45 static Dirlist bootlist =
46 {
47         Qboot,
48         bootdir,
49         bootdata,
50         1,
51         Nbootfiles
52 };
53
54 /*
55  *  add a file to the list
56  */
57 static void
58 addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm)
59 {
60         Dirtab *d;
61
62         if(l->ndir >= l->mdir)
63                 panic("too many root files");
64         l->data[l->ndir] = contents;
65         d = &l->dir[l->ndir];
66         if(strlen(name) >= sizeof d->name)
67                 panic("root file name too long: %s", name);
68         strcpy(d->name, name);
69         d->length = len;
70         d->perm = perm;
71         d->qid.type = 0;
72         d->qid.vers = 0;
73         d->qid.path = ++l->ndir + l->base;
74         if(perm & DMDIR)
75                 d->qid.type |= QTDIR;
76 }
77
78 /*
79  *  add a root file
80  */
81 void
82 addbootfile(char *name, uchar *contents, ulong len)
83 {
84         addlist(&bootlist, name, contents, len, 0555);
85 }
86
87 /*
88  *  add a root directory
89  */
90 static void
91 addrootdir(char *name)
92 {
93         addlist(&rootlist, name, nil, 0, DMDIR|0555);
94 }
95
96 static void
97 rootreset(void)
98 {
99         addrootdir("bin");
100         addrootdir("dev");
101         addrootdir("env");
102         addrootdir("fd");
103         addrootdir("mnt");
104         addrootdir("net");
105         addrootdir("net.alt");
106         addrootdir("proc");
107         addrootdir("root");
108         addrootdir("srv");
109         addrootdir("shr");
110 }
111
112 static Chan*
113 rootattach(char *spec)
114 {
115         return devattach('/', spec);
116 }
117
118 static int
119 rootgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
120 {
121         int t;
122         Dirtab *d;
123         Dirlist *l;
124
125         switch((int)c->qid.path){
126         case Qdir:
127                 if(s == DEVDOTDOT){
128                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
129                         return 1;
130                 }
131                 return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
132         case Qboot:
133                 if(s == DEVDOTDOT){
134                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
135                         return 1;
136                 }
137                 return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
138         default:
139                 if(s == DEVDOTDOT){
140                         if((int)c->qid.path < Qboot)
141                                 devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
142                         else
143                                 devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
144                         return 1;
145                 }
146                 if(s != 0)
147                         return -1;
148                 if((int)c->qid.path < Qboot){
149                         t = c->qid.path-1;
150                         l = &rootlist;
151                 }else{
152                         t = c->qid.path - Qboot - 1;
153                         l = &bootlist;
154                 }
155                 if(t >= l->ndir)
156                         return -1;
157 if(t < 0){
158 print("rootgen %llud %d %d\n", c->qid.path, s, t);
159 panic("whoops");
160 }
161                 d = &l->dir[t];
162                 devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
163                 return 1;
164         }
165 }
166
167 static Walkqid*
168 rootwalk(Chan *c, Chan *nc, char **name, int nname)
169 {
170         return devwalk(c,  nc, name, nname, nil, 0, rootgen);
171 }
172
173 static int
174 rootstat(Chan *c, uchar *dp, int n)
175 {
176         return devstat(c, dp, n, nil, 0, rootgen);
177 }
178
179 static Chan*
180 rootopen(Chan *c, int omode)
181 {
182         return devopen(c, omode, nil, 0, devgen);
183 }
184
185 /*
186  * sysremove() knows this is a nop
187  */
188 static void
189 rootclose(Chan*)
190 {
191 }
192
193 static long
194 rootread(Chan *c, void *buf, long n, vlong off)
195 {
196         ulong t;
197         Dirtab *d;
198         Dirlist *l;
199         uchar *data;
200         ulong offset = off;
201
202         t = c->qid.path;
203         switch(t){
204         case Qdir:
205         case Qboot:
206                 return devdirread(c, buf, n, nil, 0, rootgen);
207         }
208
209         if(t<Qboot)
210                 l = &rootlist;
211         else{
212                 t -= Qboot;
213                 l = &bootlist;
214         }
215
216         t--;
217         if(t >= l->ndir)
218                 error(Egreg);
219
220         d = &l->dir[t];
221         data = l->data[t];
222         if(offset >= d->length)
223                 return 0;
224         if(offset+n > d->length)
225                 n = d->length - offset;
226 #ifdef asdf
227 print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n", 
228                 t, buf, data, offset, offset, n,
229                 ((ulong*)(data+offset))[0],
230                 ((ulong*)(data+offset))[1],
231                 ((ulong*)(data+offset))[2]);
232 #endif asdf
233         memmove(buf, data+offset, n);
234         return n;
235 }
236
237 static long
238 rootwrite(Chan*, void*, long, vlong)
239 {
240         error(Egreg);
241         return 0;
242 }
243
244 Dev rootdevtab = {
245         '/',
246         "root",
247
248         rootreset,
249         devinit,
250         devshutdown,
251         rootattach,
252         rootwalk,
253         rootstat,
254         rootopen,
255         devcreate,
256         rootclose,
257         rootread,
258         devbread,
259         rootwrite,
260         devbwrite,
261         devremove,
262         devwstat,
263 };
264