FreeBSD/Linux Kernel Cross Reference
sys/port/devroot.c
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 == 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 %llud %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*
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 int
171 rootstat(Chan *c, uchar *dp, int n)
172 {
173 return devstat(c, dp, n, nil, 0, rootgen);
174 }
175
176 static Chan*
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
186 rootclose(Chan*)
187 {
188 }
189
190 static long
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 #ifdef asdf
224 print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n",
225 t, buf, data, offset, offset, n,
226 ((ulong*)(data+offset))[0],
227 ((ulong*)(data+offset))[1],
228 ((ulong*)(data+offset))[2]);
229 #endif asdf
230 memmove(buf, data+offset, n);
231 return n;
232 }
233
234 static long
235 rootwrite(Chan*, void*, long, vlong)
236 {
237 error(Egreg);
238 return 0;
239 }
240
241 Dev rootdevtab = {
242 '/',
243 "root",
244
245 rootreset,
246 devinit,
247 devshutdown,
248 rootattach,
249 rootwalk,
250 rootstat,
251 rootopen,
252 devcreate,
253 rootclose,
254 rootread,
255 devbread,
256 rootwrite,
257 devbwrite,
258 devremove,
259 devwstat,
260 };
261
Cache object: c11d27645c88dea9cca3a4c64e7633b6
|