Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
enum
9
{
10
	Maxfdata	= 8192,
11
	Maxiosize	= IOHDRSZ+Maxfdata,
12
};
13
 
14
void io(int);
15
void rversion(void);
16
void	rattach(void);
17
void	rauth(void);
18
void	rclunk(void);
19
void	rcreate(void);
20
void	rflush(void);
21
void	ropen(void);
22
void	rread(void);
23
void	rremove(void);
24
void	rsession(void);
25
void	rstat(void);
26
void	rwalk(void);
27
void	rwrite(void);
28
void	rwstat(void);
29
 
30
static int	openflags(int);
31
static void	rmservice(void);
32
static void	usage(void);
33
 
34
#define Reqsize (sizeof(Fcall)+Maxfdata)
35
 
36
Fcall *req;
37
Fcall *rep;
38
 
39
uchar mdata[Maxiosize];
40
char fdata[Maxfdata];
41
uchar statbuf[STATMAX];
42
int errno;
43
 
44
static char	srvfile[64];
45
 
46
extern Xfsub	*xsublist[];
47
extern int	nclust;
48
 
49
jmp_buf	err_lab[16];
50
int	nerr_lab;
51
char	err_msg[ERRMAX];
52
 
53
int	chatty;
54
int	nojoliet;
55
int	noplan9;
56
int norock;
57
 
58
void	(*fcalls[])(void) = {
59
	[Tversion]	rversion,
60
	[Tflush]	rflush,
61
	[Tauth]	rauth,
62
	[Tattach]	rattach,
63
	[Twalk]		rwalk,
64
	[Topen]		ropen,
65
	[Tcreate]	rcreate,
66
	[Tread]		rread,
67
	[Twrite]	rwrite,
68
	[Tclunk]	rclunk,
69
	[Tremove]	rremove,
70
	[Tstat]		rstat,
71
	[Twstat]	rwstat,
72
};
73
 
74
void
75
main(int argc, char **argv)
76
{
77
	int srvfd, pipefd[2], stdio;
78
	Xfsub **xs;
79
 
80
	stdio = 0;
81
	ARGBEGIN {
82
	case '9':
83
		noplan9 = 1;
84
		break;
85
	case 'c':
86
		nclust = atoi(EARGF(usage()));
87
		if (nclust <= 0)
88
			sysfatal("nclust %d non-positive", nclust);
89
		break;
90
	case 'f':
91
		deffile = EARGF(usage());
92
		break;
93
	case 'r':
94
		norock = 1;
95
		break;
96
	case 's':
97
		stdio = 1;
98
		break;
99
	case 'v':
100
		chatty = 1;
101
		break;
102
	case 'J':
103
		nojoliet = 1;
104
		break;
105
	default:
106
		usage();
107
	} ARGEND
108
 
109
	switch(argc) {
110
	case 0:
111
		break;
112
	case 1:
113
		srvname = argv[0];
114
		break;
115
	default:
116
		usage();
117
	}
118
 
119
	iobuf_init();
120
	for(xs=xsublist; *xs; xs++)
121
		(*(*xs)->reset)();
122
 
123
	if(stdio) {
124
		pipefd[0] = 0;
125
		pipefd[1] = 1;
126
	} else {
127
		close(0);
128
		close(1);
129
		open("/dev/null", OREAD);
130
		open("/dev/null", OWRITE);
131
		if(pipe(pipefd) < 0)
132
			panic(1, "pipe");
133
		sprint(srvfile, "/srv/%s", srvname);
134
		srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
135
		if(srvfd < 0)
136
			panic(1, srvfile);
137
		fprint(srvfd, "%d", pipefd[0]);
138
		close(pipefd[0]);
139
		fprint(2, "%s %d: serving %s\n", argv0, getpid(), srvfile);
140
	}
141
	srvfd = pipefd[1];
142
 
143
	switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){
144
	case -1:
145
		panic(1, "fork");
146
	default:
147
		_exits(0);
148
	case 0:
149
		break;
150
	}
151
 
152
	io(srvfd);
153
	exits(0);
154
}
155
 
