]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/devroot.c
devshr: fixed crash
[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         strcpy(d->name, name);
67         d->length = len;
68         d->perm = perm;
69         d->qid.type = 0;
70         d->qid.vers = 0;
71         d->qid.path = ++l->ndir + l->base;
72         if(perm & DMDIR)
73                 d->qid.type |= QTDIR;
74 }
75
76 /*
77  *  add a root file
78  */
79 void
80 addbootfile(char *name, uchar *contents, ulong len)
81 {
82         addlist(&bootlist, name, contents, len, 0555);
83 }
84
85 /*
86  *  add a root directory
87  */
88 static void
89 addrootdir(char *name)
90 {
91         addlist(&rootlist, name, nil, 0, DMDIR|0555);
92 }
93
94 static void
95 rootreset(void)
96 {
97         addrootdir("bin");
98         addrootdir("dev");
99         addrootdir("env");
100         addrootdir("fd");
101         addrootdir("mnt");
102         addrootdir("net");
103         addrootdir("net.alt");
104         addrootdir("proc");
105         addrootdir("root");
106         addrootdir("srv");
107 }
108
109 static Chan*
110 rootattach(char *spec)
111 {
112         return devattach('/', spec);
113 }
114
115 static int
116 rootgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
117 {
118         int t;
119         Dirtab *d;
120         Dirlist *l;
121
122         switch((int)c->qid.path){
123         case Qdir:
124                 if(s == DEVDOTDOT){
125                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
126                         return 1;
127                 }
128                 return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
129         case Qboot:
130                 if(s == DEVDOTDOT){
131                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
132                         return 1;
133                 }
134                 return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
135         default:
136                 if(s == DEVDOTDOT){
137                         if((int)c->qid.path < Qboot)
138                                 devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
139                         else
140                                 devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
141                         return 1;
142                 }
143                 if(s != 0)
144                         return -1;
145                 if((int)c->qid.path < Qboot){
146                         t = c->qid.path-1;
147                         l = &rootlist;
148                 }else{
149                         t = c->qid.path - Qboot - 1;
150                         l = &bootlist;
151                 }
152                 if(t >= l->ndir)
153                         return -1;
154 if(t < 0){
155 print("rootgen %llud %d %d\n", c->qid.path, s, t);
156 panic("whoops");
157 }
158                 d = &l->dir[t];
159                 devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
160                 return 1;
161         }
162 }
163
164 static Walkqid*
165 rootwalk(Chan *c, Chan *nc, char **name, int nname)
166 {
167         return devwalk(c,  nc, name, nname, nil, 0, rootgen);
168 }
169
170 static int
171 rootstat(Chan *c, uchar *dp, int n)
172 {
173         return devstat(c, dp, n, nil, 0, rootgen);
174 }
175
176 static Chan*
177 rootopen(Chan *c, int omode)
178 {
179         return devopen(c, omode, nil, 0, devgen);
180 }
181
182 /*
183  * sysremove() knows this is a nop
184  */
185 static void
186 rootclose(Chan*)
187 {
188 }
189
190 static long
191 rootread(Chan *c, void *buf, long n, vlong off)
192 {
193         ulong t;
194         Dirtab *d;
195         Dirlist *l;
196         uchar *data;
197         ulong offset = off;
198
199         t = c->qid.path;
200         switch(t){
201         case Qdir:
202         case Qboot:
203                 return devdirread(c, buf, n, nil, 0, rootgen);
204         }
205
206         if(t<Qboot)
207                 l = &rootlist;
208         else{
209                 t -= Qboot;
210                 l = &bootlist;
211         }
212
213         t--;
214         if(t >= l->ndir)
215                 error(Egreg);
216
217         d = &l->dir[t];
218         data = l->data[t];
219         if(offset >= d->length)
220                 return 0;
221         if(offset+n > d->length)
222                 n = d->length - offset;
223 #ifdef asdf
224 print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n", 
225                 t, buf, data, offset, offset, n,
226                 ((ulong*)(data+offset))[0],
227                 ((ulong*)(data+offset))[1],
228                 ((ulong*)(data+offset))[2]);
229 #endif asdf
230         memmove(buf, data+offset, n);
231         return n;
232 }
233
234 static long
235 rootwrite(Chan*, void*, long, vlong)
236 {
237         error(Egreg);
238         return 0;
239 }
240
241 Dev rootdevtab = {
242         '/',
243         "root",
244
245         rootreset,
246         devinit,
247         devshutdown,
248         rootattach,
249         rootwalk,
250         rootstat,
251         rootopen,
252         devcreate,
253         rootclose,
254         rootread,
255         devbread,
256         rootwrite,
257         devbwrite,
258         devremove,
259         devwstat,
260 };
261