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 <venti.h>
4
 
5
static char *okvers[] = {
6
	"02",
7
	nil,
8
};
9
 
10
/*
11
static char EBigString[] = "string too long";
12
static char EBigPacket[] = "packet too long";
13
static char ENullString[] = "missing string";
14
*/
15
static char EBadVersion[] = "bad format in version string";
16
 
17
static int
18
vtreadversion(VtConn *z, char *q, char *v, int nv)
19
{
20
	int n;
21
 
22
	for(;;){
23
		if(nv <= 1){
24
			werrstr("version too long");
25
			return -1;
26
		}
27
		n = read(z->infd, v, 1);
28
		if(n <= 0){
29
			if(n == 0)
30
				werrstr("unexpected eof");
31
			return -1;
32
		}
33
		if(*v == '\n'){
34
			*v = 0;
35
			break;
36
		}
37
		if((uchar)*v < ' ' || (uchar)*v > 0x7f || (*q && *v != *q)){
38
			werrstr(EBadVersion);
39
			return -1;
40
		}
41
		v++;
42
		nv--;
43
		if(*q)
44
			q++;
45
	}
46
	return 0;
47
}
48
 
49
int
50
vtversion(VtConn *z)
51
{
52
	char buf[VtMaxStringSize], *p, *ep, *prefix, *pp;
53
	int i;
54
 
55
	qlock(&z->lk);
56
	if(z->state != VtStateAlloc){
57
		werrstr("bad session state");
58
		qunlock(&z->lk);
59
		return -1;
60
	}
61
 
62
	qlock(&z->inlk);
63
	qlock(&z->outlk);
64
 
65
	p = buf;
66
	ep = buf + sizeof buf;
67
	prefix = "venti-";
68
	p = seprint(p, ep, "%s", prefix);
69
	p += strlen(p);
70
	for(i=0; okvers[i]; i++)
71
		p = seprint(p, ep, "%s%s", i ? ":" : "", okvers[i]);
72
	p = seprint(p, ep, "-libventi\n");
73
	assert(p-buf < sizeof buf);
74
 
75
	if(write(z->outfd, buf, p-buf) != p-buf)
76
		goto Err;
77
	vtdebug(z, "version string out: %s", buf);
78
 
79
	if(vtreadversion(z, prefix, buf, sizeof buf) < 0)
80
		goto Err;
81
	vtdebug(z, "version string in: %s", buf);
82
 
83
	p = buf+strlen(prefix);
84
	for(; *p; p=pp){
85
		if(*p == ':' || *p == '-')
86
			p++;
87
		pp = strpbrk(p, ":-");
88
		if(pp == nil)
89
			pp = p+strlen(p);
90
		for(i=0; okvers[i]; i++)
91
			if(strlen(okvers[i]) == pp-p && memcmp(okvers[i], p, pp-p) == 0){
92
				*pp = 0;
93
				z->version = vtstrdup(p);
94
				goto Okay;
95
			}
96
	}
97
	werrstr("unable to negotiate version");
98
	goto Err;
99
 
100
Okay:
101
	z->state = VtStateConnected;
102
	qunlock(&z->inlk);
103
	qunlock(&z->outlk);
104
	qunlock(&z->lk);
105
	return 0;
106
 
107
Err:
108
	werrstr("vtversion: %r");
109
	if(z->infd >= 0)
110
		close(z->infd);
111
	if(z->outfd >= 0 && z->outfd != z->infd)
112
		close(z->outfd);
113
	z->infd = -1;
114
	z->outfd = -1;
115
	z->state = VtStateClosed;
116
	qunlock(&z->inlk);
117
	qunlock(&z->outlk);
118
	qunlock(&z->lk);
119
	return -1;
120
}