156
void
157
io(int srvfd)
158
{
159
	int n, pid;
160
	Fcall xreq, xrep;
161
 
162
	req = &xreq;
163
	rep = &xrep;
164
	pid = getpid();
165
	fmtinstall('F', fcallfmt);
166
 
167
	for(;;){
168
		/*
169
		 * reading from a pipe or a network device
170
		 * will give an error after a few eof reads.
171
		 * however, we cannot tell the difference
172
		 * between a zero-length read and an interrupt
173
		 * on the processes writing to us,
174
		 * so we wait for the error.
175
		 */
176
		n = read9pmsg(srvfd, mdata, sizeof mdata);
177
		if(n < 0)
178
			break;
179
		if(n == 0)
180
			continue;
181
		if(convM2S(mdata, n, req) == 0)
182
			continue;
183
 
184
		if(chatty)
185
			fprint(2, "9660srv %d:<-%F\n", pid, req);
186
 
187
		errno = 0;
188
		if(!waserror()){
189
			err_msg[0] = 0;
190
			if(req->type >= nelem(fcalls) || !fcalls[req->type])
191
				error("bad fcall type");
192
			(*fcalls[req->type])();
193
			poperror();
194
		}
195
 
196
		if(err_msg[0]){
197
			rep->type = Rerror;
198
			rep->ename = err_msg;
199
		}else{
200
			rep->type = req->type + 1;
201
			rep->fid = req->fid;
202
		}
203
		rep->tag = req->tag;
204
 
205
		if(chatty)
206
			fprint(2, "9660srv %d:->%F\n", pid, rep);
207
		n = convS2M(rep, mdata, sizeof mdata);
208
		if(n == 0)
209
			panic(1, "convS2M error on write");
210
		if(write(srvfd, mdata, n) != n)
211
			panic(1, "mount write");
212
		if(nerr_lab != 0)
213
			panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux", nerr_lab,
214
			err_lab[0][JMPBUFPC], err_lab[1][JMPBUFPC],
215
			err_lab[2][JMPBUFPC], err_lab[3][JMPBUFPC],
216
			err_lab[4][JMPBUFPC], err_lab[5][JMPBUFPC]);
217
	}
218
	chat("server shut down");
219
}
220
 
221
static void
222
usage(void)
223
{
224
	fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);
225
	exits("usage");
226
}
227
 
228
void
229
error(char *p)
230
{
231
	strecpy(err_msg, err_msg+sizeof err_msg, p);
232
	nexterror();
233
}
234
 
235
void
236
nexterror(void)
237
{
238
	longjmp(err_lab[--nerr_lab], 1);
239
}
240
 
241
void*
242
ealloc(long n)
243
{
244
	void *p;
245
 
246
	p = malloc(n);
247
	if(p == 0)
248
		error("no memory");
249
	return p;
250
}
251
 
252
void
253
setnames(Dir *d, char *n)
254
{
255
	d->name = n;
256
	d->uid = n+Maxname;
257
	d->gid = n+Maxname*2;
258
	d->muid = n+Maxname*3;
259
 
260
	d->name[0] = '\0';
261
	d->uid[0] = '\0';
262
	d->gid[0] = '\0';
263
	d->muid[0] = '\0';
264
}
265
 
266
void
267
rversion(void)
268
{
269
	if(req->msize > Maxiosize)
270
		rep->msize = Maxiosize;
271
	else
272
		rep->msize = req->msize;
273
	rep->version = "9P2000";
274
}
275
 
276
void
277
rauth(void)
278
{
279
	error("9660srv: authentication not required");
280
}
281
 
282
void
283
rflush(void)
284
{
285
}
286
 
287
void
288
rattach(void)
289
{
290
	Xfs *xf;
291
	Xfile *root;
292
	Xfsub **xs;
293
 
294
	chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",
295
		req->fid, req->uname, req->aname);
296
 
297
	if(waserror()){
298
		xfile(req->fid, Clunk);
299
		nexterror();
300
	}
301
	root = xfile(req->fid, Clean);
302
	root->qid = (Qid){0, 0, QTDIR};
303
	root->xf = xf = ealloc(sizeof(Xfs));
