smbcomlocking.c 3.6 KB

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