1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <thread.h> 5 #include <9p.h> 6 7 static void 8 usage(void) 9 { 10 fprint(2, "mntgen [-s srvname] [mtpt]\n"); 11 exits("usage"); 12 } 13 14 ulong time0; 15 16 typedef struct Tab Tab; 17 struct Tab 18 { 19 char *name; 20 ulong qid; 21 ulong time; 22 int ref; 23 }; 24 25 Tab *tab; 26 int ntab; 27 int mtab; 28 ulong qidgen; 29 30 static Tab* 31 findtab(ulong path) 32 { 33 int i; 34 35 for(i=0; i<ntab; i++) 36 if(tab[i].qid == path) 37 return &tab[i]; 38 return nil; 39 } 40 41 static void 42 fsopen(Req *r) 43 { 44 if(r->ifcall.mode != OREAD) 45 respond(r, "permission denied"); 46 else 47 respond(r, nil); 48 } 49 50 static int 51 dirgen(int i, Dir *d, void*) 52 { 53 if(i >= ntab) 54 return -1; 55 memset(d, 0, sizeof *d); 56 d->qid.type = QTDIR; 57 d->uid = estrdup9p("sys"); 58 d->gid = estrdup9p("sys"); 59 d->mode = DMDIR|0555; 60 d->length = 0; 61 if(i == -1){ 62 d->name = estrdup9p("/"); 63 d->atime = d->mtime = time0; 64 }else{ 65 d->qid.path = tab[i].qid; 66 d->name = estrdup9p(tab[i].name); 67 d->atime = d->mtime = tab[i].time; 68 } 69 return 0; 70 } 71 72 static void 73 fsread(Req *r) 74 { 75 if(r->fid->qid.path == 0) 76 dirread9p(r, dirgen, nil); 77 else 78 r->ofcall.count = 0; 79 respond(r, nil); 80 } 81 82 static void 83 fsstat(Req *r) 84 { 85 Tab *t; 86 ulong qid; 87 88 qid = r->fid->qid.path; 89 if(qid == 0) 90 dirgen(-1, &r->d, nil); 91 else{ 92 if((t = findtab(qid)) == nil){ 93 respond(r, "path not found (???)"); 94 return; 95 } 96 dirgen(t-tab, &r->d, nil); 97 } 98 respond(r, nil); 99 } 100 101 static char* 102 fswalk1(Fid *fid, char *name, void*) 103 { 104 int i; 105 Tab *t; 106 107 if(fid->qid.path != 0){ 108 /* nothing in child directory */ 109 if(strcmp(name, "..") == 0){ 110 if((t = findtab(fid->qid.path)) != nil) 111 t->ref--; 112 fid->qid.path = 0; 113 return nil; 114 } 115 return "path not found"; 116 } 117 /* root */ 118 if(strcmp(name, "..") == 0) 119 return nil; 120 for(i=0; i<ntab; i++) 121 if(strcmp(tab[i].name, name) == 0){ 122 tab[i].ref++; 123 fid->qid.path = tab[i].qid; 124 return nil; 125 } 126 127 /* create it */ 128 if(ntab == mtab){ 129 if(mtab == 0) 130 mtab = 16; 131 else 132 mtab *= 2; 133 tab = erealloc9p(tab, sizeof(tab[0])*mtab); 134 } 135 tab[ntab].qid = ++qidgen; 136 fid->qid.path = tab[ntab].qid; 137 tab[ntab].name = estrdup9p(name); 138 tab[ntab].time = time(0); 139 tab[ntab].ref = 1; 140 ntab++; 141 142 return nil; 143 } 144 145 static char* 146 fsclone(Fid *fid, Fid*, void*) 147 { 148 Tab *t; 149 150 if((t = findtab(fid->qid.path)) != nil) 151 t->ref++; 152 return nil; 153 } 154 155 static void 156 fswalk(Req *r) 157 { 158 walkandclone(r, fswalk1, fsclone, nil); 159 } 160 161 static void 162 fsclunk(Fid *fid) 163 { 164 Tab *t; 165 ulong qid; 166 167 qid = fid->qid.path; 168 if(qid == 0) 169 return; 170 if((t = findtab(qid)) == nil){ 171 fprint(2, "warning: cannot find %lux\n", qid); 172 return; 173 } 174 if(--t->ref == 0){ 175 free(t->name); 176 tab[t-tab] = tab[--ntab]; 177 }else if(t->ref < 0) 178 fprint(2, "warning: negative ref count for %s\n", t->name); 179 } 180 181 static void 182 fsattach(Req *r) 183 { 184 char *spec; 185 186 spec = r->ifcall.aname; 187 if(spec && spec[0]){ 188 respond(r, "invalid attach specifier"); 189 return; 190 } 191 192 r->ofcall.qid = (Qid){0, 0, QTDIR}; 193 r->fid->qid = r->ofcall.qid; 194 respond(r, nil); 195 } 196 197 Srv fs= 198 { 199 .attach= fsattach, 200 .open= fsopen, 201 .read= fsread, 202 .stat= fsstat, 203 .walk= fswalk, 204 .destroyfid= fsclunk 205 }; 206 207 void 208 main(int argc, char **argv) 209 { 210 char *service; 211 212 time0 = time(0); 213 service = nil; 214 ARGBEGIN{ 215 case 'D': 216 chatty9p++; 217 break; 218 case 's': 219 service = EARGF(usage()); 220 break; 221 default: 222 usage(); 223 }ARGEND 224 225 if(argc > 1) 226 usage(); 227 postmountsrv(&fs, service, argc ? argv[0] : "/n", MAFTER); 228 exits(nil); 229 } 230