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