xref: /plan9-contrib/sys/src/9k/port/devroot.c (revision 9ef1f84b659abcb917c5c090acbce0772e494f21)
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