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