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 "9p1.h"
6
 
7
#define	MAXFDATA	(8*1024)
8
#define	MAXRPC		(MAXFDATA+160)
9
 
10
/*
11
 * reassemble 9P messages for stream based protocols
12
 * interposed between devmnt and the network by srv for tcp connections
13
 * fcall expects devmnt on fd0, network fd1
14
 */
15
uchar msglen[256] =
16
{
17
	[Tnop9p1]		3,
18
	[Rnop9p1]		3,
19
	[Tsession9p1]	3+CHALLEN,
20
	[Rsession9p1]	3+NAMEREC+DOMLEN+CHALLEN,
21
	[Terror9p1]	0,
22
	[Rerror9p1]	67,
23
	[Tflush9p1]	5,
24
	[Rflush9p1]	3,
25
	[Tattach9p1]	5+2*NAMEREC+TICKETLEN+AUTHENTLEN,
26
	[Rattach9p1]	13+AUTHENTLEN,
27
	[Tclone9p1]	7,
28
	[Rclone9p1]	5,
29
	[Twalk9p1]		33,
30
	[Rwalk9p1]		13,
31
	[Topen9p1]		6,
32
	[Ropen9p1]		13,
33
	[Tcreate9p1]	38,
34
	[Rcreate9p1]	13,
35
	[Tread9p1]		15,
36
	[Rread9p1]		8,
37
	[Twrite9p1]	16,
38
	[Rwrite9p1]	7,
39
	[Tclunk9p1]	5,
40
	[Rclunk9p1]	5,
41
	[Tremove9p1]	5,
42
	[Rremove9p1]	5,
43
	[Tstat9p1]		5,
44
	[Rstat9p1]		121,
45
	[Twstat9p1]	121,
46
	[Rwstat9p1]	5,
47
	[Tclwalk9p1]	35,
48
	[Rclwalk9p1]	13,
49
};
50
 
51
enum
52
{
53
	Twritehdr	= 16,	/* Min bytes for Twrite */
54
	Rreadhdr	= 8,	/* Min bytes for Rread */
55
	Twritecnt	= 13,	/* Offset in byte stream of write count */
56
	Rreadcnt	= 5,	/* Offset for Readcnt */
57
};
58
 
59
int
60
mntrpclen(uchar *d, int n)
61
{
62
	uchar t;
63
	int len, off;
64
 
65
	if(n < 1)
66
		return 0;
67
 
68
	t = d[0];
69
	switch(t) {			/* This is the type */
70
	default:
71
		len = msglen[t];
72
		if(len == 0)		/* Illegal type so consume */
73
			return n;
74
		if(n < len)
75
			return 0;
76
		return len;
77
	case Twrite9p1:			/* Fmt: TGGFFOOOOOOOOCC */
78
		len = Twritehdr;	/* T = type, G = tag, F = fid */
79
		off = Twritecnt;	/* O = offset, C = count */
80
		break;
81
	case Rread9p1:			/* Fmt: TGGFFCC */
82
		len = Rreadhdr;
83
		off = Rreadcnt;
84
		break;
85
	}
86
	if(n < off+2)
87
		return 0;
88
 
89
	len += d[off]|(d[off+1]<<8);
90
	if(n < len)
91
		return 0;
92
 
93
	return len;
94
}
95
 
96
int
97
fcall(int fd)
98
{
99
	int i, r, n, l;
100
	uchar *p, *buf;
101
	int pipefd[2];
102
 
103
	if(pipe(pipefd) < 0)
104
		fatal("fcall pipe: %r");
105
 
106
	buf = malloc(MAXRPC);
107
	if(buf == nil)
108
		fatal("fcall malloc");
109
 
110
	switch(rfork(RFPROC|RFMEM|RFFDG|RFCNAMEG)){
111
	default:
112
		return pipefd[0];	/* parent returns fd */	
113
	case 0:
114
		break;	/* child builds buffers */
115
	case -1:
116
		fatal("fcall fork: %r");
117
	}
118
 
119
	/* close file descriptors */
120
	for(i=0; i<20; i++)
121
		if(i!=fd && i!=pipefd[1])
122
			close(i);
123
 
124
	l = MAXRPC;
125
	p = buf;
126
	for(;;) {
127
		n = read(fd, p, l);
128
		if(n < 0)
129
			break;
130
		p += n;
131
		l -= n;
132
 
133
		for(;;) {
134
			r = mntrpclen(buf, p - buf);
135
			if(r == 0)
136
				break;
137
 
138
			if(write(pipefd[1], buf, r) < 0)
139
				break;
140
 
141
			n = (p - buf) - r;
142
			memmove(buf, buf+r, n);
143
			p = buf+n;
144
			l = MAXRPC - n;
145
		}
146
	}
147
	close(pipefd[1]);
148
	fatal(nil);
149
	return -1;
150
}