xref: /plan9-contrib/sys/src/9/port/devroot.c (revision fb7f0c934c48abaed6040d054ef636408c3c522d)
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 != 0)
137 			return -1;
138 		if((int)c->qid.path < Qboot){
139 			t = c->qid.path-1;
140 			l = &rootlist;
141 		}else{
142 			t = c->qid.path - Qboot - 1;
143 			l = &bootlist;
144 		}
145 		if(t >= l->ndir)
146 			return -1;
147 		d = &l->dir[t];
148 		devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
149 		return 1;
150 	}
151 	return -1;
152 }
153 
154 static Walkqid*
155 rootwalk(Chan *c, Chan *nc, char **name, int nname)
156 {
157 	return devwalk(c,  nc, name, nname, nil, 0, rootgen);
158 }
159 
160 static int
161 rootstat(Chan *c, uchar *dp, int n)
162 {
163 	return devstat(c, dp, n, nil, 0, rootgen);
164 }
165 
166 static Chan*
167 rootopen(Chan *c, int omode)
168 {
169 	return devopen(c, omode, nil, 0, devgen);
170 }
171 
172 /*
173  * sysremove() knows this is a nop
174  */
175 static void
176 rootclose(Chan*)
177 {
178 }
179 
180 static long
181 rootread(Chan *c, void *buf, long n, vlong off)
182 {
183 	ulong t;
184 	Dirtab *d;
185 	Dirlist *l;
186 	uchar *data;
187 	ulong offset = off;
188 
189 	t = c->qid.path;
190 	switch(t){
191 	case Qdir:
192 	case Qboot:
193 		return devdirread(c, buf, n, nil, 0, rootgen);
194 	}
195 
196 	if(t<Qboot)
197 		l = &rootlist;
198 	else{
199 		t -= Qboot;
200 		l = &bootlist;
201 	}
202 
203 	t--;
204 	if(t >= l->ndir)
205 		error(Egreg);
206 
207 	d = &l->dir[t];
208 	data = l->data[t];
209 	if(offset >= d->length)
210 		return 0;
211 	if(offset+n > d->length)
212 		n = d->length - offset;
213 	memmove(buf, data+offset, n);
214 	return n;
215 }
216 
217 static long
218 rootwrite(Chan*, void*, long, vlong)
219 {
220 	error(Egreg);
221 	return 0;
222 }
223 
224 Dev rootdevtab = {
225 	'/',
226 	"root",
227 
228 	rootreset,
229 	devinit,
230 	devshutdown,
231 	rootattach,
232 	rootwalk,
233 	rootstat,
234 	rootopen,
235 	devcreate,
236 	rootclose,
237 	rootread,
238 	devbread,
239 	rootwrite,
240 	devbwrite,
241 	devremove,
242 	devwstat,
243 };
244 
245