xref: /plan9-contrib/sys/src/9/port/devroot.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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 	Qdir=	0,
10 
11 	Nfiles=32,	/* max root files */
12 };
13 
14 extern ulong	bootlen;
15 extern uchar	bootcode[];
16 
17 Dirtab rootdir[Nfiles];
18 
19 static uchar	*rootdata[Nfiles];
20 static int	nroot = 0;
21 
22 typedef struct Recover Recover;
23 struct Recover
24 {
25 	int	len;
26 	char	*req;
27 	Recover	*next;
28 };
29 
30 struct
31 {
32 	Lock;
33 	QLock;
34 	Rendez;
35 	Recover	*q;
36 }reclist;
37 
38 /*
39  *  add a root file
40  */
41 static void
42 addroot(char *name, uchar *contents, ulong len, int perm)
43 {
44 	Dirtab *d;
45 
46 	if(nroot >= Nfiles)
47 		panic("too many root files");
48 	rootdata[nroot] = contents;
49 	d = &rootdir[nroot];
50 	strcpy(d->name, name);
51 	d->length = len;
52 	d->perm = perm;
53 	d->qid.path = nroot+1;
54 	if(perm & CHDIR)
55 		d->qid.path |= CHDIR;
56 	nroot++;
57 }
58 
59 /*
60  *  add a root file
61  */
62 void
63 addrootfile(char *name, uchar *contents, ulong len)
64 {
65 	addroot(name, contents, len, 0555);
66 }
67 
68 /*
69  *  add a root file
70  */
71 static void
72 addrootdir(char *name)
73 {
74 	addroot(name, nil, 0, CHDIR|0555);
75 }
76 
77 static void
78 rootreset(void)
79 {
80 	addrootdir("bin");
81 	addrootdir("dev");
82 	addrootdir("env");
83 	addrootdir("net");
84 	addrootdir("net.alt");
85 	addrootdir("proc");
86 	addrootdir("root");
87 	addrootdir("srv");
88 
89 	addrootfile("boot", bootcode, bootlen);	/* always have a boot file */
90 }
91 
92 static Chan*
93 rootattach(char *spec)
94 {
95 	return devattach('/', spec);
96 }
97 
98 static int
99 rootwalk(Chan *c, char *name)
100 {
101 	if(strcmp(name, "..") == 0) {
102 		c->qid.path = Qdir|CHDIR;
103 		return 1;
104 	}
105 	if((c->qid.path & ~CHDIR) != Qdir)
106 		return 0;
107 	return devwalk(c, name, rootdir, nroot, devgen);
108 }
109 
110 static void
111 rootstat(Chan *c, char *dp)
112 {
113 	devstat(c, dp, rootdir, nroot, devgen);
114 }
115 
116 static Chan*
117 rootopen(Chan *c, int omode)
118 {
119 	switch(c->qid.path & ~CHDIR) {
120 	default:
121 		break;
122 	}
123 
124 	return devopen(c, omode, rootdir, nroot, devgen);
125 }
126 
127 /*
128  * sysremove() knows this is a nop
129  */
130 static void
131 rootclose(Chan *c)
132 {
133 	switch(c->qid.path) {
134 	default:
135 		break;
136 	}
137 }
138 
139 static int
140 rdrdy(void*)
141 {
142 	return reclist.q != 0;
143 }
144 
145 static long
146 rootread(Chan *c, void *buf, long n, vlong off)
147 {
148 	ulong t;
149 	Dirtab *d;
150 	uchar *data;
151 	ulong offset = off;
152 
153 	t = c->qid.path & ~CHDIR;
154 	switch(t){
155 	case Qdir:
156 		return devdirread(c, buf, n, rootdir, nroot, devgen);
157 	}
158 
159 	d = &rootdir[t-1];
160 	data = rootdata[t-1];
161 	if(offset >= d->length)
162 		return 0;
163 	if(offset+n > d->length)
164 		n = d->length - offset;
165 	memmove(buf, data+offset, n);
166 	return n;
167 }
168 
169 static long
170 rootwrite(Chan *c, void*, long, vlong)
171 {
172 	switch(c->qid.path & ~CHDIR){
173 	default:
174 		error(Egreg);
175 	}
176 	return 0;
177 }
178 
179 static void
180 rootcreate(Chan *c, char *name, int mode, ulong perm)
181 {
182 	if(!iseve() || c->qid.path != (CHDIR|Qdir) ||
183 	   (perm & CHDIR) == 0 || mode != OREAD)
184 		error(Eperm);
185 	addrootdir(name);
186 	c->flag |= COPEN;
187 	c->mode = OREAD;
188 }
189 
190 Dev rootdevtab = {
191 	'/',
192 	"root",
193 
194 	rootreset,
195 	devinit,
196 	rootattach,
197 	devclone,
198 	rootwalk,
199 	rootstat,
200 	rootopen,
201 	rootcreate,
202 	rootclose,
203 	rootread,
204 	devbread,
205 	rootwrite,
206 	devbwrite,
207 	devremove,
208 	devwstat,
209 };
210