xref: /plan9/sys/src/cmd/aquarela/smbcomlocking.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include "headers.h"
2*8ccd4a63SDavid du Colombier 
3*8ccd4a63SDavid du Colombier static int
getlock(SmbBuffer * b,int large,ushort * pidp,uvlong * offsetp,uvlong * lengthp)4*8ccd4a63SDavid du Colombier getlock(SmbBuffer *b, int large, ushort *pidp, uvlong *offsetp, uvlong *lengthp)
5*8ccd4a63SDavid du Colombier {
6*8ccd4a63SDavid du Colombier 	ulong ohigh, olow;
7*8ccd4a63SDavid du Colombier 	ulong lhigh, llow;
8*8ccd4a63SDavid du Colombier 	if (!smbbuffergets(b, pidp))
9*8ccd4a63SDavid du Colombier 		return 0;
10*8ccd4a63SDavid du Colombier 	if (large && !smbbuffergetbytes(b, nil, 2))
11*8ccd4a63SDavid du Colombier 		return 0;
12*8ccd4a63SDavid du Colombier 	if (large) {
13*8ccd4a63SDavid du Colombier 		if (!smbbuffergetl(b, &ohigh) || !smbbuffergetl(b, &olow)
14*8ccd4a63SDavid du Colombier 			|| !smbbuffergetl(b, &lhigh) || !smbbuffergetl(b, &llow))
15*8ccd4a63SDavid du Colombier 			return 0;
16*8ccd4a63SDavid du Colombier 		*offsetp = ((uvlong)ohigh << 32) | olow;
17*8ccd4a63SDavid du Colombier 		*lengthp = ((uvlong)lhigh << 32) | llow;
18*8ccd4a63SDavid du Colombier 		return 1;
19*8ccd4a63SDavid du Colombier 	}
20*8ccd4a63SDavid du Colombier 	if (!smbbuffergetl(b, &olow) || !smbbuffergetl(b, &llow))
21*8ccd4a63SDavid du Colombier 		return 0;
22*8ccd4a63SDavid du Colombier 	*offsetp = olow;
23*8ccd4a63SDavid du Colombier 	*lengthp = llow;
24*8ccd4a63SDavid du Colombier 	return 1;
25*8ccd4a63SDavid du Colombier }
26*8ccd4a63SDavid du Colombier 
27*8ccd4a63SDavid du Colombier SmbProcessResult
smbcomlockingandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)28*8ccd4a63SDavid du Colombier smbcomlockingandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
29*8ccd4a63SDavid du Colombier {
30*8ccd4a63SDavid du Colombier 	uchar andxcommand;
31*8ccd4a63SDavid du Colombier 	ushort andxoffset;
32*8ccd4a63SDavid du Colombier 	ulong andxoffsetfixup;
33*8ccd4a63SDavid du Colombier 	ushort fid;
34*8ccd4a63SDavid du Colombier 	uchar locktype;
35*8ccd4a63SDavid du Colombier 	uchar oplocklevel;
36*8ccd4a63SDavid du Colombier 	ulong timeout;
37*8ccd4a63SDavid du Colombier 	ushort numberofunlocks;
38*8ccd4a63SDavid du Colombier 	ushort numberoflocks;
39*8ccd4a63SDavid du Colombier 	SmbTree *t;
40*8ccd4a63SDavid du Colombier 	SmbFile *f;
41*8ccd4a63SDavid du Colombier 	int l;
42*8ccd4a63SDavid du Colombier 	SmbProcessResult pr;
43*8ccd4a63SDavid du Colombier 	ulong backupoffset;
44*8ccd4a63SDavid du Colombier 	int large;
45*8ccd4a63SDavid du Colombier 
46*8ccd4a63SDavid du Colombier 	if (!smbcheckwordcount("comlockingandx", h, 8))
47*8ccd4a63SDavid du Colombier 		return SmbProcessResultFormat;
48*8ccd4a63SDavid du Colombier 
49*8ccd4a63SDavid du Colombier 	andxcommand = *pdata++;
50*8ccd4a63SDavid du Colombier 	pdata++;
51*8ccd4a63SDavid du Colombier 	andxoffset = smbnhgets(pdata); pdata += 2;
52*8ccd4a63SDavid du Colombier 	fid = smbnhgets(pdata); pdata += 2;
53*8ccd4a63SDavid du Colombier 	locktype = *pdata++;
54*8ccd4a63SDavid du Colombier 	oplocklevel = *pdata++;
55*8ccd4a63SDavid du Colombier 	timeout = smbnhgetl(pdata); pdata += 4;
56*8ccd4a63SDavid du Colombier 	numberofunlocks = smbnhgets(pdata); pdata += 2;
57*8ccd4a63SDavid du Colombier 	numberoflocks = smbnhgets(pdata);
58*8ccd4a63SDavid du Colombier 	smblogprint(h->command, "smbcomlockingandx: fid 0x%.4ux locktype 0x%.2ux oplocklevel 0x%.2ux timeout %lud numberofunlocks %d numberoflocks %ud\n",
59*8ccd4a63SDavid du Colombier 		fid, locktype, oplocklevel, timeout, numberofunlocks, numberoflocks);
60*8ccd4a63SDavid du Colombier 	large = locktype & 0x10;
61*8ccd4a63SDavid du Colombier 	locktype &= ~0x10;
62*8ccd4a63SDavid du Colombier 	if (locktype != 0 || oplocklevel != 0) {
63*8ccd4a63SDavid du Colombier 		smblogprint(-1, "smbcomlockingandx: locktype 0x%.2ux unimplemented\n", locktype);
64*8ccd4a63SDavid du Colombier 		return SmbProcessResultUnimp;
65*8ccd4a63SDavid du Colombier 	}
66*8ccd4a63SDavid du Colombier 	if (oplocklevel != 0) {
67*8ccd4a63SDavid du Colombier 		smblogprint(-1, "smbcomlockingandx: oplocklevel 0x%.2ux unimplemented\n", oplocklevel);
68*8ccd4a63SDavid du Colombier 		return SmbProcessResultUnimp;
69*8ccd4a63SDavid du Colombier 	}
70*8ccd4a63SDavid du Colombier 	t = smbidmapfind(s->tidmap, h->tid);
71*8ccd4a63SDavid du Colombier 	if (t == nil) {
72*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRSRV, ERRinvtid);
73*8ccd4a63SDavid du Colombier 	error:
74*8ccd4a63SDavid du Colombier 		return SmbProcessResultError;
75*8ccd4a63SDavid du Colombier 	}
76*8ccd4a63SDavid du Colombier 	f = smbidmapfind(s->fidmap, fid);
77*8ccd4a63SDavid du Colombier 	if (f == nil) {
78*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRbadfid);
79*8ccd4a63SDavid du Colombier 		goto error;
80*8ccd4a63SDavid du Colombier 	}
81*8ccd4a63SDavid du Colombier 	backupoffset = smbbufferreadoffset(b);
82*8ccd4a63SDavid du Colombier 	for (l = 0; l < numberofunlocks; l++) {
83*8ccd4a63SDavid du Colombier 		ushort pid;
84*8ccd4a63SDavid du Colombier 		uvlong offset;
85*8ccd4a63SDavid du Colombier 		uvlong length;
86*8ccd4a63SDavid du Colombier 		if (!getlock(b, large, &pid, &offset, &length)) {
87*8ccd4a63SDavid du Colombier 			pr = SmbProcessResultFormat;
88*8ccd4a63SDavid du Colombier 			goto done;
89*8ccd4a63SDavid du Colombier 		}
90*8ccd4a63SDavid du Colombier 		smblogprint(h->command, "smbcomlockingandx: unlock pid 0x%.4ux offset %llud length %llud\n",
91*8ccd4a63SDavid du Colombier 			pid, offset, length);
92*8ccd4a63SDavid du Colombier 		smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
93*8ccd4a63SDavid du Colombier 	}
94*8ccd4a63SDavid du Colombier 	for (l = 0; l < numberoflocks; l++) {
95*8ccd4a63SDavid du Colombier 		ushort pid;
96*8ccd4a63SDavid du Colombier 		uvlong offset;
97*8ccd4a63SDavid du Colombier 		uvlong length;
98*8ccd4a63SDavid du Colombier 		if (!getlock(b, large, &pid, &offset, &length)) {
99*8ccd4a63SDavid du Colombier 			pr = SmbProcessResultFormat;
100*8ccd4a63SDavid du Colombier 			goto done;
101*8ccd4a63SDavid du Colombier 		}
102*8ccd4a63SDavid du Colombier 		smblogprint(h->command, "smbcomlockingandx: lock pid 0x%.4ux offset %llud length %llud\n",
103*8ccd4a63SDavid du Colombier 			pid, offset, length);
104*8ccd4a63SDavid du Colombier 		if (!smbsharedfilelock(f->sf, s, h->pid, offset, offset + length))
105*8ccd4a63SDavid du Colombier 			break;
106*8ccd4a63SDavid du Colombier 	}
107*8ccd4a63SDavid du Colombier 	if (l < numberoflocks) {
108*8ccd4a63SDavid du Colombier 		ushort i;
109*8ccd4a63SDavid du Colombier 		ushort pid;
110*8ccd4a63SDavid du Colombier 		uvlong offset;
111*8ccd4a63SDavid du Colombier 		uvlong length;
112*8ccd4a63SDavid du Colombier 		smbbufferreadbackup(b, backupoffset);
113*8ccd4a63SDavid du Colombier 		for (i  = 0; i < l; i++) {
114*8ccd4a63SDavid du Colombier 			assert(getlock(b, large, &pid, &offset, &length));
115*8ccd4a63SDavid du Colombier 			smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
116*8ccd4a63SDavid du Colombier 		}
117*8ccd4a63SDavid du Colombier 		smbseterror(s, ERRDOS, ERRlock);
118*8ccd4a63SDavid du Colombier 		goto error;
119*8ccd4a63SDavid du Colombier 	}
120*8ccd4a63SDavid du Colombier 	h->wordcount = 2;
121*8ccd4a63SDavid du Colombier 	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)
122*8ccd4a63SDavid du Colombier 		|| !smbbufferputs(s->response, 0)) {	// bytecount 0
123*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultMisc;
124*8ccd4a63SDavid du Colombier 		goto done;
125*8ccd4a63SDavid du Colombier 	}
126*8ccd4a63SDavid du Colombier 	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
127*8ccd4a63SDavid du Colombier 		pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
128*8ccd4a63SDavid du Colombier 	else
129*8ccd4a63SDavid du Colombier 		pr = SmbProcessResultReply;
130*8ccd4a63SDavid du Colombier done:
131*8ccd4a63SDavid du Colombier 	return pr;
132*8ccd4a63SDavid du Colombier }
133