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 Qdir= 0, 10 11 Nfiles=32, /* max root files */ 12 }; 13 14 extern ulong bootlen; 15 extern uchar bootcode[]; 16 17 Dirtab rootdir[Nfiles]; 18 19 static uchar *rootdata[Nfiles]; 20 static int nroot = 0; 21 22 typedef struct Recover Recover; 23 struct Recover 24 { 25 int len; 26 char *req; 27 Recover *next; 28 }; 29 30 struct 31 { 32 Lock; 33 QLock; 34 Rendez; 35 Recover *q; 36 }reclist; 37 38 /* 39 * add a root file 40 */ 41 static void 42 addroot(char *name, uchar *contents, ulong len, int perm) 43 { 44 Dirtab *d; 45 46 if(nroot >= Nfiles) 47 panic("too many root files"); 48 rootdata[nroot] = contents; 49 d = &rootdir[nroot]; 50 strcpy(d->name, name); 51 d->length = len; 52 d->perm = perm; 53 d->qid.path = nroot+1; 54 if(perm & CHDIR) 55 d->qid.path |= CHDIR; 56 nroot++; 57 } 58 59 /* 60 * add a root file 61 */ 62 void 63 addrootfile(char *name, uchar *contents, ulong len) 64 { 65 addroot(name, contents, len, 0555); 66 } 67 68 /* 69 * add a root file 70 */ 71 static void 72 addrootdir(char *name) 73 { 74 addroot(name, nil, 0, CHDIR|0555); 75 } 76 77 static void 78 rootreset(void) 79 { 80 addrootdir("bin"); 81 addrootdir("dev"); 82 addrootdir("env"); 83 addrootdir("net"); 84 addrootdir("net.alt"); 85 addrootdir("proc"); 86 addrootdir("root"); 87 addrootdir("srv"); 88 89 addrootfile("boot", bootcode, bootlen); /* always have a boot file */ 90 } 91 92 static Chan* 93 rootattach(char *spec) 94 { 95 return devattach('/', spec); 96 } 97 98 static int 99 rootwalk(Chan *c, char *name) 100 { 101 if(strcmp(name, "..") == 0) { 102 c->qid.path = Qdir|CHDIR; 103 return 1; 104 } 105 if((c->qid.path & ~CHDIR) != Qdir) 106 return 0; 107 return devwalk(c, name, rootdir, nroot, devgen); 108 } 109 110 static void 111 rootstat(Chan *c, char *dp) 112 { 113 devstat(c, dp, rootdir, nroot, devgen); 114 } 115 116 static Chan* 117 rootopen(Chan *c, int omode) 118 { 119 switch(c->qid.path & ~CHDIR) { 120 default: 121 break; 122 } 123 124 return devopen(c, omode, rootdir, nroot, devgen); 125 } 126 127 /* 128 * sysremove() knows this is a nop 129 */ 130 static void 131 rootclose(Chan *c) 132 { 133 switch(c->qid.path) { 134 default: 135 break; 136 } 137 } 138 139 static int 140 rdrdy(void*) 141 { 142 return reclist.q != 0; 143 } 144 145 static long 146 rootread(Chan *c, void *buf, long n, vlong off) 147 { 148 ulong t; 149 Dirtab *d; 150 uchar *data; 151 ulong offset = off; 152 153 t = c->qid.path & ~CHDIR; 154 switch(t){ 155 case Qdir: 156 return devdirread(c, buf, n, rootdir, nroot, devgen); 157 } 158 159 d = &rootdir[t-1]; 160 data = rootdata[t-1]; 161 if(offset >= d->length) 162 return 0; 163 if(offset+n > d->length) 164 n = d->length - offset; 165 memmove(buf, data+offset, n); 166 return n; 167 } 168 169 static long 170 rootwrite(Chan *c, void*, long, vlong) 171 { 172 switch(c->qid.path & ~CHDIR){ 173 default: 174 error(Egreg); 175 } 176 return 0; 177 } 178 179 static void 180 rootcreate(Chan *c, char *name, int mode, ulong perm) 181 { 182 if(!iseve() || c->qid.path != (CHDIR|Qdir) || 183 (perm & CHDIR) == 0 || mode != OREAD) 184 error(Eperm); 185 addrootdir(name); 186 c->flag |= COPEN; 187 c->mode = OREAD; 188 } 189 190 Dev rootdevtab = { 191 '/', 192 "root", 193 194 rootreset, 195 devinit, 196 rootattach, 197 devclone, 198 rootwalk, 199 rootstat, 200 rootopen, 201 rootcreate, 202 rootclose, 203 rootread, 204 devbread, 205 rootwrite, 206 devbwrite, 207 devremove, 208 devwstat, 209 }; 210