xref: /plan9/sys/src/cmd/unix/drawterm/kern/devroot.c (revision 0d601874851962e88c6c60fdd2e637bba04e13c2)
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