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
addlist(Dirlist * l,char * name,uchar * contents,ulong len,int perm)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
addbootfile(char * name,uchar * contents,ulong len)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
addrootdir(char * name)89 addrootdir(char *name)
90 {
91 addlist(&rootlist, name, nil, 0, DMDIR|0555);
92 }
93
94 static void
rootreset(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*
rootattach(char * spec)110 rootattach(char *spec)
111 {
112 return devattach('/', spec);
113 }
114
115 static int
rootgen(Chan * c,char * name,Dirtab *,int,int s,Dir * dp)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 %#llux %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*
rootwalk(Chan * c,Chan * nc,char ** name,int nname)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 long
rootstat(Chan * c,uchar * dp,long n)171 rootstat(Chan *c, uchar *dp, long n)
172 {
173 return devstat(c, dp, n, nil, 0, rootgen);
174 }
175
176 static Chan*
rootopen(Chan * c,int omode)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
rootclose(Chan *)186 rootclose(Chan*)
187 {
188 }
189
190 static long
rootread(Chan * c,void * buf,long n,vlong off)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 memmove(buf, data+offset, n);
224 return n;
225 }
226
227 static long
rootwrite(Chan *,void *,long,vlong)228 rootwrite(Chan*, void*, long, vlong)
229 {
230 error(Egreg);
231 return 0;
232 }
233
234 Dev rootdevtab = {
235 '/',
236 "root",
237
238 rootreset,
239 devinit,
240 devshutdown,
241 rootattach,
242 rootwalk,
243 rootstat,
244 rootopen,
245 devcreate,
246 rootclose,
247 rootread,
248 devbread,
249 rootwrite,
250 devbwrite,
251 devremove,
252 devwstat,
253 };
254
255