diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aquarela/smbcomlocking.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aquarela/smbcomlocking.c')
-rwxr-xr-x | sys/src/cmd/aquarela/smbcomlocking.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/sys/src/cmd/aquarela/smbcomlocking.c b/sys/src/cmd/aquarela/smbcomlocking.c new file mode 100755 index 000000000..8fc33146d --- /dev/null +++ b/sys/src/cmd/aquarela/smbcomlocking.c @@ -0,0 +1,132 @@ +#include "headers.h" + +static int +getlock(SmbBuffer *b, int large, ushort *pidp, uvlong *offsetp, uvlong *lengthp) +{ + ulong ohigh, olow; + ulong lhigh, llow; + if (!smbbuffergets(b, pidp)) + return 0; + if (large && !smbbuffergetbytes(b, nil, 2)) + return 0; + if (large) { + if (!smbbuffergetl(b, &ohigh) || !smbbuffergetl(b, &olow) + || !smbbuffergetl(b, &lhigh) || !smbbuffergetl(b, &llow)) + return 0; + *offsetp = ((uvlong)ohigh << 32) | olow; + *lengthp = ((uvlong)lhigh << 32) | llow; + return 1; + } + if (!smbbuffergetl(b, &olow) || !smbbuffergetl(b, &llow)) + return 0; + *offsetp = olow; + *lengthp = llow; + return 1; +} + +SmbProcessResult +smbcomlockingandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) +{ + uchar andxcommand; + ushort andxoffset; + ulong andxoffsetfixup; + ushort fid; + uchar locktype; + uchar oplocklevel; + ulong timeout; + ushort numberofunlocks; + ushort numberoflocks; + SmbTree *t; + SmbFile *f; + int l; + SmbProcessResult pr; + ulong backupoffset; + int large; + + if (!smbcheckwordcount("comlockingandx", h, 8)) + return SmbProcessResultFormat; + + andxcommand = *pdata++; + pdata++; + andxoffset = smbnhgets(pdata); pdata += 2; + fid = smbnhgets(pdata); pdata += 2; + locktype = *pdata++; + oplocklevel = *pdata++; + timeout = smbnhgetl(pdata); pdata += 4; + numberofunlocks = smbnhgets(pdata); pdata += 2; + numberoflocks = smbnhgets(pdata); + smblogprint(h->command, "smbcomlockingandx: fid 0x%.4ux locktype 0x%.2ux oplocklevel 0x%.2ux timeout %lud numberofunlocks %d numberoflocks %ud\n", + fid, locktype, oplocklevel, timeout, numberofunlocks, numberoflocks); + large = locktype & 0x10; + locktype &= ~0x10; + if (locktype != 0 || oplocklevel != 0) { + smblogprint(-1, "smbcomlockingandx: locktype 0x%.2ux unimplemented\n", locktype); + return SmbProcessResultUnimp; + } + if (oplocklevel != 0) { + smblogprint(-1, "smbcomlockingandx: oplocklevel 0x%.2ux unimplemented\n", oplocklevel); + return SmbProcessResultUnimp; + } + t = smbidmapfind(s->tidmap, h->tid); + if (t == nil) { + smbseterror(s, ERRSRV, ERRinvtid); + error: + return SmbProcessResultError; + } + f = smbidmapfind(s->fidmap, fid); + if (f == nil) { + smbseterror(s, ERRDOS, ERRbadfid); + goto error; + } + backupoffset = smbbufferreadoffset(b); + for (l = 0; l < numberofunlocks; l++) { + ushort pid; + uvlong offset; + uvlong length; + if (!getlock(b, large, &pid, &offset, &length)) { + pr = SmbProcessResultFormat; + goto done; + } + smblogprint(h->command, "smbcomlockingandx: unlock pid 0x%.4ux offset %llud length %llud\n", + pid, offset, length); + smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length); + } + for (l = 0; l < numberoflocks; l++) { + ushort pid; + uvlong offset; + uvlong length; + if (!getlock(b, large, &pid, &offset, &length)) { + pr = SmbProcessResultFormat; + goto done; + } + smblogprint(h->command, "smbcomlockingandx: lock pid 0x%.4ux offset %llud length %llud\n", + pid, offset, length); + if (!smbsharedfilelock(f->sf, s, h->pid, offset, offset + length)) + break; + } + if (l < numberoflocks) { + ushort i; + ushort pid; + uvlong offset; + uvlong length; + smbbufferreadbackup(b, backupoffset); + for (i = 0; i < l; i++) { + assert(getlock(b, large, &pid, &offset, &length)); + smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length); + } + smbseterror(s, ERRDOS, ERRlock); + goto error; + } + h->wordcount = 2; + if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup) + || !smbbufferputs(s->response, 0)) { // bytecount 0 + pr = SmbProcessResultMisc; + goto done; + } + if (andxcommand != SMB_COM_NO_ANDX_COMMAND) + pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b); + else + pr = SmbProcessResultReply; +done: + return pr; +} |