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