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