]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/devroot.c
provide /n and /mnt early in bootrc to allow consistent use in /lib/namespace
[plan9front.git] / sys / src / 9 / 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         if(strlen(name) >= sizeof d->name)
67                 panic("root file name too long: %s", name);
68         strcpy(d->name, name);
69         d->length = len;
70         d->perm = perm;
71         d->qid.type = 0;
72         d->qid.vers = 0;
73         d->qid.path = ++l->ndir + l->base;
74         if(perm & DMDIR)
75                 d->qid.type |= QTDIR;
76 }
77
78 /*
79  *  add a root file
80  */
81 void
82 addbootfile(char *name, uchar *contents, ulong len)
83 {
84         addlist(&bootlist, name, contents, len, 0555);
85 }
86
87 /*
88  *  add a root directory
89  */
90 static void
91 addrootdir(char *name)
92 {
93         addlist(&rootlist, name, nil, 0, DMDIR|0555);
94 }
95
96 static void
97 rootreset(void)
98 {
99         addrootdir("bin");
100         addrootdir("dev");
101         addrootdir("env");
102         addrootdir("fd");
103         addrootdir("mnt");
104         addrootdir("n");
105         addrootdir("net");
106         addrootdir("net.alt");
107         addrootdir("proc");
108         addrootdir("root");
109         addrootdir("srv");
110         addrootdir("shr");
111 }
112
113 static Chan*
114 rootattach(char *spec)
115 {
116         return devattach('/', spec);
117 }
118
119 static int
120 rootgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
121 {
122         int t;
123         Dirtab *d;
124         Dirlist *l;
125
126         switch((int)c->qid.path){
127         case Qdir:
128                 if(s == DEVDOTDOT){
129                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
130                         return 1;
131                 }
132                 return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
133         case Qboot:
134                 if(s == DEVDOTDOT){
135                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
136                         return 1;
137                 }
138                 return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
139         default:
140                 if(s == DEVDOTDOT){
141                         if((int)c->qid.path < Qboot)
142                                 devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
143                         else
144                                 devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
145                         return 1;
146                 }
147                 if(s != 0)
148                         return -1;
149                 if((int)c->qid.path < Qboot){
150                         t = c->qid.path-1;
151                         l = &rootlist;
152                 }else{
153                         t = c->qid.path - Qboot - 1;
154                         l = &bootlist;
155                 }
156                 if(t >= l->ndir)
157                         return -1;
158 if(t < 0){
159 print("rootgen %llud %d %d\n", c->qid.path, s, t);
160 panic("whoops");
161 }
162                 d = &l->dir[t];
163                 devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
164                 return 1;
165         }
166 }
167
168 static Walkqid*
169 rootwalk(Chan *c, Chan *nc, char **name, int nname)
170 {
171         return devwalk(c,  nc, name, nname, nil, 0, rootgen);
172 }
173
174 static int
175 rootstat(Chan *c, uchar *dp, int n)
176 {
177         return devstat(c, dp, n, nil, 0, rootgen);
178 }
179
180 static Chan*
181 rootopen(Chan *c, int omode)
182 {
183         return devopen(c, omode, nil, 0, devgen);
184 }
185
186 /*
187  * sysremove() knows this is a nop
188  */
189 static void
190 rootclose(Chan*)
191 {
192 }
193
194 static long
195 rootread(Chan *c, void *buf, long n, vlong off)
196 {
197         ulong t;
198         Dirtab *d;
199         Dirlist *l;
200         uchar *data;
201         ulong offset = off;
202
203         t = c->qid.path;
204         switch(t){
205         case Qdir:
206         case Qboot:
207                 return devdirread(c, buf, n, nil, 0, rootgen);
208         }
209
210         if(t<Qboot)
211                 l = &rootlist;
212         else{
213                 t -= Qboot;
214                 l = &bootlist;
215         }
216
217         t--;
218         if(t >= l->ndir)
219                 error(Egreg);
220
221         d = &l->dir[t];
222         data = l->data[t];
223         if(offset >= d->length)
224                 return 0;
225         if(offset+n > d->length)
226                 n = d->length - offset;
227 #ifdef asdf
228 print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n", 
229                 t, buf, data, offset, offset, n,
230                 ((ulong*)(data+offset))[0],
231                 ((ulong*)(data+offset))[1],
232                 ((ulong*)(data+offset))[2]);
233 #endif asdf
234         memmove(buf, data+offset, n);
235         return n;
236 }
237
238 static long
239 rootwrite(Chan*, void*, long, vlong)
240 {
241         error(Egreg);
242         return 0;
243 }
244
245 Dev rootdevtab = {
246         '/',
247         "root",
248
249         rootreset,
250         devinit,
251         devshutdown,
252         rootattach,
253         rootwalk,
254         rootstat,
255         rootopen,
256         devcreate,
257         rootclose,
258         rootread,
259         devbread,
260         rootwrite,
261         devbwrite,
262         devremove,
263         devwstat,
264 };
265