304
	memset(xf, 0, sizeof(Xfs));
305
	xf->ref = 1;
306
	xf->d = getxdata(req->aname);
307
 
308
	for(xs=xsublist; *xs; xs++)
309
		if((*(*xs)->attach)(root) >= 0){
310
			poperror();
311
			xf->s = *xs;
312
			xf->rootqid = root->qid;
313
			rep->qid = root->qid;
314
			return;
315
		}
316
	error("unknown format");
317
}
318
 
319
Xfile*
320
doclone(Xfile *of, int newfid)
321
{
322
	Xfile *nf, *next;
323
 
324
	nf = xfile(newfid, Clean);
325
	if(waserror()){
326
		xfile(newfid, Clunk);
327
		nexterror();
328
	}
329
	next = nf->next;
330
	*nf = *of;
331
	nf->next = next;
332
	nf->fid = newfid;
333
	refxfs(nf->xf, 1);
334
	if(nf->len){
335
		nf->ptr = ealloc(nf->len);
336
		memmove(nf->ptr, of->ptr, nf->len);
337
	}else
338
		nf->ptr = of->ptr;
339
	(*of->xf->s->clone)(of, nf);
340
	poperror();
341
	return nf;
342
}
343
 
344
void
345
rwalk(void)
346
{
347
	Xfile *f, *nf;
348
	Isofile *oldptr;
349
	int oldlen;
350
	Qid oldqid;
351
 
352
	rep->nwqid = 0;
353
	nf = nil;
354
	f = xfile(req->fid, Asis);
355
	if(req->fid != req->newfid)
356
		f = nf = doclone(f, req->newfid);
357
 
358
	/* save old state in case of error */
359
	oldqid = f->qid;
360
	oldlen = f->len;
361
	oldptr = f->ptr;
362
	if(oldlen){
363
		oldptr = ealloc(oldlen);
364
		memmove(oldptr, f->ptr, oldlen);
365
	}
366
 
367
	if(waserror()){
368
		/*
369
		 * if nf != nil, nf == f, which is derived from req->newfid,
370
		 * so we can't clunk req->newfid with xfile, which would put
371
		 * f back on the free list, until we're done with f below.
372
		 */
373
		if(rep->nwqid == req->nwname){
374
			if(oldlen)
375
				free(oldptr);
376
		}else{
377
			/* restore previous state */
378
			f->qid = oldqid;
379
			if(f->len)
380
				free(f->ptr);
381
			f->ptr = oldptr;
382
			f->len = oldlen;
383
		}
384
		if(nf != nil)
385
			xfile(req->newfid, Clunk);
386
		if(rep->nwqid==req->nwname || rep->nwqid > 0){
387
			err_msg[0] = '\0';
388
			return;
389
		}
390
		nexterror();
391
	}
392
 
393
	for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
394
		chat("\twalking %s\n", req->wname[rep->nwqid]);
395
		if(!(f->qid.type & QTDIR)){
396
			chat("\tnot dir: type=%#x\n", f->qid.type);
397
			error("walk in non-directory");
398
		}
399
 
400
		if(strcmp(req->wname[rep->nwqid], "..")==0){
401
			if(f->qid.path != f->xf->rootqid.path)
402
				(*f->xf->s->walkup)(f);
403
		}else
404
			(*f->xf->s->walk)(f, req->wname[rep->nwqid]);
405
		rep->wqid[rep->nwqid] = f->qid;
406
	}
407
	poperror();
408
	if(oldlen)
409
		free(oldptr);
410
}
411
 
412
void
413
ropen(void)
414
{
415
	Xfile *f;
416
 
417
	f = xfile(req->fid, Asis);
418
	if(f->flags&Omodes)
419
		error("open on open file");
420
	if(req->mode&ORCLOSE)
421
		error("no removes");
422
	(*f->xf->s->open)(f, req->mode);
423
	f->flags = openflags(req->mode);
424
	rep->qid = f->qid;
425
	rep->iounit = 0;
426
}
427
 
