smbcomlocking.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "headers.h"
  10. static int
  11. getlock(SmbBuffer *b, int large, uint16_t *pidp, uint64_t *offsetp,
  12. uint64_t *lengthp)
  13. {
  14. uint32_t ohigh, olow;
  15. uint32_t lhigh, llow;
  16. if (!smbbuffergets(b, pidp))
  17. return 0;
  18. if (large && !smbbuffergetbytes(b, nil, 2))
  19. return 0;
  20. if (large) {
  21. if (!smbbuffergetl(b, &ohigh) || !smbbuffergetl(b, &olow)
  22. || !smbbuffergetl(b, &lhigh) || !smbbuffergetl(b, &llow))
  23. return 0;
  24. *offsetp = ((uint64_t)ohigh << 32) | olow;
  25. *lengthp = ((uint64_t)lhigh << 32) | llow;
  26. return 1;
  27. }
  28. if (!smbbuffergetl(b, &olow) || !smbbuffergetl(b, &llow))
  29. return 0;
  30. *offsetp = olow;
  31. *lengthp = llow;
  32. return 1;
  33. }
  34. SmbProcessResult
  35. smbcomlockingandx(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b)
  36. {
  37. uint8_t andxcommand;
  38. uint16_t andxoffset;
  39. uint32_t andxoffsetfixup;
  40. uint16_t fid;
  41. uint8_t locktype;
  42. uint8_t oplocklevel;
  43. uint32_t timeout;
  44. uint16_t numberofunlocks;
  45. uint16_t numberoflocks;
  46. SmbTree *t;
  47. SmbFile *f;
  48. int l;
  49. SmbProcessResult pr;
  50. uint32_t backupoffset;
  51. int large;
  52. if (!smbcheckwordcount("comlockingandx", h, 8))
  53. return SmbProcessResultFormat;
  54. andxcommand = *pdata++;
  55. pdata++;
  56. andxoffset = smbnhgets(pdata); pdata += 2;
  57. fid = smbnhgets(pdata); pdata += 2;
  58. locktype = *pdata++;
  59. oplocklevel = *pdata++;
  60. timeout = smbnhgetl(pdata); pdata += 4;
  61. numberofunlocks = smbnhgets(pdata); pdata += 2;
  62. numberoflocks = smbnhgets(pdata);
  63. smblogprint(h->command, "smbcomlockingandx: fid 0x%.4x locktype 0x%.2x oplocklevel 0x%.2x timeout %lu numberofunlocks %d numberoflocks %u\n",
  64. fid, locktype, oplocklevel, timeout, numberofunlocks, numberoflocks);
  65. large = locktype & 0x10;
  66. locktype &= ~0x10;
  67. if (locktype != 0 || oplocklevel != 0) {
  68. smblogprint(-1, "smbcomlockingandx: locktype 0x%.2x unimplemented\n", locktype);
  69. return SmbProcessResultUnimp;
  70. }
  71. if (oplocklevel != 0) {
  72. smblogprint(-1, "smbcomlockingandx: oplocklevel 0x%.2x unimplemented\n", oplocklevel);
  73. return SmbProcessResultUnimp;
  74. }
  75. t = smbidmapfind(s->tidmap, h->tid);
  76. if (t == nil) {
  77. smbseterror(s, ERRSRV, ERRinvtid);
  78. error:
  79. return SmbProcessResultError;
  80. }
  81. f = smbidmapfind(s->fidmap, fid);
  82. if (f == nil) {
  83. smbseterror(s, ERRDOS, ERRbadfid);
  84. goto error;
  85. }
  86. backupoffset = smbbufferreadoffset(b);
  87. for (l = 0; l < numberofunlocks; l++) {
  88. uint16_t pid;
  89. uint64_t offset;
  90. uint64_t length;
  91. if (!getlock(b, large, &pid, &offset, &length)) {
  92. pr = SmbProcessResultFormat;
  93. goto done;
  94. }
  95. smblogprint(h->command, "smbcomlockingandx: unlock pid 0x%.4x offset %llu length %llu\n",
  96. pid, offset, length);
  97. smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
  98. }
  99. for (l = 0; l < numberoflocks; l++) {
  100. uint16_t pid;
  101. uint64_t offset;
  102. uint64_t length;
  103. if (!getlock(b, large, &pid, &offset, &length)) {
  104. pr = SmbProcessResultFormat;
  105. goto done;
  106. }
  107. smblogprint(h->command, "smbcomlockingandx: lock pid 0x%.4x offset %llu length %llu\n",
  108. pid, offset, length);
  109. if (!smbsharedfilelock(f->sf, s, h->pid, offset, offset + length))
  110. break;
  111. }
  112. if (l < numberoflocks) {
  113. uint16_t i;
  114. uint16_t pid;
  115. uint64_t offset;
  116. uint64_t length;
  117. smbbufferreadbackup(b, backupoffset);
  118. for (i = 0; i < l; i++) {
  119. assert(getlock(b, large, &pid, &offset, &length));
  120. smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
  121. }
  122. smbseterror(s, ERRDOS, ERRlock);
  123. goto error;
  124. }
  125. h->wordcount = 2;
  126. if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)
  127. || !smbbufferputs(s->response, 0)) { // bytecount 0
  128. pr = SmbProcessResultMisc;
  129. goto done;
  130. }
  131. if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
  132. pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
  133. else
  134. pr = SmbProcessResultReply;
  135. done:
  136. return pr;
  137. }