devroot.c (4237B)
1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "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 *dt, int i, 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 *c) 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 230 memmove(buf, data+offset, n); 231 return n; 232 } 233 234 static long 235 rootwrite(Chan *c, void *v, long l, vlong vl) 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