summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aquarela/smbcomread.c
blob: 11a358bdc814f5f2e7b4fe8c6df3e73909ae57a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "headers.h"

SmbProcessResult
smbcomreadandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
{
	uchar andxcommand;
	ushort andxoffset;
	ulong andxoffsetfixup;
	ulong datafixup;
	ulong bytecountfixup;
	ushort fid;
	SmbTree *t;
	SmbFile *f;
	vlong offset;
	ushort maxcount;
	long toread;
	long nb;

	if (h->wordcount != 10 && h->wordcount != 12)
		return SmbProcessResultFormat;

	andxcommand = *pdata++;
	pdata++;
	andxoffset = smbnhgets(pdata); pdata += 2;
	fid = smbnhgets(pdata); pdata += 2;
	offset = smbnhgetl(pdata); pdata += 4;
	maxcount = smbnhgets(pdata); pdata += 2;
	pdata += 2;	// mincount
	pdata += 4;	// timeout ?
	pdata += 2;	// remaining
	if (h->wordcount == 12)
		offset |= (vlong)smbnhgetl(pdata) << 32;

	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		return SmbProcessResultError;
	}
	f = smbidmapfind(s->fidmap, fid);
	if (f == nil) {
		smbseterror(s, ERRDOS, ERRbadfid);
		return SmbProcessResultError;
	}
	
	if (!f->ioallowed) {
		smbseterror(s, ERRDOS, ERRbadaccess);
		return SmbProcessResultError;
	}

	h->wordcount = 12;
	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup))
		return SmbProcessResultMisc;
	if (!smbbufferputs(s->response, -1)			// remaining
		|| !smbbufferputs(s->response, 0)		// datacompactionmode
		|| !smbbufferputs(s->response, 0))		// reserved
		return SmbProcessResultMisc;
	datafixup = smbbufferwriteoffset(s->response);
	if (!smbbufferputbytes(s->response, nil, 6)
		|| !smbbufferfill(s->response, 0, 8))		// reserved
		return SmbProcessResultMisc;
	bytecountfixup = smbbufferwriteoffset(s->response);
	if (!smbbufferputs(s->response, 0)
		|| !smbbufferputb(s->response, 0))
		return SmbProcessResultMisc;
	smbbufferwritelimit(s->response, smbbufferwriteoffset(s->response) + 65535);
	smbbufferoffsetputs(s->response, datafixup + 2, smbbufferwriteoffset(s->response));
	seek(f->fd, offset, 0);
	toread = smbbufferwritespace(s->response);	
	if (toread > maxcount)
		toread = maxcount;
	nb = readn(f->fd, smbbufferwritepointer(s->response), toread);
	if (nb < 0) {
		smbseterror(s, ERRDOS, ERRbadaccess);
		return SmbProcessResultError;
	}
	if (!smbbufferputbytes(s->response, nil, nb)
		|| !smbbufferfixuprelatives(s->response, bytecountfixup)
		|| !smbbufferoffsetputs(s->response, datafixup, nb)
		|| !smbbufferoffsetputs(s->response, datafixup + 4, nb >> 16))
		return SmbProcessResultMisc;
	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
		return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
	return SmbProcessResultReply;
}