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