xref: /plan9/sys/src/cmd/mntgen.c (revision d9d5974c9cc932150e07925488df051092dba4ce)
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