xref: /plan9-contrib/sys/src/cmd/9660srv/main.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include "dat.h"
6 #include "fns.h"
7 
8 static int	openflags(int);
9 static void	rattach(void);
10 static void	rsession(void);
11 static void	rclone(void);
12 static void	rclunk(void);
13 static void	rcreate(void);
14 static void	rflush(void);
15 static void	rmservice(void);
16 static void	rnop(void);
17 static void	ropen(void);
18 static void	rread(void);
19 static void	rremove(void);
20 static void	rsession(void);
21 static void	rstat(void);
22 static void	rwalk(void);
23 static void	rwrite(void);
24 static void	rwstat(void);
25 static void	usage(void);
26 
27 static Fcall	thdr;
28 static Fcall	rhdr;
29 static char	data[MAXMSG+MAXFDATA];
30 static char	fdata[MAXFDATA];
31 static char	srvfile[2*NAMELEN];
32 
33 extern Xfsub	*xsublist[];
34 
35 jmp_buf	err_lab[16];
36 int	nerr_lab;
37 char	err_msg[ERRLEN];
38 
39 int	chatty;
40 int	nojoliet;
41 int	noplan9;
42 
43 void
44 main(int argc, char **argv)
45 {
46 	int srvfd, pipefd[2], n, nw, stdio;
47 	Xfsub **xs;
48 
49 	stdio = 0;
50 	ARGBEGIN {
51 	case 'v':
52 		chatty = 1;
53 		break;
54 	case 'f':
55 		deffile = ARGF();
56 		break;
57 	case 's':
58 		stdio = 1;
59 		break;
60 	case '9':
61 		noplan9 = 1;
62 		break;
63 	case 'J':
64 		nojoliet = 1;
65 		break;
66 	default:
67 		usage();
68 	} ARGEND
69 
70 	switch(argc) {
71 	case 0:
72 		break;
73 	case 1:
74 		srvname = argv[0];
75 		break;
76 	default:
77 		usage();
78 	}
79 
80 	iobuf_init();
81 	for(xs=xsublist; *xs; xs++)
82 		(*(*xs)->reset)();
83 
84 	if(stdio) {
85 		pipefd[0] = 0;
86 		pipefd[1] = 1;
87 	} else {
88 		close(0);
89 		close(1);
90 		open("/dev/null", OREAD);
91 		open("/dev/null", OWRITE);
92 		if(pipe(pipefd) < 0)
93 			panic(1, "pipe");
94 		sprint(srvfile, "/srv/%s", srvname);
95 		srvfd = create(srvfile, OWRITE, 0666);
96 		if(srvfd < 0)
97 			panic(1, srvfile);
98 		atexit(rmservice);
99 		fprint(srvfd, "%d", pipefd[0]);
100 		close(pipefd[0]);
101 		close(srvfd);
102 		fprint(2, "%s %d: serving %s\n", argv0, getpid(), srvfile);
103 	}
104 	srvfd = pipefd[1];
105 
106 	switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){
107 	case -1:
108 		panic(1, "fork");
109 	default:
110 		_exits(0);
111 	case 0:
112 		break;
113 	}
114 
115 	while((n = read(srvfd, data, sizeof data)) > 0){
116 		if(convM2S(data, &thdr, n) <= 0)
117 			panic(0, "convM2S");
118 		if(!waserror()){
119 			switch(thdr.type){
120 			default:	panic(0, "type %d", thdr.type);
121 							break;
122 			case Tnop:	rnop();		break;
123 			case Tsession:	rsession();	break;
124 			case Tflush:	rflush();	break;
125 			case Tattach:	rattach();	break;
126 			case Tclone:	rclone();	break;
127 			case Twalk:	rwalk();	break;
128 			case Topen:	ropen();	break;
129 			case Tcreate:	rcreate();	break;
130 			case Tread:	rread();	break;
131 			case Twrite:	rwrite();	break;
132 			case Tclunk:	rclunk();	break;
133 			case Tremove:	rremove();	break;
134 			case Tstat:	rstat();	break;
135 			case Twstat:	rwstat();	break;
136 			}
137 			poperror();
138 			rhdr.type = thdr.type+1;
139 		}else{
140 			rhdr.type = Rerror;
141 			strncpy(rhdr.ename, err_msg, ERRLEN);
142 		}
143 		rhdr.fid = thdr.fid;
144 		rhdr.tag = thdr.tag;
145 		chat((rhdr.type != Rerror ? "OK\n" : "%s\n"), err_msg);
146 		if((n = convS2M(&rhdr, (char *)data)) <= 0)
147 			panic(0, "convS2M");
148 		nw = write(srvfd, data, n);
149 		if(nw != n)
150 			panic(1, "write");
151 		if(nerr_lab != 0)
152 			panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux", nerr_lab,
153 			err_lab[0][JMPBUFPC], err_lab[1][JMPBUFPC],
154 			err_lab[2][JMPBUFPC], err_lab[3][JMPBUFPC],
155 			err_lab[4][JMPBUFPC], err_lab[5][JMPBUFPC]);
156 	}
157 	if(n < 0)
158 		panic(1, "read");
159 	chat("%s %d: exiting\n", argv0, getpid());
160 	exits(0);
161 }
162 
163 static void
164 usage(void)
165 {
166 	fprint(2, "usage: %s [-v] [-s] [-f devicefile] [srvname]\n", argv0);
167 	exits("usage");
168 }
169 
170 void
171 error(char *p)
172 {
173 	strncpy(err_msg, p, ERRLEN);
174 	nexterror();
175 }
176 
177 void
178 nexterror(void)
179 {
180 	longjmp(err_lab[--nerr_lab], 1);
181 }
182 
183 void*
184 ealloc(long n)
185 {
186 	void *p;
187 
188 	p = malloc(n);
189 	if(p == 0)
190 		error("no memory");
191 	return p;
192 }
193 
194 static void
195 rmservice(void)
196 {
197 	remove(srvfile);
198 }
199 
200 static void
201 rnop(void)
202 {
203 	chat("nop...");
204 }
205 
206 static void
207 rauth(void)
208 {
209 	chat("auth...");
210 	error(Eauth);
211 }
212 
213 static void
214 rsession(void)
215 {
216 	chat("session...");
217 	memset(rhdr.authid, 0, sizeof(rhdr.authid));
218 	memset(rhdr.authdom, 0, sizeof(rhdr.authdom));
219 	memset(rhdr.chal, 0, sizeof(rhdr.chal));
220 }
221 
222 static void
223 rflush(void)
224 {
225 	chat("flush...");
226 }
227 
228 static void
229 rattach(void)
230 {
231 	Xfile *root;
232 	Xfs *xf;
233 	Xfsub **xs;
234 
235 	chat("attach(fid=%d,uname=\"%s\",aname=\"%s\",auth=\"%s\")...",
236 		thdr.fid, thdr.uname, thdr.aname, thdr.auth);
237 
238 	if(waserror()){
239 		xfile(thdr.fid, Clunk);
240 		nexterror();
241 	}
242 	root = xfile(thdr.fid, Clean);
243 	root->qid = (Qid){CHDIR, 0};
244 	root->xf = xf = ealloc(sizeof(Xfs));
245 	memset(xf, 0, sizeof(Xfs));
246 	xf->ref = 1;
247 	xf->d = getxdata(thdr.aname);
248 
249 	for(xs=xsublist; *xs; xs++)
250 		if((*(*xs)->attach)(root) >= 0){
251 			poperror();
252 			xf->s = *xs;
253 			xf->rootqid = root->qid;
254 			rhdr.qid = root->qid;
255 			return;
256 		}
257 	error("unknown format");
258 }
259 
260 static void
261 rclone(void)
262 {
263 	Xfile *of, *nf, *next;
264 
265 	chat("clone(fid=%d,newfid=%d)...", thdr.fid, thdr.newfid);
266 	of = xfile(thdr.fid, Asis);
267 	nf = xfile(thdr.newfid, Clean);
268 	if(waserror()){
269 		xfile(thdr.newfid, Clunk);
270 		nexterror();
271 	}
272 	next = nf->next;
273 	*nf = *of;
274 	nf->next = next;
275 	nf->fid = thdr.newfid;
276 	refxfs(nf->xf, 1);
277 	if(nf->len){
278 		nf->ptr = ealloc(nf->len);
279 		memmove(nf->ptr, of->ptr, nf->len);
280 	}else
281 		nf->ptr = of->ptr;
282 	(*of->xf->s->clone)(of, nf);
283 	poperror();
284 }
285 
286 static void
287 rwalk(void)
288 {
289 	Xfile *f;
290 
291 	chat("walk(fid=%d,name=\"%s\")...", thdr.fid, thdr.name);
292 	f=xfile(thdr.fid, Asis);
293 	if(!(f->qid.path & CHDIR)){
294 		chat("qid.path=0x%x...", f->qid.path);
295 		error("walk in non-directory");
296 	}
297 	if(strcmp(thdr.name, ".")==0)
298 		/* nop */;
299 	else if(strcmp(thdr.name, "..")==0){
300 		if(f->qid.path==f->xf->rootqid.path)
301 			error("walkup from root");
302 		(*f->xf->s->walkup)(f);
303 	}else
304 		(*f->xf->s->walk)(f, thdr.name);
305 	rhdr.qid = f->qid;
306 }
307 
308 static void
309 ropen(void)
310 {
311 	Xfile *f;
312 
313 	chat("open(fid=%d,mode=%d)...", thdr.fid, thdr.mode);
314 	f = xfile(thdr.fid, Asis);
315 	if(f->flags&Omodes)
316 		error("open on open file");
317 	(*f->xf->s->open)(f, thdr.mode);
318 	chat("f->qid=0x%8.8lux...", f->qid.path);
319 	f->flags = openflags(thdr.mode);
320 	rhdr.qid = f->qid;
321 }
322 
323 static void
324 rcreate(void)
325 {
326 	Xfile *f;
327 
328 	chat("create(fid=%d,name=\"%s\",perm=%uo,mode=%d)...",
329 		thdr.fid, thdr.name, thdr.perm, thdr.mode);
330 	if(strcmp(thdr.name, ".") == 0 || strcmp(thdr.name, "..") == 0)
331 		error("create . or ..");
332 	f = xfile(thdr.fid, Asis);
333 	if(f->flags&Omodes)
334 		error("create on open file");
335 	if(!(f->qid.path&CHDIR))
336 		error("create in non-directory");
337 	(*f->xf->s->create)(f, thdr.name, thdr.perm, thdr.mode);
338 	chat("f->qid=0x%8.8lux...", f->qid.path);
339 	f->flags = openflags(thdr.mode);
340 	rhdr.qid = f->qid;
341 }
342 
343 static void
344 rread(void)
345 {
346 	Xfile *f;
347 
348 	chat("read(fid=%d,offset=%d,count=%d)...",
349 		thdr.fid, thdr.offset, thdr.count);
350 	f=xfile(thdr.fid, Asis);
351 	if (!(f->flags&Oread))
352 		error("file not opened for reading");
353 	if(f->qid.path & CHDIR){
354 		if(thdr.count%DIRLEN || thdr.offset%DIRLEN){
355 			chat("count%%%d=%d,offset%%%d=%d...",
356 				DIRLEN, thdr.count%DIRLEN,
357 				DIRLEN, thdr.offset%DIRLEN);
358 			error("bad offset or count");
359 		}
360 		rhdr.count = (*f->xf->s->readdir)(f, fdata, thdr.offset, thdr.count);
361 	}else
362 		rhdr.count = (*f->xf->s->read)(f, fdata, thdr.offset, thdr.count);
363 	rhdr.data = fdata;
364 	chat("rcnt=%d...", rhdr.count);
365 }
366 
367 static void
368 rwrite(void)
369 {
370 	Xfile *f;
371 
372 	chat("write(fid=%d,offset=%d,count=%d)...",
373 		thdr.fid, thdr.offset, thdr.count);
374 	f=xfile(thdr.fid, Asis);
375 	if(!(f->flags&Owrite))
376 		error("file not opened for writing");
377 	rhdr.count = (*f->xf->s->write)(f, thdr.data, thdr.offset, thdr.count);
378 	chat("rcnt=%d...", rhdr.count);
379 }
380 
381 static void
382 rclunk(void)
383 {
384 	Xfile *f;
385 
386 	chat("clunk(fid=%d)...", thdr.fid);
387 	if(!waserror()){
388 		f = xfile(thdr.fid, Asis);
389 		if(f->flags&Orclose)
390 			(*f->xf->s->remove)(f);
391 		else
392 			(*f->xf->s->clunk)(f);
393 		poperror();
394 	}
395 	xfile(thdr.fid, Clunk);
396 }
397 
398 static void
399 rremove(void)
400 {
401 	Xfile *f;
402 
403 	chat("remove(fid=%d)...", thdr.fid);
404 	if(waserror()){
405 		xfile(thdr.fid, Clunk);
406 		nexterror();
407 	}
408 	f=xfile(thdr.fid, Asis);
409 	(*f->xf->s->remove)(f);
410 	poperror();
411 	xfile(thdr.fid, Clunk);
412 }
413 
414 static void
415 rstat(void)
416 {
417 	Xfile *f;
418 	Dir dir;
419 
420 	chat("stat(fid=%d)...", thdr.fid);
421 	f=xfile(thdr.fid, Asis);
422 	(*f->xf->s->stat)(f, &dir);
423 	if(chatty)
424 		showdir(2, &dir);
425 	convD2M(&dir, rhdr.stat);
426 }
427 
428 static void
429 rwstat(void)
430 {
431 	Xfile *f;
432 	Dir dir;
433 
434 	chat("wstat(fid=%d)...", thdr.fid);
435 	f=xfile(thdr.fid, Asis);
436 	convM2D(rhdr.stat, &dir);
437 	(*f->xf->s->wstat)(f, &dir);
438 }
439 
440 static int
441 openflags(int mode)
442 {
443 	int flags = 0;
444 
445 	switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
446 	case OREAD:
447 	case OEXEC:
448 		flags = Oread; break;
449 	case OWRITE:
450 		flags = Owrite; break;
451 	case ORDWR:
452 		flags = Oread|Owrite; break;
453 	}
454 	if(mode & ORCLOSE)
455 		flags |= Orclose;
456 	return flags;
457 }
458 
459 void
460 showdir(int fd, Dir *s)
461 {
462 	char a_time[32], m_time[32];
463 	char *p;
464 
465 	strcpy(a_time, ctime(s->atime));
466 	if(p=strchr(a_time, '\n'))	/* assign = */
467 		*p = 0;
468 	strcpy(m_time, ctime(s->mtime));
469 	if(p=strchr(m_time, '\n'))	/* assign = */
470 		*p = 0;
471 	fprint(fd, "name=\"%s\" qid=(0x%8.8lux,%lud) type=%d dev=%d \
472 mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
473 		s->name, s->qid.path, s->qid.vers, s->type, s->dev,
474 		s->mode, s->mode,
475 		a_time, m_time, s->length, s->uid, s->gid);
476 }
477 
478 #define	SIZE	1024
479 
480 void
481 chat(char *fmt, ...)
482 {
483 	va_list arg;
484 	char buf[SIZE], *out;
485 
486 	if(chatty){
487 		va_start(arg, fmt);
488 		out = doprint(buf, buf+SIZE, fmt, arg);
489 		va_end(arg);
490 		write(2, buf, out-buf);
491 	}
492 }
493 
494 void
495 panic(int rflag, char *fmt, ...)
496 {
497 	va_list arg;
498 	char buf[SIZE]; int n;
499 
500 	n = sprint(buf, "%s %d: ", argv0, getpid());
501 	va_start(arg, fmt);
502 	doprint(buf+n, buf+SIZE, fmt, arg);
503 	va_end(arg);
504 	fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
505 	if(chatty){
506 		fprint(2, "abort\n");
507 		abort();
508 	}
509 	exits("panic");
510 }
511