LCOV - code coverage report
Current view: top level - source4/torture/raw - lock.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1618 1995 81.1 %
Date: 2024-06-13 04:01:37 Functions: 18 18 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for various lock operations
       4             :    Copyright (C) Andrew Tridgell 2003
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "torture/torture.h"
      22             : #include "libcli/raw/libcliraw.h"
      23             : #include "libcli/raw/raw_proto.h"
      24             : #include "system/time.h"
      25             : #include "system/filesys.h"
      26             : #include "libcli/libcli.h"
      27             : #include "torture/util.h"
      28             : #include "libcli/composite/composite.h"
      29             : #include "libcli/smb_composite/smb_composite.h"
      30             : #include "lib/cmdline/cmdline.h"
      31             : #include "param/param.h"
      32             : #include "torture/raw/proto.h"
      33             : 
      34             : #define CHECK_STATUS(status, correct) do { \
      35             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      36             :                 torture_result(tctx, TORTURE_FAIL, \
      37             :                         "(%s) Incorrect status %s - should be %s\n", \
      38             :                         __location__, nt_errstr(status), nt_errstr(correct)); \
      39             :                 ret = false; \
      40             :                 goto done; \
      41             :         }} while (0)
      42             : 
      43             : #define CHECK_STATUS_CONT(status, correct) do { \
      44             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      45             :                 torture_result(tctx, TORTURE_FAIL, \
      46             :                         "(%s) Incorrect status %s - should be %s\n", \
      47             :                         __location__, nt_errstr(status), nt_errstr(correct)); \
      48             :                 ret = false; \
      49             :         }} while (0)
      50             : 
      51             : #define CHECK_STATUS_OR(status, correct1, correct2) do { \
      52             :         if ((!NT_STATUS_EQUAL(status, correct1)) && \
      53             :             (!NT_STATUS_EQUAL(status, correct2))) { \
      54             :                 torture_result(tctx, TORTURE_FAIL, \
      55             :                         "(%s) Incorrect status %s - should be %s or %s\n", \
      56             :                         __location__, nt_errstr(status), nt_errstr(correct1), \
      57             :                         nt_errstr(correct2)); \
      58             :                 ret = false; \
      59             :                 goto done; \
      60             :         }} while (0)
      61             : 
      62             : #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
      63             :         if ((!NT_STATUS_EQUAL(status, correct1)) && \
      64             :             (!NT_STATUS_EQUAL(status, correct2))) { \
      65             :                 torture_result(tctx, TORTURE_FAIL, \
      66             :                         "(%s) Incorrect status %s - should be %s or %s\n", \
      67             :                         __location__, nt_errstr(status), nt_errstr(correct1), \
      68             :                         nt_errstr(correct2)); \
      69             :                 ret = false; \
      70             :         }} while (0)
      71             : #define BASEDIR "\\testlock"
      72             : 
      73             : #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
      74             : #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
      75             : #define TARGET_IS_WINDOWS(_tctx) \
      76             :         ((torture_setting_bool(_tctx, "w2k3", false)) || \
      77             :          (torture_setting_bool(_tctx, "w2k8", false)) || \
      78             :          (torture_setting_bool(_tctx, "win7", false)))
      79             : #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
      80             : #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
      81             : 
      82             : #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
      83             :         (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
      84             : #define TARGET_SUPPORTS_SMBEXIT(_tctx) \
      85             :     (torture_setting_bool(_tctx, "smbexit_pdu_support", true))
      86             : #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
      87             :     (torture_setting_bool(_tctx, "smblock_pdu_support", true))
      88             : #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
      89             :     (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
      90             : #define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \
      91             :     (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true))
      92             : /*
      93             :   test SMBlock and SMBunlock ops
      94             : */
      95           1 : static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
      96             : {
      97             :         union smb_lock io;
      98             :         NTSTATUS status;
      99           1 :         bool ret = true;
     100             :         int fnum;
     101           1 :         const char *fname = BASEDIR "\\test.txt";
     102             : 
     103           1 :         if (!TARGET_SUPPORTS_SMBLOCK(tctx))
     104           0 :                 torture_skip(tctx, "Target does not support the SMBlock PDU");
     105             : 
     106           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     107             : 
     108           1 :         torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
     109           1 :         io.generic.level = RAW_LOCK_LOCK;
     110             :         
     111           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     112           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     113             :                        "Failed to create %s - %s\n",
     114             :                        fname, smbcli_errstr(cli->tree)));
     115             : 
     116           1 :         torture_comment(tctx, "Trying 0/0 lock\n");
     117           1 :         io.lock.level = RAW_LOCK_LOCK;
     118           1 :         io.lock.in.file.fnum = fnum;
     119           1 :         io.lock.in.count = 0;
     120           1 :         io.lock.in.offset = 0;
     121           1 :         status = smb_raw_lock(cli->tree, &io);
     122           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     123           1 :         cli->session->pid++;
     124           1 :         status = smb_raw_lock(cli->tree, &io);
     125           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     126           1 :         cli->session->pid--;
     127           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     128           1 :         status = smb_raw_lock(cli->tree, &io);
     129           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     130             : 
     131           1 :         torture_comment(tctx, "Trying 0/1 lock\n");
     132           1 :         io.lock.level = RAW_LOCK_LOCK;
     133           1 :         io.lock.in.file.fnum = fnum;
     134           1 :         io.lock.in.count = 1;
     135           1 :         io.lock.in.offset = 0;
     136           1 :         status = smb_raw_lock(cli->tree, &io);
     137           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     138           1 :         cli->session->pid++;
     139           1 :         status = smb_raw_lock(cli->tree, &io);
     140           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     141           1 :         cli->session->pid--;
     142           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     143           1 :         status = smb_raw_lock(cli->tree, &io);
     144           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     145           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     146           1 :         status = smb_raw_lock(cli->tree, &io);
     147           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     148             : 
     149           1 :         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
     150           1 :         io.lock.level = RAW_LOCK_LOCK;
     151           1 :         io.lock.in.file.fnum = fnum;
     152           1 :         io.lock.in.count = 4000;
     153           1 :         io.lock.in.offset = 0xEEFFFFFF;
     154           1 :         status = smb_raw_lock(cli->tree, &io);
     155           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     156           1 :         cli->session->pid++;
     157           1 :         status = smb_raw_lock(cli->tree, &io);
     158           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     159           1 :         cli->session->pid--;
     160           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     161           1 :         status = smb_raw_lock(cli->tree, &io);
     162           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     163           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     164           1 :         status = smb_raw_lock(cli->tree, &io);
     165           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     166             : 
     167           1 :         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
     168           1 :         io.lock.level = RAW_LOCK_LOCK;
     169           1 :         io.lock.in.file.fnum = fnum;
     170           1 :         io.lock.in.count = 4000;
     171           1 :         io.lock.in.offset = 0xEEFFFFFF;
     172           1 :         status = smb_raw_lock(cli->tree, &io);
     173           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     174           1 :         cli->session->pid++;
     175           1 :         status = smb_raw_lock(cli->tree, &io);
     176           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     177           1 :         cli->session->pid--;
     178           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     179           1 :         status = smb_raw_lock(cli->tree, &io);
     180           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     181           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     182           1 :         status = smb_raw_lock(cli->tree, &io);
     183           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     184             : 
     185           1 :         torture_comment(tctx, "Trying max lock\n");
     186           1 :         io.lock.level = RAW_LOCK_LOCK;
     187           1 :         io.lock.in.file.fnum = fnum;
     188           1 :         io.lock.in.count = 4000;
     189           1 :         io.lock.in.offset = 0xEF000000;
     190           1 :         status = smb_raw_lock(cli->tree, &io);
     191           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     192           1 :         cli->session->pid++;
     193           1 :         status = smb_raw_lock(cli->tree, &io);
     194           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     195           1 :         cli->session->pid--;
     196           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     197           1 :         status = smb_raw_lock(cli->tree, &io);
     198           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     199           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     200           1 :         status = smb_raw_lock(cli->tree, &io);
     201           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     202             : 
     203           1 :         torture_comment(tctx, "Trying wrong pid unlock\n");
     204           1 :         io.lock.level = RAW_LOCK_LOCK;
     205           1 :         io.lock.in.file.fnum = fnum;
     206           1 :         io.lock.in.count = 4002;
     207           1 :         io.lock.in.offset = 10001;
     208           1 :         status = smb_raw_lock(cli->tree, &io);
     209           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     210           1 :         cli->session->pid++;
     211           1 :         io.lock.level = RAW_LOCK_UNLOCK;
     212           1 :         status = smb_raw_lock(cli->tree, &io);
     213           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     214           1 :         cli->session->pid--;
     215           1 :         status = smb_raw_lock(cli->tree, &io);
     216           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     217             : 
     218           2 : done:
     219           1 :         smbcli_close(cli->tree, fnum);
     220           1 :         smb_raw_exit(cli->session);
     221           1 :         smbcli_deltree(cli->tree, BASEDIR);
     222           1 :         return ret;
     223             : }
     224             : 
     225             : 
     226             : /*
     227             :   test locking&X ops
     228             : */
     229           1 : static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
     230             : {
     231             :         union smb_lock io;
     232             :         struct smb_lock_entry lock[1];
     233             :         NTSTATUS status;
     234           1 :         bool ret = true;
     235             :         int fnum;
     236           1 :         const char *fname = BASEDIR "\\test.txt";
     237             : 
     238           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     239             : 
     240           1 :         torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
     241           1 :         io.generic.level = RAW_LOCK_LOCKX;
     242             :         
     243           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     244           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     245             :                        "Failed to create %s - %s\n",
     246             :                        fname, smbcli_errstr(cli->tree)));
     247             : 
     248           1 :         io.lockx.level = RAW_LOCK_LOCKX;
     249           1 :         io.lockx.in.file.fnum = fnum;
     250           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     251           1 :         io.lockx.in.timeout = 0;
     252           1 :         io.lockx.in.ulock_cnt = 0;
     253           1 :         io.lockx.in.lock_cnt = 1;
     254           1 :         lock[0].pid = cli->session->pid;
     255           1 :         lock[0].offset = 10;
     256           1 :         lock[0].count = 1;
     257           1 :         io.lockx.in.locks = &lock[0];
     258           1 :         status = smb_raw_lock(cli->tree, &io);
     259           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     260             : 
     261             : 
     262           1 :         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
     263           1 :         io.lockx.in.ulock_cnt = 0;
     264           1 :         io.lockx.in.lock_cnt = 1;
     265           1 :         lock[0].count = 4000;
     266           1 :         lock[0].offset = 0xEEFFFFFF;
     267           1 :         status = smb_raw_lock(cli->tree, &io);
     268           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     269           1 :         lock[0].pid++;
     270           1 :         status = smb_raw_lock(cli->tree, &io);
     271           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     272           1 :         lock[0].pid--;
     273           1 :         io.lockx.in.ulock_cnt = 1;
     274           1 :         io.lockx.in.lock_cnt = 0;
     275           1 :         status = smb_raw_lock(cli->tree, &io);
     276           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     277           1 :         status = smb_raw_lock(cli->tree, &io);
     278           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     279             : 
     280           1 :         torture_comment(tctx, "Trying 0xEF000000 lock\n");
     281           1 :         io.lockx.in.ulock_cnt = 0;
     282           1 :         io.lockx.in.lock_cnt = 1;
     283           1 :         lock[0].count = 4000;
     284           1 :         lock[0].offset = 0xEF000000;
     285           1 :         status = smb_raw_lock(cli->tree, &io);
     286           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     287           1 :         lock[0].pid++;
     288           1 :         status = smb_raw_lock(cli->tree, &io);
     289           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     290           1 :         lock[0].pid--;
     291           1 :         io.lockx.in.ulock_cnt = 1;
     292           1 :         io.lockx.in.lock_cnt = 0;
     293           1 :         status = smb_raw_lock(cli->tree, &io);
     294           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     295           1 :         status = smb_raw_lock(cli->tree, &io);
     296           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     297             : 
     298           1 :         torture_comment(tctx, "Trying zero lock\n");
     299           1 :         io.lockx.in.ulock_cnt = 0;
     300           1 :         io.lockx.in.lock_cnt = 1;
     301           1 :         lock[0].count = 0;
     302           1 :         lock[0].offset = ~0;
     303           1 :         status = smb_raw_lock(cli->tree, &io);
     304           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     305           1 :         lock[0].pid++;
     306           1 :         status = smb_raw_lock(cli->tree, &io);
     307           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     308           1 :         lock[0].pid--;
     309           1 :         io.lockx.in.ulock_cnt = 1;
     310           1 :         io.lockx.in.lock_cnt = 0;
     311           1 :         status = smb_raw_lock(cli->tree, &io);
     312           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     313           1 :         status = smb_raw_lock(cli->tree, &io);
     314           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     315             : 
     316           1 :         torture_comment(tctx, "Trying max lock\n");
     317           1 :         io.lockx.in.ulock_cnt = 0;
     318           1 :         io.lockx.in.lock_cnt = 1;
     319           1 :         lock[0].count = 0;
     320           1 :         lock[0].offset = ~0;
     321           1 :         status = smb_raw_lock(cli->tree, &io);
     322           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     323           1 :         lock[0].pid++;
     324           1 :         status = smb_raw_lock(cli->tree, &io);
     325           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     326           1 :         lock[0].pid--;
     327           1 :         io.lockx.in.ulock_cnt = 1;
     328           1 :         io.lockx.in.lock_cnt = 0;
     329           1 :         status = smb_raw_lock(cli->tree, &io);
     330           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     331           1 :         status = smb_raw_lock(cli->tree, &io);
     332           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     333             : 
     334           1 :         torture_comment(tctx, "Trying 2^63\n");
     335           1 :         io.lockx.in.ulock_cnt = 0;
     336           1 :         io.lockx.in.lock_cnt = 1;
     337           1 :         lock[0].count = 1;
     338           1 :         lock[0].offset = 1;
     339           1 :         lock[0].offset <<= 63;
     340           1 :         status = smb_raw_lock(cli->tree, &io);
     341           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     342           1 :         lock[0].pid++;
     343           1 :         status = smb_raw_lock(cli->tree, &io);
     344           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     345           1 :         lock[0].pid--;
     346           1 :         io.lockx.in.ulock_cnt = 1;
     347           1 :         io.lockx.in.lock_cnt = 0;
     348           1 :         status = smb_raw_lock(cli->tree, &io);
     349           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     350           1 :         status = smb_raw_lock(cli->tree, &io);
     351           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     352             : 
     353           1 :         torture_comment(tctx, "Trying 2^63 - 1\n");
     354           1 :         io.lockx.in.ulock_cnt = 0;
     355           1 :         io.lockx.in.lock_cnt = 1;
     356           1 :         lock[0].count = 1;
     357           1 :         lock[0].offset = 1;
     358           1 :         lock[0].offset <<= 63;
     359           1 :         lock[0].offset--;
     360           1 :         status = smb_raw_lock(cli->tree, &io);
     361           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     362           1 :         lock[0].pid++;
     363           1 :         status = smb_raw_lock(cli->tree, &io);
     364           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     365           1 :         lock[0].pid--;
     366           1 :         io.lockx.in.ulock_cnt = 1;
     367           1 :         io.lockx.in.lock_cnt = 0;
     368           1 :         status = smb_raw_lock(cli->tree, &io);
     369           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     370           1 :         status = smb_raw_lock(cli->tree, &io);
     371           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     372             : 
     373           1 :         torture_comment(tctx, "Trying max lock 2\n");
     374           1 :         io.lockx.in.ulock_cnt = 0;
     375           1 :         io.lockx.in.lock_cnt = 1;
     376           1 :         lock[0].count = 1;
     377           1 :         lock[0].offset = ~0;
     378           1 :         status = smb_raw_lock(cli->tree, &io);
     379           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     380           1 :         lock[0].pid++;
     381           1 :         lock[0].count = 2;
     382           1 :         status = smb_raw_lock(cli->tree, &io);
     383           1 :         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
     384           1 :                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
     385             :         else
     386           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     387           1 :         lock[0].pid--;
     388           1 :         io.lockx.in.ulock_cnt = 1;
     389           1 :         io.lockx.in.lock_cnt = 0;
     390           1 :         lock[0].count = 1;
     391           1 :         status = smb_raw_lock(cli->tree, &io);
     392             : 
     393           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     394           1 :         status = smb_raw_lock(cli->tree, &io);
     395           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     396             : 
     397           2 : done:
     398           1 :         smbcli_close(cli->tree, fnum);
     399           1 :         smb_raw_exit(cli->session);
     400           1 :         smbcli_deltree(cli->tree, BASEDIR);
     401           1 :         return ret;
     402             : }
     403             : 
     404             : /*
     405             :   test high pid
     406             : */
     407           1 : static bool test_pidhigh(struct torture_context *tctx, 
     408             :                                                  struct smbcli_state *cli)
     409             : {
     410             :         union smb_lock io;
     411             :         struct smb_lock_entry lock[1];
     412             :         NTSTATUS status;
     413           1 :         bool ret = true;
     414             :         int fnum;
     415           1 :         const char *fname = BASEDIR "\\test.txt";
     416           1 :         uint8_t c = 1;
     417             : 
     418           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     419             : 
     420           1 :         torture_comment(tctx, "Testing high pid\n");
     421           1 :         io.generic.level = RAW_LOCK_LOCKX;
     422             : 
     423           1 :         cli->session->pid = 1;
     424             :         
     425           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     426           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     427             :                        "Failed to create %s - %s\n",
     428             :                        fname, smbcli_errstr(cli->tree)));
     429             : 
     430           1 :         if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
     431           0 :                 torture_result(tctx, TORTURE_FAIL,
     432             :                         "Failed to write 1 byte - %s\n",
     433             :                         smbcli_errstr(cli->tree));
     434           0 :                 ret = false;
     435           0 :                 goto done;
     436             :         }
     437             : 
     438           1 :         io.lockx.level = RAW_LOCK_LOCKX;
     439           1 :         io.lockx.in.file.fnum = fnum;
     440           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     441           1 :         io.lockx.in.timeout = 0;
     442           1 :         io.lockx.in.ulock_cnt = 0;
     443           1 :         io.lockx.in.lock_cnt = 1;
     444           1 :         lock[0].pid = cli->session->pid;
     445           1 :         lock[0].offset = 0;
     446           1 :         lock[0].count = 0xFFFFFFFF;
     447           1 :         io.lockx.in.locks = &lock[0];
     448           1 :         status = smb_raw_lock(cli->tree, &io);
     449           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     450             : 
     451           1 :         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
     452           0 :                 torture_result(tctx, TORTURE_FAIL,
     453             :                         "Failed to read 1 byte - %s\n",
     454             :                         smbcli_errstr(cli->tree));
     455           0 :                 ret = false;
     456           0 :                 goto done;
     457             :         }
     458             : 
     459           1 :         cli->session->pid = 2;
     460             : 
     461           1 :         if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
     462           0 :                 torture_result(tctx, TORTURE_FAIL,
     463             :                         "pid is incorrect handled for read with lock!\n");
     464           0 :                 ret = false;
     465           0 :                 goto done;
     466             :         }
     467             : 
     468           1 :         cli->session->pid = 0x10001;
     469             : 
     470           1 :         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
     471           0 :                 torture_result(tctx, TORTURE_FAIL,
     472             :                         "High pid is used on this server!\n");
     473           0 :                 ret = false;
     474             :         } else {
     475           1 :                 torture_warning(tctx, "High pid is not used on this server (correct)\n");
     476             :         }
     477             : 
     478           1 : done:
     479           1 :         smbcli_close(cli->tree, fnum);
     480           1 :         smb_raw_exit(cli->session);
     481           1 :         smbcli_deltree(cli->tree, BASEDIR);
     482           1 :         return ret;
     483             : }
     484             : 
     485             : 
     486             : /*
     487             :   test locking&X async operation
     488             : */
     489           1 : static bool test_async(struct torture_context *tctx, 
     490             :                                            struct smbcli_state *cli)
     491             : {
     492             :         struct smbcli_session *session;
     493             :         struct smb_composite_sesssetup setup;
     494             :         struct smbcli_tree *tree;
     495             :         union smb_tcon tcon;
     496             :         const char *host, *share;
     497             :         union smb_lock io;
     498             :         struct smb_lock_entry lock[2];
     499             :         NTSTATUS status;
     500           1 :         bool ret = true;
     501             :         int fnum;
     502           1 :         const char *fname = BASEDIR "\\test.txt";
     503             :         time_t t;
     504             :         struct smbcli_request *req, *req2;
     505             :         struct smbcli_session_options options;
     506             : 
     507           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     508             : 
     509           1 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
     510             : 
     511           1 :         torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
     512           1 :         io.generic.level = RAW_LOCK_LOCKX;
     513             : 
     514           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     515           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     516             :                        "Failed to create %s - %s\n",
     517             :                        fname, smbcli_errstr(cli->tree)));
     518             : 
     519           1 :         io.lockx.level = RAW_LOCK_LOCKX;
     520           1 :         io.lockx.in.file.fnum = fnum;
     521           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     522           1 :         io.lockx.in.timeout = 0;
     523           1 :         io.lockx.in.ulock_cnt = 0;
     524           1 :         io.lockx.in.lock_cnt = 1;
     525           1 :         lock[0].pid = cli->session->pid;
     526           1 :         lock[0].offset = 100;
     527           1 :         lock[0].count = 10;
     528           1 :         lock[1].pid = cli->session->pid;
     529           1 :         lock[1].offset = 110;
     530           1 :         lock[1].count = 10;
     531           1 :         io.lockx.in.locks = &lock[0];
     532           1 :         status = smb_raw_lock(cli->tree, &io);
     533           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     534             : 
     535           1 :         t = time_mono(NULL);
     536             : 
     537           1 :         torture_comment(tctx, "Testing cancel by CANCEL_LOCK\n");
     538             : 
     539             :         /* setup a timed lock */
     540           1 :         io.lockx.in.timeout = 10000;
     541           1 :         req = smb_raw_lock_send(cli->tree, &io);
     542           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     543             :                        "Failed to setup timed lock (%s)\n", __location__));
     544             : 
     545             :         /* cancel the wrong range */
     546           1 :         lock[0].offset = 0;
     547           1 :         io.lockx.in.timeout = 0;
     548           1 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
     549           1 :         status = smb_raw_lock(cli->tree, &io);
     550           1 :         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
     551             : 
     552             :         /* cancel with the wrong bits set */
     553           1 :         lock[0].offset = 100;
     554           1 :         io.lockx.in.timeout = 0;
     555           1 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
     556           1 :         status = smb_raw_lock(cli->tree, &io);
     557           1 :         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
     558             : 
     559             :         /* cancel the right range */
     560           1 :         lock[0].offset = 100;
     561           1 :         io.lockx.in.timeout = 0;
     562           1 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     563           1 :         status = smb_raw_lock(cli->tree, &io);
     564           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     565             : 
     566             :         /* receive the failed lock request */
     567           1 :         status = smbcli_request_simple_recv(req);
     568           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     569             : 
     570           1 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     571             :                        "lock cancel was not immediate (%s)\n", __location__));
     572             : 
     573             :         /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
     574             :          * if the lock vector contains one entry. When given multiple cancel
     575             :          * requests in a single PDU we expect the server to return an
     576             :          * error. Samba4 handles this correctly. Windows servers seem to
     577             :          * accept the request but only cancel the first lock.  Samba3
     578             :          * now does what Windows does (JRA).
     579             :          */
     580           1 :         torture_comment(tctx, "Testing multiple cancel\n");
     581             : 
     582             :         /* acquire second lock */
     583           1 :         io.lockx.in.timeout = 0;
     584           1 :         io.lockx.in.ulock_cnt = 0;
     585           1 :         io.lockx.in.lock_cnt = 1;
     586           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     587           1 :         io.lockx.in.locks = &lock[1];
     588           1 :         status = smb_raw_lock(cli->tree, &io);
     589           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     590             : 
     591             :         /* setup 2 timed locks */
     592           1 :         t = time_mono(NULL);
     593           1 :         io.lockx.in.timeout = 10000;
     594           1 :         io.lockx.in.lock_cnt = 1;
     595           1 :         io.lockx.in.locks = &lock[0];
     596           1 :         req = smb_raw_lock_send(cli->tree, &io);
     597           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     598             :                        "Failed to setup timed lock (%s)\n", __location__));
     599           1 :         io.lockx.in.locks = &lock[1];
     600           1 :         req2 = smb_raw_lock_send(cli->tree, &io);
     601           1 :         torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
     602             :                        "Failed to setup timed lock (%s)\n", __location__));
     603             : 
     604             :         /* try to cancel both locks in the same packet */
     605           1 :         io.lockx.in.timeout = 0;
     606           1 :         io.lockx.in.lock_cnt = 2;
     607           1 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     608           1 :         io.lockx.in.locks = lock;
     609           1 :         status = smb_raw_lock(cli->tree, &io);
     610           1 :         CHECK_STATUS(status, NT_STATUS_OK);
     611             : 
     612           0 :         torture_warning(tctx, "Target server accepted a lock cancel "
     613             :                               "request with multiple locks. This violates "
     614             :                               "MS-CIFS 2.2.4.32.1.\n");
     615             : 
     616             :         /* receive the failed lock requests */
     617           0 :         status = smbcli_request_simple_recv(req);
     618           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     619             : 
     620           0 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     621             :                        "first lock was not cancelled immediately (%s)\n",
     622             :                        __location__));
     623             : 
     624             :         /* send cancel to second lock */
     625           0 :         io.lockx.in.timeout = 0;
     626           0 :         io.lockx.in.lock_cnt = 1;
     627           0 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK |
     628             :                            LOCKING_ANDX_LARGE_FILES;
     629           0 :         io.lockx.in.locks = &lock[1];
     630           0 :         status = smb_raw_lock(cli->tree, &io);
     631           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     632             : 
     633           0 :         status = smbcli_request_simple_recv(req2);
     634           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     635             : 
     636           0 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     637             :                        "second lock was not cancelled immediately (%s)\n",
     638             :                        __location__));
     639             : 
     640             :         /* cleanup the second lock */
     641           0 :         io.lockx.in.ulock_cnt = 1;
     642           0 :         io.lockx.in.lock_cnt = 0;
     643           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     644           0 :         io.lockx.in.locks = &lock[1];
     645           0 :         status = smb_raw_lock(cli->tree, &io);
     646           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     647             : 
     648             :         /* If a lock request contained multiple ranges and we are cancelling
     649             :          * one while it's still pending, what happens? */
     650           0 :         torture_comment(tctx, "Testing cancel 1/2 lock request\n");
     651             : 
     652             :         /* Send request with two ranges */
     653           0 :         io.lockx.in.timeout = -1;
     654           0 :         io.lockx.in.ulock_cnt = 0;
     655           0 :         io.lockx.in.lock_cnt = 2;
     656           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     657           0 :         io.lockx.in.locks = lock;
     658           0 :         req = smb_raw_lock_send(cli->tree, &io);
     659           0 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     660             :                        "Failed to setup pending lock (%s)\n", __location__));
     661             : 
     662             :         /* Try to cancel the first lock range */
     663           0 :         io.lockx.in.timeout = 0;
     664           0 :         io.lockx.in.lock_cnt = 1;
     665           0 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     666           0 :         io.lockx.in.locks = &lock[0];
     667           0 :         status = smb_raw_lock(cli->tree, &io);
     668           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     669             : 
     670             :         /* Locking request should've failed and second range should be
     671             :          * unlocked */
     672           0 :         status = smbcli_request_simple_recv(req);
     673           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     674             : 
     675           0 :         io.lockx.in.timeout = 0;
     676           0 :         io.lockx.in.ulock_cnt = 0;
     677           0 :         io.lockx.in.lock_cnt = 1;
     678           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     679           0 :         io.lockx.in.locks = &lock[1];
     680           0 :         status = smb_raw_lock(cli->tree, &io);
     681           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     682             : 
     683             :         /* Cleanup both locks */
     684           0 :         io.lockx.in.ulock_cnt = 2;
     685           0 :         io.lockx.in.lock_cnt = 0;
     686           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     687           0 :         io.lockx.in.locks = lock;
     688           0 :         status = smb_raw_lock(cli->tree, &io);
     689           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     690             : 
     691           0 :         torture_comment(tctx, "Testing cancel 2/2 lock request\n");
     692             : 
     693             :         /* Lock second range so it contends */
     694           0 :         io.lockx.in.timeout = 0;
     695           0 :         io.lockx.in.ulock_cnt = 0;
     696           0 :         io.lockx.in.lock_cnt = 1;
     697           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     698           0 :         io.lockx.in.locks = &lock[1];
     699           0 :         status = smb_raw_lock(cli->tree, &io);
     700           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     701             : 
     702             :         /* Send request with two ranges */
     703           0 :         io.lockx.in.timeout = -1;
     704           0 :         io.lockx.in.ulock_cnt = 0;
     705           0 :         io.lockx.in.lock_cnt = 2;
     706           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     707           0 :         io.lockx.in.locks = lock;
     708           0 :         req = smb_raw_lock_send(cli->tree, &io);
     709           0 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     710             :                        "Failed to setup pending lock (%s)\n", __location__));
     711             : 
     712             :         /* Try to cancel the second lock range */
     713           0 :         io.lockx.in.timeout = 0;
     714           0 :         io.lockx.in.lock_cnt = 1;
     715           0 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     716           0 :         io.lockx.in.locks = &lock[1];
     717           0 :         status = smb_raw_lock(cli->tree, &io);
     718           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     719             : 
     720             :         /* Locking request should've failed and first range should be
     721             :          * unlocked */
     722           0 :         status = smbcli_request_simple_recv(req);
     723           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     724             : 
     725           0 :         io.lockx.in.timeout = 0;
     726           0 :         io.lockx.in.ulock_cnt = 0;
     727           0 :         io.lockx.in.lock_cnt = 1;
     728           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     729           0 :         io.lockx.in.locks = &lock[0];
     730           0 :         status = smb_raw_lock(cli->tree, &io);
     731           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     732             : 
     733             :         /* Cleanup both locks */
     734           0 :         io.lockx.in.ulock_cnt = 2;
     735           0 :         io.lockx.in.lock_cnt = 0;
     736           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     737           0 :         io.lockx.in.locks = lock;
     738           0 :         status = smb_raw_lock(cli->tree, &io);
     739           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     740             : 
     741           0 :         torture_comment(tctx, "Testing cancel by unlock\n");
     742           0 :         io.lockx.in.ulock_cnt = 0;
     743           0 :         io.lockx.in.lock_cnt = 1;
     744           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     745           0 :         io.lockx.in.timeout = 0;
     746           0 :         io.lockx.in.locks = &lock[0];
     747           0 :         status = smb_raw_lock(cli->tree, &io);
     748           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     749             : 
     750           0 :         io.lockx.in.timeout = 5000;
     751           0 :         req = smb_raw_lock_send(cli->tree, &io);
     752           0 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     753             :                        "Failed to setup timed lock (%s)\n", __location__));
     754             : 
     755           0 :         io.lockx.in.ulock_cnt = 1;
     756           0 :         io.lockx.in.lock_cnt = 0;
     757           0 :         status = smb_raw_lock(cli->tree, &io);
     758           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     759             : 
     760           0 :         t = time_mono(NULL);
     761           0 :         status = smbcli_request_simple_recv(req);
     762           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     763             : 
     764           0 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     765             :                        "lock cancel by unlock was not immediate (%s) - took %d secs\n",
     766             :                        __location__, (int)(time_mono(NULL)-t)));
     767             : 
     768           0 :         torture_comment(tctx, "Testing cancel by close\n");
     769           0 :         io.lockx.in.ulock_cnt = 0;
     770           0 :         io.lockx.in.lock_cnt = 1;
     771           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     772           0 :         io.lockx.in.timeout = 0;
     773           0 :         status = smb_raw_lock(cli->tree, &io);
     774           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     775             : 
     776             :         {
     777             :                 /*
     778             :                  * Make the test block on the second lock
     779             :                  * request. This is to regression-test 64c0367.
     780             :                  */
     781           0 :                 uint64_t tmp = lock[1].offset;
     782           0 :                 lock[1].offset = lock[0].offset;
     783           0 :                 lock[0].offset = tmp;
     784             :         }
     785             : 
     786           0 :         t = time_mono(NULL);
     787           0 :         io.lockx.in.timeout = 10000;
     788           0 :         io.lockx.in.lock_cnt = 2;
     789           0 :         req = smb_raw_lock_send(cli->tree, &io);
     790           0 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     791             :                        "Failed to setup timed lock (%s)\n", __location__));
     792             : 
     793           0 :         status = smbcli_close(cli->tree, fnum);
     794           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     795             : 
     796           0 :         status = smbcli_request_simple_recv(req);
     797           0 :         if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
     798           0 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     799             :         else
     800           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     801             : 
     802           0 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     803             :                        "lock cancel by close was not immediate (%s)\n", __location__));
     804             : 
     805             :         {
     806             :                 /*
     807             :                  * Undo the change for 64c0367
     808             :                  */
     809           0 :                 uint64_t tmp = lock[1].offset;
     810           0 :                 lock[1].offset = lock[0].offset;
     811           0 :                 lock[0].offset = tmp;
     812             :         }
     813             : 
     814           0 :         torture_comment(tctx, "create a new sessions\n");
     815           0 :         session = smbcli_session_init(cli->transport, tctx, false, options);
     816           0 :         setup.in.sesskey = cli->transport->negotiate.sesskey;
     817           0 :         setup.in.capabilities = cli->transport->negotiate.capabilities;
     818           0 :         setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
     819           0 :         setup.in.credentials = samba_cmdline_get_creds();
     820           0 :         setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
     821           0 :         status = smb_composite_sesssetup(session, &setup);
     822           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     823           0 :         session->vuid = setup.out.vuid;
     824             : 
     825           0 :         torture_comment(tctx, "create new tree context\n");
     826           0 :         share = torture_setting_string(tctx, "share", NULL);
     827           0 :         host  = torture_setting_string(tctx, "host", NULL);
     828           0 :         tree = smbcli_tree_init(session, tctx, false);
     829           0 :         tcon.generic.level = RAW_TCON_TCONX;
     830           0 :         tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE;
     831           0 :         tcon.tconx.in.password = data_blob(NULL, 0);
     832           0 :         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
     833           0 :         tcon.tconx.in.device = "A:";
     834           0 :         status = smb_raw_tcon(tree, tctx, &tcon);
     835           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     836           0 :         tree->tid = tcon.tconx.out.tid;
     837             : 
     838           0 :         torture_comment(tctx, "Testing cancel by exit\n");
     839           0 :         if (TARGET_SUPPORTS_SMBEXIT(tctx)) {
     840           0 :                 fname = BASEDIR "\\test_exit.txt";
     841           0 :                 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     842           0 :                 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     843             :                                "Failed to reopen %s - %s\n",
     844             :                                fname, smbcli_errstr(tree)));
     845             : 
     846           0 :                 io.lockx.level = RAW_LOCK_LOCKX;
     847           0 :                 io.lockx.in.file.fnum = fnum;
     848           0 :                 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     849           0 :                 io.lockx.in.timeout = 0;
     850           0 :                 io.lockx.in.ulock_cnt = 0;
     851           0 :                 io.lockx.in.lock_cnt = 1;
     852           0 :                 lock[0].pid = session->pid;
     853           0 :                 lock[0].offset = 100;
     854           0 :                 lock[0].count = 10;
     855           0 :                 io.lockx.in.locks = &lock[0];
     856           0 :                 status = smb_raw_lock(tree, &io);
     857           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     858             : 
     859           0 :                 io.lockx.in.ulock_cnt = 0;
     860           0 :                 io.lockx.in.lock_cnt = 1;
     861           0 :                 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     862           0 :                 io.lockx.in.timeout = 0;
     863           0 :                 status = smb_raw_lock(tree, &io);
     864           0 :                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     865             : 
     866           0 :                 io.lockx.in.timeout = 10000;
     867           0 :                 t = time_mono(NULL);
     868           0 :                 req = smb_raw_lock_send(tree, &io);
     869           0 :                 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     870             :                                "Failed to setup timed lock (%s)\n",
     871             :                                __location__));
     872             : 
     873           0 :                 status = smb_raw_exit(session);
     874           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     875             : 
     876           0 :                 status = smbcli_request_simple_recv(req);
     877           0 :                 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
     878           0 :                         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     879             :                 else
     880           0 :                         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     881             : 
     882           0 :                 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     883             :                                "lock cancel by exit was not immediate (%s)\n",
     884             :                                __location__));
     885             :         }
     886             :         else {
     887           0 :                 torture_comment(tctx,
     888             :                                 "  skipping test, SMBExit not supported\n");
     889             :         }
     890             : 
     891           0 :         torture_comment(tctx, "Testing cancel by ulogoff\n");
     892           0 :         fname = BASEDIR "\\test_ulogoff.txt";
     893           0 :         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     894           0 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     895             :                        "Failed to reopen %s - %s\n",
     896             :                        fname, smbcli_errstr(tree)));
     897             : 
     898           0 :         io.lockx.level = RAW_LOCK_LOCKX;
     899           0 :         io.lockx.in.file.fnum = fnum;
     900           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     901           0 :         io.lockx.in.timeout = 0;
     902           0 :         io.lockx.in.ulock_cnt = 0;
     903           0 :         io.lockx.in.lock_cnt = 1;
     904           0 :         lock[0].pid = session->pid;
     905           0 :         lock[0].offset = 100;
     906           0 :         lock[0].count = 10;
     907           0 :         io.lockx.in.locks = &lock[0];
     908           0 :         status = smb_raw_lock(tree, &io);
     909           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     910             : 
     911           0 :         io.lockx.in.ulock_cnt = 0;
     912           0 :         io.lockx.in.lock_cnt = 1;
     913           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     914           0 :         io.lockx.in.timeout = 0;
     915           0 :         status = smb_raw_lock(tree, &io);
     916           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     917             : 
     918           0 :         io.lockx.in.timeout = 10000;
     919           0 :         t = time_mono(NULL);
     920           0 :         req = smb_raw_lock_send(tree, &io);
     921           0 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     922             :                        "Failed to setup timed lock (%s)\n", __location__));
     923             : 
     924           0 :         status = smb_raw_ulogoff(session);
     925           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     926             : 
     927           0 :         status = smbcli_request_simple_recv(req);
     928           0 :         if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) {
     929           0 :                 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
     930           0 :                         torture_result(tctx, TORTURE_FAIL,
     931             :                                 "lock not canceled by ulogoff - %s "
     932             :                                 "(ignored because of vfs_vifs fails it)\n",
     933             :                                 nt_errstr(status));
     934           0 :                         smb_tree_disconnect(tree);
     935           0 :                         smb_raw_exit(session);
     936           0 :                         goto done;
     937             :                 }
     938           0 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     939             :         } else {
     940           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     941             :         }
     942             : 
     943           0 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     944             :                        "lock cancel by ulogoff was not immediate (%s)\n", __location__));
     945             : 
     946           0 :         torture_comment(tctx, "Testing cancel by tdis\n");
     947           0 :         tree->session = cli->session;
     948             : 
     949           0 :         fname = BASEDIR "\\test_tdis.txt";
     950           0 :         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     951           0 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     952             :                        "Failed to reopen %s - %s\n",
     953             :                        fname, smbcli_errstr(tree)));
     954             : 
     955           0 :         io.lockx.level = RAW_LOCK_LOCKX;
     956           0 :         io.lockx.in.file.fnum = fnum;
     957           0 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     958           0 :         io.lockx.in.timeout = 0;
     959           0 :         io.lockx.in.ulock_cnt = 0;
     960           0 :         io.lockx.in.lock_cnt = 1;
     961           0 :         lock[0].pid = cli->session->pid;
     962           0 :         lock[0].offset = 100;
     963           0 :         lock[0].count = 10;
     964           0 :         io.lockx.in.locks = &lock[0];
     965           0 :         status = smb_raw_lock(tree, &io);
     966           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     967             : 
     968           0 :         status = smb_raw_lock(tree, &io);
     969           0 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     970             : 
     971           0 :         io.lockx.in.timeout = 10000;
     972           0 :         t = time_mono(NULL);
     973           0 :         req = smb_raw_lock_send(tree, &io);
     974           0 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     975             :                        "Failed to setup timed lock (%s)\n", __location__));
     976             : 
     977           0 :         status = smb_tree_disconnect(tree);
     978           0 :         CHECK_STATUS(status, NT_STATUS_OK);
     979             : 
     980           0 :         status = smbcli_request_simple_recv(req);
     981           0 :         if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
     982           0 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     983             :         else
     984           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     985             : 
     986           0 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     987             :                        "lock cancel by tdis was not immediate (%s)\n", __location__));
     988             : 
     989           1 : done:
     990           1 :         smb_raw_exit(cli->session);
     991           1 :         smbcli_deltree(cli->tree, BASEDIR);
     992           1 :         return ret;
     993             : }
     994             : 
     995             : /*
     996             :   test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
     997             : */
     998           1 : static bool test_errorcode(struct torture_context *tctx, 
     999             :                                                    struct smbcli_state *cli)
    1000             : {
    1001             :         union smb_lock io;
    1002             :         union smb_open op;
    1003             :         struct smb_lock_entry lock[2];
    1004             :         NTSTATUS status;
    1005           1 :         bool ret = true;
    1006             :         int fnum, fnum2;
    1007             :         const char *fname;
    1008             :         struct smbcli_request *req;
    1009             :         time_t start;
    1010             :         int t;
    1011             :         int delay;
    1012           1 :         uint16_t deny_mode = 0;
    1013             : 
    1014           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1015             : 
    1016           1 :         torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
    1017             : 
    1018           1 :         torture_comment(tctx, "Testing with timeout = 0\n");
    1019           1 :         fname = BASEDIR "\\test0.txt";
    1020           1 :         t = 0;
    1021             : 
    1022             :         /*
    1023             :          * the first run is with t = 0,
    1024             :          * the second with t > 0 (=1)
    1025             :          */
    1026           2 : next_run:
    1027             :         /*
    1028             :          * use the DENY_DOS mode, that creates two fnum's of one low-level
    1029             :          * file handle, this demonstrates that the cache is per fnum, not
    1030             :          * per file handle
    1031             :          */
    1032           2 :         if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
    1033           2 :             deny_mode = OPENX_MODE_DENY_DOS;
    1034             :         else
    1035           0 :             deny_mode = OPENX_MODE_DENY_NONE;
    1036             : 
    1037           2 :         op.openx.level = RAW_OPEN_OPENX;
    1038           2 :         op.openx.in.fname = fname;
    1039           2 :         op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
    1040           2 :         op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
    1041           2 :         op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
    1042           2 :         op.openx.in.search_attrs = 0;
    1043           2 :         op.openx.in.file_attrs = 0;
    1044           2 :         op.openx.in.write_time = 0;
    1045           2 :         op.openx.in.size = 0;
    1046           2 :         op.openx.in.timeout = 0;
    1047             : 
    1048           2 :         status = smb_raw_open(cli->tree, tctx, &op);
    1049           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1050           2 :         fnum = op.openx.out.file.fnum;
    1051             : 
    1052           2 :         status = smb_raw_open(cli->tree, tctx, &op);
    1053           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1054           2 :         fnum2 = op.openx.out.file.fnum;
    1055             : 
    1056           2 :         io.lockx.level = RAW_LOCK_LOCKX;
    1057           2 :         io.lockx.in.file.fnum = fnum;
    1058           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1059           2 :         io.lockx.in.timeout = t;
    1060           2 :         io.lockx.in.ulock_cnt = 0;
    1061           2 :         io.lockx.in.lock_cnt = 1;
    1062           2 :         lock[0].pid = cli->session->pid;
    1063           2 :         lock[0].offset = 100;
    1064           2 :         lock[0].count = 10;
    1065           2 :         io.lockx.in.locks = &lock[0];
    1066           2 :         status = smb_raw_lock(cli->tree, &io);
    1067           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1068             : 
    1069             :         /*
    1070             :          * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
    1071             :          * this also demonstrates that the error code cache is per file handle
    1072             :          * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
    1073             :          */
    1074           2 :         io.lockx.in.file.fnum = fnum2;
    1075           2 :         status = smb_raw_lock(cli->tree, &io);
    1076           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1077             : 
    1078           2 :         io.lockx.in.file.fnum = fnum;
    1079           2 :         status = smb_raw_lock(cli->tree, &io);
    1080           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1081             : 
    1082             :         /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
    1083           2 :         io.lockx.in.file.fnum = fnum;
    1084           2 :         status = smb_raw_lock(cli->tree, &io);
    1085           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1086             : 
    1087           2 :         io.lockx.in.file.fnum = fnum2;
    1088           2 :         status = smb_raw_lock(cli->tree, &io);
    1089           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1090             : 
    1091           2 :         io.lockx.in.file.fnum = fnum;
    1092           2 :         status = smb_raw_lock(cli->tree, &io);
    1093           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1094             : 
    1095           2 :         io.lockx.in.file.fnum = fnum2;
    1096           2 :         status = smb_raw_lock(cli->tree, &io);
    1097           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1098             : 
    1099             :         /* demonstrate that the smbpid doesn't matter */
    1100           2 :         lock[0].pid++;
    1101           2 :         io.lockx.in.file.fnum = fnum;
    1102           2 :         status = smb_raw_lock(cli->tree, &io);
    1103           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1104             : 
    1105           2 :         io.lockx.in.file.fnum = fnum2;
    1106           2 :         status = smb_raw_lock(cli->tree, &io);
    1107           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1108           2 :         lock[0].pid--;
    1109             : 
    1110             :         /* 
    1111             :          * demonstrate the a successful lock with count = 0 and the same offset,
    1112             :          * doesn't reset the error cache
    1113             :          */
    1114           2 :         lock[0].offset = 100;
    1115           2 :         lock[0].count = 0;
    1116           2 :         io.lockx.in.file.fnum = fnum;
    1117           2 :         status = smb_raw_lock(cli->tree, &io);
    1118           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1119             : 
    1120           2 :         io.lockx.in.file.fnum = fnum2;
    1121           2 :         status = smb_raw_lock(cli->tree, &io);
    1122           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1123             : 
    1124           2 :         lock[0].offset = 100;
    1125           2 :         lock[0].count = 10;
    1126           2 :         io.lockx.in.file.fnum = fnum;
    1127           2 :         status = smb_raw_lock(cli->tree, &io);
    1128           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1129             : 
    1130           2 :         io.lockx.in.file.fnum = fnum2;
    1131           2 :         status = smb_raw_lock(cli->tree, &io);
    1132           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1133             : 
    1134             :         /* 
    1135             :          * demonstrate the a successful lock with count = 0 and outside the locked range,
    1136             :          * doesn't reset the error cache
    1137             :          */
    1138           2 :         lock[0].offset = 110;
    1139           2 :         lock[0].count = 0;
    1140           2 :         io.lockx.in.file.fnum = fnum;
    1141           2 :         status = smb_raw_lock(cli->tree, &io);
    1142           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1143             : 
    1144           2 :         io.lockx.in.file.fnum = fnum2;
    1145           2 :         status = smb_raw_lock(cli->tree, &io);
    1146           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1147             : 
    1148           2 :         lock[0].offset = 100;
    1149           2 :         lock[0].count = 10;
    1150           2 :         io.lockx.in.file.fnum = fnum;
    1151           2 :         status = smb_raw_lock(cli->tree, &io);
    1152           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1153             : 
    1154           2 :         io.lockx.in.file.fnum = fnum2;
    1155           2 :         status = smb_raw_lock(cli->tree, &io);
    1156           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1157             : 
    1158           2 :         lock[0].offset = 99;
    1159           2 :         lock[0].count = 0;
    1160           2 :         io.lockx.in.file.fnum = fnum;
    1161           2 :         status = smb_raw_lock(cli->tree, &io);
    1162           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1163             : 
    1164           2 :         io.lockx.in.file.fnum = fnum2;
    1165           2 :         status = smb_raw_lock(cli->tree, &io);
    1166           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1167             : 
    1168           2 :         lock[0].offset = 100;
    1169           2 :         lock[0].count = 10;
    1170           2 :         io.lockx.in.file.fnum = fnum;
    1171           2 :         status = smb_raw_lock(cli->tree, &io);
    1172           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1173             : 
    1174           2 :         io.lockx.in.file.fnum = fnum2;
    1175           2 :         status = smb_raw_lock(cli->tree, &io);
    1176           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1177             : 
    1178             :         /* demonstrate that a changing count doesn't reset the error cache */
    1179           2 :         lock[0].offset = 100;
    1180           2 :         lock[0].count = 5;
    1181           2 :         io.lockx.in.file.fnum = fnum;
    1182           2 :         status = smb_raw_lock(cli->tree, &io);
    1183           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1184             : 
    1185           2 :         io.lockx.in.file.fnum = fnum2;
    1186           2 :         status = smb_raw_lock(cli->tree, &io);
    1187           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1188             : 
    1189           2 :         lock[0].offset = 100;
    1190           2 :         lock[0].count = 15;
    1191           2 :         io.lockx.in.file.fnum = fnum;
    1192           2 :         status = smb_raw_lock(cli->tree, &io);
    1193           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1194             : 
    1195           2 :         io.lockx.in.file.fnum = fnum2;
    1196           2 :         status = smb_raw_lock(cli->tree, &io);
    1197           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1198             : 
    1199             :         /* 
    1200             :          * demonstrate the a lock with count = 0 and inside the locked range,
    1201             :          * fails and resets the error cache
    1202             :          */
    1203           2 :         lock[0].offset = 101;
    1204           2 :         lock[0].count = 0;
    1205           2 :         io.lockx.in.file.fnum = fnum;
    1206           2 :         status = smb_raw_lock(cli->tree, &io);
    1207           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1208           2 :         status = smb_raw_lock(cli->tree, &io);
    1209           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1210             : 
    1211           2 :         io.lockx.in.file.fnum = fnum2;
    1212           2 :         status = smb_raw_lock(cli->tree, &io);
    1213           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1214           2 :         status = smb_raw_lock(cli->tree, &io);
    1215           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1216             : 
    1217           2 :         lock[0].offset = 100;
    1218           2 :         lock[0].count = 10;
    1219           2 :         io.lockx.in.file.fnum = fnum;
    1220           2 :         status = smb_raw_lock(cli->tree, &io);
    1221           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1222           2 :         status = smb_raw_lock(cli->tree, &io);
    1223           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1224             : 
    1225           2 :         io.lockx.in.file.fnum = fnum2;
    1226           2 :         status = smb_raw_lock(cli->tree, &io);
    1227           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1228           2 :         status = smb_raw_lock(cli->tree, &io);
    1229           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1230             : 
    1231             :         /* demonstrate the a changing offset, resets the error cache */
    1232           2 :         lock[0].offset = 105;
    1233           2 :         lock[0].count = 10;
    1234           2 :         io.lockx.in.file.fnum = fnum;
    1235           2 :         status = smb_raw_lock(cli->tree, &io);
    1236           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1237           2 :         status = smb_raw_lock(cli->tree, &io);
    1238           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1239             : 
    1240           2 :         io.lockx.in.file.fnum = fnum2;
    1241           2 :         status = smb_raw_lock(cli->tree, &io);
    1242           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1243           2 :         status = smb_raw_lock(cli->tree, &io);
    1244           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1245             : 
    1246           2 :         lock[0].offset = 100;
    1247           2 :         lock[0].count = 10;
    1248           2 :         io.lockx.in.file.fnum = fnum;
    1249           2 :         status = smb_raw_lock(cli->tree, &io);
    1250           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1251           2 :         status = smb_raw_lock(cli->tree, &io);
    1252           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1253             : 
    1254           2 :         io.lockx.in.file.fnum = fnum2;
    1255           2 :         status = smb_raw_lock(cli->tree, &io);
    1256           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1257           2 :         status = smb_raw_lock(cli->tree, &io);
    1258           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1259             : 
    1260           2 :         lock[0].offset = 95;
    1261           2 :         lock[0].count = 9;
    1262           2 :         io.lockx.in.file.fnum = fnum;
    1263           2 :         status = smb_raw_lock(cli->tree, &io);
    1264           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1265           2 :         status = smb_raw_lock(cli->tree, &io);
    1266           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1267             : 
    1268           2 :         io.lockx.in.file.fnum = fnum2;
    1269           2 :         status = smb_raw_lock(cli->tree, &io);
    1270           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1271           2 :         status = smb_raw_lock(cli->tree, &io);
    1272           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1273             : 
    1274           2 :         lock[0].offset = 100;
    1275           2 :         lock[0].count = 10;
    1276           2 :         io.lockx.in.file.fnum = fnum;
    1277           2 :         status = smb_raw_lock(cli->tree, &io);
    1278           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1279           2 :         status = smb_raw_lock(cli->tree, &io);
    1280           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1281             : 
    1282           2 :         io.lockx.in.file.fnum = fnum2;
    1283           2 :         status = smb_raw_lock(cli->tree, &io);
    1284           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1285           2 :         status = smb_raw_lock(cli->tree, &io);
    1286           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1287             : 
    1288             :         /* 
    1289             :          * demonstrate the a successful lock in a different range, 
    1290             :          * doesn't reset the cache, the failing lock on the 2nd handle
    1291             :          * resets the cache
    1292             :          */
    1293           2 :         lock[0].offset = 120;
    1294           2 :         lock[0].count = 15;
    1295           2 :         io.lockx.in.file.fnum = fnum;
    1296           2 :         status = smb_raw_lock(cli->tree, &io);
    1297           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    1298             : 
    1299           2 :         io.lockx.in.file.fnum = fnum2;
    1300           2 :         status = smb_raw_lock(cli->tree, &io);
    1301           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1302             : 
    1303           2 :         lock[0].offset = 100;
    1304           2 :         lock[0].count = 10;
    1305           2 :         io.lockx.in.file.fnum = fnum;
    1306           2 :         status = smb_raw_lock(cli->tree, &io);
    1307           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1308           2 :         status = smb_raw_lock(cli->tree, &io);
    1309           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1310             : 
    1311           2 :         io.lockx.in.file.fnum = fnum2;
    1312           2 :         status = smb_raw_lock(cli->tree, &io);
    1313           2 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1314           2 :         status = smb_raw_lock(cli->tree, &io);
    1315           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1316             : 
    1317             :         /* end of the loop */
    1318           2 :         if (t == 0) {
    1319           1 :                 smb_raw_exit(cli->session);
    1320           1 :                 t = 1;
    1321           1 :                 torture_comment(tctx, "Testing with timeout > 0 (=%d)\n",
    1322             :                                 t);
    1323           1 :                 fname = BASEDIR "\\test1.txt";
    1324           1 :                 goto next_run;
    1325             :         }
    1326             : 
    1327           1 :         t = 4000;
    1328           1 :         torture_comment(tctx, "Testing special cases with timeout > 0 (=%d)\n",
    1329             :                         t);
    1330             : 
    1331             :         /*
    1332             :          * the following 3 test sections demonstrate that
    1333             :          * the cache is only set when the error is reported
    1334             :          * to the client (after the timeout went by)
    1335             :          */
    1336           1 :         smb_raw_exit(cli->session);
    1337           1 :         torture_comment(tctx, "Testing a conflict while a lock is pending\n");
    1338           1 :         fname = BASEDIR "\\test2.txt";
    1339           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1340           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1341             :                        "Failed to reopen %s - %s\n",
    1342             :                        fname, smbcli_errstr(cli->tree)));
    1343             : 
    1344           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    1345           1 :         io.lockx.in.file.fnum = fnum;
    1346           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1347           1 :         io.lockx.in.timeout = 0;
    1348           1 :         io.lockx.in.ulock_cnt = 0;
    1349           1 :         io.lockx.in.lock_cnt = 1;
    1350           1 :         lock[0].pid = cli->session->pid;
    1351           1 :         lock[0].offset = 100;
    1352           1 :         lock[0].count = 10;
    1353           1 :         io.lockx.in.locks = &lock[0];
    1354           1 :         status = smb_raw_lock(cli->tree, &io);
    1355           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1356             : 
    1357           1 :         start = time_mono(NULL);
    1358           1 :         io.lockx.in.timeout = t;
    1359           1 :         req = smb_raw_lock_send(cli->tree, &io);
    1360           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    1361             :                        "Failed to setup timed lock (%s)\n", __location__));
    1362             : 
    1363           1 :         io.lockx.in.timeout = 0;
    1364           1 :         lock[0].offset = 105;
    1365           1 :         lock[0].count = 10;
    1366           1 :         status = smb_raw_lock(cli->tree, &io);
    1367           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1368             : 
    1369           1 :         status = smbcli_request_simple_recv(req);
    1370           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1371             : 
    1372           1 :         delay = t / 1000;
    1373           1 :         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
    1374           0 :                 delay /= 2;
    1375             :         }
    1376             : 
    1377           1 :         torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
    1378             :                        "lock comes back to early timeout[%d] delay[%d]"
    1379             :                        "(%s)\n", t, delay, __location__));
    1380             : 
    1381           1 :         status = smb_raw_lock(cli->tree, &io);
    1382           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1383             : 
    1384           1 :         smbcli_close(cli->tree, fnum);
    1385           1 :         fname = BASEDIR "\\test3.txt";
    1386           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1387           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1388             :                        "Failed to reopen %s - %s\n",
    1389             :                        fname, smbcli_errstr(cli->tree)));
    1390             : 
    1391           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    1392           1 :         io.lockx.in.file.fnum = fnum;
    1393           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1394           1 :         io.lockx.in.timeout = 0;
    1395           1 :         io.lockx.in.ulock_cnt = 0;
    1396           1 :         io.lockx.in.lock_cnt = 1;
    1397           1 :         lock[0].pid = cli->session->pid;
    1398           1 :         lock[0].offset = 100;
    1399           1 :         lock[0].count = 10;
    1400           1 :         io.lockx.in.locks = &lock[0];
    1401           1 :         status = smb_raw_lock(cli->tree, &io);
    1402           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1403             : 
    1404           1 :         start = time_mono(NULL);
    1405           1 :         io.lockx.in.timeout = t;
    1406           1 :         req = smb_raw_lock_send(cli->tree, &io);
    1407           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    1408             :                        "Failed to setup timed lock (%s)\n", __location__));
    1409             : 
    1410           1 :         io.lockx.in.timeout = 0;
    1411           1 :         lock[0].offset = 105;
    1412           1 :         lock[0].count = 10;
    1413           1 :         status = smb_raw_lock(cli->tree, &io);
    1414           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1415             : 
    1416           1 :         status = smbcli_request_simple_recv(req);
    1417           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1418             : 
    1419           1 :         delay = t / 1000;
    1420           1 :         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
    1421           0 :                 delay /= 2;
    1422             :         }
    1423             : 
    1424           1 :         torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
    1425             :                        "lock comes back to early timeout[%d] delay[%d]"
    1426             :                        "(%s)\n", t, delay, __location__));
    1427             : 
    1428           1 :         lock[0].offset = 100;
    1429           1 :         lock[0].count = 10;
    1430           1 :         status = smb_raw_lock(cli->tree, &io);
    1431           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1432             : 
    1433           1 :         smbcli_close(cli->tree, fnum);
    1434           1 :         fname = BASEDIR "\\test4.txt";
    1435           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1436           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1437             :                        "Failed to reopen %s - %s\n",
    1438             :                        fname, smbcli_errstr(cli->tree)));
    1439             : 
    1440           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    1441           1 :         io.lockx.in.file.fnum = fnum;
    1442           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1443           1 :         io.lockx.in.timeout = 0;
    1444           1 :         io.lockx.in.ulock_cnt = 0;
    1445           1 :         io.lockx.in.lock_cnt = 1;
    1446           1 :         lock[0].pid = cli->session->pid;
    1447           1 :         lock[0].offset = 100;
    1448           1 :         lock[0].count = 10;
    1449           1 :         io.lockx.in.locks = &lock[0];
    1450           1 :         status = smb_raw_lock(cli->tree, &io);
    1451           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1452             : 
    1453           1 :         start = time_mono(NULL);
    1454           1 :         io.lockx.in.timeout = t;
    1455           1 :         req = smb_raw_lock_send(cli->tree, &io);
    1456           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    1457             :                        "Failed to setup timed lock (%s)\n", __location__));
    1458             : 
    1459           1 :         io.lockx.in.timeout = 0;
    1460           1 :         status = smb_raw_lock(cli->tree, &io);
    1461           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1462             : 
    1463           1 :         status = smbcli_request_simple_recv(req);
    1464           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1465             : 
    1466           1 :         delay = t / 1000;
    1467           1 :         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
    1468           0 :                 delay /= 2;
    1469             :         }
    1470             : 
    1471           1 :         torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
    1472             :                        "lock comes back to early timeout[%d] delay[%d]"
    1473             :                        "(%s)\n", t, delay, __location__));
    1474             : 
    1475           1 :         status = smb_raw_lock(cli->tree, &io);
    1476           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1477             : 
    1478           2 : done:
    1479           1 :         smb_raw_exit(cli->session);
    1480           1 :         smbcli_deltree(cli->tree, BASEDIR);
    1481           1 :         return ret;
    1482             : }
    1483             : 
    1484             : 
    1485             : /*
    1486             :   test LOCKING_ANDX_CHANGE_LOCKTYPE
    1487             : */
    1488           1 : static bool test_changetype(struct torture_context *tctx, 
    1489             :                                                         struct smbcli_state *cli)
    1490             : {
    1491             :         union smb_lock io;
    1492             :         struct smb_lock_entry lock[2];
    1493             :         NTSTATUS status;
    1494           1 :         bool ret = true;
    1495             :         int fnum;
    1496           1 :         uint8_t c = 0;
    1497           1 :         const char *fname = BASEDIR "\\test.txt";
    1498             : 
    1499           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1500             : 
    1501           1 :         torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
    1502           1 :         io.generic.level = RAW_LOCK_LOCKX;
    1503             :         
    1504           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1505           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1506             :                        "Failed to create %s - %s\n",
    1507             :                        fname, smbcli_errstr(cli->tree)));
    1508             : 
    1509           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    1510           1 :         io.lockx.in.file.fnum = fnum;
    1511           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1512           1 :         io.lockx.in.timeout = 0;
    1513           1 :         io.lockx.in.ulock_cnt = 0;
    1514           1 :         io.lockx.in.lock_cnt = 1;
    1515           1 :         lock[0].pid = cli->session->pid;
    1516           1 :         lock[0].offset = 100;
    1517           1 :         lock[0].count = 10;
    1518           1 :         io.lockx.in.locks = &lock[0];
    1519           1 :         status = smb_raw_lock(cli->tree, &io);
    1520           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1521             : 
    1522           1 :         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
    1523           0 :                 torture_result(tctx, TORTURE_FAIL,
    1524             :                         "allowed write on read locked region (%s)\n", __location__);
    1525           0 :                 ret = false;
    1526           0 :                 goto done;
    1527             :         }
    1528             : 
    1529             :         /* windows server don't seem to support this */
    1530           1 :         io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
    1531           1 :         status = smb_raw_lock(cli->tree, &io);
    1532           1 :         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
    1533             : 
    1534           1 :         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
    1535           0 :                 torture_result(tctx, TORTURE_FAIL,
    1536             :                         "allowed write after lock change (%s)\n", __location__);
    1537           0 :                 ret = false;
    1538           0 :                 goto done;
    1539             :         }
    1540             : 
    1541           2 : done:
    1542           1 :         smbcli_close(cli->tree, fnum);
    1543           1 :         smb_raw_exit(cli->session);
    1544           1 :         smbcli_deltree(cli->tree, BASEDIR);
    1545           1 :         return ret;
    1546             : }
    1547             : 
    1548             : struct double_lock_test {
    1549             :         struct smb_lock_entry lock1;
    1550             :         struct smb_lock_entry lock2;
    1551             :         NTSTATUS exp_status;
    1552             : };
    1553             : 
    1554             : /**
    1555             :  * Tests zero byte locks.
    1556             :  */
    1557             : static struct double_lock_test zero_byte_tests[] = {
    1558             :         /* {pid, offset, count}, {pid, offset, count}, status */
    1559             : 
    1560             :         /** First, takes a zero byte lock at offset 10. Then:
    1561             :         *   - Taking 0 byte lock at 10 should succeed.
    1562             :         *   - Taking 1 byte locks at 9,10,11 should succeed.
    1563             :         *   - Taking 2 byte lock at 9 should fail.
    1564             :         *   - Taking 2 byte lock at 10 should succeed.
    1565             :         *   - Taking 3 byte lock at 9 should fail.
    1566             :         */
    1567             :         {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
    1568             :         {{1000, 10, 0}, {1001, 9, 1},  NT_STATUS_OK},
    1569             :         {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
    1570             :         {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
    1571             :         {{1000, 10, 0}, {1001, 9, 2},  NT_STATUS_LOCK_NOT_GRANTED},
    1572             :         {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
    1573             :         {{1000, 10, 0}, {1001, 9, 3},  NT_STATUS_LOCK_NOT_GRANTED},
    1574             : 
    1575             :         /** Same, but opposite order. */
    1576             :         {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
    1577             :         {{1001, 9, 1},  {1000, 10, 0}, NT_STATUS_OK},
    1578             :         {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
    1579             :         {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
    1580             :         {{1001, 9, 2},  {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
    1581             :         {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
    1582             :         {{1001, 9, 3},  {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
    1583             : 
    1584             :         /** Zero zero case. */
    1585             :         {{1000, 0, 0},  {1001, 0, 0},  NT_STATUS_OK},
    1586             : };
    1587             : 
    1588           1 : static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
    1589             : {
    1590             :         union smb_lock io;
    1591             :         NTSTATUS status;
    1592           1 :         bool ret = true;
    1593             :         int fnum, i;
    1594           1 :         const char *fname = BASEDIR "\\zero.txt";
    1595             : 
    1596           1 :         torture_comment(tctx, "Testing zero length byte range locks:\n");
    1597             : 
    1598           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1599             : 
    1600           1 :         io.generic.level = RAW_LOCK_LOCKX;
    1601             : 
    1602           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1603           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1604             :                        "Failed to create %s - %s\n",
    1605             :                        fname, smbcli_errstr(cli->tree)));
    1606             : 
    1607             :         /* Setup initial parameters */
    1608           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    1609           1 :         io.lockx.in.file.fnum = fnum;
    1610           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
    1611           1 :         io.lockx.in.timeout = 0;
    1612             : 
    1613             :         /* Try every combination of locks in zero_byte_tests. The first lock is
    1614             :          * assumed to succeed. The second lock may contend, depending on the
    1615             :          * expected status. */
    1616          17 :         for (i = 0;
    1617          16 :              i < ARRAY_SIZE(zero_byte_tests);
    1618          15 :              i++) {
    1619          45 :                 torture_comment(tctx, "  ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
    1620             :                     zero_byte_tests[i].lock1.pid,
    1621          15 :                     (unsigned long long) zero_byte_tests[i].lock1.offset,
    1622          15 :                     (unsigned long long) zero_byte_tests[i].lock1.count,
    1623             :                     zero_byte_tests[i].lock2.pid,
    1624          15 :                     (unsigned long long) zero_byte_tests[i].lock2.offset,
    1625          15 :                     (unsigned long long) zero_byte_tests[i].lock2.count,
    1626             :                     nt_errstr(zero_byte_tests[i].exp_status));
    1627             : 
    1628             :                 /* Lock both locks. */
    1629          15 :                 io.lockx.in.ulock_cnt = 0;
    1630          15 :                 io.lockx.in.lock_cnt = 1;
    1631             : 
    1632          15 :                 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
    1633             :                                                     &zero_byte_tests[i].lock1);
    1634          15 :                 status = smb_raw_lock(cli->tree, &io);
    1635          15 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1636             : 
    1637          15 :                 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
    1638             :                                                     &zero_byte_tests[i].lock2);
    1639          15 :                 status = smb_raw_lock(cli->tree, &io);
    1640             : 
    1641          15 :                 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
    1642             :                         NT_STATUS_LOCK_NOT_GRANTED)) {
    1643             :                         /* Allow either of the failure messages and keep going
    1644             :                          * if we see the wrong status. */
    1645           4 :                         CHECK_STATUS_OR_CONT(status,
    1646             :                             NT_STATUS_LOCK_NOT_GRANTED,
    1647             :                             NT_STATUS_FILE_LOCK_CONFLICT);
    1648             : 
    1649             :                 } else {
    1650          11 :                         CHECK_STATUS_CONT(status,
    1651             :                             zero_byte_tests[i].exp_status);
    1652             :                 }
    1653             : 
    1654             :                 /* Unlock both locks. */
    1655          15 :                 io.lockx.in.ulock_cnt = 1;
    1656          15 :                 io.lockx.in.lock_cnt = 0;
    1657             : 
    1658          15 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    1659          11 :                         status = smb_raw_lock(cli->tree, &io);
    1660          11 :                         CHECK_STATUS(status, NT_STATUS_OK);
    1661             :                 }
    1662             : 
    1663          15 :                 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
    1664             :                                                     &zero_byte_tests[i].lock1);
    1665          15 :                 status = smb_raw_lock(cli->tree, &io);
    1666          15 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1667             :         }
    1668             : 
    1669           1 : done:
    1670           1 :         smbcli_close(cli->tree, fnum);
    1671           1 :         smb_raw_exit(cli->session);
    1672           1 :         smbcli_deltree(cli->tree, BASEDIR);
    1673           1 :         return ret;
    1674             : }
    1675             : 
    1676           1 : static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
    1677             : {
    1678             :         union smb_lock io;
    1679             :         NTSTATUS status;
    1680           1 :         bool ret = true;
    1681             :         int fnum1, fnum2;
    1682           1 :         const char *fname = BASEDIR "\\unlock.txt";
    1683             :         struct smb_lock_entry lock1;
    1684             :         struct smb_lock_entry lock2;
    1685             : 
    1686           1 :         torture_comment(tctx, "Testing LOCKX unlock:\n");
    1687             : 
    1688           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1689             : 
    1690           1 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1691           1 :         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
    1692             :                        "Failed to create %s - %s\n",
    1693             :                        fname, smbcli_errstr(cli->tree)));
    1694             : 
    1695           1 :         fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1696           1 :         torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
    1697             :                        "Failed to create %s - %s\n",
    1698             :                        fname, smbcli_errstr(cli->tree)));
    1699             : 
    1700             :         /* Setup initial parameters */
    1701           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    1702           1 :         io.lockx.in.timeout = 0;
    1703             : 
    1704           1 :         lock1.pid = cli->session->pid;
    1705           1 :         lock1.offset = 0;
    1706           1 :         lock1.count = 10;
    1707           1 :         lock2.pid = cli->session->pid - 1;
    1708           1 :         lock2.offset = 0;
    1709           1 :         lock2.count = 10;
    1710             : 
    1711             :         /**
    1712             :          * Take exclusive lock, then unlock it with a shared-unlock call.
    1713             :          */
    1714           1 :         torture_comment(tctx, "  taking exclusive lock.\n");
    1715           1 :         io.lockx.in.ulock_cnt = 0;
    1716           1 :         io.lockx.in.lock_cnt = 1;
    1717           1 :         io.lockx.in.mode = 0;
    1718           1 :         io.lockx.in.file.fnum = fnum1;
    1719           1 :         io.lockx.in.locks = &lock1;
    1720           1 :         status = smb_raw_lock(cli->tree, &io);
    1721           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1722             : 
    1723           1 :         torture_comment(tctx, "  unlock the exclusive with a shared unlock call.\n");
    1724           1 :         io.lockx.in.ulock_cnt = 1;
    1725           1 :         io.lockx.in.lock_cnt = 0;
    1726           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1727           1 :         io.lockx.in.file.fnum = fnum1;
    1728           1 :         io.lockx.in.locks = &lock1;
    1729           1 :         status = smb_raw_lock(cli->tree, &io);
    1730           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1731             : 
    1732           1 :         torture_comment(tctx, "  try shared lock on pid2/fnum2, testing the unlock.\n");
    1733           1 :         io.lockx.in.ulock_cnt = 0;
    1734           1 :         io.lockx.in.lock_cnt = 1;
    1735           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1736           1 :         io.lockx.in.file.fnum = fnum2;
    1737           1 :         io.lockx.in.locks = &lock2;
    1738           1 :         status = smb_raw_lock(cli->tree, &io);
    1739           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1740             : 
    1741             :         /**
    1742             :          * Unlock a shared lock with an exclusive-unlock call.
    1743             :          */
    1744           1 :         torture_comment(tctx, "  unlock new shared lock with exclusive unlock call.\n");
    1745           1 :         io.lockx.in.ulock_cnt = 1;
    1746           1 :         io.lockx.in.lock_cnt = 0;
    1747           1 :         io.lockx.in.mode = 0;
    1748           1 :         io.lockx.in.file.fnum = fnum2;
    1749           1 :         io.lockx.in.locks = &lock2;
    1750           1 :         status = smb_raw_lock(cli->tree, &io);
    1751           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1752             : 
    1753           1 :         torture_comment(tctx, "  try exclusive lock on pid1, testing the unlock.\n");
    1754           1 :         io.lockx.in.ulock_cnt = 0;
    1755           1 :         io.lockx.in.lock_cnt = 1;
    1756           1 :         io.lockx.in.mode = 0;
    1757           1 :         io.lockx.in.file.fnum = fnum1;
    1758           1 :         io.lockx.in.locks = &lock1;
    1759           1 :         status = smb_raw_lock(cli->tree, &io);
    1760           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1761             : 
    1762             :         /* cleanup */
    1763           1 :         io.lockx.in.ulock_cnt = 1;
    1764           1 :         io.lockx.in.lock_cnt = 0;
    1765           1 :         status = smb_raw_lock(cli->tree, &io);
    1766           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1767             : 
    1768             :         /**
    1769             :          * Test unlocking of 0-byte locks.
    1770             :          */
    1771             : 
    1772           1 :         torture_comment(tctx, "  lock shared and exclusive 0-byte locks, testing that Windows "
    1773             :             "always unlocks the exclusive first.\n");
    1774           1 :         lock1.pid = cli->session->pid;
    1775           1 :         lock1.offset = 10;
    1776           1 :         lock1.count = 0;
    1777           1 :         lock2.pid = cli->session->pid;
    1778           1 :         lock2.offset = 5;
    1779           1 :         lock2.count = 10;
    1780           1 :         io.lockx.in.ulock_cnt = 0;
    1781           1 :         io.lockx.in.lock_cnt = 1;
    1782           1 :         io.lockx.in.file.fnum = fnum1;
    1783           1 :         io.lockx.in.locks = &lock1;
    1784             : 
    1785             :         /* lock 0-byte shared
    1786             :          * Note: Order of the shared/exclusive locks doesn't matter. */
    1787           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1788           1 :         status = smb_raw_lock(cli->tree, &io);
    1789           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1790             : 
    1791             :         /* lock 0-byte exclusive */
    1792           1 :         io.lockx.in.mode = 0;
    1793           1 :         status = smb_raw_lock(cli->tree, &io);
    1794           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1795             : 
    1796             :         /* test contention */
    1797           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1798           1 :         io.lockx.in.locks = &lock2;
    1799           1 :         io.lockx.in.file.fnum = fnum2;
    1800           1 :         status = smb_raw_lock(cli->tree, &io);
    1801           1 :         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
    1802             :             NT_STATUS_FILE_LOCK_CONFLICT);
    1803             : 
    1804             :         /* unlock */
    1805           1 :         io.lockx.in.ulock_cnt = 1;
    1806           1 :         io.lockx.in.lock_cnt = 0;
    1807           1 :         io.lockx.in.file.fnum = fnum1;
    1808           1 :         io.lockx.in.locks = &lock1;
    1809           1 :         status = smb_raw_lock(cli->tree, &io);
    1810           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1811             : 
    1812             :         /* test - can we take a shared lock? */
    1813           1 :         io.lockx.in.ulock_cnt = 0;
    1814           1 :         io.lockx.in.lock_cnt = 1;
    1815           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1816           1 :         io.lockx.in.file.fnum = fnum2;
    1817           1 :         io.lockx.in.locks = &lock2;
    1818           1 :         status = smb_raw_lock(cli->tree, &io);
    1819             : 
    1820             :         /* XXX Samba 3 will fail this test. This is temporary(because this isn't
    1821             :          * new to Win7, it succeeds in WinXP too), until I can come to a
    1822             :          * resolution as to whether Samba should support this or not. There is
    1823             :          * code to preference unlocking exclusive locks before shared locks,
    1824             :          * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
    1825           1 :         if (TARGET_IS_SAMBA3(tctx)) {
    1826           0 :                 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
    1827             :                     NT_STATUS_FILE_LOCK_CONFLICT);
    1828             :         } else {
    1829           1 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1830             :         }
    1831             : 
    1832             :         /* cleanup */
    1833           1 :         io.lockx.in.ulock_cnt = 1;
    1834           1 :         io.lockx.in.lock_cnt = 0;
    1835           1 :         status = smb_raw_lock(cli->tree, &io);
    1836             : 
    1837             :         /* XXX Same as above. */
    1838           1 :         if (TARGET_IS_SAMBA3(tctx)) {
    1839           0 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1840             :         } else {
    1841           1 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1842             :         }
    1843             : 
    1844           1 :         io.lockx.in.file.fnum = fnum1;
    1845           1 :         io.lockx.in.locks = &lock1;
    1846           1 :         status = smb_raw_lock(cli->tree, &io);
    1847           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1848             : 
    1849           2 : done:
    1850           1 :         smbcli_close(cli->tree, fnum1);
    1851           1 :         smbcli_close(cli->tree, fnum2);
    1852           1 :         smb_raw_exit(cli->session);
    1853           1 :         smbcli_deltree(cli->tree, BASEDIR);
    1854           1 :         return ret;
    1855             : }
    1856             : 
    1857           1 : static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
    1858             : {
    1859             :         union smb_lock io;
    1860             :         NTSTATUS status;
    1861           1 :         bool ret = true;
    1862             :         int fnum1;
    1863           1 :         const char *fname = BASEDIR "\\unlock_multiple.txt";
    1864             :         struct smb_lock_entry lock1;
    1865             :         struct smb_lock_entry lock2;
    1866             :         struct smb_lock_entry locks[2];
    1867             : 
    1868           1 :         torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
    1869             : 
    1870           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1871             : 
    1872           1 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1873           1 :         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
    1874             :                        "Failed to create %s - %s\n",
    1875             :                        fname, smbcli_errstr(cli->tree)));
    1876             : 
    1877             :         /* Setup initial parameters */
    1878           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    1879           1 :         io.lockx.in.timeout = 0;
    1880             : 
    1881           1 :         lock1.pid = cli->session->pid;
    1882           1 :         lock1.offset = 0;
    1883           1 :         lock1.count = 10;
    1884           1 :         lock2.pid = cli->session->pid;
    1885           1 :         lock2.offset = 10;
    1886           1 :         lock2.count = 10;
    1887             : 
    1888           1 :         locks[0] = lock1;
    1889           1 :         locks[1] = lock2;
    1890             : 
    1891           1 :         io.lockx.in.file.fnum = fnum1;
    1892           1 :         io.lockx.in.mode = 0; /* exclusive */
    1893             : 
    1894             :         /** Test1: Take second lock, but not first. */
    1895           1 :         torture_comment(tctx, "  unlock 2 locks, first one not locked. Expect no locks "
    1896             :             "unlocked. \n");
    1897             : 
    1898           1 :         io.lockx.in.ulock_cnt = 0;
    1899           1 :         io.lockx.in.lock_cnt = 1;
    1900           1 :         io.lockx.in.locks = &lock2;
    1901           1 :         status = smb_raw_lock(cli->tree, &io);
    1902           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1903             : 
    1904             :         /* Try to unlock both locks. */
    1905           1 :         io.lockx.in.ulock_cnt = 2;
    1906           1 :         io.lockx.in.lock_cnt = 0;
    1907           1 :         io.lockx.in.locks = locks;
    1908             : 
    1909           1 :         status = smb_raw_lock(cli->tree, &io);
    1910           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1911             : 
    1912             :         /* Second lock should not be unlocked. */
    1913           1 :         io.lockx.in.ulock_cnt = 0;
    1914           1 :         io.lockx.in.lock_cnt = 1;
    1915           1 :         io.lockx.in.locks = &lock2;
    1916           1 :         status = smb_raw_lock(cli->tree, &io);
    1917           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1918             : 
    1919             :         /* cleanup */
    1920           1 :         io.lockx.in.ulock_cnt = 1;
    1921           1 :         io.lockx.in.lock_cnt = 0;
    1922           1 :         io.lockx.in.locks = &lock2;
    1923           1 :         status = smb_raw_lock(cli->tree, &io);
    1924           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1925             : 
    1926             :         /** Test2: Take first lock, but not second. */
    1927           1 :         torture_comment(tctx, "  unlock 2 locks, second one not locked. Expect first lock "
    1928             :             "unlocked.\n");
    1929             : 
    1930           1 :         io.lockx.in.ulock_cnt = 0;
    1931           1 :         io.lockx.in.lock_cnt = 1;
    1932           1 :         io.lockx.in.locks = &lock1;
    1933           1 :         status = smb_raw_lock(cli->tree, &io);
    1934           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1935             : 
    1936             :         /* Try to unlock both locks. */
    1937           1 :         io.lockx.in.ulock_cnt = 2;
    1938           1 :         io.lockx.in.lock_cnt = 0;
    1939           1 :         io.lockx.in.locks = locks;
    1940             : 
    1941           1 :         status = smb_raw_lock(cli->tree, &io);
    1942           1 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1943             : 
    1944             :         /* First lock should be unlocked. */
    1945           1 :         io.lockx.in.ulock_cnt = 0;
    1946           1 :         io.lockx.in.lock_cnt = 1;
    1947           1 :         io.lockx.in.locks = &lock1;
    1948           1 :         status = smb_raw_lock(cli->tree, &io);
    1949           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1950             : 
    1951             :         /* cleanup */
    1952           1 :         io.lockx.in.ulock_cnt = 1;
    1953           1 :         io.lockx.in.lock_cnt = 0;
    1954           1 :         io.lockx.in.locks = &lock1;
    1955           1 :         status = smb_raw_lock(cli->tree, &io);
    1956           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1957             : 
    1958             :         /* Test3: Request 2 locks, second will contend.  What happens to the
    1959             :          * first? */
    1960           1 :         torture_comment(tctx, "  request 2 locks, second one will contend. "
    1961             :            "Expect both to fail.\n");
    1962             : 
    1963             :         /* Lock the second range */
    1964           1 :         io.lockx.in.ulock_cnt = 0;
    1965           1 :         io.lockx.in.lock_cnt = 1;
    1966           1 :         io.lockx.in.locks = &lock2;
    1967           1 :         status = smb_raw_lock(cli->tree, &io);
    1968           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1969             : 
    1970             :         /* Request both locks */
    1971           1 :         io.lockx.in.ulock_cnt = 0;
    1972           1 :         io.lockx.in.lock_cnt = 2;
    1973           1 :         io.lockx.in.locks = locks;
    1974             : 
    1975           1 :         status = smb_raw_lock(cli->tree, &io);
    1976           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1977             : 
    1978             :         /* First lock should be unlocked. */
    1979           1 :         io.lockx.in.ulock_cnt = 0;
    1980           1 :         io.lockx.in.lock_cnt = 1;
    1981           1 :         io.lockx.in.locks = &lock1;
    1982           1 :         status = smb_raw_lock(cli->tree, &io);
    1983           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1984             : 
    1985             :         /* cleanup */
    1986           1 :         io.lockx.in.ulock_cnt = 2;
    1987           1 :         io.lockx.in.lock_cnt = 0;
    1988           1 :         io.lockx.in.locks = locks;
    1989           1 :         status = smb_raw_lock(cli->tree, &io);
    1990           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    1991             : 
    1992             :         /* Test4: Request unlock and lock. The lock contends, is the unlock
    1993             :          * then re-locked? */
    1994           1 :         torture_comment(tctx, "  request unlock and lock, second one will "
    1995             :            "contend. Expect the unlock to succeed.\n");
    1996             : 
    1997             :         /* Lock both ranges */
    1998           1 :         io.lockx.in.ulock_cnt = 0;
    1999           1 :         io.lockx.in.lock_cnt = 2;
    2000           1 :         io.lockx.in.locks = locks;
    2001           1 :         status = smb_raw_lock(cli->tree, &io);
    2002           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2003             : 
    2004             :         /* Attempt to unlock the first range and lock the second */
    2005           1 :         io.lockx.in.ulock_cnt = 1;
    2006           1 :         io.lockx.in.lock_cnt = 1;
    2007           1 :         io.lockx.in.locks = locks;
    2008           1 :         status = smb_raw_lock(cli->tree, &io);
    2009           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2010             : 
    2011             :         /* The first lock should've been unlocked */
    2012           1 :         io.lockx.in.ulock_cnt = 0;
    2013           1 :         io.lockx.in.lock_cnt = 1;
    2014           1 :         io.lockx.in.locks = &lock1;
    2015           1 :         status = smb_raw_lock(cli->tree, &io);
    2016           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2017             : 
    2018             :         /* cleanup */
    2019           1 :         io.lockx.in.ulock_cnt = 2;
    2020           1 :         io.lockx.in.lock_cnt = 0;
    2021           1 :         io.lockx.in.locks = locks;
    2022           1 :         status = smb_raw_lock(cli->tree, &io);
    2023           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2024             : 
    2025           2 : done:
    2026           1 :         smbcli_close(cli->tree, fnum1);
    2027           1 :         smb_raw_exit(cli->session);
    2028           1 :         smbcli_deltree(cli->tree, BASEDIR);
    2029           1 :         return ret;
    2030             : }
    2031             : 
    2032             : /**
    2033             :  * torture_locktest5 covers stacking pretty well, but its missing two tests:
    2034             :  * - stacking an exclusive on top of shared fails
    2035             :  * - stacking two exclusives fail
    2036             :  */
    2037           1 : static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
    2038             : {
    2039             :         union smb_lock io;
    2040             :         NTSTATUS status;
    2041           1 :         bool ret = true;
    2042             :         int fnum1;
    2043           1 :         const char *fname = BASEDIR "\\stacking.txt";
    2044             :         struct smb_lock_entry lock1;
    2045             : 
    2046           1 :         torture_comment(tctx, "Testing stacking:\n");
    2047             : 
    2048           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2049             : 
    2050           1 :         io.generic.level = RAW_LOCK_LOCKX;
    2051             : 
    2052           1 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2053           1 :         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
    2054             :                        "Failed to create %s - %s\n",
    2055             :                        fname, smbcli_errstr(cli->tree)));
    2056             : 
    2057             :         /* Setup initial parameters */
    2058           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    2059           1 :         io.lockx.in.timeout = 0;
    2060             : 
    2061           1 :         lock1.pid = cli->session->pid;
    2062           1 :         lock1.offset = 0;
    2063           1 :         lock1.count = 10;
    2064             : 
    2065             :         /**
    2066             :          * Try to take a shared lock, then stack an exclusive.
    2067             :          */
    2068           1 :         torture_comment(tctx, "  stacking an exclusive on top of a shared lock fails.\n");
    2069           1 :         io.lockx.in.file.fnum = fnum1;
    2070           1 :         io.lockx.in.locks = &lock1;
    2071             : 
    2072           1 :         io.lockx.in.ulock_cnt = 0;
    2073           1 :         io.lockx.in.lock_cnt = 1;
    2074           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    2075           1 :         status = smb_raw_lock(cli->tree, &io);
    2076           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2077             : 
    2078           1 :         io.lockx.in.ulock_cnt = 0;
    2079           1 :         io.lockx.in.lock_cnt = 1;
    2080           1 :         io.lockx.in.mode = 0;
    2081           1 :         status = smb_raw_lock(cli->tree, &io);
    2082           1 :         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
    2083             :             NT_STATUS_FILE_LOCK_CONFLICT);
    2084             : 
    2085             :         /* cleanup */
    2086           1 :         io.lockx.in.ulock_cnt = 1;
    2087           1 :         io.lockx.in.lock_cnt = 0;
    2088           1 :         status = smb_raw_lock(cli->tree, &io);
    2089           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2090             : 
    2091             :         /**
    2092             :          * Prove that two exclusive locks do not stack.
    2093             :          */
    2094           1 :         torture_comment(tctx, "  two exclusive locks do not stack.\n");
    2095           1 :         io.lockx.in.ulock_cnt = 0;
    2096           1 :         io.lockx.in.lock_cnt = 1;
    2097           1 :         io.lockx.in.mode = 0;
    2098           1 :         status = smb_raw_lock(cli->tree, &io);
    2099           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2100           1 :         status = smb_raw_lock(cli->tree, &io);
    2101           1 :         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
    2102             :             NT_STATUS_FILE_LOCK_CONFLICT);
    2103             : 
    2104             :         /* cleanup */
    2105           1 :         io.lockx.in.ulock_cnt = 1;
    2106           1 :         io.lockx.in.lock_cnt = 0;
    2107           1 :         status = smb_raw_lock(cli->tree, &io);
    2108           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2109             : 
    2110           2 : done:
    2111           1 :         smbcli_close(cli->tree, fnum1);
    2112           1 :         smb_raw_exit(cli->session);
    2113           1 :         smbcli_deltree(cli->tree, BASEDIR);
    2114           1 :         return ret;
    2115             : }
    2116             : 
    2117             : /**
    2118             :  * Test how 0-byte read requests contend with byte range locks
    2119             :  */
    2120           1 : static bool test_zerobyteread(struct torture_context *tctx,
    2121             :                               struct smbcli_state *cli)
    2122             : {
    2123             :         union smb_lock io;
    2124             :         union smb_read rd;
    2125             :         NTSTATUS status;
    2126           1 :         bool ret = true;
    2127             :         int fnum1, fnum2;
    2128           1 :         const char *fname = BASEDIR "\\zerobyteread.txt";
    2129             :         struct smb_lock_entry lock1;
    2130           1 :         uint8_t c = 1;
    2131             : 
    2132           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2133             : 
    2134           1 :         io.generic.level = RAW_LOCK_LOCKX;
    2135             : 
    2136           1 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2137           1 :         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
    2138             :                        "Failed to create %s - %s\n",
    2139             :                        fname, smbcli_errstr(cli->tree)));
    2140             : 
    2141           1 :         fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2142           1 :         torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
    2143             :                        "Failed to create %s - %s\n",
    2144             :                        fname, smbcli_errstr(cli->tree)));
    2145             : 
    2146             :         /* Setup initial parameters */
    2147           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    2148           1 :         io.lockx.in.timeout = 0;
    2149             : 
    2150           1 :         lock1.pid = cli->session->pid;
    2151           1 :         lock1.offset = 0;
    2152           1 :         lock1.count = 10;
    2153             : 
    2154           1 :         ZERO_STRUCT(rd);
    2155           1 :         rd.readx.level = RAW_READ_READX;
    2156             : 
    2157           1 :         torture_comment(tctx, "Testing zero byte read on lock range:\n");
    2158             : 
    2159             :         /* Take an exclusive lock */
    2160           1 :         torture_comment(tctx, "  taking exclusive lock.\n");
    2161           1 :         io.lockx.in.ulock_cnt = 0;
    2162           1 :         io.lockx.in.lock_cnt = 1;
    2163           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2164           1 :         io.lockx.in.file.fnum = fnum1;
    2165           1 :         io.lockx.in.locks = &lock1;
    2166           1 :         status = smb_raw_lock(cli->tree, &io);
    2167           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2168             : 
    2169             :         /* Try a zero byte read */
    2170           1 :         torture_comment(tctx, "  reading 0 bytes.\n");
    2171           1 :         rd.readx.in.file.fnum = fnum2;
    2172           1 :         rd.readx.in.offset    = 5;
    2173           1 :         rd.readx.in.mincnt    = 0;
    2174           1 :         rd.readx.in.maxcnt    = 0;
    2175           1 :         rd.readx.in.remaining = 0;
    2176           1 :         rd.readx.in.read_for_execute = false;
    2177           1 :         rd.readx.out.data     = &c;
    2178           1 :         status = smb_raw_read(cli->tree, &rd);
    2179           1 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2180             :                                       "zero byte read did not return 0 bytes");
    2181           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2182             : 
    2183             :         /* Unlock lock */
    2184           0 :         io.lockx.in.ulock_cnt = 1;
    2185           0 :         io.lockx.in.lock_cnt = 0;
    2186           0 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2187           0 :         io.lockx.in.file.fnum = fnum1;
    2188           0 :         io.lockx.in.locks = &lock1;
    2189           0 :         status = smb_raw_lock(cli->tree, &io);
    2190           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2191             : 
    2192           0 :         torture_comment(tctx, "Testing zero byte read on zero byte lock "
    2193             :                               "range:\n");
    2194             : 
    2195             :         /* Take an exclusive lock */
    2196           0 :         torture_comment(tctx, "  taking exclusive 0-byte lock.\n");
    2197           0 :         io.lockx.in.ulock_cnt = 0;
    2198           0 :         io.lockx.in.lock_cnt = 1;
    2199           0 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2200           0 :         io.lockx.in.file.fnum = fnum1;
    2201           0 :         io.lockx.in.locks = &lock1;
    2202           0 :         lock1.offset = 5;
    2203           0 :         lock1.count = 0;
    2204           0 :         status = smb_raw_lock(cli->tree, &io);
    2205           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2206             : 
    2207             :         /* Try a zero byte read before the lock */
    2208           0 :         torture_comment(tctx, "  reading 0 bytes before the lock.\n");
    2209           0 :         rd.readx.in.file.fnum = fnum2;
    2210           0 :         rd.readx.in.offset    = 4;
    2211           0 :         rd.readx.in.mincnt    = 0;
    2212           0 :         rd.readx.in.maxcnt    = 0;
    2213           0 :         rd.readx.in.remaining = 0;
    2214           0 :         rd.readx.in.read_for_execute = false;
    2215           0 :         rd.readx.out.data     = &c;
    2216           0 :         status = smb_raw_read(cli->tree, &rd);
    2217           0 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2218             :                                       "zero byte read did not return 0 bytes");
    2219           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2220             : 
    2221             :         /* Try a zero byte read on the lock */
    2222           0 :         torture_comment(tctx, "  reading 0 bytes on the lock.\n");
    2223           0 :         rd.readx.in.file.fnum = fnum2;
    2224           0 :         rd.readx.in.offset    = 5;
    2225           0 :         rd.readx.in.mincnt    = 0;
    2226           0 :         rd.readx.in.maxcnt    = 0;
    2227           0 :         rd.readx.in.remaining = 0;
    2228           0 :         rd.readx.in.read_for_execute = false;
    2229           0 :         rd.readx.out.data     = &c;
    2230           0 :         status = smb_raw_read(cli->tree, &rd);
    2231           0 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2232             :                                       "zero byte read did not return 0 bytes");
    2233           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2234             : 
    2235             :         /* Try a zero byte read after the lock */
    2236           0 :         torture_comment(tctx, "  reading 0 bytes after the lock.\n");
    2237           0 :         rd.readx.in.file.fnum = fnum2;
    2238           0 :         rd.readx.in.offset    = 6;
    2239           0 :         rd.readx.in.mincnt    = 0;
    2240           0 :         rd.readx.in.maxcnt    = 0;
    2241           0 :         rd.readx.in.remaining = 0;
    2242           0 :         rd.readx.in.read_for_execute = false;
    2243           0 :         rd.readx.out.data     = &c;
    2244           0 :         status = smb_raw_read(cli->tree, &rd);
    2245           0 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2246             :                                       "zero byte read did not return 0 bytes");
    2247           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2248             : 
    2249             :         /* Unlock lock */
    2250           0 :         io.lockx.in.ulock_cnt = 1;
    2251           0 :         io.lockx.in.lock_cnt = 0;
    2252           0 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2253           0 :         io.lockx.in.file.fnum = fnum1;
    2254           0 :         io.lockx.in.locks = &lock1;
    2255           0 :         status = smb_raw_lock(cli->tree, &io);
    2256           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    2257             : 
    2258           1 : done:
    2259           1 :         smbcli_close(cli->tree, fnum1);
    2260           1 :         smbcli_close(cli->tree, fnum2);
    2261           1 :         smb_raw_exit(cli->session);
    2262           1 :         smbcli_deltree(cli->tree, BASEDIR);
    2263           1 :         return ret;
    2264             : }
    2265             : /*
    2266             :   test multi Locking&X operation
    2267             : */
    2268           1 : static bool test_multilock(struct torture_context *tctx,
    2269             :                                            struct smbcli_state *cli)
    2270             : {
    2271             :         union smb_lock io;
    2272             :         struct smb_lock_entry lock[2];
    2273             :         NTSTATUS status;
    2274           1 :         bool ret = true;
    2275             :         int fnum;
    2276           1 :         const char *fname = BASEDIR "\\multilock_test.txt";
    2277             :         time_t t;
    2278             :         struct smbcli_request *req;
    2279             :         struct smbcli_session_options options;
    2280             : 
    2281           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2282             : 
    2283           1 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
    2284             : 
    2285           1 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock\n");
    2286           1 :         io.generic.level = RAW_LOCK_LOCKX;
    2287             : 
    2288             :         /* Create the test file. */
    2289           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2290           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    2291             :                        "Failed to create %s - %s\n",
    2292             :                        fname, smbcli_errstr(cli->tree)));
    2293             : 
    2294             :         /*
    2295             :          * Lock regions 100->109, 120->129 as
    2296             :          * two separate write locks in one request.
    2297             :          */
    2298           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    2299           1 :         io.lockx.in.file.fnum = fnum;
    2300           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2301           1 :         io.lockx.in.timeout = 0;
    2302           1 :         io.lockx.in.ulock_cnt = 0;
    2303           1 :         io.lockx.in.lock_cnt = 2;
    2304           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2305           1 :         lock[0].pid = cli->session->pid;
    2306           1 :         lock[0].offset = 100;
    2307           1 :         lock[0].count = 10;
    2308           1 :         lock[1].pid = cli->session->pid;
    2309           1 :         lock[1].offset = 120;
    2310           1 :         lock[1].count = 10;
    2311           1 :         io.lockx.in.locks = &lock[0];
    2312           1 :         status = smb_raw_lock(cli->tree, &io);
    2313           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2314             : 
    2315             :         /*
    2316             :          * Now request the same locks on a different
    2317             :          * context as blocking locks with infinite timeout.
    2318             :          */
    2319             : 
    2320           1 :         io.lockx.in.timeout = 20000;
    2321           1 :         lock[0].pid = cli->session->pid+1;
    2322           1 :         lock[1].pid = cli->session->pid+1;
    2323           1 :         req = smb_raw_lock_send(cli->tree, &io);
    2324           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    2325             :                        "Failed to setup timed locks (%s)\n", __location__));
    2326             : 
    2327             :         /* Unlock lock[0] */
    2328           1 :         io.lockx.in.timeout = 0;
    2329           1 :         io.lockx.in.ulock_cnt = 1;
    2330           1 :         io.lockx.in.lock_cnt = 0;
    2331           1 :         io.lockx.in.locks = &lock[0];
    2332           1 :         lock[0].pid = cli->session->pid;
    2333           1 :         status = smb_raw_lock(cli->tree, &io);
    2334           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2335             : 
    2336             :         /* Start the clock. */
    2337           1 :         t = time_mono(NULL);
    2338             : 
    2339             :         /* Unlock lock[1] */
    2340           1 :         io.lockx.in.timeout = 0;
    2341           1 :         io.lockx.in.ulock_cnt = 1;
    2342           1 :         io.lockx.in.lock_cnt = 0;
    2343           1 :         io.lockx.in.locks = &lock[1];
    2344           1 :         lock[1].pid = cli->session->pid;
    2345           1 :         status = smb_raw_lock(cli->tree, &io);
    2346           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2347             : 
    2348             :         /* receive the successful blocked lock requests */
    2349           1 :         status = smbcli_request_simple_recv(req);
    2350           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2351             : 
    2352             :         /* Fail if this took more than 2 seconds. */
    2353           1 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    2354             :                        "Blocking locks were not granted immediately (%s)\n",
    2355             :                        __location__));
    2356           1 : done:
    2357           1 :         smb_raw_exit(cli->session);
    2358           1 :         smbcli_deltree(cli->tree, BASEDIR);
    2359           1 :         return ret;
    2360             : }
    2361             : 
    2362             : /*
    2363             :   test multi2 Locking&X operation
    2364             :   This test is designed to show that
    2365             :   lock precedence on the server is based
    2366             :   on the order received, not on the ability
    2367             :   to grant. For example:
    2368             : 
    2369             :   A blocked lock request containing 2 locks
    2370             :   will be satified before a subsequent blocked
    2371             :   lock request over one of the same regions,
    2372             :   even if that region is then unlocked. E.g.
    2373             : 
    2374             :   (a) lock 100->109, 120->129 (granted)
    2375             :   (b) lock 100->109, 120-129 (blocks)
    2376             :   (c) lock 100->109          (blocks)
    2377             :   (d) unlock 100->109
    2378             : 
    2379             :   lock (c) will not be granted as lock (b)
    2380             :   will take precedence.
    2381             : */
    2382           1 : static bool test_multilock2(struct torture_context *tctx,
    2383             :                                            struct smbcli_state *cli)
    2384             : {
    2385             :         union smb_lock io;
    2386             :         struct smb_lock_entry lock[2];
    2387             :         NTSTATUS status;
    2388           1 :         bool ret = true;
    2389             :         int fnum;
    2390           1 :         const char *fname = BASEDIR "\\multilock2_test.txt";
    2391             :         time_t t;
    2392             :         struct smbcli_request *req;
    2393             :         struct smbcli_request *req2;
    2394             :         struct smbcli_session_options options;
    2395             : 
    2396           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2397             : 
    2398           1 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
    2399             : 
    2400           1 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 2\n");
    2401           1 :         io.generic.level = RAW_LOCK_LOCKX;
    2402             : 
    2403             :         /* Create the test file. */
    2404           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2405           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    2406             :                        "Failed to create %s - %s\n",
    2407             :                        fname, smbcli_errstr(cli->tree)));
    2408             : 
    2409             :         /*
    2410             :          * Lock regions 100->109, 120->129 as
    2411             :          * two separate write locks in one request.
    2412             :          */
    2413           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    2414           1 :         io.lockx.in.file.fnum = fnum;
    2415           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2416           1 :         io.lockx.in.timeout = 0;
    2417           1 :         io.lockx.in.ulock_cnt = 0;
    2418           1 :         io.lockx.in.lock_cnt = 2;
    2419           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2420           1 :         lock[0].pid = cli->session->pid;
    2421           1 :         lock[0].offset = 100;
    2422           1 :         lock[0].count = 10;
    2423           1 :         lock[1].pid = cli->session->pid;
    2424           1 :         lock[1].offset = 120;
    2425           1 :         lock[1].count = 10;
    2426           1 :         io.lockx.in.locks = &lock[0];
    2427           1 :         status = smb_raw_lock(cli->tree, &io);
    2428           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2429             : 
    2430             :         /*
    2431             :          * Now request the same locks on a different
    2432             :          * context as blocking locks.
    2433             :          */
    2434             : 
    2435           1 :         io.lockx.in.timeout = 20000;
    2436           1 :         lock[0].pid = cli->session->pid+1;
    2437           1 :         lock[1].pid = cli->session->pid+1;
    2438           1 :         req = smb_raw_lock_send(cli->tree, &io);
    2439           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    2440             :                        "Failed to setup timed locks (%s)\n", __location__));
    2441             : 
    2442             :         /*
    2443             :          * Request the first lock again on a separate context.
    2444             :          * Wait 2 seconds. This should time out (the previous
    2445             :          * multi-lock request should take precedence).
    2446             :          */
    2447             : 
    2448           1 :         io.lockx.in.timeout = 2000;
    2449           1 :         lock[0].pid = cli->session->pid+2;
    2450           1 :         io.lockx.in.lock_cnt = 1;
    2451           1 :         req2 = smb_raw_lock_send(cli->tree, &io);
    2452           1 :         torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
    2453             :                        "Failed to setup timed locks (%s)\n", __location__));
    2454             : 
    2455             :         /* Unlock lock[0] */
    2456           1 :         io.lockx.in.timeout = 0;
    2457           1 :         io.lockx.in.ulock_cnt = 1;
    2458           1 :         io.lockx.in.lock_cnt = 0;
    2459           1 :         io.lockx.in.locks = &lock[0];
    2460           1 :         lock[0].pid = cli->session->pid;
    2461           1 :         status = smb_raw_lock(cli->tree, &io);
    2462           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2463             : 
    2464             :         /* Did the second lock complete (should time out) ? */
    2465           1 :         status = smbcli_request_simple_recv(req2);
    2466           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2467             : 
    2468           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2469             :                        "req should still wait");
    2470             : 
    2471             :         /* Start the clock. */
    2472           1 :         t = time_mono(NULL);
    2473             : 
    2474             :         /* Unlock lock[1] */
    2475           1 :         io.lockx.in.timeout = 0;
    2476           1 :         io.lockx.in.ulock_cnt = 1;
    2477           1 :         io.lockx.in.lock_cnt = 0;
    2478           1 :         io.lockx.in.locks = &lock[1];
    2479           1 :         lock[1].pid = cli->session->pid;
    2480           1 :         status = smb_raw_lock(cli->tree, &io);
    2481           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2482             : 
    2483             :         /* receive the successful blocked lock requests */
    2484           1 :         status = smbcli_request_simple_recv(req);
    2485           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2486             : 
    2487             :         /* Fail if this took more than 2 seconds. */
    2488           1 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    2489             :                        "Blocking locks were not granted immediately (%s)\n",
    2490             :                        __location__));
    2491           1 : done:
    2492           1 :         smb_raw_exit(cli->session);
    2493           1 :         smbcli_deltree(cli->tree, BASEDIR);
    2494           1 :         return ret;
    2495             : }
    2496             : 
    2497             : /*
    2498             :   test multi3 Locking&X operation
    2499             :   This test is designed to show that
    2500             :   lock precedence on the server is based
    2501             :   on the order received, not on the ability
    2502             :   to grant.
    2503             : 
    2504             :   Compared to test_multilock2() (above)
    2505             :   this test demonstrates that completely
    2506             :   unrelated ranges work independently.
    2507             : 
    2508             :   For example:
    2509             : 
    2510             :   A blocked lock request containing 2 locks
    2511             :   will be satified before a subsequent blocked
    2512             :   lock request over one of the same regions,
    2513             :   even if that region is then unlocked. But
    2514             :   a lock of a different region goes through. E.g.
    2515             : 
    2516             :   All locks are LOCKING_ANDX_EXCLUSIVE_LOCK (rw).
    2517             : 
    2518             :   (a) lock 100->109, 120->129 (granted)
    2519             :   (b) lock 100->109, 120->129 (blocks, timeout=20s)
    2520             :   (c) lock 100->109           (blocks, timeout=2s)
    2521             :   (d) lock 110->119           (granted)
    2522             :   (e) lock 110->119           (blocks, timeout=20s)
    2523             :   (f) unlock 100->109 (a)
    2524             :   (g) lock 100->109           (not granted, blocked by (b))
    2525             :   (h) lock 100->109           (not granted, blocked by itself (b))
    2526             :   (i) lock (c) will not be granted(conflict, times out)
    2527             :       as lock (b) will take precedence.
    2528             :   (j) unlock 110-119 (d)
    2529             :   (k) lock (e) completes and is not blocked by (a) nor (b)
    2530             :   (l) lock 100->109           (not granted(conflict), blocked by (b))
    2531             :   (m) lock 100->109           (not granted(conflict), blocked by itself (b))
    2532             :   (n) unlock 120-129 (a)
    2533             :   (o) lock (b) completes
    2534             : */
    2535           1 : static bool test_multilock3(struct torture_context *tctx,
    2536             :                             struct smbcli_state *cli)
    2537             : {
    2538             :         union smb_lock io;
    2539             :         struct smb_lock_entry lock[2];
    2540             :         union smb_lock io3;
    2541             :         struct smb_lock_entry lock3[1];
    2542             :         NTSTATUS status;
    2543           1 :         bool ret = true;
    2544             :         int fnum;
    2545           1 :         const char *fname = BASEDIR "\\multilock3_test.txt";
    2546             :         time_t t;
    2547           1 :         struct smbcli_request *req = NULL;
    2548           1 :         struct smbcli_request *req2 = NULL;
    2549           1 :         struct smbcli_request *req4 = NULL;
    2550             : 
    2551           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    2552             :                        "Failed to setup up test directory: " BASEDIR);
    2553             : 
    2554           1 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 3\n");
    2555           1 :         io.generic.level = RAW_LOCK_LOCKX;
    2556             : 
    2557             :         /* Create the test file. */
    2558           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2559           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    2560             :                        "Failed to create %s - %s\n",
    2561             :                        fname, smbcli_errstr(cli->tree)));
    2562             : 
    2563             :         /*
    2564             :          * a)
    2565             :          * Lock regions 100->109, 120->129 as
    2566             :          * two separate write locks in one request.
    2567             :          */
    2568           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    2569           1 :         io.lockx.in.file.fnum = fnum;
    2570           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2571           1 :         io.lockx.in.timeout = 0;
    2572           1 :         io.lockx.in.ulock_cnt = 0;
    2573           1 :         io.lockx.in.lock_cnt = 2;
    2574           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2575           1 :         lock[0].pid = cli->session->pid;
    2576           1 :         lock[0].offset = 100;
    2577           1 :         lock[0].count = 10;
    2578           1 :         lock[1].pid = cli->session->pid;
    2579           1 :         lock[1].offset = 120;
    2580           1 :         lock[1].count = 10;
    2581           1 :         io.lockx.in.locks = &lock[0];
    2582           1 :         status = smb_raw_lock(cli->tree, &io);
    2583           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2584             : 
    2585             :         /*
    2586             :          * b)
    2587             :          * Now request the same locks on a different
    2588             :          * context as blocking locks.
    2589             :          */
    2590           1 :         io.lockx.in.timeout = 20000;
    2591           1 :         lock[0].pid = cli->session->pid+1;
    2592           1 :         lock[1].pid = cli->session->pid+1;
    2593           1 :         req = smb_raw_lock_send(cli->tree, &io);
    2594           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    2595             :                        "Failed to setup timed locks (%s)\n", __location__));
    2596             : 
    2597             :         /*
    2598             :          * c)
    2599             :          * Request the first lock again on a separate context.
    2600             :          * Wait 2 seconds. This should time out (the previous
    2601             :          * multi-lock request should take precedence).
    2602             :          */
    2603           1 :         io.lockx.in.timeout = 2000;
    2604           1 :         lock[0].pid = cli->session->pid+2;
    2605           1 :         io.lockx.in.lock_cnt = 1;
    2606           1 :         req2 = smb_raw_lock_send(cli->tree, &io);
    2607           1 :         torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
    2608             :                        "Failed to setup timed locks (%s)\n", __location__));
    2609             : 
    2610             :         /*
    2611             :          * d)
    2612             :          * Lock regions 110->119
    2613             :          */
    2614           1 :         io3.lockx.level = RAW_LOCK_LOCKX;
    2615           1 :         io3.lockx.in.file.fnum = fnum;
    2616           1 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2617           1 :         io3.lockx.in.timeout = 0;
    2618           1 :         io3.lockx.in.ulock_cnt = 0;
    2619           1 :         io3.lockx.in.lock_cnt = 1;
    2620           1 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2621           1 :         lock3[0].pid = cli->session->pid+3;
    2622           1 :         lock3[0].offset = 110;
    2623           1 :         lock3[0].count = 10;
    2624           1 :         io3.lockx.in.locks = &lock3[0];
    2625           1 :         status = smb_raw_lock(cli->tree, &io3);
    2626           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2627             : 
    2628             :         /*
    2629             :          * e)
    2630             :          * try 110-119 again
    2631             :          */
    2632           1 :         io3.lockx.in.timeout = 20000;
    2633           1 :         lock3[0].pid = cli->session->pid+4;
    2634           1 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    2635           1 :         torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx,
    2636             :                        "Failed to setup timed locks (%s)\n", __location__));
    2637             : 
    2638             :         /*
    2639             :          * f)
    2640             :          * Unlock (a) lock[0] 100-109
    2641             :          */
    2642           1 :         io.lockx.in.timeout = 0;
    2643           1 :         io.lockx.in.ulock_cnt = 1;
    2644           1 :         io.lockx.in.lock_cnt = 0;
    2645           1 :         io.lockx.in.locks = &lock[0];
    2646           1 :         lock[0].pid = cli->session->pid;
    2647           1 :         status = smb_raw_lock(cli->tree, &io);
    2648           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2649             : 
    2650             :         /*
    2651             :          * g)
    2652             :          * try to lock lock[0] 100-109 again
    2653             :          */
    2654           1 :         lock[0].pid = cli->session->pid+5;
    2655           1 :         io.lockx.in.ulock_cnt = 0;
    2656           1 :         io.lockx.in.lock_cnt = 1;
    2657           1 :         status = smb_raw_lock(cli->tree, &io);
    2658           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2659             : 
    2660             :         /*
    2661             :          * h)
    2662             :          * try to lock lock[0] 100-109 again with
    2663             :          * the pid that's still waiting
    2664             :          */
    2665           1 :         lock[0].pid = cli->session->pid+1;
    2666           1 :         io.lockx.in.ulock_cnt = 0;
    2667           1 :         io.lockx.in.lock_cnt = 1;
    2668           1 :         status = smb_raw_lock(cli->tree, &io);
    2669           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2670             : 
    2671           1 :         torture_assert(tctx, req2->state <= SMBCLI_REQUEST_RECV,
    2672             :                        "req2 should still wait");
    2673             : 
    2674             :         /*
    2675             :          * i)
    2676             :          * Did the second lock complete (should time out) ?
    2677             :          */
    2678           1 :         status = smbcli_request_simple_recv(req2);
    2679           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2680             : 
    2681           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2682             :                        "req should still wait");
    2683           1 :         torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV,
    2684             :                        "req4 should still wait");
    2685             : 
    2686             :         /*
    2687             :          * j)
    2688             :          * Unlock (d) lock[0] 110-119
    2689             :          */
    2690           1 :         io3.lockx.in.timeout = 0;
    2691           1 :         io3.lockx.in.ulock_cnt = 1;
    2692           1 :         io3.lockx.in.lock_cnt = 0;
    2693           1 :         lock3[0].pid = cli->session->pid+3;
    2694           1 :         status = smb_raw_lock(cli->tree, &io3);
    2695           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2696             : 
    2697             :         /*
    2698             :          * k)
    2699             :          * receive the successful blocked lock request (e)
    2700             :          * on 110-119 while the 100-109/120-129 is still waiting.
    2701             :          */
    2702           1 :         status = smbcli_request_simple_recv(req4);
    2703           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2704             : 
    2705             :         /*
    2706             :          * l)
    2707             :          * try to lock lock[0] 100-109 again
    2708             :          */
    2709           1 :         lock[0].pid = cli->session->pid+6;
    2710           1 :         io.lockx.in.ulock_cnt = 0;
    2711           1 :         io.lockx.in.lock_cnt = 1;
    2712           1 :         status = smb_raw_lock(cli->tree, &io);
    2713           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2714             : 
    2715           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2716             :                        "req should still wait");
    2717             : 
    2718             :         /*
    2719             :          * m)
    2720             :          * try to lock lock[0] 100-109 again with
    2721             :          * the pid that's still waiting
    2722             :          */
    2723           1 :         lock[0].pid = cli->session->pid+1;
    2724           1 :         io.lockx.in.ulock_cnt = 0;
    2725           1 :         io.lockx.in.lock_cnt = 1;
    2726           1 :         status = smb_raw_lock(cli->tree, &io);
    2727           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2728             : 
    2729           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2730             :                        "req should still wait");
    2731             : 
    2732             :         /* Start the clock. */
    2733           1 :         t = time_mono(NULL);
    2734             : 
    2735             :         /*
    2736             :          * n)
    2737             :          * Unlock lock[1] 120-129 */
    2738           1 :         io.lockx.in.timeout = 0;
    2739           1 :         io.lockx.in.ulock_cnt = 1;
    2740           1 :         io.lockx.in.lock_cnt = 0;
    2741           1 :         io.lockx.in.locks = &lock[1];
    2742           1 :         lock[1].pid = cli->session->pid;
    2743           1 :         status = smb_raw_lock(cli->tree, &io);
    2744           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2745             : 
    2746             :         /*
    2747             :          * o)
    2748             :          * receive the successful blocked lock request (b)
    2749             :          */
    2750           1 :         status = smbcli_request_simple_recv(req);
    2751           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2752             : 
    2753             :         /* Fail if this took more than 2 seconds. */
    2754           1 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    2755             :                        "Blocking locks were not granted immediately (%s)\n",
    2756             :                        __location__));
    2757           1 : done:
    2758           1 :         smb_raw_exit(cli->session);
    2759           1 :         smbcli_deltree(cli->tree, BASEDIR);
    2760           1 :         return ret;
    2761             : }
    2762             : 
    2763             : /*
    2764             :   test multi4 Locking&X operation
    2765             :   This test is designed to show that
    2766             :   lock precedence on the server is based
    2767             :   on the order received, not on the ability
    2768             :   to grant.
    2769             : 
    2770             :   Compared to test_multilock3() (above)
    2771             :   this test demonstrates that pending read-only/shared
    2772             :   locks doesn't block shared locks others.
    2773             : 
    2774             :   The outstanding requests build an implicit
    2775             :   database that's checked before checking
    2776             :   the already granted locks in the real database.
    2777             : 
    2778             :   For example:
    2779             : 
    2780             :   A blocked read-lock request containing 2 locks
    2781             :   will be still be blocked, while one region
    2782             :   is still write-locked. While it doesn't block
    2783             :   other read-lock requests for the other region. E.g.
    2784             : 
    2785             :   (a) lock(rw) 100->109, 120->129 (granted)
    2786             :   (b) lock(ro) 100->109, 120->129 (blocks, timeout=20s)
    2787             :   (c) lock(ro) 100->109           (blocks, timeout=MAX)
    2788             :   (d) lock(rw) 110->119           (granted)
    2789             :   (e) lock(rw) 110->119           (blocks, timeout=20s)
    2790             :   (f) unlock 100->109 (a)
    2791             :   (g) lock(ro) (c) completes and is not blocked by (a) nor (b)
    2792             :   (h) lock(rw) 100->109           (not granted, blocked by (c))
    2793             :   (i) lock(rw) 100->109 (pid (b)) (not granted(conflict), blocked by (c))
    2794             :   (j) unlock 110-119
    2795             :   (k) lock (e) completes and is not blocked by (a) nor (b)
    2796             :   (l) lock 100->109               (not granted(conflict), blocked by (b))
    2797             :   (m) lock 100->109 (pid (b))     (not granted(conflict), blocked by itself (b))
    2798             :   (n) unlock 120-129 (a)
    2799             :   (o) lock (b) completes
    2800             : */
    2801           1 : static bool test_multilock4(struct torture_context *tctx,
    2802             :                             struct smbcli_state *cli)
    2803             : {
    2804             :         union smb_lock io;
    2805             :         struct smb_lock_entry lock[2];
    2806             :         union smb_lock io3;
    2807             :         struct smb_lock_entry lock3[1];
    2808             :         NTSTATUS status;
    2809           1 :         bool ret = true;
    2810             :         int fnum;
    2811           1 :         const char *fname = BASEDIR "\\multilock4_test.txt";
    2812             :         time_t t;
    2813           1 :         struct smbcli_request *req = NULL;
    2814           1 :         struct smbcli_request *req2 = NULL;
    2815           1 :         struct smbcli_request *req4 = NULL;
    2816             : 
    2817           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    2818             :                        "Failed to setup up test directory: " BASEDIR);
    2819             : 
    2820           1 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 4\n");
    2821           1 :         io.generic.level = RAW_LOCK_LOCKX;
    2822             : 
    2823             :         /* Create the test file. */
    2824           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2825           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    2826             :                        "Failed to create %s - %s\n",
    2827             :                        fname, smbcli_errstr(cli->tree)));
    2828             : 
    2829             :         /*
    2830             :          * a)
    2831             :          * Lock regions 100->109, 120->129 as
    2832             :          * two separate write locks in one request.
    2833             :          */
    2834           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    2835           1 :         io.lockx.in.file.fnum = fnum;
    2836           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2837           1 :         io.lockx.in.timeout = 0;
    2838           1 :         io.lockx.in.ulock_cnt = 0;
    2839           1 :         io.lockx.in.lock_cnt = 2;
    2840           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2841           1 :         lock[0].pid = cli->session->pid;
    2842           1 :         lock[0].offset = 100;
    2843           1 :         lock[0].count = 10;
    2844           1 :         lock[1].pid = cli->session->pid;
    2845           1 :         lock[1].offset = 120;
    2846           1 :         lock[1].count = 10;
    2847           1 :         io.lockx.in.locks = &lock[0];
    2848           1 :         status = smb_raw_lock(cli->tree, &io);
    2849           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2850             : 
    2851             :         /*
    2852             :          * b)
    2853             :          * Now request the same locks on a different
    2854             :          * context as blocking locks. But readonly.
    2855             :          */
    2856           1 :         io.lockx.in.timeout = 20000;
    2857           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    2858           1 :         lock[0].pid = cli->session->pid+1;
    2859           1 :         lock[1].pid = cli->session->pid+1;
    2860           1 :         req = smb_raw_lock_send(cli->tree, &io);
    2861           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    2862             :                        "Failed to setup timed locks (%s)\n", __location__));
    2863             : 
    2864             :         /*
    2865             :          * c)
    2866             :          * Request the first lock again on a separate context.
    2867             :          * Wait forever. The previous multi-lock request (b)
    2868             :          * should take precedence. Also readonly.
    2869             :          */
    2870           1 :         io.lockx.in.timeout = UINT32_MAX;
    2871           1 :         lock[0].pid = cli->session->pid+2;
    2872           1 :         io.lockx.in.lock_cnt = 1;
    2873           1 :         req2 = smb_raw_lock_send(cli->tree, &io);
    2874           1 :         torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
    2875             :                        "Failed to setup timed locks (%s)\n", __location__));
    2876             : 
    2877             :         /*
    2878             :          * d)
    2879             :          * Lock regions 110->119
    2880             :          */
    2881           1 :         io3.lockx.level = RAW_LOCK_LOCKX;
    2882           1 :         io3.lockx.in.file.fnum = fnum;
    2883           1 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2884           1 :         io3.lockx.in.timeout = 0;
    2885           1 :         io3.lockx.in.ulock_cnt = 0;
    2886           1 :         io3.lockx.in.lock_cnt = 1;
    2887           1 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2888           1 :         lock3[0].pid = cli->session->pid+3;
    2889           1 :         lock3[0].offset = 110;
    2890           1 :         lock3[0].count = 10;
    2891           1 :         io3.lockx.in.locks = &lock3[0];
    2892           1 :         status = smb_raw_lock(cli->tree, &io3);
    2893           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2894             : 
    2895             :         /*
    2896             :          * e)
    2897             :          * try 110-119 again
    2898             :          */
    2899           1 :         io3.lockx.in.timeout = 20000;
    2900           1 :         lock3[0].pid = cli->session->pid+4;
    2901           1 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    2902           1 :         torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx,
    2903             :                        "Failed to setup timed locks (%s)\n", __location__));
    2904             : 
    2905             :         /*
    2906             :          * f)
    2907             :          * Unlock (a) lock[0] 100-109
    2908             :          */
    2909           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2910           1 :         io.lockx.in.timeout = 0;
    2911           1 :         io.lockx.in.ulock_cnt = 1;
    2912           1 :         io.lockx.in.lock_cnt = 0;
    2913           1 :         io.lockx.in.locks = &lock[0];
    2914           1 :         lock[0].pid = cli->session->pid;
    2915           1 :         status = smb_raw_lock(cli->tree, &io);
    2916           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2917             : 
    2918             :         /*
    2919             :          * g)
    2920             :          * receive the successful blocked lock request (c)
    2921             :          * on 110-119 while (b) 100-109/120-129 is still waiting.
    2922             :          */
    2923           1 :         status = smbcli_request_simple_recv(req2);
    2924           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2925             : 
    2926             :         /*
    2927             :          * h)
    2928             :          * try to lock lock[0] 100-109 again
    2929             :          * (read/write)
    2930             :          */
    2931           1 :         lock[0].pid = cli->session->pid+5;
    2932           1 :         io.lockx.in.ulock_cnt = 0;
    2933           1 :         io.lockx.in.lock_cnt = 1;
    2934           1 :         status = smb_raw_lock(cli->tree, &io);
    2935           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    2936             : 
    2937             :         /*
    2938             :          * i)
    2939             :          * try to lock lock[0] 100-109 again with the pid (b)
    2940             :          * that's still waiting.
    2941             :          */
    2942           1 :         lock[0].pid = cli->session->pid+1;
    2943           1 :         io.lockx.in.ulock_cnt = 0;
    2944           1 :         io.lockx.in.lock_cnt = 1;
    2945           1 :         status = smb_raw_lock(cli->tree, &io);
    2946           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2947             : 
    2948           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2949             :                        "req should still wait");
    2950           1 :         torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV,
    2951             :                        "req4 should still wait");
    2952             : 
    2953             :         /*
    2954             :          * j)
    2955             :          * Unlock (d) lock[0] 110-119
    2956             :          */
    2957           1 :         io3.lockx.in.timeout = 0;
    2958           1 :         io3.lockx.in.ulock_cnt = 1;
    2959           1 :         io3.lockx.in.lock_cnt = 0;
    2960           1 :         lock3[0].pid = cli->session->pid+3;
    2961           1 :         status = smb_raw_lock(cli->tree, &io3);
    2962           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2963             : 
    2964             :         /*
    2965             :          * k)
    2966             :          * receive the successful blocked
    2967             :          * lock request (e) on 110-119.
    2968             :          */
    2969           1 :         status = smbcli_request_simple_recv(req4);
    2970           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    2971             : 
    2972             :         /*
    2973             :          * l)
    2974             :          * try to lock lock[0] 100-109 again
    2975             :          */
    2976           1 :         lock[0].pid = cli->session->pid+6;
    2977           1 :         io.lockx.in.ulock_cnt = 0;
    2978           1 :         io.lockx.in.lock_cnt = 1;
    2979           1 :         status = smb_raw_lock(cli->tree, &io);
    2980           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2981             : 
    2982             :         /*
    2983             :          * m)
    2984             :          * try to lock lock[0] 100-109 again with the pid (b)
    2985             :          * that's still waiting
    2986             :          */
    2987           1 :         lock[0].pid = cli->session->pid+1;
    2988           1 :         io.lockx.in.ulock_cnt = 0;
    2989           1 :         io.lockx.in.lock_cnt = 1;
    2990           1 :         status = smb_raw_lock(cli->tree, &io);
    2991           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2992             : 
    2993           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2994             :                        "req should still wait");
    2995             : 
    2996             :         /* Start the clock. */
    2997           1 :         t = time_mono(NULL);
    2998             : 
    2999             :         /*
    3000             :          * n)
    3001             :          * Unlock (a) lock[1] 120-129
    3002             :          */
    3003           1 :         io.lockx.in.timeout = 0;
    3004           1 :         io.lockx.in.ulock_cnt = 1;
    3005           1 :         io.lockx.in.lock_cnt = 0;
    3006           1 :         io.lockx.in.locks = &lock[1];
    3007           1 :         lock[1].pid = cli->session->pid;
    3008           1 :         status = smb_raw_lock(cli->tree, &io);
    3009           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3010             : 
    3011             :         /*
    3012             :          * o)
    3013             :          * receive the successful blocked lock request (b)
    3014             :          */
    3015           1 :         status = smbcli_request_simple_recv(req);
    3016           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3017             : 
    3018             :         /* Fail if this took more than 2 seconds. */
    3019           1 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    3020             :                        "Blocking locks were not granted immediately (%s)\n",
    3021             :                        __location__));
    3022           1 : done:
    3023           1 :         smb_raw_exit(cli->session);
    3024           1 :         smbcli_deltree(cli->tree, BASEDIR);
    3025           1 :         return ret;
    3026             : }
    3027             : 
    3028             : /*
    3029             :   test multi5 Locking&X operation
    3030             :   This test is designed to show that
    3031             :   lock precedence on the server is based
    3032             :   on the order received, not on the ability
    3033             :   to grant.
    3034             : 
    3035             :   Compared to test_multilock3() (above)
    3036             :   this test demonstrates that the initial
    3037             :   lock request that block the following
    3038             :   exclusive locks can be a shared lock.
    3039             : 
    3040             :   For example:
    3041             : 
    3042             :   All locks except (a) are LOCKING_ANDX_EXCLUSIVE_LOCK (rw).
    3043             : 
    3044             :   (a) lock(ro) 100->109, 120->129 (granted)
    3045             :   (b) lock 100->109, 120->129 (blocks, timeout=20s)
    3046             :   (c) lock 100->109           (blocks, timeout=2s)
    3047             :   (d) lock 110->119           (granted)
    3048             :   (e) lock 110->119           (blocks, timeout=20s)
    3049             :   (f) unlock 100->109 (a)
    3050             :   (g) lock 100->109           (not granted, blocked by (b))
    3051             :   (h) lock 100->109           (not granted, blocked by itself (b))
    3052             :   (i) lock (c) will not be granted(conflict, times out)
    3053             :       as lock (b) will take precedence.
    3054             :   (j) unlock 110-119 (d)
    3055             :   (k) lock (e) completes and is not blocked by (a) nor (b)
    3056             :   (l) lock 100->109           (not granted(conflict), blocked by (b))
    3057             :   (m) lock 100->109           (not granted(conflict), blocked by itself (b))
    3058             :   (n) unlock 120-129 (a)
    3059             :   (o) lock (b) completes
    3060             : */
    3061           1 : static bool test_multilock5(struct torture_context *tctx,
    3062             :                             struct smbcli_state *cli)
    3063             : {
    3064             :         union smb_lock io;
    3065             :         struct smb_lock_entry lock[2];
    3066             :         union smb_lock io3;
    3067             :         struct smb_lock_entry lock3[1];
    3068             :         NTSTATUS status;
    3069           1 :         bool ret = true;
    3070             :         int fnum;
    3071           1 :         const char *fname = BASEDIR "\\multilock5_test.txt";
    3072             :         time_t t;
    3073           1 :         struct smbcli_request *req = NULL;
    3074           1 :         struct smbcli_request *req2 = NULL;
    3075           1 :         struct smbcli_request *req4 = NULL;
    3076             : 
    3077           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    3078             :                        "Failed to setup up test directory: " BASEDIR);
    3079             : 
    3080           1 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 5\n");
    3081           1 :         io.generic.level = RAW_LOCK_LOCKX;
    3082             : 
    3083             :         /* Create the test file. */
    3084           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    3085           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    3086             :                        "Failed to create %s - %s\n",
    3087             :                        fname, smbcli_errstr(cli->tree)));
    3088             : 
    3089             :         /*
    3090             :          * a)
    3091             :          * Lock regions 100->109, 120->129 as
    3092             :          * two separate write locks in one request.
    3093             :          * (read only)
    3094             :          */
    3095           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    3096           1 :         io.lockx.in.file.fnum = fnum;
    3097           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3098           1 :         io.lockx.in.timeout = 0;
    3099           1 :         io.lockx.in.ulock_cnt = 0;
    3100           1 :         io.lockx.in.lock_cnt = 2;
    3101           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    3102           1 :         lock[0].pid = cli->session->pid;
    3103           1 :         lock[0].offset = 100;
    3104           1 :         lock[0].count = 10;
    3105           1 :         lock[1].pid = cli->session->pid;
    3106           1 :         lock[1].offset = 120;
    3107           1 :         lock[1].count = 10;
    3108           1 :         io.lockx.in.locks = &lock[0];
    3109           1 :         status = smb_raw_lock(cli->tree, &io);
    3110           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3111             : 
    3112             :         /*
    3113             :          * b)
    3114             :          * Now request the same locks on a different
    3115             :          * context as blocking locks.
    3116             :          * (read write)
    3117             :          */
    3118           1 :         io.lockx.in.timeout = 20000;
    3119           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3120           1 :         lock[0].pid = cli->session->pid+1;
    3121           1 :         lock[1].pid = cli->session->pid+1;
    3122           1 :         req = smb_raw_lock_send(cli->tree, &io);
    3123           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    3124             :                        "Failed to setup timed locks (%s)\n", __location__));
    3125             : 
    3126             :         /*
    3127             :          * c)
    3128             :          * Request the first lock again on a separate context.
    3129             :          * Wait 2 seconds. This should time out (the previous
    3130             :          * multi-lock request should take precedence).
    3131             :          * (read write)
    3132             :          */
    3133           1 :         io.lockx.in.timeout = 2000;
    3134           1 :         lock[0].pid = cli->session->pid+2;
    3135           1 :         io.lockx.in.lock_cnt = 1;
    3136           1 :         req2 = smb_raw_lock_send(cli->tree, &io);
    3137           1 :         torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
    3138             :                        "Failed to setup timed locks (%s)\n", __location__));
    3139             : 
    3140             :         /*
    3141             :          * d)
    3142             :          * Lock regions 110->119
    3143             :          */
    3144           1 :         io3.lockx.level = RAW_LOCK_LOCKX;
    3145           1 :         io3.lockx.in.file.fnum = fnum;
    3146           1 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3147           1 :         io3.lockx.in.timeout = 0;
    3148           1 :         io3.lockx.in.ulock_cnt = 0;
    3149           1 :         io3.lockx.in.lock_cnt = 1;
    3150           1 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3151           1 :         lock3[0].pid = cli->session->pid+3;
    3152           1 :         lock3[0].offset = 110;
    3153           1 :         lock3[0].count = 10;
    3154           1 :         io3.lockx.in.locks = &lock3[0];
    3155           1 :         status = smb_raw_lock(cli->tree, &io3);
    3156           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3157             : 
    3158             :         /*
    3159             :          * e)
    3160             :          * try 110-119 again
    3161             :          */
    3162           1 :         io3.lockx.in.timeout = 20000;
    3163           1 :         lock3[0].pid = cli->session->pid+4;
    3164           1 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    3165           1 :         torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx,
    3166             :                        "Failed to setup timed locks (%s)\n", __location__));
    3167             : 
    3168             :         /*
    3169             :          * f)
    3170             :          * Unlock (a) lock[0] 100-109
    3171             :          *
    3172             :          * Note we send LOCKING_ANDX_EXCLUSIVE_LOCK
    3173             :          * while the lock used LOCKING_ANDX_SHARED_LOCK
    3174             :          * to check if that also works.
    3175             :          */
    3176           1 :         io.lockx.in.timeout = 0;
    3177           1 :         io.lockx.in.ulock_cnt = 1;
    3178           1 :         io.lockx.in.lock_cnt = 0;
    3179           1 :         io.lockx.in.locks = &lock[0];
    3180           1 :         lock[0].pid = cli->session->pid;
    3181           1 :         status = smb_raw_lock(cli->tree, &io);
    3182           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3183             : 
    3184             :         /*
    3185             :          * g)
    3186             :          * try to lock lock[0] 100-109 again
    3187             :          */
    3188           1 :         lock[0].pid = cli->session->pid+5;
    3189           1 :         io.lockx.in.ulock_cnt = 0;
    3190           1 :         io.lockx.in.lock_cnt = 1;
    3191           1 :         status = smb_raw_lock(cli->tree, &io);
    3192           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3193             : 
    3194             :         /*
    3195             :          * h)
    3196             :          * try to lock lock[0] 100-109 again with the pid (b)
    3197             :          * that's still waiting.
    3198             :          * (read write)
    3199             :          */
    3200           1 :         lock[0].pid = cli->session->pid+1;
    3201           1 :         io.lockx.in.ulock_cnt = 0;
    3202           1 :         io.lockx.in.lock_cnt = 1;
    3203           1 :         status = smb_raw_lock(cli->tree, &io);
    3204           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3205             : 
    3206           1 :         torture_assert(tctx, req2->state <= SMBCLI_REQUEST_RECV,
    3207             :                        "req2 should still wait");
    3208             : 
    3209             :         /*
    3210             :          * i)
    3211             :          * Did the second lock complete (should time out) ?
    3212             :          */
    3213           1 :         status = smbcli_request_simple_recv(req2);
    3214           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3215             : 
    3216           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3217             :                        "req should still wait");
    3218           1 :         torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV,
    3219             :                        "req4 should still wait");
    3220             : 
    3221             :         /*
    3222             :          * j)
    3223             :          * Unlock (d) lock[0] 110-119
    3224             :          */
    3225           1 :         io3.lockx.in.timeout = 0;
    3226           1 :         io3.lockx.in.ulock_cnt = 1;
    3227           1 :         io3.lockx.in.lock_cnt = 0;
    3228           1 :         lock3[0].pid = cli->session->pid+3;
    3229           1 :         status = smb_raw_lock(cli->tree, &io3);
    3230           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3231             : 
    3232             :         /*
    3233             :          * k)
    3234             :          * receive the successful blocked lock requests
    3235             :          * on 110-119 while the 100-109/120-129 is still waiting.
    3236             :          */
    3237           1 :         status = smbcli_request_simple_recv(req4);
    3238           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3239             : 
    3240             :         /*
    3241             :          * l)
    3242             :          * try to lock lock[0] 100-109 again
    3243             :          */
    3244           1 :         lock[0].pid = cli->session->pid+6;
    3245           1 :         io.lockx.in.ulock_cnt = 0;
    3246           1 :         io.lockx.in.lock_cnt = 1;
    3247           1 :         status = smb_raw_lock(cli->tree, &io);
    3248           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3249             : 
    3250             :         /*
    3251             :          * m)
    3252             :          * try to lock lock[0] 100-109 again with the pid (b)
    3253             :          * that's still waiting
    3254             :          */
    3255           1 :         lock[0].pid = cli->session->pid+1;
    3256           1 :         io.lockx.in.ulock_cnt = 0;
    3257           1 :         io.lockx.in.lock_cnt = 1;
    3258           1 :         status = smb_raw_lock(cli->tree, &io);
    3259           1 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3260             : 
    3261           1 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3262             :                        "req should still wait");
    3263             : 
    3264             :         /* Start the clock. */
    3265           1 :         t = time_mono(NULL);
    3266             : 
    3267             :         /*
    3268             :          * n)
    3269             :          * Unlock (a) lock[1] 120-129
    3270             :          */
    3271           1 :         io.lockx.in.timeout = 0;
    3272           1 :         io.lockx.in.ulock_cnt = 1;
    3273           1 :         io.lockx.in.lock_cnt = 0;
    3274           1 :         io.lockx.in.locks = &lock[1];
    3275           1 :         lock[1].pid = cli->session->pid;
    3276           1 :         status = smb_raw_lock(cli->tree, &io);
    3277           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3278             : 
    3279             :         /*
    3280             :          * o)
    3281             :          * receive the successful blocked lock request (b)
    3282             :          */
    3283           1 :         status = smbcli_request_simple_recv(req);
    3284           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3285             : 
    3286             :         /* Fail if this took more than 2 seconds. */
    3287           1 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    3288             :                        "Blocking locks were not granted immediately (%s)\n",
    3289             :                        __location__));
    3290           1 : done:
    3291           1 :         smb_raw_exit(cli->session);
    3292           1 :         smbcli_deltree(cli->tree, BASEDIR);
    3293           1 :         return ret;
    3294             : }
    3295             : 
    3296             : /*
    3297             :   test multi6 Locking&X operation
    3298             :   This test is designed to show that
    3299             :   lock precedence on the server is based
    3300             :   on the order received, not on the ability
    3301             :   to grant.
    3302             : 
    3303             :   Compared to test_multilock4() (above)
    3304             :   this test demonstrates the behavior if
    3305             :   only just the first blocking lock
    3306             :   being a shared lock.
    3307             : 
    3308             :   For example:
    3309             : 
    3310             :   All locks except (b) are LOCKING_ANDX_EXCLUSIVE_LOCK (rw).
    3311             : 
    3312             :   (a) lock 100->109, 120->129 (granted)
    3313             :   (b) lock(ro) 100->109, 120->129 (blocks, timeout=20s)
    3314             :   (c) lock 100->109           (blocks, timeout=2s)
    3315             :   (d) lock 110->119           (granted)
    3316             :   (e) lock 110->119           (blocks, timeout=20s)
    3317             :   (f) unlock 100->109 (a)
    3318             :   (g) lock 100->109           (not granted, blocked by (b))
    3319             :   (h) lock 100->109           (not granted, blocked by itself (b))
    3320             :   (i) lock (c) will not be granted(conflict, times out)
    3321             :       as lock (b) will take precedence.
    3322             :   (j) unlock 110-119 (d)
    3323             :   (k) lock (e) completes and is not blocked by (a) nor (b)
    3324             :   (l) lock 100->109           (not granted(conflict), blocked by (b))
    3325             :   (m) lock 100->109           (not granted(conflict), blocked by itself (b))
    3326             :   (n) unlock 120-129 (a)
    3327             :   (o) lock (b) completes
    3328             : */
    3329           1 : static bool test_multilock6(struct torture_context *tctx,
    3330             :                             struct smbcli_state *cli)
    3331             : {
    3332             :         union smb_lock io;
    3333             :         struct smb_lock_entry lock[2];
    3334             :         union smb_lock io3;
    3335             :         struct smb_lock_entry lock3[1];
    3336             :         NTSTATUS status;
    3337           1 :         bool ret = true;
    3338             :         int fnum;
    3339           1 :         const char *fname = BASEDIR "\\multilock6_test.txt";
    3340             :         time_t t;
    3341           1 :         struct smbcli_request *req = NULL;
    3342           1 :         struct smbcli_request *req2 = NULL;
    3343           1 :         struct smbcli_request *req4 = NULL;
    3344             : 
    3345           1 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    3346             :                        "Failed to setup up test directory: " BASEDIR);
    3347             : 
    3348           1 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 6\n");
    3349           1 :         io.generic.level = RAW_LOCK_LOCKX;
    3350             : 
    3351             :         /* Create the test file. */
    3352           1 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    3353           1 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    3354             :                        "Failed to create %s - %s\n",
    3355             :                        fname, smbcli_errstr(cli->tree)));
    3356             : 
    3357             :         /*
    3358             :          * a)
    3359             :          * Lock regions 100->109, 120->129 as
    3360             :          * two separate write locks in one request.
    3361             :          */
    3362           1 :         io.lockx.level = RAW_LOCK_LOCKX;
    3363           1 :         io.lockx.in.file.fnum = fnum;
    3364           1 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3365           1 :         io.lockx.in.timeout = 0;
    3366           1 :         io.lockx.in.ulock_cnt = 0;
    3367           1 :         io.lockx.in.lock_cnt = 2;
    3368           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3369           1 :         lock[0].pid = cli->session->pid;
    3370           1 :         lock[0].offset = 100;
    3371           1 :         lock[0].count = 10;
    3372           1 :         lock[1].pid = cli->session->pid;
    3373           1 :         lock[1].offset = 120;
    3374           1 :         lock[1].count = 10;
    3375           1 :         io.lockx.in.locks = &lock[0];
    3376           1 :         status = smb_raw_lock(cli->tree, &io);
    3377           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3378             : 
    3379             :         /*
    3380             :          * b)
    3381             :          * Now request the same locks on a different
    3382             :          * context as blocking locks.
    3383             :          * (read only)
    3384             :          */
    3385           1 :         io.lockx.in.timeout = 20000;
    3386           1 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    3387           1 :         lock[0].pid = cli->session->pid+1;
    3388           1 :         lock[1].pid = cli->session->pid+1;
    3389           1 :         req = smb_raw_lock_send(cli->tree, &io);
    3390           1 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    3391             :                        "Failed to setup timed locks (%s)\n", __location__));
    3392             : 
    3393             :         /*
    3394             :          * c)
    3395             :          * Request the first lock again on a separate context.
    3396             :          * Wait 2 seconds. This should time out (the previous
    3397             :          * multi-lock request should take precedence).
    3398             :          */
    3399           1 :         io.lockx.in.timeout = 2000;
    3400           1 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3401           1 :         lock[0].pid = cli->session->pid+2;
    3402           1 :         io.lockx.in.lock_cnt = 1;
    3403           1 :         req2 = smb_raw_lock_send(cli->tree, &io);
    3404           1 :         torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
    3405             :                        "Failed to setup timed locks (%s)\n", __location__));
    3406             : 
    3407             :         /*
    3408             :          * d)
    3409             :          * Lock regions 110->119
    3410             :          */
    3411           1 :         io3.lockx.level = RAW_LOCK_LOCKX;
    3412           1 :         io3.lockx.in.file.fnum = fnum;
    3413           1 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3414           1 :         io3.lockx.in.timeout = 0;
    3415           1 :         io3.lockx.in.ulock_cnt = 0;
    3416           1 :         io3.lockx.in.lock_cnt = 1;
    3417           1 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3418           1 :         lock3[0].pid = cli->session->pid+3;
    3419           1 :         lock3[0].offset = 110;
    3420           1 :         lock3[0].count = 10;
    3421           1 :         io3.lockx.in.locks = &lock3[0];
    3422           1 :         status = smb_raw_lock(cli->tree, &io3);
    3423           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3424             : 
    3425             :         /*
    3426             :          * e)
    3427             :          * try 110-119 again
    3428             :          */
    3429           1 :         io3.lockx.in.timeout = 20000;
    3430           1 :         lock3[0].pid = cli->session->pid+4;
    3431           1 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    3432           1 :         torture_assert(tctx,(req4 != NULL), talloc_asprintf(tctx,
    3433             :                        "Failed to setup timed locks (%s)\n", __location__));
    3434             : 
    3435             :         /*
    3436             :          * f)
    3437             :          * Unlock (a) lock[0] 100-109
    3438             :          */
    3439           1 :         io.lockx.in.timeout = 0;
    3440           1 :         io.lockx.in.ulock_cnt = 1;
    3441           1 :         io.lockx.in.lock_cnt = 0;
    3442           1 :         io.lockx.in.locks = &lock[0];
    3443           1 :         lock[0].pid = cli->session->pid;
    3444           1 :         status = smb_raw_lock(cli->tree, &io);
    3445           1 :         CHECK_STATUS(status, NT_STATUS_OK);
    3446             : 
    3447             :         /*
    3448             :          * g)
    3449             :          * try to lock lock[0] 100-109 again
    3450             :          */
    3451           1 :         lock[0].pid = cli->session->pid+5;
    3452           1 :         io.lockx.in.ulock_cnt = 0;
    3453           1 :         io.lockx.in.lock_cnt = 1;
    3454           1 :         status = smb_raw_lock(cli->tree, &io);
    3455           1 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    3456             : 
    3457             :         /*
    3458             :          * h)
    3459             :          * try to lock lock[0] 100-109 again with the pid (b)
    3460             :          * that's still waiting
    3461             :          */
    3462           0 :         lock[0].pid = cli->session->pid+1;
    3463           0 :         io.lockx.in.ulock_cnt = 0;
    3464           0 :         io.lockx.in.lock_cnt = 1;
    3465           0 :         status = smb_raw_lock(cli->tree, &io);
    3466           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3467             : 
    3468           0 :         torture_assert(tctx, req2->state <= SMBCLI_REQUEST_RECV,
    3469             :                        "req2 should still wait");
    3470             : 
    3471             :         /*
    3472             :          * i)
    3473             :          * Did the second lock (c) complete (should time out) ?
    3474             :          */
    3475           0 :         status = smbcli_request_simple_recv(req2);
    3476           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3477             : 
    3478           0 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3479             :                        "req should still wait");
    3480           0 :         torture_assert(tctx, req4->state <= SMBCLI_REQUEST_RECV,
    3481             :                        "req4 should still wait");
    3482             : 
    3483             :         /*
    3484             :          * j)
    3485             :          * Unlock (d) lock[0] 110-119
    3486             :          */
    3487           0 :         io3.lockx.in.timeout = 0;
    3488           0 :         io3.lockx.in.ulock_cnt = 1;
    3489           0 :         io3.lockx.in.lock_cnt = 0;
    3490           0 :         lock3[0].pid = cli->session->pid+3;
    3491           0 :         status = smb_raw_lock(cli->tree, &io3);
    3492           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3493             : 
    3494             :         /*
    3495             :          * k)
    3496             :          * receive the successful blocked lock request (e)
    3497             :          * on 110-119 while (b) 100-109/120-129 is still waiting.
    3498             :          */
    3499           0 :         status = smbcli_request_simple_recv(req4);
    3500           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3501             : 
    3502             :         /*
    3503             :          * l)
    3504             :          * try to lock lock[0] 100-109 again
    3505             :          */
    3506           0 :         lock[0].pid = cli->session->pid+6;
    3507           0 :         io.lockx.in.ulock_cnt = 0;
    3508           0 :         io.lockx.in.lock_cnt = 1;
    3509           0 :         status = smb_raw_lock(cli->tree, &io);
    3510           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3511             : 
    3512             :         /*
    3513             :          * m)
    3514             :          * try to lock lock[0] 100-109 again with the pid (b)
    3515             :          * that's still waiting
    3516             :          */
    3517           0 :         lock[0].pid = cli->session->pid+1;
    3518           0 :         io.lockx.in.ulock_cnt = 0;
    3519           0 :         io.lockx.in.lock_cnt = 1;
    3520           0 :         status = smb_raw_lock(cli->tree, &io);
    3521           0 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3522             : 
    3523           0 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3524             :                        "req should still wait");
    3525             : 
    3526             :         /* Start the clock. */
    3527           0 :         t = time_mono(NULL);
    3528             : 
    3529             :         /*
    3530             :          * n)
    3531             :          * Unlock (a) lock[1] 120-129
    3532             :          */
    3533           0 :         io.lockx.in.timeout = 0;
    3534           0 :         io.lockx.in.ulock_cnt = 1;
    3535           0 :         io.lockx.in.lock_cnt = 0;
    3536           0 :         io.lockx.in.locks = &lock[1];
    3537           0 :         lock[1].pid = cli->session->pid;
    3538           0 :         status = smb_raw_lock(cli->tree, &io);
    3539           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3540             : 
    3541             :         /*
    3542             :          * o)
    3543             :          * receive the successful blocked lock request (b)
    3544             :          */
    3545           0 :         status = smbcli_request_simple_recv(req);
    3546           0 :         CHECK_STATUS(status, NT_STATUS_OK);
    3547             : 
    3548             :         /* Fail if this took more than 2 seconds. */
    3549           0 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    3550             :                        "Blocking locks were not granted immediately (%s)\n",
    3551             :                        __location__));
    3552           0 : done:
    3553           1 :         smb_raw_exit(cli->session);
    3554           1 :         smbcli_deltree(cli->tree, BASEDIR);
    3555           1 :         return ret;
    3556             : }
    3557             : 
    3558             : /*
    3559             :    basic testing of lock calls
    3560             : */
    3561         964 : struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
    3562             : {
    3563         964 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "lock");
    3564             : 
    3565         964 :         torture_suite_add_1smb_test(suite, "lockx", test_lockx);
    3566         964 :         torture_suite_add_1smb_test(suite, "lock", test_lock);
    3567         964 :         torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
    3568         964 :         torture_suite_add_1smb_test(suite, "async", test_async);
    3569         964 :         torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
    3570         964 :         torture_suite_add_1smb_test(suite, "changetype", test_changetype);
    3571             : 
    3572         964 :         torture_suite_add_1smb_test(suite, "stacking", test_stacking);
    3573         964 :         torture_suite_add_1smb_test(suite, "unlock", test_unlock);
    3574         964 :         torture_suite_add_1smb_test(suite, "multiple_unlock",
    3575             :             test_multiple_unlock);
    3576         964 :         torture_suite_add_1smb_test(suite, "zerobytelocks", test_zerobytelocks);
    3577         964 :         torture_suite_add_1smb_test(suite, "zerobyteread", test_zerobyteread);
    3578         964 :         torture_suite_add_1smb_test(suite, "multilock", test_multilock);
    3579         964 :         torture_suite_add_1smb_test(suite, "multilock2", test_multilock2);
    3580         964 :         torture_suite_add_1smb_test(suite, "multilock3", test_multilock3);
    3581         964 :         torture_suite_add_1smb_test(suite, "multilock4", test_multilock4);
    3582         964 :         torture_suite_add_1smb_test(suite, "multilock5", test_multilock5);
    3583         964 :         torture_suite_add_1smb_test(suite, "multilock6", test_multilock6);
    3584             : 
    3585         964 :         return suite;
    3586             : }

Generated by: LCOV version 1.13