1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <thread.h> 5 #include <9p.h> 6 7 typedef struct Name Name; 8 9 enum { 10 Qroot = ~0, 11 }; 12 13 struct Name { 14 Ref; // one per fid in use. 15 char* s; 16 }; 17 18 static void aopen(Req*); 19 static void aread(Req*); 20 static void astat(Req*); 21 static void awstat(Req*); 22 static char* awalk1(Fid* fid, char *name, Qid *qid); 23 static char* aclone(Fid*, Fid*); 24 static void aattach(Req*); 25 static void aclunk(Fid*); 26 27 Name** names; 28 int nnames; 29 30 31 Srv asrv = { 32 .tree = nil, 33 .attach = aattach, 34 .auth = nil, 35 .open = aopen, 36 .create = nil, 37 .read = aread, 38 .write = nil, 39 .remove = nil, 40 .flush = nil, 41 .stat = astat, 42 .wstat = awstat, 43 .walk = nil, 44 .walk1 = awalk1, 45 .clone = aclone, 46 .destroyfid = aclunk, 47 .destroyreq = nil, 48 .end = nil, 49 .aux = nil, 50 51 .infd = -1, 52 .outfd = -1, 53 .nopipe = 0, 54 .srvfd = -1, 55 }; 56 57 58 static void 59 usage(void) 60 { 61 fprint(2, "usage: mntgen [-s srv] [mnt]\n"); 62 exits("usage"); 63 } 64 65 66 static Name* 67 newname(char* name) 68 { 69 Name* n; 70 71 if ((nnames % 100) == 0) 72 names = realloc(names, (nnames+100)*sizeof(Name*)); 73 n = names[nnames++] = malloc(sizeof(Name)); 74 n->s = strdup(name); 75 n->ref = 1; 76 return n; 77 } 78 79 static void 80 closename(int i) 81 { 82 assert (i >= 0 && i < nnames && names[i] != nil); 83 if (decref(names[i]) <= 0){ 84 free(names[i]->s); 85 free(names[i]); 86 names[i] = nil; // never reused; qids are unique 87 } 88 } 89 90 static int 91 n2i(int n) 92 { 93 int i; 94 95 for(i=0; i<nnames; i++) 96 if(names[i] != nil && n-- == 0) 97 return i; 98 return -1; 99 } 100 101 static int 102 agen(int n, Dir *dir, void* a) 103 { 104 int i; 105 106 i = n2i(n); 107 if (a == nil || i < 0) 108 return -1; 109 dir->qid.type = QTDIR; 110 dir->qid.path = i; 111 dir->qid.vers = 0; 112 dir->name = estrdup9p(names[i]->s); 113 dir->uid = estrdup9p("sys"); 114 dir->gid = estrdup9p("sys"); 115 dir->mode= 0555|DMDIR; 116 dir->length= 0; 117 return 0; 118 } 119 120 static void 121 aattach(Req* r) 122 { 123 Qid q; 124 125 q.type = QTDIR; 126 q.path = Qroot; 127 q.vers = 0; 128 r->fid->qid = q; 129 r->ofcall.qid = q; 130 respond(r, nil); 131 } 132 133 static void 134 aopen(Req* r) 135 { 136 respond(r, nil); 137 } 138 139 static void 140 aread(Req* r) 141 { 142 Qid q; 143 144 q = r->fid->qid; 145 if (q.path < 0 || q.path >= nnames && q.path != Qroot) 146 respond(r, "bug: bad qid"); 147 if (q.path == Qroot) 148 dirread9p(r, agen, names); 149 else 150 dirread9p(r, agen, nil); 151 respond(r, nil); 152 } 153 154 static void 155 astat(Req* r) 156 { 157 Qid q; 158 159 q = r->fid->qid; 160 if (q.path < 0 || q.path >= nnames && q.path != Qroot) 161 respond(r, "bug: bad qid"); 162 r->d.qid = q; 163 if (q.path == Qroot) 164 r->d.name = estrdup9p("/"); 165 else 166 r->d.name = estrdup9p(names[q.path]->s); 167 r->d.uid = estrdup9p("sys"); 168 r->d.gid = estrdup9p("sys"); 169 r->d.length= 0; 170 r->d.mode= 0555|DMDIR; 171 respond(r, nil); 172 } 173 174 static void 175 awstat(Req* r) 176 { 177 respond(r, "wstat not allowed"); 178 } 179 180 static char* 181 awalk1(Fid* fid, char *name, Qid *qid) 182 { 183 int i, oldi; 184 185 oldi = fid->qid.path; 186 if (strcmp(name, "..") == 0){ 187 i = Qroot; 188 goto done; 189 } 190 if (fid->qid.path != Qroot) 191 return "no such name"; 192 for (i = 0; i < nnames; i++) 193 if (names[i] != nil && strcmp(name, names[i]->s) == 0){ 194 incref(names[i]); 195 break; 196 } 197 if (i == nnames) 198 newname(name); 199 done: 200 if (oldi >=0 && oldi < nnames) 201 closename(oldi); 202 qid->path = i; 203 qid->type = QTDIR; 204 qid->vers = 0; 205 fid->qid = *qid; 206 return nil; 207 } 208 209 static char* 210 aclone(Fid* old, Fid*) 211 { 212 int i; 213 214 i = old->qid.path; 215 if (i >= 0 && i < nnames) 216 incref(names[i]); 217 return nil; 218 } 219 220 static void 221 aclunk(Fid* fid) 222 { 223 int i; 224 225 i = fid->qid.path; 226 if (i >= 0 && i < nnames) 227 closename(i); 228 } 229 230 void 231 main(int argc, char* argv[]) 232 { 233 char* mnt; 234 char* srvname; 235 236 srvname = nil; 237 ARGBEGIN{ 238 case 's': 239 srvname = EARGF(usage()); 240 break; 241 default: 242 usage(); 243 }ARGEND; 244 245 if (argc > 1) 246 usage(); 247 if (argc == 0) 248 mnt = "/n"; 249 else 250 mnt = *argv; 251 postmountsrv(&asrv, srvname, mnt, MAFTER); 252 exits(nil); 253 } 254