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