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 != 0) 137 return -1; 138 if((int)c->qid.path < Qboot){ 139 t = c->qid.path-1; 140 l = &rootlist; 141 }else{ 142 t = c->qid.path - Qboot - 1; 143 l = &bootlist; 144 } 145 if(t >= l->ndir) 146 return -1; 147 d = &l->dir[t]; 148 devdir(c, d->qid, d->name, d->length, eve, d->perm, dp); 149 return 1; 150 } 151 return -1; 152 } 153 154 static Walkqid* 155 rootwalk(Chan *c, Chan *nc, char **name, int nname) 156 { 157 return devwalk(c, nc, name, nname, nil, 0, rootgen); 158 } 159 160 static int 161 rootstat(Chan *c, uchar *dp, int n) 162 { 163 return devstat(c, dp, n, nil, 0, rootgen); 164 } 165 166 static Chan* 167 rootopen(Chan *c, int omode) 168 { 169 return devopen(c, omode, nil, 0, devgen); 170 } 171 172 /* 173 * sysremove() knows this is a nop 174 */ 175 static void 176 rootclose(Chan*) 177 { 178 } 179 180 static long 181 rootread(Chan *c, void *buf, long n, vlong off) 182 { 183 ulong t; 184 Dirtab *d; 185 Dirlist *l; 186 uchar *data; 187 ulong offset = off; 188 189 t = c->qid.path; 190 switch(t){ 191 case Qdir: 192 case Qboot: 193 return devdirread(c, buf, n, nil, 0, rootgen); 194 } 195 196 if(t<Qboot) 197 l = &rootlist; 198 else{ 199 t -= Qboot; 200 l = &bootlist; 201 } 202 203 t--; 204 if(t >= l->ndir) 205 error(Egreg); 206 207 d = &l->dir[t]; 208 data = l->data[t]; 209 if(offset >= d->length) 210 return 0; 211 if(offset+n > d->length) 212 n = d->length - offset; 213 memmove(buf, data+offset, n); 214 return n; 215 } 216 217 static long 218 rootwrite(Chan*, void*, long, vlong) 219 { 220 error(Egreg); 221 return 0; 222 } 223 224 Dev rootdevtab = { 225 '/', 226 "root", 227 228 rootreset, 229 devinit, 230 devshutdown, 231 rootattach, 232 rootwalk, 233 rootstat, 234 rootopen, 235 devcreate, 236 rootclose, 237 rootread, 238 devbread, 239 rootwrite, 240 devbwrite, 241 devremove, 242 devwstat, 243 }; 244 245