xref: /plan9/sys/src/9/port/devroot.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
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 Dev rootdevtab = {
180 	'/',
181 	"root",
182 
183 	rootreset,
184 	devinit,
185 	rootattach,
186 	devclone,
187 	rootwalk,
188 	rootstat,
189 	rootopen,
190 	devcreate,
191 	rootclose,
192 	rootread,
193 	devbread,
194 	rootwrite,
195 	devbwrite,
196 	devremove,
197 	devwstat,
198 };
199