428
void
429
rcreate(void)
430
{
431
	error("no creates");
432
/*
433
	Xfile *f;
434
 
435
	if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)
436
		error("create . or ..");
437
	f = xfile(req->fid, Asis);
438
	if(f->flags&Omodes)
439
		error("create on open file");
440
	if(!(f->qid.path&CHDIR))
441
		error("create in non-directory");
442
	(*f->xf->s->create)(f, req->name, req->perm, req->mode);
443
	chat("f->qid=0x%8.8lux...", f->qid.path);
444
	f->flags = openflags(req->mode);
445
	rep->qid = f->qid;
446
*/
447
}
448
 
449
void
450
rread(void)
451
{
452
	Xfile *f;
453
 
454
	f=xfile(req->fid, Asis);
455
	if (!(f->flags&Oread))
456
		error("file not opened for reading");
457
	if(f->qid.type & QTDIR)
458
		rep->count = (*f->xf->s->readdir)(f, (uchar*)fdata, req->offset, req->count);
459
	else
460
		rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);
461
	rep->data = fdata;
462
}
463
 
464
void
465
rwrite(void)
466
{
467
	Xfile *f;
468
 
469
	f=xfile(req->fid, Asis);
470
	if(!(f->flags&Owrite))
471
		error("file not opened for writing");
472
	rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);
473
}
474
 
475
void
476
rclunk(void)
477
{
478
	Xfile *f;
479
 
480
	if(!waserror()){
481
		f = xfile(req->fid, Asis);
482
		(*f->xf->s->clunk)(f);
483
		poperror();
484
	}
485
	xfile(req->fid, Clunk);
486
}
487
 
488
void
489
rremove(void)
490
{
491
	error("no removes");
492
}
493
 
494
void
495
rstat(void)
496
{
497
	Xfile *f;
498
	Dir dir;
499
 
500
	chat("stat(fid=%d)...", req->fid);
501
	f=xfile(req->fid, Asis);
502
	setnames(&dir, fdata);
503
	(*f->xf->s->stat)(f, &dir);
504
	if(chatty)
505
		showdir(2, &dir);
506
	rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
507
	rep->stat = statbuf;
508
}
509
 
510
void
511
rwstat(void)
512
{
513
	error("no wstat");
514
}
515
 
516
static int
517
openflags(int mode)
518
{
519
	int flags = 0;
520
 
521
	switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
522
	case OREAD:
523
	case OEXEC:
524
		flags = Oread; break;
525
	case OWRITE:
526
		flags = Owrite; break;
527
	case ORDWR:
528
		flags = Oread|Owrite; break;
529
	}
530
	if(mode & ORCLOSE)
531
		flags |= Orclose;
532
	return flags;
533
}
534
 
535
void
536
showdir(int fd, Dir *s)
537
{
538
	char a_time[32], m_time[32];
539
	char *p;
540
 
541
	strcpy(a_time, ctime(s->atime));
542
	if(p=strchr(a_time, '\n'))	/* assign = */
543
		*p = 0;
544
	strcpy(m_time, ctime(s->mtime));
545
	if(p=strchr(m_time, '\n'))	/* assign = */
546
		*p = 0;
547
	fprint(fd, "name=\"%s\" qid=(0x%llux,%lud) type=%d dev=%d \
548
mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
549
		s->name, s->qid.path, s->qid.vers, s->type, s->dev,
550
		s->mode, s->mode,
551
		a_time, m_time, s->length, s->uid, s->gid);
552
}
553
 
554
#define	SIZE	1024
555
 
556
void
557
chat(char *fmt, ...)
558
{
559
	va_list arg;
560
 
561
	if(chatty){
562
		va_start(arg, fmt);
563
		vfprint(2, fmt, arg);
564
		va_end(arg);
565
	}
566
}
567
 
568
void
569
panic(int rflag, char *fmt, ...)
570
{
571
	va_list arg;
572
	char buf[SIZE]; int n;
573
 
574
	n = sprint(buf, "%s %d: ", argv0, getpid());
575
	va_start(arg, fmt);
576
	vseprint(buf+n, buf+SIZE, fmt, arg);
577
	va_end(arg);
578
	fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
579
	if(chatty){
580
		fprint(2, "abort\n");
581
		abort();
582
	}
583
	exits("panic");
584
}