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