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