xref: /plan9/sys/src/cmd/aquarela/smbcomread.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include "headers.h"
2*8ccd4a63SDavid du Colombier 
3*8ccd4a63SDavid du Colombier SmbProcessResult
smbcomreadandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)4*8ccd4a63SDavid du Colombier smbcomreadandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
5*8ccd4a63SDavid du Colombier {
6*8ccd4a63SDavid du Colombier 	uchar andxcommand;
7*8ccd4a63SDavid du Colombier 	ushort andxoffset;
8*8ccd4a63SDavid du Colombier 	ulong andxoffsetfixup;
9*8ccd4a63SDavid du Colombier 	ulong datafixup;
10*8ccd4a63SDavid du Colombier 	ulong bytecountfixup;
11*8ccd4a63SDavid du Colombier 	ushort fid;
12*8ccd4a63SDavid du Colombier 	SmbTree *t;
13*8ccd4a63SDavid du Colombier 	SmbFile *f;
14*8ccd4a63SDavid du Colombier 	vlong offset;
15*8ccd4a63SDavid du Colombier 	ushort maxcount;
16*8ccd4a63SDavid du Colombier 	long toread;
17*8ccd4a63SDavid du Colombier 	long nb;
18*8ccd4a63SDavid du Colombier 
19*8ccd4a63SDavid du Colombier 	if (h->wordcount != 10 && h->wordcount != 12)
20*8ccd4a63SDavid du Colombier 		return SmbProcessResultFormat;
21*8ccd4a63SDavid du Colombier 
22*8ccd4a63SDavid du Colombier 	andxcommand = *pdata++;
23*8ccd4a63SDavid du Colombier 	pdata++;
24*8ccd4a63SDavid du Colombier 	andxoffset = smbnhgets(pdata); pdata += 2;
25*8ccd4a63SDavid du Colombier 	fid = smbnhgets(pdata); pdata += 2;
26*8ccd4a63SDavid du Colombier 	offset = smbnhgetl(pdata); pdata += 4;
27*8ccd4a63SDavid du Colombier 	maxcount = smbnhgets(pdata); pdata += 2;
28*8ccd4a63SDavid du Colombier 	pdata += 2;	// mincount
29*8ccd4a63SDavid du Colombier 	pdata += 4;	// timeout ?
30*8ccd4a63SDavid du Colombier 	pdata += 2;	// remaining
31*8ccd4a63SDavid du Colombier 	if (h->wordcount == 12)
32*8ccd4a63SDavid du Colombier 		offset |= (vlong)smbnhgetl(pdata) << 32;
33*8ccd4a63SDavid du Colombier 
34*8ccd4a63SDavid du Colombier 	t = smbidmapfind(s->tidmap, h->tid);
35*8ccd4a63SDavid du Colombier 	if (t == nil) {
36*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRSRV, ERRinvtid);
37*8ccd4a63SDavid du Colombier 		return SmbProcessResultError;
38*8ccd4a63SDavid du Colombier 	}
39*8ccd4a63SDavid du Colombier 	f = smbidmapfind(s->fidmap, fid);
40*8ccd4a63SDavid du Colombier 	if (f == nil) {
41*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRbadfid);
42*8ccd4a63SDavid du Colombier 		return SmbProcessResultError;
43*8ccd4a63SDavid du Colombier 	}
44*8ccd4a63SDavid du Colombier 
45*8ccd4a63SDavid du Colombier 	if (!f->ioallowed) {
46*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRbadaccess);
47*8ccd4a63SDavid du Colombier 		return SmbProcessResultError;
48*8ccd4a63SDavid du Colombier 	}
49*8ccd4a63SDavid du Colombier 
50*8ccd4a63SDavid du Colombier 	h->wordcount = 12;
51*8ccd4a63SDavid du Colombier 	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup))
52*8ccd4a63SDavid du Colombier 		return SmbProcessResultMisc;
53*8ccd4a63SDavid du Colombier 	if (!smbbufferputs(s->response, -1)			// remaining
54*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(s->response, 0)		// datacompactionmode
55*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(s->response, 0))		// reserved
56*8ccd4a63SDavid du Colombier 		return SmbProcessResultMisc;
57*8ccd4a63SDavid du Colombier 	datafixup = smbbufferwriteoffset(s->response);
58*8ccd4a63SDavid du Colombier 	if (!smbbufferputbytes(s->response, nil, 6)
59*8ccd4a63SDavid du Colombier 		|| !smbbufferfill(s->response, 0, 8))		// reserved
60*8ccd4a63SDavid du Colombier 		return SmbProcessResultMisc;
61*8ccd4a63SDavid du Colombier 	bytecountfixup = smbbufferwriteoffset(s->response);
62*8ccd4a63SDavid du Colombier 	if (!smbbufferputs(s->response, 0)
63*8ccd4a63SDavid du Colombier 		|| !smbbufferputb(s->response, 0))
64*8ccd4a63SDavid du Colombier 		return SmbProcessResultMisc;
65*8ccd4a63SDavid du Colombier 	smbbufferwritelimit(s->response, smbbufferwriteoffset(s->response) + 65535);
66*8ccd4a63SDavid du Colombier 	smbbufferoffsetputs(s->response, datafixup + 2, smbbufferwriteoffset(s->response));
67*8ccd4a63SDavid du Colombier 	seek(f->fd, offset, 0);
68*8ccd4a63SDavid du Colombier 	toread = smbbufferwritespace(s->response);
69*8ccd4a63SDavid du Colombier 	if (toread > maxcount)
70*8ccd4a63SDavid du Colombier 		toread = maxcount;
71*8ccd4a63SDavid du Colombier 	nb = readn(f->fd, smbbufferwritepointer(s->response), toread);
72*8ccd4a63SDavid du Colombier 	if (nb < 0) {
73*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRbadaccess);
74*8ccd4a63SDavid du Colombier 		return SmbProcessResultError;
75*8ccd4a63SDavid du Colombier 	}
76*8ccd4a63SDavid du Colombier 	if (!smbbufferputbytes(s->response, nil, nb)
77*8ccd4a63SDavid du Colombier 		|| !smbbufferfixuprelatives(s->response, bytecountfixup)
78*8ccd4a63SDavid du Colombier 		|| !smbbufferoffsetputs(s->response, datafixup, nb)
79*8ccd4a63SDavid du Colombier 		|| !smbbufferoffsetputs(s->response, datafixup + 4, nb >> 16))
80*8ccd4a63SDavid du Colombier 		return SmbProcessResultMisc;
81*8ccd4a63SDavid du Colombier 	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
82*8ccd4a63SDavid du Colombier 		return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
83*8ccd4a63SDavid du Colombier 	return SmbProcessResultReply;
84*8ccd4a63SDavid du Colombier }
85