1 #include "u.h" 2 #include "lib.h" 3 #include "dat.h" 4 #include "fns.h" 5 #include "error.h" 6 7 enum 8 { 9 Qdir = 0, 10 Qboot = 0x1000, 11 Qmnt = 0x2000, 12 Qfactotum, 13 14 Nrootfiles = 32, 15 Nbootfiles = 32, 16 Nmntfiles = 2, 17 }; 18 19 typedef struct Dirlist Dirlist; 20 struct Dirlist 21 { 22 uint base; 23 Dirtab *dir; 24 uchar **data; 25 int ndir; 26 int mdir; 27 }; 28 29 static Dirtab rootdir[Nrootfiles] = { 30 "#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555, 31 "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555, 32 "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, 33 }; 34 static uchar *rootdata[Nrootfiles]; 35 static Dirlist rootlist = 36 { 37 0, 38 rootdir, 39 rootdata, 40 3, 41 Nrootfiles 42 }; 43 44 static Dirtab bootdir[Nbootfiles] = { 45 "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555, 46 }; 47 static uchar *bootdata[Nbootfiles]; 48 static Dirlist bootlist = 49 { 50 Qboot, 51 bootdir, 52 bootdata, 53 1, 54 Nbootfiles 55 }; 56 57 static uchar *mntdata[Nmntfiles]; 58 static Dirtab mntdir[Nmntfiles] = { 59 "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, 60 "factotum", {Qfactotum, 0, QTDIR}, 0, DMDIR|0555, 61 }; 62 static Dirlist mntlist = 63 { 64 Qmnt, 65 mntdir, 66 mntdata, 67 2, 68 Nmntfiles 69 }; 70 71 /* 72 * add a file to the list 73 */ 74 static void 75 addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm) 76 { 77 Dirtab *d; 78 79 if(l->ndir >= l->mdir) 80 panic("too many root files"); 81 l->data[l->ndir] = contents; 82 d = &l->dir[l->ndir]; 83 strcpy(d->name, name); 84 d->length = len; 85 d->perm = perm; 86 d->qid.type = 0; 87 d->qid.vers = 0; 88 d->qid.path = ++l->ndir + l->base; 89 if(perm & DMDIR) 90 d->qid.type |= QTDIR; 91 } 92 93 /* 94 * add a root file 95 */ 96 void 97 addbootfile(char *name, uchar *contents, ulong len) 98 { 99 addlist(&bootlist, name, contents, len, 0555); 100 } 101 102 /* 103 * add a root directory 104 */ 105 static void 106 addrootdir(char *name) 107 { 108 addlist(&rootlist, name, nil, 0, DMDIR|0555); 109 } 110 111 static void 112 rootreset(void) 113 { 114 addrootdir("bin"); 115 addrootdir("dev"); 116 addrootdir("env"); 117 addrootdir("fd"); 118 addrootdir("net"); 119 addrootdir("net.alt"); 120 addrootdir("proc"); 121 addrootdir("root"); 122 addrootdir("srv"); 123 } 124 125 static Chan* 126 rootattach(char *spec) 127 { 128 return devattach('/', spec); 129 } 130 131 static int 132 rootgen(Chan *c, char *name, Dirtab *dirt, int ndirt, int s, Dir *dp) 133 { 134 int t; 135 Dirtab *d; 136 Dirlist *l; 137 138 USED(dirt); 139 USED(ndirt); 140 141 switch((int)c->qid.path){ 142 case Qdir: 143 if(s == DEVDOTDOT){ 144 Qid tqiddir = {Qdir, 0, QTDIR}; 145 devdir(c, tqiddir, "#/", 0, eve, 0555, dp); 146 return 1; 147 } 148 return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp); 149 case Qmnt: 150 if(s == DEVDOTDOT){ 151 Qid tqiddir = {Qdir, 0, QTDIR}; 152 devdir(c, tqiddir, "#/", 0, eve, 0555, dp); 153 return 1; 154 } 155 return devgen(c, name, mntlist.dir, mntlist.ndir, s, dp); 156 case Qboot: 157 if(s == DEVDOTDOT){ 158 Qid tqiddir = {Qdir, 0, QTDIR}; 159 devdir(c, tqiddir, "#/", 0, eve, 0555, dp); 160 return 1; 161 } 162 return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp); 163 default: 164 if(s == DEVDOTDOT){ 165 Qid tqiddir = {Qdir, 0, QTDIR}; 166 tqiddir.path = c->qid.path&0xF000; 167 devdir(c, tqiddir, "#/", 0, eve, 0555, dp); 168 return 1; 169 } 170 if(s != 0) 171 return -1; 172 switch((int)c->qid.path & 0xF000){ 173 case Qdir: 174 t = c->qid.path-1; 175 l = &rootlist; 176 break; 177 case Qboot: 178 t = c->qid.path - Qboot - 1; 179 l = &bootlist; 180 break; 181 case Qmnt: 182 t = c->qid.path - Qmnt - 1; 183 l = &mntlist; 184 break; 185 default: 186 return -1; 187 } 188 if(t >= l->ndir) 189 return -1; 190 if(t < 0){ 191 print("rootgen %llud %d %d\n", c->qid.path, s, t); 192 panic("whoops"); 193 } 194 d = &l->dir[t]; 195 devdir(c, d->qid, d->name, d->length, eve, d->perm, dp); 196 return 1; 197 } 198 return -1; 199 } 200 201 static Walkqid* 202 rootwalk(Chan *c, Chan *nc, char **name, int nname) 203 { 204 return devwalk(c, nc, name, nname, nil, 0, rootgen); 205 } 206 207 static int 208 rootstat(Chan *c, uchar *dp, int n) 209 { 210 return devstat(c, dp, n, nil, 0, rootgen); 211 } 212 213 static Chan* 214 rootopen(Chan *c, int omode) 215 { 216 return devopen(c, omode, nil, 0, devgen); 217 } 218 219 /* 220 * sysremove() knows this is a nop 221 */ 222 static void 223 rootclose(Chan *c) 224 { 225 USED(c); 226 } 227 228 static long 229 rootread(Chan *c, void *buf, long n, vlong off) 230 { 231 ulong t; 232 Dirtab *d; 233 Dirlist *l; 234 uchar *data; 235 ulong offset = off; 236 237 t = c->qid.path; 238 switch(t){ 239 case Qdir: 240 case Qboot: 241 case Qmnt: 242 return devdirread(c, buf, n, nil, 0, rootgen); 243 } 244 245 if(t&Qboot) 246 l = &bootlist; 247 else if(t&Qmnt) 248 l = &mntlist; 249 else 250 l = &bootlist; 251 t &= 0xFFF; 252 t--; 253 254 if(t >= l->ndir) 255 error(Egreg); 256 257 d = &l->dir[t]; 258 data = l->data[t]; 259 if(offset >= d->length) 260 return 0; 261 if(offset+n > d->length) 262 n = d->length - offset; 263 memmove(buf, data+offset, n); 264 return n; 265 } 266 267 static long 268 rootwrite(Chan *c, void *v, long n, vlong o) 269 { 270 USED(c); 271 USED(v); 272 USED(n); 273 USED(o); 274 275 error(Egreg); 276 return 0; 277 } 278 279 Dev rootdevtab = { 280 '/', 281 "root", 282 283 rootreset, 284 devinit, 285 devshutdown, 286 rootattach, 287 rootwalk, 288 rootstat, 289 rootopen, 290 devcreate, 291 rootclose, 292 rootread, 293 devbread, 294 rootwrite, 295 devbwrite, 296 devremove, 297 devwstat, 298 }; 299 300