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 Dev rootdevtab = { 180 '/', 181 "root", 182 183 rootreset, 184 devinit, 185 rootattach, 186 devclone, 187 rootwalk, 188 rootstat, 189 rootopen, 190 devcreate, 191 rootclose, 192 rootread, 193 devbread, 194 rootwrite, 195 devbwrite, 196 devremove, 197 devwstat, 198 }; 199