LCOV - code coverage report
Current view: top level - source4/torture/raw - lock.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 1963 2098 93.6 %
Date: 2024-02-28 12:06:22 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           3 : static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
      96             : {
      97           0 :         union smb_lock io;
      98           0 :         NTSTATUS status;
      99           3 :         bool ret = true;
     100           0 :         int fnum;
     101           3 :         const char *fname = BASEDIR "\\test.txt";
     102             : 
     103           3 :         if (!TARGET_SUPPORTS_SMBLOCK(tctx))
     104           0 :                 torture_skip(tctx, "Target does not support the SMBlock PDU");
     105             : 
     106           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     107             : 
     108           3 :         torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
     109           3 :         io.generic.level = RAW_LOCK_LOCK;
     110             :         
     111           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     112           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     113             :                        "Failed to create %s - %s\n",
     114             :                        fname, smbcli_errstr(cli->tree)));
     115             : 
     116           3 :         torture_comment(tctx, "Trying 0/0 lock\n");
     117           3 :         io.lock.level = RAW_LOCK_LOCK;
     118           3 :         io.lock.in.file.fnum = fnum;
     119           3 :         io.lock.in.count = 0;
     120           3 :         io.lock.in.offset = 0;
     121           3 :         status = smb_raw_lock(cli->tree, &io);
     122           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     123           3 :         cli->session->pid++;
     124           3 :         status = smb_raw_lock(cli->tree, &io);
     125           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     126           3 :         cli->session->pid--;
     127           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     128           3 :         status = smb_raw_lock(cli->tree, &io);
     129           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     130             : 
     131           3 :         torture_comment(tctx, "Trying 0/1 lock\n");
     132           3 :         io.lock.level = RAW_LOCK_LOCK;
     133           3 :         io.lock.in.file.fnum = fnum;
     134           3 :         io.lock.in.count = 1;
     135           3 :         io.lock.in.offset = 0;
     136           3 :         status = smb_raw_lock(cli->tree, &io);
     137           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     138           3 :         cli->session->pid++;
     139           3 :         status = smb_raw_lock(cli->tree, &io);
     140           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     141           3 :         cli->session->pid--;
     142           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     143           3 :         status = smb_raw_lock(cli->tree, &io);
     144           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     145           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     146           3 :         status = smb_raw_lock(cli->tree, &io);
     147           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     148             : 
     149           3 :         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
     150           3 :         io.lock.level = RAW_LOCK_LOCK;
     151           3 :         io.lock.in.file.fnum = fnum;
     152           3 :         io.lock.in.count = 4000;
     153           3 :         io.lock.in.offset = 0xEEFFFFFF;
     154           3 :         status = smb_raw_lock(cli->tree, &io);
     155           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     156           3 :         cli->session->pid++;
     157           3 :         status = smb_raw_lock(cli->tree, &io);
     158           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     159           3 :         cli->session->pid--;
     160           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     161           3 :         status = smb_raw_lock(cli->tree, &io);
     162           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     163           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     164           3 :         status = smb_raw_lock(cli->tree, &io);
     165           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     166             : 
     167           3 :         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
     168           3 :         io.lock.level = RAW_LOCK_LOCK;
     169           3 :         io.lock.in.file.fnum = fnum;
     170           3 :         io.lock.in.count = 4000;
     171           3 :         io.lock.in.offset = 0xEEFFFFFF;
     172           3 :         status = smb_raw_lock(cli->tree, &io);
     173           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     174           3 :         cli->session->pid++;
     175           3 :         status = smb_raw_lock(cli->tree, &io);
     176           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     177           3 :         cli->session->pid--;
     178           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     179           3 :         status = smb_raw_lock(cli->tree, &io);
     180           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     181           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     182           3 :         status = smb_raw_lock(cli->tree, &io);
     183           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     184             : 
     185           3 :         torture_comment(tctx, "Trying max lock\n");
     186           3 :         io.lock.level = RAW_LOCK_LOCK;
     187           3 :         io.lock.in.file.fnum = fnum;
     188           3 :         io.lock.in.count = 4000;
     189           3 :         io.lock.in.offset = 0xEF000000;
     190           3 :         status = smb_raw_lock(cli->tree, &io);
     191           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     192           3 :         cli->session->pid++;
     193           3 :         status = smb_raw_lock(cli->tree, &io);
     194           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     195           3 :         cli->session->pid--;
     196           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     197           3 :         status = smb_raw_lock(cli->tree, &io);
     198           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     199           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     200           3 :         status = smb_raw_lock(cli->tree, &io);
     201           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     202             : 
     203           3 :         torture_comment(tctx, "Trying wrong pid unlock\n");
     204           3 :         io.lock.level = RAW_LOCK_LOCK;
     205           3 :         io.lock.in.file.fnum = fnum;
     206           3 :         io.lock.in.count = 4002;
     207           3 :         io.lock.in.offset = 10001;
     208           3 :         status = smb_raw_lock(cli->tree, &io);
     209           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     210           3 :         cli->session->pid++;
     211           3 :         io.lock.level = RAW_LOCK_UNLOCK;
     212           3 :         status = smb_raw_lock(cli->tree, &io);
     213           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     214           3 :         cli->session->pid--;
     215           3 :         status = smb_raw_lock(cli->tree, &io);
     216           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     217             : 
     218           3 : done:
     219           3 :         smbcli_close(cli->tree, fnum);
     220           3 :         smb_raw_exit(cli->session);
     221           3 :         smbcli_deltree(cli->tree, BASEDIR);
     222           3 :         return ret;
     223             : }
     224             : 
     225             : 
     226             : /*
     227             :   test locking&X ops
     228             : */
     229           3 : static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
     230             : {
     231           0 :         union smb_lock io;
     232           0 :         struct smb_lock_entry lock[1];
     233           0 :         NTSTATUS status;
     234           3 :         bool ret = true;
     235           0 :         int fnum;
     236           3 :         const char *fname = BASEDIR "\\test.txt";
     237             : 
     238           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     239             : 
     240           3 :         torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
     241           3 :         io.generic.level = RAW_LOCK_LOCKX;
     242             :         
     243           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     244           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     245             :                        "Failed to create %s - %s\n",
     246             :                        fname, smbcli_errstr(cli->tree)));
     247             : 
     248           3 :         io.lockx.level = RAW_LOCK_LOCKX;
     249           3 :         io.lockx.in.file.fnum = fnum;
     250           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     251           3 :         io.lockx.in.timeout = 0;
     252           3 :         io.lockx.in.ulock_cnt = 0;
     253           3 :         io.lockx.in.lock_cnt = 1;
     254           3 :         lock[0].pid = cli->session->pid;
     255           3 :         lock[0].offset = 10;
     256           3 :         lock[0].count = 1;
     257           3 :         io.lockx.in.locks = &lock[0];
     258           3 :         status = smb_raw_lock(cli->tree, &io);
     259           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     260             : 
     261             : 
     262           3 :         torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
     263           3 :         io.lockx.in.ulock_cnt = 0;
     264           3 :         io.lockx.in.lock_cnt = 1;
     265           3 :         lock[0].count = 4000;
     266           3 :         lock[0].offset = 0xEEFFFFFF;
     267           3 :         status = smb_raw_lock(cli->tree, &io);
     268           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     269           3 :         lock[0].pid++;
     270           3 :         status = smb_raw_lock(cli->tree, &io);
     271           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     272           3 :         lock[0].pid--;
     273           3 :         io.lockx.in.ulock_cnt = 1;
     274           3 :         io.lockx.in.lock_cnt = 0;
     275           3 :         status = smb_raw_lock(cli->tree, &io);
     276           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     277           3 :         status = smb_raw_lock(cli->tree, &io);
     278           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     279             : 
     280           3 :         torture_comment(tctx, "Trying 0xEF000000 lock\n");
     281           3 :         io.lockx.in.ulock_cnt = 0;
     282           3 :         io.lockx.in.lock_cnt = 1;
     283           3 :         lock[0].count = 4000;
     284           3 :         lock[0].offset = 0xEF000000;
     285           3 :         status = smb_raw_lock(cli->tree, &io);
     286           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     287           3 :         lock[0].pid++;
     288           3 :         status = smb_raw_lock(cli->tree, &io);
     289           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     290           3 :         lock[0].pid--;
     291           3 :         io.lockx.in.ulock_cnt = 1;
     292           3 :         io.lockx.in.lock_cnt = 0;
     293           3 :         status = smb_raw_lock(cli->tree, &io);
     294           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     295           3 :         status = smb_raw_lock(cli->tree, &io);
     296           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     297             : 
     298           3 :         torture_comment(tctx, "Trying zero lock\n");
     299           3 :         io.lockx.in.ulock_cnt = 0;
     300           3 :         io.lockx.in.lock_cnt = 1;
     301           3 :         lock[0].count = 0;
     302           3 :         lock[0].offset = ~0;
     303           3 :         status = smb_raw_lock(cli->tree, &io);
     304           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     305           3 :         lock[0].pid++;
     306           3 :         status = smb_raw_lock(cli->tree, &io);
     307           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     308           3 :         lock[0].pid--;
     309           3 :         io.lockx.in.ulock_cnt = 1;
     310           3 :         io.lockx.in.lock_cnt = 0;
     311           3 :         status = smb_raw_lock(cli->tree, &io);
     312           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     313           3 :         status = smb_raw_lock(cli->tree, &io);
     314           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     315             : 
     316           3 :         torture_comment(tctx, "Trying max lock\n");
     317           3 :         io.lockx.in.ulock_cnt = 0;
     318           3 :         io.lockx.in.lock_cnt = 1;
     319           3 :         lock[0].count = 0;
     320           3 :         lock[0].offset = ~0;
     321           3 :         status = smb_raw_lock(cli->tree, &io);
     322           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     323           3 :         lock[0].pid++;
     324           3 :         status = smb_raw_lock(cli->tree, &io);
     325           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     326           3 :         lock[0].pid--;
     327           3 :         io.lockx.in.ulock_cnt = 1;
     328           3 :         io.lockx.in.lock_cnt = 0;
     329           3 :         status = smb_raw_lock(cli->tree, &io);
     330           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     331           3 :         status = smb_raw_lock(cli->tree, &io);
     332           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     333             : 
     334           3 :         torture_comment(tctx, "Trying 2^63\n");
     335           3 :         io.lockx.in.ulock_cnt = 0;
     336           3 :         io.lockx.in.lock_cnt = 1;
     337           3 :         lock[0].count = 1;
     338           3 :         lock[0].offset = 1;
     339           3 :         lock[0].offset <<= 63;
     340           3 :         status = smb_raw_lock(cli->tree, &io);
     341           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     342           3 :         lock[0].pid++;
     343           3 :         status = smb_raw_lock(cli->tree, &io);
     344           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     345           3 :         lock[0].pid--;
     346           3 :         io.lockx.in.ulock_cnt = 1;
     347           3 :         io.lockx.in.lock_cnt = 0;
     348           3 :         status = smb_raw_lock(cli->tree, &io);
     349           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     350           3 :         status = smb_raw_lock(cli->tree, &io);
     351           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     352             : 
     353           3 :         torture_comment(tctx, "Trying 2^63 - 1\n");
     354           3 :         io.lockx.in.ulock_cnt = 0;
     355           3 :         io.lockx.in.lock_cnt = 1;
     356           3 :         lock[0].count = 1;
     357           3 :         lock[0].offset = 1;
     358           3 :         lock[0].offset <<= 63;
     359           3 :         lock[0].offset--;
     360           3 :         status = smb_raw_lock(cli->tree, &io);
     361           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     362           3 :         lock[0].pid++;
     363           3 :         status = smb_raw_lock(cli->tree, &io);
     364           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     365           3 :         lock[0].pid--;
     366           3 :         io.lockx.in.ulock_cnt = 1;
     367           3 :         io.lockx.in.lock_cnt = 0;
     368           3 :         status = smb_raw_lock(cli->tree, &io);
     369           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     370           3 :         status = smb_raw_lock(cli->tree, &io);
     371           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     372             : 
     373           3 :         torture_comment(tctx, "Trying max lock 2\n");
     374           3 :         io.lockx.in.ulock_cnt = 0;
     375           3 :         io.lockx.in.lock_cnt = 1;
     376           3 :         lock[0].count = 1;
     377           3 :         lock[0].offset = ~0;
     378           3 :         status = smb_raw_lock(cli->tree, &io);
     379           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     380           3 :         lock[0].pid++;
     381           3 :         lock[0].count = 2;
     382           3 :         status = smb_raw_lock(cli->tree, &io);
     383           3 :         if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
     384           3 :                 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
     385             :         else
     386           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     387           3 :         lock[0].pid--;
     388           3 :         io.lockx.in.ulock_cnt = 1;
     389           3 :         io.lockx.in.lock_cnt = 0;
     390           3 :         lock[0].count = 1;
     391           3 :         status = smb_raw_lock(cli->tree, &io);
     392             : 
     393           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     394           3 :         status = smb_raw_lock(cli->tree, &io);
     395           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     396             : 
     397           3 : done:
     398           3 :         smbcli_close(cli->tree, fnum);
     399           3 :         smb_raw_exit(cli->session);
     400           3 :         smbcli_deltree(cli->tree, BASEDIR);
     401           3 :         return ret;
     402             : }
     403             : 
     404             : /*
     405             :   test high pid
     406             : */
     407           3 : static bool test_pidhigh(struct torture_context *tctx, 
     408             :                                                  struct smbcli_state *cli)
     409             : {
     410           0 :         union smb_lock io;
     411           0 :         struct smb_lock_entry lock[1];
     412           0 :         NTSTATUS status;
     413           3 :         bool ret = true;
     414           0 :         int fnum;
     415           3 :         const char *fname = BASEDIR "\\test.txt";
     416           3 :         uint8_t c = 1;
     417             : 
     418           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     419             : 
     420           3 :         torture_comment(tctx, "Testing high pid\n");
     421           3 :         io.generic.level = RAW_LOCK_LOCKX;
     422             : 
     423           3 :         cli->session->pid = 1;
     424             :         
     425           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     426           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     427             :                        "Failed to create %s - %s\n",
     428             :                        fname, smbcli_errstr(cli->tree)));
     429             : 
     430           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
     439           3 :         io.lockx.in.file.fnum = fnum;
     440           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     441           3 :         io.lockx.in.timeout = 0;
     442           3 :         io.lockx.in.ulock_cnt = 0;
     443           3 :         io.lockx.in.lock_cnt = 1;
     444           3 :         lock[0].pid = cli->session->pid;
     445           3 :         lock[0].offset = 0;
     446           3 :         lock[0].count = 0xFFFFFFFF;
     447           3 :         io.lockx.in.locks = &lock[0];
     448           3 :         status = smb_raw_lock(cli->tree, &io);
     449           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     450             : 
     451           3 :         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           3 :         cli->session->pid = 2;
     460             : 
     461           3 :         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           3 :         cli->session->pid = 0x10001;
     469             : 
     470           3 :         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           3 :                 torture_warning(tctx, "High pid is not used on this server (correct)\n");
     476             :         }
     477             : 
     478           3 : done:
     479           3 :         smbcli_close(cli->tree, fnum);
     480           3 :         smb_raw_exit(cli->session);
     481           3 :         smbcli_deltree(cli->tree, BASEDIR);
     482           3 :         return ret;
     483             : }
     484             : 
     485             : 
     486             : /*
     487             :   test locking&X async operation
     488             : */
     489           3 : static bool test_async(struct torture_context *tctx, 
     490             :                                            struct smbcli_state *cli)
     491             : {
     492           0 :         struct smbcli_session *session;
     493           0 :         struct smb_composite_sesssetup setup;
     494           0 :         struct smbcli_tree *tree;
     495           0 :         union smb_tcon tcon;
     496           0 :         const char *host, *share;
     497           0 :         union smb_lock io;
     498           0 :         struct smb_lock_entry lock[2];
     499           0 :         NTSTATUS status;
     500           3 :         bool ret = true;
     501           0 :         int fnum;
     502           3 :         const char *fname = BASEDIR "\\test.txt";
     503           0 :         time_t t;
     504           0 :         struct smbcli_request *req, *req2;
     505           0 :         struct smbcli_session_options options;
     506             : 
     507           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
     508             : 
     509           3 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
     510             : 
     511           3 :         torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
     512           3 :         io.generic.level = RAW_LOCK_LOCKX;
     513             : 
     514           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     515           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     516             :                        "Failed to create %s - %s\n",
     517             :                        fname, smbcli_errstr(cli->tree)));
     518             : 
     519           3 :         io.lockx.level = RAW_LOCK_LOCKX;
     520           3 :         io.lockx.in.file.fnum = fnum;
     521           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     522           3 :         io.lockx.in.timeout = 0;
     523           3 :         io.lockx.in.ulock_cnt = 0;
     524           3 :         io.lockx.in.lock_cnt = 1;
     525           3 :         lock[0].pid = cli->session->pid;
     526           3 :         lock[0].offset = 100;
     527           3 :         lock[0].count = 10;
     528           3 :         lock[1].pid = cli->session->pid;
     529           3 :         lock[1].offset = 110;
     530           3 :         lock[1].count = 10;
     531           3 :         io.lockx.in.locks = &lock[0];
     532           3 :         status = smb_raw_lock(cli->tree, &io);
     533           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     534             : 
     535           3 :         t = time_mono(NULL);
     536             : 
     537           3 :         torture_comment(tctx, "Testing cancel by CANCEL_LOCK\n");
     538             : 
     539             :         /* setup a timed lock */
     540           3 :         io.lockx.in.timeout = 10000;
     541           3 :         req = smb_raw_lock_send(cli->tree, &io);
     542           3 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     543             :                        "Failed to setup timed lock (%s)\n", __location__));
     544             : 
     545             :         /* cancel the wrong range */
     546           3 :         lock[0].offset = 0;
     547           3 :         io.lockx.in.timeout = 0;
     548           3 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
     549           3 :         status = smb_raw_lock(cli->tree, &io);
     550           3 :         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
     551             : 
     552             :         /* cancel with the wrong bits set */
     553           3 :         lock[0].offset = 100;
     554           3 :         io.lockx.in.timeout = 0;
     555           3 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
     556           3 :         status = smb_raw_lock(cli->tree, &io);
     557           3 :         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
     558             : 
     559             :         /* cancel the right range */
     560           3 :         lock[0].offset = 100;
     561           3 :         io.lockx.in.timeout = 0;
     562           3 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     563           3 :         status = smb_raw_lock(cli->tree, &io);
     564           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     565             : 
     566             :         /* receive the failed lock request */
     567           3 :         status = smbcli_request_simple_recv(req);
     568           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     569             : 
     570           3 :         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           3 :         torture_comment(tctx, "Testing multiple cancel\n");
     581             : 
     582             :         /* acquire second lock */
     583           3 :         io.lockx.in.timeout = 0;
     584           3 :         io.lockx.in.ulock_cnt = 0;
     585           3 :         io.lockx.in.lock_cnt = 1;
     586           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     587           3 :         io.lockx.in.locks = &lock[1];
     588           3 :         status = smb_raw_lock(cli->tree, &io);
     589           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     590             : 
     591             :         /* setup 2 timed locks */
     592           3 :         t = time_mono(NULL);
     593           3 :         io.lockx.in.timeout = 10000;
     594           3 :         io.lockx.in.lock_cnt = 1;
     595           3 :         io.lockx.in.locks = &lock[0];
     596           3 :         req = smb_raw_lock_send(cli->tree, &io);
     597           3 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     598             :                        "Failed to setup timed lock (%s)\n", __location__));
     599           3 :         io.lockx.in.locks = &lock[1];
     600           3 :         req2 = smb_raw_lock_send(cli->tree, &io);
     601           3 :         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           3 :         io.lockx.in.timeout = 0;
     606           3 :         io.lockx.in.lock_cnt = 2;
     607           3 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     608           3 :         io.lockx.in.locks = lock;
     609           3 :         status = smb_raw_lock(cli->tree, &io);
     610           3 :         CHECK_STATUS(status, NT_STATUS_OK);
     611             : 
     612           2 :         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           2 :         status = smbcli_request_simple_recv(req);
     618           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     619             : 
     620           2 :         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           2 :         io.lockx.in.timeout = 0;
     626           2 :         io.lockx.in.lock_cnt = 1;
     627           2 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK |
     628             :                            LOCKING_ANDX_LARGE_FILES;
     629           2 :         io.lockx.in.locks = &lock[1];
     630           2 :         status = smb_raw_lock(cli->tree, &io);
     631           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     632             : 
     633           2 :         status = smbcli_request_simple_recv(req2);
     634           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     635             : 
     636           2 :         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           2 :         io.lockx.in.ulock_cnt = 1;
     642           2 :         io.lockx.in.lock_cnt = 0;
     643           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     644           2 :         io.lockx.in.locks = &lock[1];
     645           2 :         status = smb_raw_lock(cli->tree, &io);
     646           2 :         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           2 :         torture_comment(tctx, "Testing cancel 1/2 lock request\n");
     651             : 
     652             :         /* Send request with two ranges */
     653           2 :         io.lockx.in.timeout = -1;
     654           2 :         io.lockx.in.ulock_cnt = 0;
     655           2 :         io.lockx.in.lock_cnt = 2;
     656           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     657           2 :         io.lockx.in.locks = lock;
     658           2 :         req = smb_raw_lock_send(cli->tree, &io);
     659           2 :         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           2 :         io.lockx.in.timeout = 0;
     664           2 :         io.lockx.in.lock_cnt = 1;
     665           2 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     666           2 :         io.lockx.in.locks = &lock[0];
     667           2 :         status = smb_raw_lock(cli->tree, &io);
     668           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     669             : 
     670             :         /* Locking request should've failed and second range should be
     671             :          * unlocked */
     672           2 :         status = smbcli_request_simple_recv(req);
     673           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     674             : 
     675           2 :         io.lockx.in.timeout = 0;
     676           2 :         io.lockx.in.ulock_cnt = 0;
     677           2 :         io.lockx.in.lock_cnt = 1;
     678           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     679           2 :         io.lockx.in.locks = &lock[1];
     680           2 :         status = smb_raw_lock(cli->tree, &io);
     681           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     682             : 
     683             :         /* Cleanup both locks */
     684           2 :         io.lockx.in.ulock_cnt = 2;
     685           2 :         io.lockx.in.lock_cnt = 0;
     686           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     687           2 :         io.lockx.in.locks = lock;
     688           2 :         status = smb_raw_lock(cli->tree, &io);
     689           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     690             : 
     691           2 :         torture_comment(tctx, "Testing cancel 2/2 lock request\n");
     692             : 
     693             :         /* Lock second range so it contends */
     694           2 :         io.lockx.in.timeout = 0;
     695           2 :         io.lockx.in.ulock_cnt = 0;
     696           2 :         io.lockx.in.lock_cnt = 1;
     697           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     698           2 :         io.lockx.in.locks = &lock[1];
     699           2 :         status = smb_raw_lock(cli->tree, &io);
     700           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     701             : 
     702             :         /* Send request with two ranges */
     703           2 :         io.lockx.in.timeout = -1;
     704           2 :         io.lockx.in.ulock_cnt = 0;
     705           2 :         io.lockx.in.lock_cnt = 2;
     706           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     707           2 :         io.lockx.in.locks = lock;
     708           2 :         req = smb_raw_lock_send(cli->tree, &io);
     709           2 :         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           2 :         io.lockx.in.timeout = 0;
     714           2 :         io.lockx.in.lock_cnt = 1;
     715           2 :         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
     716           2 :         io.lockx.in.locks = &lock[1];
     717           2 :         status = smb_raw_lock(cli->tree, &io);
     718           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     719             : 
     720             :         /* Locking request should've failed and first range should be
     721             :          * unlocked */
     722           2 :         status = smbcli_request_simple_recv(req);
     723           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     724             : 
     725           2 :         io.lockx.in.timeout = 0;
     726           2 :         io.lockx.in.ulock_cnt = 0;
     727           2 :         io.lockx.in.lock_cnt = 1;
     728           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     729           2 :         io.lockx.in.locks = &lock[0];
     730           2 :         status = smb_raw_lock(cli->tree, &io);
     731           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     732             : 
     733             :         /* Cleanup both locks */
     734           2 :         io.lockx.in.ulock_cnt = 2;
     735           2 :         io.lockx.in.lock_cnt = 0;
     736           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     737           2 :         io.lockx.in.locks = lock;
     738           2 :         status = smb_raw_lock(cli->tree, &io);
     739           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     740             : 
     741           2 :         torture_comment(tctx, "Testing cancel by unlock\n");
     742           2 :         io.lockx.in.ulock_cnt = 0;
     743           2 :         io.lockx.in.lock_cnt = 1;
     744           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     745           2 :         io.lockx.in.timeout = 0;
     746           2 :         io.lockx.in.locks = &lock[0];
     747           2 :         status = smb_raw_lock(cli->tree, &io);
     748           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     749             : 
     750           2 :         io.lockx.in.timeout = 5000;
     751           2 :         req = smb_raw_lock_send(cli->tree, &io);
     752           2 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     753             :                        "Failed to setup timed lock (%s)\n", __location__));
     754             : 
     755           2 :         io.lockx.in.ulock_cnt = 1;
     756           2 :         io.lockx.in.lock_cnt = 0;
     757           2 :         status = smb_raw_lock(cli->tree, &io);
     758           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     759             : 
     760           2 :         t = time_mono(NULL);
     761           2 :         status = smbcli_request_simple_recv(req);
     762           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     763             : 
     764           2 :         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           2 :         torture_comment(tctx, "Testing cancel by close\n");
     769           2 :         io.lockx.in.ulock_cnt = 0;
     770           2 :         io.lockx.in.lock_cnt = 1;
     771           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     772           2 :         io.lockx.in.timeout = 0;
     773           2 :         status = smb_raw_lock(cli->tree, &io);
     774           2 :         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           2 :                 uint64_t tmp = lock[1].offset;
     782           2 :                 lock[1].offset = lock[0].offset;
     783           2 :                 lock[0].offset = tmp;
     784             :         }
     785             : 
     786           2 :         t = time_mono(NULL);
     787           2 :         io.lockx.in.timeout = 10000;
     788           2 :         io.lockx.in.lock_cnt = 2;
     789           2 :         req = smb_raw_lock_send(cli->tree, &io);
     790           2 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     791             :                        "Failed to setup timed lock (%s)\n", __location__));
     792             : 
     793           2 :         status = smbcli_close(cli->tree, fnum);
     794           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     795             : 
     796           2 :         status = smbcli_request_simple_recv(req);
     797           2 :         if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
     798           2 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     799             :         else
     800           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     801             : 
     802           2 :         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           2 :                 uint64_t tmp = lock[1].offset;
     810           2 :                 lock[1].offset = lock[0].offset;
     811           2 :                 lock[0].offset = tmp;
     812             :         }
     813             : 
     814           2 :         torture_comment(tctx, "create a new sessions\n");
     815           2 :         session = smbcli_session_init(cli->transport, tctx, false, options);
     816           2 :         setup.in.sesskey = cli->transport->negotiate.sesskey;
     817           2 :         setup.in.capabilities = cli->transport->negotiate.capabilities;
     818           2 :         setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
     819           2 :         setup.in.credentials = samba_cmdline_get_creds();
     820           2 :         setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
     821           2 :         status = smb_composite_sesssetup(session, &setup);
     822           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     823           2 :         session->vuid = setup.out.vuid;
     824             : 
     825           2 :         torture_comment(tctx, "create new tree context\n");
     826           2 :         share = torture_setting_string(tctx, "share", NULL);
     827           2 :         host  = torture_setting_string(tctx, "host", NULL);
     828           2 :         tree = smbcli_tree_init(session, tctx, false);
     829           2 :         tcon.generic.level = RAW_TCON_TCONX;
     830           2 :         tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE;
     831           2 :         tcon.tconx.in.password = data_blob(NULL, 0);
     832           2 :         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
     833           2 :         tcon.tconx.in.device = "A:";
     834           2 :         status = smb_raw_tcon(tree, tctx, &tcon);
     835           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     836           2 :         tree->tid = tcon.tconx.out.tid;
     837             : 
     838           2 :         torture_comment(tctx, "Testing cancel by exit\n");
     839           2 :         if (TARGET_SUPPORTS_SMBEXIT(tctx)) {
     840           2 :                 fname = BASEDIR "\\test_exit.txt";
     841           2 :                 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     842           2 :                 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     843             :                                "Failed to reopen %s - %s\n",
     844             :                                fname, smbcli_errstr(tree)));
     845             : 
     846           2 :                 io.lockx.level = RAW_LOCK_LOCKX;
     847           2 :                 io.lockx.in.file.fnum = fnum;
     848           2 :                 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     849           2 :                 io.lockx.in.timeout = 0;
     850           2 :                 io.lockx.in.ulock_cnt = 0;
     851           2 :                 io.lockx.in.lock_cnt = 1;
     852           2 :                 lock[0].pid = session->pid;
     853           2 :                 lock[0].offset = 100;
     854           2 :                 lock[0].count = 10;
     855           2 :                 io.lockx.in.locks = &lock[0];
     856           2 :                 status = smb_raw_lock(tree, &io);
     857           2 :                 CHECK_STATUS(status, NT_STATUS_OK);
     858             : 
     859           2 :                 io.lockx.in.ulock_cnt = 0;
     860           2 :                 io.lockx.in.lock_cnt = 1;
     861           2 :                 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     862           2 :                 io.lockx.in.timeout = 0;
     863           2 :                 status = smb_raw_lock(tree, &io);
     864           2 :                 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     865             : 
     866           2 :                 io.lockx.in.timeout = 10000;
     867           2 :                 t = time_mono(NULL);
     868           2 :                 req = smb_raw_lock_send(tree, &io);
     869           2 :                 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     870             :                                "Failed to setup timed lock (%s)\n",
     871             :                                __location__));
     872             : 
     873           2 :                 status = smb_raw_exit(session);
     874           2 :                 CHECK_STATUS(status, NT_STATUS_OK);
     875             : 
     876           2 :                 status = smbcli_request_simple_recv(req);
     877           2 :                 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
     878           2 :                         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     879             :                 else
     880           0 :                         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     881             : 
     882           2 :                 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           2 :         torture_comment(tctx, "Testing cancel by ulogoff\n");
     892           2 :         fname = BASEDIR "\\test_ulogoff.txt";
     893           2 :         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     894           2 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     895             :                        "Failed to reopen %s - %s\n",
     896             :                        fname, smbcli_errstr(tree)));
     897             : 
     898           2 :         io.lockx.level = RAW_LOCK_LOCKX;
     899           2 :         io.lockx.in.file.fnum = fnum;
     900           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     901           2 :         io.lockx.in.timeout = 0;
     902           2 :         io.lockx.in.ulock_cnt = 0;
     903           2 :         io.lockx.in.lock_cnt = 1;
     904           2 :         lock[0].pid = session->pid;
     905           2 :         lock[0].offset = 100;
     906           2 :         lock[0].count = 10;
     907           2 :         io.lockx.in.locks = &lock[0];
     908           2 :         status = smb_raw_lock(tree, &io);
     909           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     910             : 
     911           2 :         io.lockx.in.ulock_cnt = 0;
     912           2 :         io.lockx.in.lock_cnt = 1;
     913           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     914           2 :         io.lockx.in.timeout = 0;
     915           2 :         status = smb_raw_lock(tree, &io);
     916           2 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     917             : 
     918           2 :         io.lockx.in.timeout = 10000;
     919           2 :         t = time_mono(NULL);
     920           2 :         req = smb_raw_lock_send(tree, &io);
     921           2 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     922             :                        "Failed to setup timed lock (%s)\n", __location__));
     923             : 
     924           2 :         status = smb_raw_ulogoff(session);
     925           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     926             : 
     927           2 :         status = smbcli_request_simple_recv(req);
     928           2 :         if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) {
     929           2 :                 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           2 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     939             :         } else {
     940           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     941             :         }
     942             : 
     943           2 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     944             :                        "lock cancel by ulogoff was not immediate (%s)\n", __location__));
     945             : 
     946           2 :         torture_comment(tctx, "Testing cancel by tdis\n");
     947           2 :         tree->session = cli->session;
     948             : 
     949           2 :         fname = BASEDIR "\\test_tdis.txt";
     950           2 :         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     951           2 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
     952             :                        "Failed to reopen %s - %s\n",
     953             :                        fname, smbcli_errstr(tree)));
     954             : 
     955           2 :         io.lockx.level = RAW_LOCK_LOCKX;
     956           2 :         io.lockx.in.file.fnum = fnum;
     957           2 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
     958           2 :         io.lockx.in.timeout = 0;
     959           2 :         io.lockx.in.ulock_cnt = 0;
     960           2 :         io.lockx.in.lock_cnt = 1;
     961           2 :         lock[0].pid = cli->session->pid;
     962           2 :         lock[0].offset = 100;
     963           2 :         lock[0].count = 10;
     964           2 :         io.lockx.in.locks = &lock[0];
     965           2 :         status = smb_raw_lock(tree, &io);
     966           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     967             : 
     968           2 :         status = smb_raw_lock(tree, &io);
     969           2 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
     970             : 
     971           2 :         io.lockx.in.timeout = 10000;
     972           2 :         t = time_mono(NULL);
     973           2 :         req = smb_raw_lock_send(tree, &io);
     974           2 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
     975             :                        "Failed to setup timed lock (%s)\n", __location__));
     976             : 
     977           2 :         status = smb_tree_disconnect(tree);
     978           2 :         CHECK_STATUS(status, NT_STATUS_OK);
     979             : 
     980           2 :         status = smbcli_request_simple_recv(req);
     981           2 :         if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
     982           2 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     983             :         else
     984           0 :                 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     985             : 
     986           2 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
     987             :                        "lock cancel by tdis was not immediate (%s)\n", __location__));
     988             : 
     989           2 : done:
     990           3 :         smb_raw_exit(cli->session);
     991           3 :         smbcli_deltree(cli->tree, BASEDIR);
     992           3 :         return ret;
     993             : }
     994             : 
     995             : /*
     996             :   test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
     997             : */
     998           3 : static bool test_errorcode(struct torture_context *tctx, 
     999             :                                                    struct smbcli_state *cli)
    1000             : {
    1001           0 :         union smb_lock io;
    1002           0 :         union smb_open op;
    1003           0 :         struct smb_lock_entry lock[2];
    1004           0 :         NTSTATUS status;
    1005           3 :         bool ret = true;
    1006           0 :         int fnum, fnum2;
    1007           0 :         const char *fname;
    1008           0 :         struct smbcli_request *req;
    1009           0 :         time_t start;
    1010           0 :         int t;
    1011           0 :         int delay;
    1012           3 :         uint16_t deny_mode = 0;
    1013             : 
    1014           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1015             : 
    1016           3 :         torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
    1017             : 
    1018           3 :         torture_comment(tctx, "Testing with timeout = 0\n");
    1019           3 :         fname = BASEDIR "\\test0.txt";
    1020           3 :         t = 0;
    1021             : 
    1022             :         /*
    1023             :          * the first run is with t = 0,
    1024             :          * the second with t > 0 (=1)
    1025             :          */
    1026           6 : 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           6 :         if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
    1033           6 :             deny_mode = OPENX_MODE_DENY_DOS;
    1034             :         else
    1035           0 :             deny_mode = OPENX_MODE_DENY_NONE;
    1036             : 
    1037           6 :         op.openx.level = RAW_OPEN_OPENX;
    1038           6 :         op.openx.in.fname = fname;
    1039           6 :         op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
    1040           6 :         op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
    1041           6 :         op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
    1042           6 :         op.openx.in.search_attrs = 0;
    1043           6 :         op.openx.in.file_attrs = 0;
    1044           6 :         op.openx.in.write_time = 0;
    1045           6 :         op.openx.in.size = 0;
    1046           6 :         op.openx.in.timeout = 0;
    1047             : 
    1048           6 :         status = smb_raw_open(cli->tree, tctx, &op);
    1049           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1050           6 :         fnum = op.openx.out.file.fnum;
    1051             : 
    1052           6 :         status = smb_raw_open(cli->tree, tctx, &op);
    1053           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1054           6 :         fnum2 = op.openx.out.file.fnum;
    1055             : 
    1056           6 :         io.lockx.level = RAW_LOCK_LOCKX;
    1057           6 :         io.lockx.in.file.fnum = fnum;
    1058           6 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1059           6 :         io.lockx.in.timeout = t;
    1060           6 :         io.lockx.in.ulock_cnt = 0;
    1061           6 :         io.lockx.in.lock_cnt = 1;
    1062           6 :         lock[0].pid = cli->session->pid;
    1063           6 :         lock[0].offset = 100;
    1064           6 :         lock[0].count = 10;
    1065           6 :         io.lockx.in.locks = &lock[0];
    1066           6 :         status = smb_raw_lock(cli->tree, &io);
    1067           6 :         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           6 :         io.lockx.in.file.fnum = fnum2;
    1075           6 :         status = smb_raw_lock(cli->tree, &io);
    1076           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1077             : 
    1078           6 :         io.lockx.in.file.fnum = fnum;
    1079           6 :         status = smb_raw_lock(cli->tree, &io);
    1080           6 :         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           6 :         io.lockx.in.file.fnum = fnum;
    1084           6 :         status = smb_raw_lock(cli->tree, &io);
    1085           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1086             : 
    1087           6 :         io.lockx.in.file.fnum = fnum2;
    1088           6 :         status = smb_raw_lock(cli->tree, &io);
    1089           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1090             : 
    1091           6 :         io.lockx.in.file.fnum = fnum;
    1092           6 :         status = smb_raw_lock(cli->tree, &io);
    1093           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1094             : 
    1095           6 :         io.lockx.in.file.fnum = fnum2;
    1096           6 :         status = smb_raw_lock(cli->tree, &io);
    1097           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1098             : 
    1099             :         /* demonstrate that the smbpid doesn't matter */
    1100           6 :         lock[0].pid++;
    1101           6 :         io.lockx.in.file.fnum = fnum;
    1102           6 :         status = smb_raw_lock(cli->tree, &io);
    1103           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1104             : 
    1105           6 :         io.lockx.in.file.fnum = fnum2;
    1106           6 :         status = smb_raw_lock(cli->tree, &io);
    1107           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1108           6 :         lock[0].pid--;
    1109             : 
    1110             :         /* 
    1111             :          * demonstrate that a successful lock with count = 0 and the same offset,
    1112             :          * doesn't reset the error cache
    1113             :          */
    1114           6 :         lock[0].offset = 100;
    1115           6 :         lock[0].count = 0;
    1116           6 :         io.lockx.in.file.fnum = fnum;
    1117           6 :         status = smb_raw_lock(cli->tree, &io);
    1118           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1119             : 
    1120           6 :         io.lockx.in.file.fnum = fnum2;
    1121           6 :         status = smb_raw_lock(cli->tree, &io);
    1122           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1123             : 
    1124           6 :         lock[0].offset = 100;
    1125           6 :         lock[0].count = 10;
    1126           6 :         io.lockx.in.file.fnum = fnum;
    1127           6 :         status = smb_raw_lock(cli->tree, &io);
    1128           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1129             : 
    1130           6 :         io.lockx.in.file.fnum = fnum2;
    1131           6 :         status = smb_raw_lock(cli->tree, &io);
    1132           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1133             : 
    1134             :         /* 
    1135             :          * demonstrate that a successful lock with count = 0 and outside the locked range,
    1136             :          * doesn't reset the error cache
    1137             :          */
    1138           6 :         lock[0].offset = 110;
    1139           6 :         lock[0].count = 0;
    1140           6 :         io.lockx.in.file.fnum = fnum;
    1141           6 :         status = smb_raw_lock(cli->tree, &io);
    1142           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1143             : 
    1144           6 :         io.lockx.in.file.fnum = fnum2;
    1145           6 :         status = smb_raw_lock(cli->tree, &io);
    1146           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1147             : 
    1148           6 :         lock[0].offset = 100;
    1149           6 :         lock[0].count = 10;
    1150           6 :         io.lockx.in.file.fnum = fnum;
    1151           6 :         status = smb_raw_lock(cli->tree, &io);
    1152           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1153             : 
    1154           6 :         io.lockx.in.file.fnum = fnum2;
    1155           6 :         status = smb_raw_lock(cli->tree, &io);
    1156           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1157             : 
    1158           6 :         lock[0].offset = 99;
    1159           6 :         lock[0].count = 0;
    1160           6 :         io.lockx.in.file.fnum = fnum;
    1161           6 :         status = smb_raw_lock(cli->tree, &io);
    1162           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1163             : 
    1164           6 :         io.lockx.in.file.fnum = fnum2;
    1165           6 :         status = smb_raw_lock(cli->tree, &io);
    1166           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1167             : 
    1168           6 :         lock[0].offset = 100;
    1169           6 :         lock[0].count = 10;
    1170           6 :         io.lockx.in.file.fnum = fnum;
    1171           6 :         status = smb_raw_lock(cli->tree, &io);
    1172           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1173             : 
    1174           6 :         io.lockx.in.file.fnum = fnum2;
    1175           6 :         status = smb_raw_lock(cli->tree, &io);
    1176           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1177             : 
    1178             :         /* demonstrate that a changing count doesn't reset the error cache */
    1179           6 :         lock[0].offset = 100;
    1180           6 :         lock[0].count = 5;
    1181           6 :         io.lockx.in.file.fnum = fnum;
    1182           6 :         status = smb_raw_lock(cli->tree, &io);
    1183           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1184             : 
    1185           6 :         io.lockx.in.file.fnum = fnum2;
    1186           6 :         status = smb_raw_lock(cli->tree, &io);
    1187           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1188             : 
    1189           6 :         lock[0].offset = 100;
    1190           6 :         lock[0].count = 15;
    1191           6 :         io.lockx.in.file.fnum = fnum;
    1192           6 :         status = smb_raw_lock(cli->tree, &io);
    1193           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1194             : 
    1195           6 :         io.lockx.in.file.fnum = fnum2;
    1196           6 :         status = smb_raw_lock(cli->tree, &io);
    1197           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1198             : 
    1199             :         /* 
    1200             :          * demonstrate that a lock with count = 0 and inside the locked range,
    1201             :          * fails and resets the error cache
    1202             :          */
    1203           6 :         lock[0].offset = 101;
    1204           6 :         lock[0].count = 0;
    1205           6 :         io.lockx.in.file.fnum = fnum;
    1206           6 :         status = smb_raw_lock(cli->tree, &io);
    1207           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1208           6 :         status = smb_raw_lock(cli->tree, &io);
    1209           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1210             : 
    1211           6 :         io.lockx.in.file.fnum = fnum2;
    1212           6 :         status = smb_raw_lock(cli->tree, &io);
    1213           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1214           6 :         status = smb_raw_lock(cli->tree, &io);
    1215           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1216             : 
    1217           6 :         lock[0].offset = 100;
    1218           6 :         lock[0].count = 10;
    1219           6 :         io.lockx.in.file.fnum = fnum;
    1220           6 :         status = smb_raw_lock(cli->tree, &io);
    1221           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1222           6 :         status = smb_raw_lock(cli->tree, &io);
    1223           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1224             : 
    1225           6 :         io.lockx.in.file.fnum = fnum2;
    1226           6 :         status = smb_raw_lock(cli->tree, &io);
    1227           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1228           6 :         status = smb_raw_lock(cli->tree, &io);
    1229           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1230             : 
    1231             :         /* demonstrate that a changing offset resets the error cache */
    1232           6 :         lock[0].offset = 105;
    1233           6 :         lock[0].count = 10;
    1234           6 :         io.lockx.in.file.fnum = fnum;
    1235           6 :         status = smb_raw_lock(cli->tree, &io);
    1236           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1237           6 :         status = smb_raw_lock(cli->tree, &io);
    1238           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1239             : 
    1240           6 :         io.lockx.in.file.fnum = fnum2;
    1241           6 :         status = smb_raw_lock(cli->tree, &io);
    1242           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1243           6 :         status = smb_raw_lock(cli->tree, &io);
    1244           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1245             : 
    1246           6 :         lock[0].offset = 100;
    1247           6 :         lock[0].count = 10;
    1248           6 :         io.lockx.in.file.fnum = fnum;
    1249           6 :         status = smb_raw_lock(cli->tree, &io);
    1250           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1251           6 :         status = smb_raw_lock(cli->tree, &io);
    1252           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1253             : 
    1254           6 :         io.lockx.in.file.fnum = fnum2;
    1255           6 :         status = smb_raw_lock(cli->tree, &io);
    1256           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1257           6 :         status = smb_raw_lock(cli->tree, &io);
    1258           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1259             : 
    1260           6 :         lock[0].offset = 95;
    1261           6 :         lock[0].count = 9;
    1262           6 :         io.lockx.in.file.fnum = fnum;
    1263           6 :         status = smb_raw_lock(cli->tree, &io);
    1264           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1265           6 :         status = smb_raw_lock(cli->tree, &io);
    1266           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1267             : 
    1268           6 :         io.lockx.in.file.fnum = fnum2;
    1269           6 :         status = smb_raw_lock(cli->tree, &io);
    1270           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1271           6 :         status = smb_raw_lock(cli->tree, &io);
    1272           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1273             : 
    1274           6 :         lock[0].offset = 100;
    1275           6 :         lock[0].count = 10;
    1276           6 :         io.lockx.in.file.fnum = fnum;
    1277           6 :         status = smb_raw_lock(cli->tree, &io);
    1278           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1279           6 :         status = smb_raw_lock(cli->tree, &io);
    1280           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1281             : 
    1282           6 :         io.lockx.in.file.fnum = fnum2;
    1283           6 :         status = smb_raw_lock(cli->tree, &io);
    1284           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1285           6 :         status = smb_raw_lock(cli->tree, &io);
    1286           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1287             : 
    1288             :         /* 
    1289             :          * demonstrate that 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           6 :         lock[0].offset = 120;
    1294           6 :         lock[0].count = 15;
    1295           6 :         io.lockx.in.file.fnum = fnum;
    1296           6 :         status = smb_raw_lock(cli->tree, &io);
    1297           6 :         CHECK_STATUS(status, NT_STATUS_OK);
    1298             : 
    1299           6 :         io.lockx.in.file.fnum = fnum2;
    1300           6 :         status = smb_raw_lock(cli->tree, &io);
    1301           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1302             : 
    1303           6 :         lock[0].offset = 100;
    1304           6 :         lock[0].count = 10;
    1305           6 :         io.lockx.in.file.fnum = fnum;
    1306           6 :         status = smb_raw_lock(cli->tree, &io);
    1307           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1308           6 :         status = smb_raw_lock(cli->tree, &io);
    1309           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1310             : 
    1311           6 :         io.lockx.in.file.fnum = fnum2;
    1312           6 :         status = smb_raw_lock(cli->tree, &io);
    1313           6 :         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
    1314           6 :         status = smb_raw_lock(cli->tree, &io);
    1315           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1316             : 
    1317             :         /* end of the loop */
    1318           6 :         if (t == 0) {
    1319           3 :                 smb_raw_exit(cli->session);
    1320           3 :                 t = 1;
    1321           3 :                 torture_comment(tctx, "Testing with timeout > 0 (=%d)\n",
    1322             :                                 t);
    1323           3 :                 fname = BASEDIR "\\test1.txt";
    1324           3 :                 goto next_run;
    1325             :         }
    1326             : 
    1327           3 :         t = 4000;
    1328           3 :         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           3 :         smb_raw_exit(cli->session);
    1337           3 :         torture_comment(tctx, "Testing a conflict while a lock is pending\n");
    1338           3 :         fname = BASEDIR "\\test2.txt";
    1339           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1340           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1341             :                        "Failed to reopen %s - %s\n",
    1342             :                        fname, smbcli_errstr(cli->tree)));
    1343             : 
    1344           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    1345           3 :         io.lockx.in.file.fnum = fnum;
    1346           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1347           3 :         io.lockx.in.timeout = 0;
    1348           3 :         io.lockx.in.ulock_cnt = 0;
    1349           3 :         io.lockx.in.lock_cnt = 1;
    1350           3 :         lock[0].pid = cli->session->pid;
    1351           3 :         lock[0].offset = 100;
    1352           3 :         lock[0].count = 10;
    1353           3 :         io.lockx.in.locks = &lock[0];
    1354           3 :         status = smb_raw_lock(cli->tree, &io);
    1355           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1356             : 
    1357           3 :         start = time_mono(NULL);
    1358           3 :         io.lockx.in.timeout = t;
    1359           3 :         req = smb_raw_lock_send(cli->tree, &io);
    1360           3 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    1361             :                        "Failed to setup timed lock (%s)\n", __location__));
    1362             : 
    1363           3 :         io.lockx.in.timeout = 0;
    1364           3 :         lock[0].offset = 105;
    1365           3 :         lock[0].count = 10;
    1366           3 :         status = smb_raw_lock(cli->tree, &io);
    1367           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1368             : 
    1369           3 :         status = smbcli_request_simple_recv(req);
    1370           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1371             : 
    1372           3 :         delay = t / 1000;
    1373           3 :         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
    1374           0 :                 delay /= 2;
    1375             :         }
    1376             : 
    1377           3 :         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           3 :         status = smb_raw_lock(cli->tree, &io);
    1382           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1383             : 
    1384           3 :         smbcli_close(cli->tree, fnum);
    1385           3 :         fname = BASEDIR "\\test3.txt";
    1386           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1387           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1388             :                        "Failed to reopen %s - %s\n",
    1389             :                        fname, smbcli_errstr(cli->tree)));
    1390             : 
    1391           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    1392           3 :         io.lockx.in.file.fnum = fnum;
    1393           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1394           3 :         io.lockx.in.timeout = 0;
    1395           3 :         io.lockx.in.ulock_cnt = 0;
    1396           3 :         io.lockx.in.lock_cnt = 1;
    1397           3 :         lock[0].pid = cli->session->pid;
    1398           3 :         lock[0].offset = 100;
    1399           3 :         lock[0].count = 10;
    1400           3 :         io.lockx.in.locks = &lock[0];
    1401           3 :         status = smb_raw_lock(cli->tree, &io);
    1402           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1403             : 
    1404           3 :         start = time_mono(NULL);
    1405           3 :         io.lockx.in.timeout = t;
    1406           3 :         req = smb_raw_lock_send(cli->tree, &io);
    1407           3 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    1408             :                        "Failed to setup timed lock (%s)\n", __location__));
    1409             : 
    1410           3 :         io.lockx.in.timeout = 0;
    1411           3 :         lock[0].offset = 105;
    1412           3 :         lock[0].count = 10;
    1413           3 :         status = smb_raw_lock(cli->tree, &io);
    1414           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1415             : 
    1416           3 :         status = smbcli_request_simple_recv(req);
    1417           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1418             : 
    1419           3 :         delay = t / 1000;
    1420           3 :         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
    1421           0 :                 delay /= 2;
    1422             :         }
    1423             : 
    1424           3 :         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           3 :         lock[0].offset = 100;
    1429           3 :         lock[0].count = 10;
    1430           3 :         status = smb_raw_lock(cli->tree, &io);
    1431           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1432             : 
    1433           3 :         smbcli_close(cli->tree, fnum);
    1434           3 :         fname = BASEDIR "\\test4.txt";
    1435           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1436           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1437             :                        "Failed to reopen %s - %s\n",
    1438             :                        fname, smbcli_errstr(cli->tree)));
    1439             : 
    1440           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    1441           3 :         io.lockx.in.file.fnum = fnum;
    1442           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    1443           3 :         io.lockx.in.timeout = 0;
    1444           3 :         io.lockx.in.ulock_cnt = 0;
    1445           3 :         io.lockx.in.lock_cnt = 1;
    1446           3 :         lock[0].pid = cli->session->pid;
    1447           3 :         lock[0].offset = 100;
    1448           3 :         lock[0].count = 10;
    1449           3 :         io.lockx.in.locks = &lock[0];
    1450           3 :         status = smb_raw_lock(cli->tree, &io);
    1451           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1452             : 
    1453           3 :         start = time_mono(NULL);
    1454           3 :         io.lockx.in.timeout = t;
    1455           3 :         req = smb_raw_lock_send(cli->tree, &io);
    1456           3 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    1457             :                        "Failed to setup timed lock (%s)\n", __location__));
    1458             : 
    1459           3 :         io.lockx.in.timeout = 0;
    1460           3 :         status = smb_raw_lock(cli->tree, &io);
    1461           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1462             : 
    1463           3 :         status = smbcli_request_simple_recv(req);
    1464           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1465             : 
    1466           3 :         delay = t / 1000;
    1467           3 :         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
    1468           0 :                 delay /= 2;
    1469             :         }
    1470             : 
    1471           3 :         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           3 :         status = smb_raw_lock(cli->tree, &io);
    1476           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1477             : 
    1478           3 : done:
    1479           3 :         smb_raw_exit(cli->session);
    1480           3 :         smbcli_deltree(cli->tree, BASEDIR);
    1481           3 :         return ret;
    1482             : }
    1483             : 
    1484             : 
    1485             : /*
    1486             :   test LOCKING_ANDX_CHANGE_LOCKTYPE
    1487             : */
    1488           3 : static bool test_changetype(struct torture_context *tctx, 
    1489             :                                                         struct smbcli_state *cli)
    1490             : {
    1491           0 :         union smb_lock io;
    1492           0 :         struct smb_lock_entry lock[2];
    1493           0 :         NTSTATUS status;
    1494           3 :         bool ret = true;
    1495           0 :         int fnum;
    1496           3 :         uint8_t c = 0;
    1497           3 :         const char *fname = BASEDIR "\\test.txt";
    1498             : 
    1499           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1500             : 
    1501           3 :         torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
    1502           3 :         io.generic.level = RAW_LOCK_LOCKX;
    1503             :         
    1504           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1505           3 :         torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
    1506             :                        "Failed to create %s - %s\n",
    1507             :                        fname, smbcli_errstr(cli->tree)));
    1508             : 
    1509           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    1510           3 :         io.lockx.in.file.fnum = fnum;
    1511           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1512           3 :         io.lockx.in.timeout = 0;
    1513           3 :         io.lockx.in.ulock_cnt = 0;
    1514           3 :         io.lockx.in.lock_cnt = 1;
    1515           3 :         lock[0].pid = cli->session->pid;
    1516           3 :         lock[0].offset = 100;
    1517           3 :         lock[0].count = 10;
    1518           3 :         io.lockx.in.locks = &lock[0];
    1519           3 :         status = smb_raw_lock(cli->tree, &io);
    1520           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1521             : 
    1522           3 :         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           3 :         io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
    1531           3 :         status = smb_raw_lock(cli->tree, &io);
    1532           3 :         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
    1533             : 
    1534           3 :         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           3 : done:
    1542           3 :         smbcli_close(cli->tree, fnum);
    1543           3 :         smb_raw_exit(cli->session);
    1544           3 :         smbcli_deltree(cli->tree, BASEDIR);
    1545           3 :         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           3 : static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
    1589             : {
    1590           0 :         union smb_lock io;
    1591           0 :         NTSTATUS status;
    1592           3 :         bool ret = true;
    1593           0 :         int fnum, i;
    1594           3 :         const char *fname = BASEDIR "\\zero.txt";
    1595             : 
    1596           3 :         torture_comment(tctx, "Testing zero length byte range locks:\n");
    1597             : 
    1598           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1599             : 
    1600           3 :         io.generic.level = RAW_LOCK_LOCKX;
    1601             : 
    1602           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1603           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    1609           3 :         io.lockx.in.file.fnum = fnum;
    1610           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
    1611           3 :         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           3 :         for (i = 0;
    1617          48 :              i < ARRAY_SIZE(zero_byte_tests);
    1618          45 :              i++) {
    1619          45 :                 torture_comment(tctx, "  ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
    1620             :                     zero_byte_tests[i].lock1.pid,
    1621          45 :                     (unsigned long long) zero_byte_tests[i].lock1.offset,
    1622          45 :                     (unsigned long long) zero_byte_tests[i].lock1.count,
    1623             :                     zero_byte_tests[i].lock2.pid,
    1624          45 :                     (unsigned long long) zero_byte_tests[i].lock2.offset,
    1625          45 :                     (unsigned long long) zero_byte_tests[i].lock2.count,
    1626             :                     nt_errstr(zero_byte_tests[i].exp_status));
    1627             : 
    1628             :                 /* Lock both locks. */
    1629          45 :                 io.lockx.in.ulock_cnt = 0;
    1630          45 :                 io.lockx.in.lock_cnt = 1;
    1631             : 
    1632          45 :                 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
    1633             :                                                     &zero_byte_tests[i].lock1);
    1634          45 :                 status = smb_raw_lock(cli->tree, &io);
    1635          45 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1636             : 
    1637          45 :                 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
    1638             :                                                     &zero_byte_tests[i].lock2);
    1639          45 :                 status = smb_raw_lock(cli->tree, &io);
    1640             : 
    1641          45 :                 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          12 :                         CHECK_STATUS_OR_CONT(status,
    1646             :                             NT_STATUS_LOCK_NOT_GRANTED,
    1647             :                             NT_STATUS_FILE_LOCK_CONFLICT);
    1648             : 
    1649             :                 } else {
    1650          33 :                         CHECK_STATUS_CONT(status,
    1651             :                             zero_byte_tests[i].exp_status);
    1652             :                 }
    1653             : 
    1654             :                 /* Unlock both locks. */
    1655          45 :                 io.lockx.in.ulock_cnt = 1;
    1656          45 :                 io.lockx.in.lock_cnt = 0;
    1657             : 
    1658          45 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
    1659          33 :                         status = smb_raw_lock(cli->tree, &io);
    1660          33 :                         CHECK_STATUS(status, NT_STATUS_OK);
    1661             :                 }
    1662             : 
    1663          45 :                 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
    1664             :                                                     &zero_byte_tests[i].lock1);
    1665          45 :                 status = smb_raw_lock(cli->tree, &io);
    1666          45 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1667             :         }
    1668             : 
    1669           3 : done:
    1670           3 :         smbcli_close(cli->tree, fnum);
    1671           3 :         smb_raw_exit(cli->session);
    1672           3 :         smbcli_deltree(cli->tree, BASEDIR);
    1673           3 :         return ret;
    1674             : }
    1675             : 
    1676           3 : static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
    1677             : {
    1678           0 :         union smb_lock io;
    1679           0 :         NTSTATUS status;
    1680           3 :         bool ret = true;
    1681           0 :         int fnum1, fnum2;
    1682           3 :         const char *fname = BASEDIR "\\unlock.txt";
    1683           0 :         struct smb_lock_entry lock1;
    1684           0 :         struct smb_lock_entry lock2;
    1685             : 
    1686           3 :         torture_comment(tctx, "Testing LOCKX unlock:\n");
    1687             : 
    1688           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1689             : 
    1690           3 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1691           3 :         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
    1692             :                        "Failed to create %s - %s\n",
    1693             :                        fname, smbcli_errstr(cli->tree)));
    1694             : 
    1695           3 :         fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1696           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    1702           3 :         io.lockx.in.timeout = 0;
    1703             : 
    1704           3 :         lock1.pid = cli->session->pid;
    1705           3 :         lock1.offset = 0;
    1706           3 :         lock1.count = 10;
    1707           3 :         lock2.pid = cli->session->pid - 1;
    1708           3 :         lock2.offset = 0;
    1709           3 :         lock2.count = 10;
    1710             : 
    1711             :         /**
    1712             :          * Take exclusive lock, then unlock it with a shared-unlock call.
    1713             :          */
    1714           3 :         torture_comment(tctx, "  taking exclusive lock.\n");
    1715           3 :         io.lockx.in.ulock_cnt = 0;
    1716           3 :         io.lockx.in.lock_cnt = 1;
    1717           3 :         io.lockx.in.mode = 0;
    1718           3 :         io.lockx.in.file.fnum = fnum1;
    1719           3 :         io.lockx.in.locks = &lock1;
    1720           3 :         status = smb_raw_lock(cli->tree, &io);
    1721           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1722             : 
    1723           3 :         torture_comment(tctx, "  unlock the exclusive with a shared unlock call.\n");
    1724           3 :         io.lockx.in.ulock_cnt = 1;
    1725           3 :         io.lockx.in.lock_cnt = 0;
    1726           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1727           3 :         io.lockx.in.file.fnum = fnum1;
    1728           3 :         io.lockx.in.locks = &lock1;
    1729           3 :         status = smb_raw_lock(cli->tree, &io);
    1730           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1731             : 
    1732           3 :         torture_comment(tctx, "  try shared lock on pid2/fnum2, testing the unlock.\n");
    1733           3 :         io.lockx.in.ulock_cnt = 0;
    1734           3 :         io.lockx.in.lock_cnt = 1;
    1735           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1736           3 :         io.lockx.in.file.fnum = fnum2;
    1737           3 :         io.lockx.in.locks = &lock2;
    1738           3 :         status = smb_raw_lock(cli->tree, &io);
    1739           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1740             : 
    1741             :         /**
    1742             :          * Unlock a shared lock with an exclusive-unlock call.
    1743             :          */
    1744           3 :         torture_comment(tctx, "  unlock new shared lock with exclusive unlock call.\n");
    1745           3 :         io.lockx.in.ulock_cnt = 1;
    1746           3 :         io.lockx.in.lock_cnt = 0;
    1747           3 :         io.lockx.in.mode = 0;
    1748           3 :         io.lockx.in.file.fnum = fnum2;
    1749           3 :         io.lockx.in.locks = &lock2;
    1750           3 :         status = smb_raw_lock(cli->tree, &io);
    1751           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1752             : 
    1753           3 :         torture_comment(tctx, "  try exclusive lock on pid1, testing the unlock.\n");
    1754           3 :         io.lockx.in.ulock_cnt = 0;
    1755           3 :         io.lockx.in.lock_cnt = 1;
    1756           3 :         io.lockx.in.mode = 0;
    1757           3 :         io.lockx.in.file.fnum = fnum1;
    1758           3 :         io.lockx.in.locks = &lock1;
    1759           3 :         status = smb_raw_lock(cli->tree, &io);
    1760           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1761             : 
    1762             :         /* cleanup */
    1763           3 :         io.lockx.in.ulock_cnt = 1;
    1764           3 :         io.lockx.in.lock_cnt = 0;
    1765           3 :         status = smb_raw_lock(cli->tree, &io);
    1766           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1767             : 
    1768             :         /**
    1769             :          * Test unlocking of 0-byte locks.
    1770             :          */
    1771             : 
    1772           3 :         torture_comment(tctx, "  lock shared and exclusive 0-byte locks, testing that Windows "
    1773             :             "always unlocks the exclusive first.\n");
    1774           3 :         lock1.pid = cli->session->pid;
    1775           3 :         lock1.offset = 10;
    1776           3 :         lock1.count = 0;
    1777           3 :         lock2.pid = cli->session->pid;
    1778           3 :         lock2.offset = 5;
    1779           3 :         lock2.count = 10;
    1780           3 :         io.lockx.in.ulock_cnt = 0;
    1781           3 :         io.lockx.in.lock_cnt = 1;
    1782           3 :         io.lockx.in.file.fnum = fnum1;
    1783           3 :         io.lockx.in.locks = &lock1;
    1784             : 
    1785             :         /* lock 0-byte shared
    1786             :          * Note: Order of the shared/exclusive locks doesn't matter. */
    1787           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1788           3 :         status = smb_raw_lock(cli->tree, &io);
    1789           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1790             : 
    1791             :         /* lock 0-byte exclusive */
    1792           3 :         io.lockx.in.mode = 0;
    1793           3 :         status = smb_raw_lock(cli->tree, &io);
    1794           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1795             : 
    1796             :         /* test contention */
    1797           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1798           3 :         io.lockx.in.locks = &lock2;
    1799           3 :         io.lockx.in.file.fnum = fnum2;
    1800           3 :         status = smb_raw_lock(cli->tree, &io);
    1801           3 :         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
    1802             :             NT_STATUS_FILE_LOCK_CONFLICT);
    1803             : 
    1804             :         /* unlock */
    1805           3 :         io.lockx.in.ulock_cnt = 1;
    1806           3 :         io.lockx.in.lock_cnt = 0;
    1807           3 :         io.lockx.in.file.fnum = fnum1;
    1808           3 :         io.lockx.in.locks = &lock1;
    1809           3 :         status = smb_raw_lock(cli->tree, &io);
    1810           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1811             : 
    1812             :         /* test - can we take a shared lock? */
    1813           3 :         io.lockx.in.ulock_cnt = 0;
    1814           3 :         io.lockx.in.lock_cnt = 1;
    1815           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1816           3 :         io.lockx.in.file.fnum = fnum2;
    1817           3 :         io.lockx.in.locks = &lock2;
    1818           3 :         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           3 :         if (TARGET_IS_SAMBA3(tctx)) {
    1826           2 :                 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           3 :         io.lockx.in.ulock_cnt = 1;
    1834           3 :         io.lockx.in.lock_cnt = 0;
    1835           3 :         status = smb_raw_lock(cli->tree, &io);
    1836             : 
    1837             :         /* XXX Same as above. */
    1838           3 :         if (TARGET_IS_SAMBA3(tctx)) {
    1839           2 :                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1840             :         } else {
    1841           1 :                 CHECK_STATUS(status, NT_STATUS_OK);
    1842             :         }
    1843             : 
    1844           3 :         io.lockx.in.file.fnum = fnum1;
    1845           3 :         io.lockx.in.locks = &lock1;
    1846           3 :         status = smb_raw_lock(cli->tree, &io);
    1847           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1848             : 
    1849           3 : done:
    1850           3 :         smbcli_close(cli->tree, fnum1);
    1851           3 :         smbcli_close(cli->tree, fnum2);
    1852           3 :         smb_raw_exit(cli->session);
    1853           3 :         smbcli_deltree(cli->tree, BASEDIR);
    1854           3 :         return ret;
    1855             : }
    1856             : 
    1857           3 : static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
    1858             : {
    1859           0 :         union smb_lock io;
    1860           0 :         NTSTATUS status;
    1861           3 :         bool ret = true;
    1862           0 :         int fnum1;
    1863           3 :         const char *fname = BASEDIR "\\unlock_multiple.txt";
    1864           0 :         struct smb_lock_entry lock1;
    1865           0 :         struct smb_lock_entry lock2;
    1866           0 :         struct smb_lock_entry locks[2];
    1867             : 
    1868           3 :         torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
    1869             : 
    1870           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    1871             : 
    1872           3 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    1873           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    1879           3 :         io.lockx.in.timeout = 0;
    1880             : 
    1881           3 :         lock1.pid = cli->session->pid;
    1882           3 :         lock1.offset = 0;
    1883           3 :         lock1.count = 10;
    1884           3 :         lock2.pid = cli->session->pid;
    1885           3 :         lock2.offset = 10;
    1886           3 :         lock2.count = 10;
    1887             : 
    1888           3 :         locks[0] = lock1;
    1889           3 :         locks[1] = lock2;
    1890             : 
    1891           3 :         io.lockx.in.file.fnum = fnum1;
    1892           3 :         io.lockx.in.mode = 0; /* exclusive */
    1893             : 
    1894             :         /** Test1: Take second lock, but not first. */
    1895           3 :         torture_comment(tctx, "  unlock 2 locks, first one not locked. Expect no locks "
    1896             :             "unlocked. \n");
    1897             : 
    1898           3 :         io.lockx.in.ulock_cnt = 0;
    1899           3 :         io.lockx.in.lock_cnt = 1;
    1900           3 :         io.lockx.in.locks = &lock2;
    1901           3 :         status = smb_raw_lock(cli->tree, &io);
    1902           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1903             : 
    1904             :         /* Try to unlock both locks. */
    1905           3 :         io.lockx.in.ulock_cnt = 2;
    1906           3 :         io.lockx.in.lock_cnt = 0;
    1907           3 :         io.lockx.in.locks = locks;
    1908             : 
    1909           3 :         status = smb_raw_lock(cli->tree, &io);
    1910           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1911             : 
    1912             :         /* Second lock should not be unlocked. */
    1913           3 :         io.lockx.in.ulock_cnt = 0;
    1914           3 :         io.lockx.in.lock_cnt = 1;
    1915           3 :         io.lockx.in.locks = &lock2;
    1916           3 :         status = smb_raw_lock(cli->tree, &io);
    1917           3 :         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
    1918             : 
    1919             :         /* cleanup */
    1920           3 :         io.lockx.in.ulock_cnt = 1;
    1921           3 :         io.lockx.in.lock_cnt = 0;
    1922           3 :         io.lockx.in.locks = &lock2;
    1923           3 :         status = smb_raw_lock(cli->tree, &io);
    1924           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1925             : 
    1926             :         /** Test2: Take first lock, but not second. */
    1927           3 :         torture_comment(tctx, "  unlock 2 locks, second one not locked. Expect first lock "
    1928             :             "unlocked.\n");
    1929             : 
    1930           3 :         io.lockx.in.ulock_cnt = 0;
    1931           3 :         io.lockx.in.lock_cnt = 1;
    1932           3 :         io.lockx.in.locks = &lock1;
    1933           3 :         status = smb_raw_lock(cli->tree, &io);
    1934           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1935             : 
    1936             :         /* Try to unlock both locks. */
    1937           3 :         io.lockx.in.ulock_cnt = 2;
    1938           3 :         io.lockx.in.lock_cnt = 0;
    1939           3 :         io.lockx.in.locks = locks;
    1940             : 
    1941           3 :         status = smb_raw_lock(cli->tree, &io);
    1942           3 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
    1943             : 
    1944             :         /* First lock should be unlocked. */
    1945           3 :         io.lockx.in.ulock_cnt = 0;
    1946           3 :         io.lockx.in.lock_cnt = 1;
    1947           3 :         io.lockx.in.locks = &lock1;
    1948           3 :         status = smb_raw_lock(cli->tree, &io);
    1949           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1950             : 
    1951             :         /* cleanup */
    1952           3 :         io.lockx.in.ulock_cnt = 1;
    1953           3 :         io.lockx.in.lock_cnt = 0;
    1954           3 :         io.lockx.in.locks = &lock1;
    1955           3 :         status = smb_raw_lock(cli->tree, &io);
    1956           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1957             : 
    1958             :         /* Test3: Request 2 locks, second will contend.  What happens to the
    1959             :          * first? */
    1960           3 :         torture_comment(tctx, "  request 2 locks, second one will contend. "
    1961             :            "Expect both to fail.\n");
    1962             : 
    1963             :         /* Lock the second range */
    1964           3 :         io.lockx.in.ulock_cnt = 0;
    1965           3 :         io.lockx.in.lock_cnt = 1;
    1966           3 :         io.lockx.in.locks = &lock2;
    1967           3 :         status = smb_raw_lock(cli->tree, &io);
    1968           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1969             : 
    1970             :         /* Request both locks */
    1971           3 :         io.lockx.in.ulock_cnt = 0;
    1972           3 :         io.lockx.in.lock_cnt = 2;
    1973           3 :         io.lockx.in.locks = locks;
    1974             : 
    1975           3 :         status = smb_raw_lock(cli->tree, &io);
    1976           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    1977             : 
    1978             :         /* First lock should be unlocked. */
    1979           3 :         io.lockx.in.ulock_cnt = 0;
    1980           3 :         io.lockx.in.lock_cnt = 1;
    1981           3 :         io.lockx.in.locks = &lock1;
    1982           3 :         status = smb_raw_lock(cli->tree, &io);
    1983           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1984             : 
    1985             :         /* cleanup */
    1986           3 :         io.lockx.in.ulock_cnt = 2;
    1987           3 :         io.lockx.in.lock_cnt = 0;
    1988           3 :         io.lockx.in.locks = locks;
    1989           3 :         status = smb_raw_lock(cli->tree, &io);
    1990           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    1991             : 
    1992             :         /* Test4: Request unlock and lock. The lock contends, is the unlock
    1993             :          * then re-locked? */
    1994           3 :         torture_comment(tctx, "  request unlock and lock, second one will "
    1995             :            "contend. Expect the unlock to succeed.\n");
    1996             : 
    1997             :         /* Lock both ranges */
    1998           3 :         io.lockx.in.ulock_cnt = 0;
    1999           3 :         io.lockx.in.lock_cnt = 2;
    2000           3 :         io.lockx.in.locks = locks;
    2001           3 :         status = smb_raw_lock(cli->tree, &io);
    2002           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2003             : 
    2004             :         /* Attempt to unlock the first range and lock the second */
    2005           3 :         io.lockx.in.ulock_cnt = 1;
    2006           3 :         io.lockx.in.lock_cnt = 1;
    2007           3 :         io.lockx.in.locks = locks;
    2008           3 :         status = smb_raw_lock(cli->tree, &io);
    2009           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2010             : 
    2011             :         /* The first lock should've been unlocked */
    2012           3 :         io.lockx.in.ulock_cnt = 0;
    2013           3 :         io.lockx.in.lock_cnt = 1;
    2014           3 :         io.lockx.in.locks = &lock1;
    2015           3 :         status = smb_raw_lock(cli->tree, &io);
    2016           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2017             : 
    2018             :         /* cleanup */
    2019           3 :         io.lockx.in.ulock_cnt = 2;
    2020           3 :         io.lockx.in.lock_cnt = 0;
    2021           3 :         io.lockx.in.locks = locks;
    2022           3 :         status = smb_raw_lock(cli->tree, &io);
    2023           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2024             : 
    2025           3 : done:
    2026           3 :         smbcli_close(cli->tree, fnum1);
    2027           3 :         smb_raw_exit(cli->session);
    2028           3 :         smbcli_deltree(cli->tree, BASEDIR);
    2029           3 :         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           3 : static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
    2038             : {
    2039           0 :         union smb_lock io;
    2040           0 :         NTSTATUS status;
    2041           3 :         bool ret = true;
    2042           0 :         int fnum1;
    2043           3 :         const char *fname = BASEDIR "\\stacking.txt";
    2044           0 :         struct smb_lock_entry lock1;
    2045             : 
    2046           3 :         torture_comment(tctx, "Testing stacking:\n");
    2047             : 
    2048           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2049             : 
    2050           3 :         io.generic.level = RAW_LOCK_LOCKX;
    2051             : 
    2052           3 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2053           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    2059           3 :         io.lockx.in.timeout = 0;
    2060             : 
    2061           3 :         lock1.pid = cli->session->pid;
    2062           3 :         lock1.offset = 0;
    2063           3 :         lock1.count = 10;
    2064             : 
    2065             :         /**
    2066             :          * Try to take a shared lock, then stack an exclusive.
    2067             :          */
    2068           3 :         torture_comment(tctx, "  stacking an exclusive on top of a shared lock fails.\n");
    2069           3 :         io.lockx.in.file.fnum = fnum1;
    2070           3 :         io.lockx.in.locks = &lock1;
    2071             : 
    2072           3 :         io.lockx.in.ulock_cnt = 0;
    2073           3 :         io.lockx.in.lock_cnt = 1;
    2074           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    2075           3 :         status = smb_raw_lock(cli->tree, &io);
    2076           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2077             : 
    2078           3 :         io.lockx.in.ulock_cnt = 0;
    2079           3 :         io.lockx.in.lock_cnt = 1;
    2080           3 :         io.lockx.in.mode = 0;
    2081           3 :         status = smb_raw_lock(cli->tree, &io);
    2082           3 :         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
    2083             :             NT_STATUS_FILE_LOCK_CONFLICT);
    2084             : 
    2085             :         /* cleanup */
    2086           3 :         io.lockx.in.ulock_cnt = 1;
    2087           3 :         io.lockx.in.lock_cnt = 0;
    2088           3 :         status = smb_raw_lock(cli->tree, &io);
    2089           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2090             : 
    2091             :         /**
    2092             :          * Prove that two exclusive locks do not stack.
    2093             :          */
    2094           3 :         torture_comment(tctx, "  two exclusive locks do not stack.\n");
    2095           3 :         io.lockx.in.ulock_cnt = 0;
    2096           3 :         io.lockx.in.lock_cnt = 1;
    2097           3 :         io.lockx.in.mode = 0;
    2098           3 :         status = smb_raw_lock(cli->tree, &io);
    2099           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2100           3 :         status = smb_raw_lock(cli->tree, &io);
    2101           3 :         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
    2102             :             NT_STATUS_FILE_LOCK_CONFLICT);
    2103             : 
    2104             :         /* cleanup */
    2105           3 :         io.lockx.in.ulock_cnt = 1;
    2106           3 :         io.lockx.in.lock_cnt = 0;
    2107           3 :         status = smb_raw_lock(cli->tree, &io);
    2108           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2109             : 
    2110           3 : done:
    2111           3 :         smbcli_close(cli->tree, fnum1);
    2112           3 :         smb_raw_exit(cli->session);
    2113           3 :         smbcli_deltree(cli->tree, BASEDIR);
    2114           3 :         return ret;
    2115             : }
    2116             : 
    2117             : /**
    2118             :  * Test how 0-byte read requests contend with byte range locks
    2119             :  */
    2120           3 : static bool test_zerobyteread(struct torture_context *tctx,
    2121             :                               struct smbcli_state *cli)
    2122             : {
    2123           0 :         union smb_lock io;
    2124           0 :         union smb_read rd;
    2125           0 :         NTSTATUS status;
    2126           3 :         bool ret = true;
    2127           0 :         int fnum1, fnum2;
    2128           3 :         const char *fname = BASEDIR "\\zerobyteread.txt";
    2129           0 :         struct smb_lock_entry lock1;
    2130           3 :         uint8_t c = 1;
    2131             : 
    2132           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2133             : 
    2134           3 :         io.generic.level = RAW_LOCK_LOCKX;
    2135             : 
    2136           3 :         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2137           3 :         torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
    2138             :                        "Failed to create %s - %s\n",
    2139             :                        fname, smbcli_errstr(cli->tree)));
    2140             : 
    2141           3 :         fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2142           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    2148           3 :         io.lockx.in.timeout = 0;
    2149             : 
    2150           3 :         lock1.pid = cli->session->pid;
    2151           3 :         lock1.offset = 0;
    2152           3 :         lock1.count = 10;
    2153             : 
    2154           3 :         ZERO_STRUCT(rd);
    2155           3 :         rd.readx.level = RAW_READ_READX;
    2156             : 
    2157           3 :         torture_comment(tctx, "Testing zero byte read on lock range:\n");
    2158             : 
    2159             :         /* Take an exclusive lock */
    2160           3 :         torture_comment(tctx, "  taking exclusive lock.\n");
    2161           3 :         io.lockx.in.ulock_cnt = 0;
    2162           3 :         io.lockx.in.lock_cnt = 1;
    2163           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2164           3 :         io.lockx.in.file.fnum = fnum1;
    2165           3 :         io.lockx.in.locks = &lock1;
    2166           3 :         status = smb_raw_lock(cli->tree, &io);
    2167           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2168             : 
    2169             :         /* Try a zero byte read */
    2170           3 :         torture_comment(tctx, "  reading 0 bytes.\n");
    2171           3 :         rd.readx.in.file.fnum = fnum2;
    2172           3 :         rd.readx.in.offset    = 5;
    2173           3 :         rd.readx.in.mincnt    = 0;
    2174           3 :         rd.readx.in.maxcnt    = 0;
    2175           3 :         rd.readx.in.remaining = 0;
    2176           3 :         rd.readx.in.read_for_execute = false;
    2177           3 :         rd.readx.out.data     = &c;
    2178           3 :         status = smb_raw_read(cli->tree, &rd);
    2179           3 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2180             :                                       "zero byte read did not return 0 bytes");
    2181           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2182             : 
    2183             :         /* Unlock lock */
    2184           2 :         io.lockx.in.ulock_cnt = 1;
    2185           2 :         io.lockx.in.lock_cnt = 0;
    2186           2 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2187           2 :         io.lockx.in.file.fnum = fnum1;
    2188           2 :         io.lockx.in.locks = &lock1;
    2189           2 :         status = smb_raw_lock(cli->tree, &io);
    2190           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    2191             : 
    2192           2 :         torture_comment(tctx, "Testing zero byte read on zero byte lock "
    2193             :                               "range:\n");
    2194             : 
    2195             :         /* Take an exclusive lock */
    2196           2 :         torture_comment(tctx, "  taking exclusive 0-byte lock.\n");
    2197           2 :         io.lockx.in.ulock_cnt = 0;
    2198           2 :         io.lockx.in.lock_cnt = 1;
    2199           2 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2200           2 :         io.lockx.in.file.fnum = fnum1;
    2201           2 :         io.lockx.in.locks = &lock1;
    2202           2 :         lock1.offset = 5;
    2203           2 :         lock1.count = 0;
    2204           2 :         status = smb_raw_lock(cli->tree, &io);
    2205           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    2206             : 
    2207             :         /* Try a zero byte read before the lock */
    2208           2 :         torture_comment(tctx, "  reading 0 bytes before the lock.\n");
    2209           2 :         rd.readx.in.file.fnum = fnum2;
    2210           2 :         rd.readx.in.offset    = 4;
    2211           2 :         rd.readx.in.mincnt    = 0;
    2212           2 :         rd.readx.in.maxcnt    = 0;
    2213           2 :         rd.readx.in.remaining = 0;
    2214           2 :         rd.readx.in.read_for_execute = false;
    2215           2 :         rd.readx.out.data     = &c;
    2216           2 :         status = smb_raw_read(cli->tree, &rd);
    2217           2 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2218             :                                       "zero byte read did not return 0 bytes");
    2219           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    2220             : 
    2221             :         /* Try a zero byte read on the lock */
    2222           2 :         torture_comment(tctx, "  reading 0 bytes on the lock.\n");
    2223           2 :         rd.readx.in.file.fnum = fnum2;
    2224           2 :         rd.readx.in.offset    = 5;
    2225           2 :         rd.readx.in.mincnt    = 0;
    2226           2 :         rd.readx.in.maxcnt    = 0;
    2227           2 :         rd.readx.in.remaining = 0;
    2228           2 :         rd.readx.in.read_for_execute = false;
    2229           2 :         rd.readx.out.data     = &c;
    2230           2 :         status = smb_raw_read(cli->tree, &rd);
    2231           2 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2232             :                                       "zero byte read did not return 0 bytes");
    2233           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    2234             : 
    2235             :         /* Try a zero byte read after the lock */
    2236           2 :         torture_comment(tctx, "  reading 0 bytes after the lock.\n");
    2237           2 :         rd.readx.in.file.fnum = fnum2;
    2238           2 :         rd.readx.in.offset    = 6;
    2239           2 :         rd.readx.in.mincnt    = 0;
    2240           2 :         rd.readx.in.maxcnt    = 0;
    2241           2 :         rd.readx.in.remaining = 0;
    2242           2 :         rd.readx.in.read_for_execute = false;
    2243           2 :         rd.readx.out.data     = &c;
    2244           2 :         status = smb_raw_read(cli->tree, &rd);
    2245           2 :         torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
    2246             :                                       "zero byte read did not return 0 bytes");
    2247           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    2248             : 
    2249             :         /* Unlock lock */
    2250           2 :         io.lockx.in.ulock_cnt = 1;
    2251           2 :         io.lockx.in.lock_cnt = 0;
    2252           2 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2253           2 :         io.lockx.in.file.fnum = fnum1;
    2254           2 :         io.lockx.in.locks = &lock1;
    2255           2 :         status = smb_raw_lock(cli->tree, &io);
    2256           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    2257             : 
    2258           3 : done:
    2259           3 :         smbcli_close(cli->tree, fnum1);
    2260           3 :         smbcli_close(cli->tree, fnum2);
    2261           3 :         smb_raw_exit(cli->session);
    2262           3 :         smbcli_deltree(cli->tree, BASEDIR);
    2263           3 :         return ret;
    2264             : }
    2265             : /*
    2266             :   test multi Locking&X operation
    2267             : */
    2268           3 : static bool test_multilock(struct torture_context *tctx,
    2269             :                                            struct smbcli_state *cli)
    2270             : {
    2271           0 :         union smb_lock io;
    2272           0 :         struct smb_lock_entry lock[2];
    2273           0 :         NTSTATUS status;
    2274           3 :         bool ret = true;
    2275           0 :         int fnum;
    2276           3 :         const char *fname = BASEDIR "\\multilock_test.txt";
    2277           0 :         time_t t;
    2278           0 :         struct smbcli_request *req;
    2279           0 :         struct smbcli_session_options options;
    2280             : 
    2281           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2282             : 
    2283           3 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
    2284             : 
    2285           3 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock\n");
    2286           3 :         io.generic.level = RAW_LOCK_LOCKX;
    2287             : 
    2288             :         /* Create the test file. */
    2289           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2290           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    2299           3 :         io.lockx.in.file.fnum = fnum;
    2300           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2301           3 :         io.lockx.in.timeout = 0;
    2302           3 :         io.lockx.in.ulock_cnt = 0;
    2303           3 :         io.lockx.in.lock_cnt = 2;
    2304           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2305           3 :         lock[0].pid = cli->session->pid;
    2306           3 :         lock[0].offset = 100;
    2307           3 :         lock[0].count = 10;
    2308           3 :         lock[1].pid = cli->session->pid;
    2309           3 :         lock[1].offset = 120;
    2310           3 :         lock[1].count = 10;
    2311           3 :         io.lockx.in.locks = &lock[0];
    2312           3 :         status = smb_raw_lock(cli->tree, &io);
    2313           3 :         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           3 :         io.lockx.in.timeout = 20000;
    2321           3 :         lock[0].pid = cli->session->pid+1;
    2322           3 :         lock[1].pid = cli->session->pid+1;
    2323           3 :         req = smb_raw_lock_send(cli->tree, &io);
    2324           3 :         torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
    2325             :                        "Failed to setup timed locks (%s)\n", __location__));
    2326             : 
    2327             :         /* Unlock lock[0] */
    2328           3 :         io.lockx.in.timeout = 0;
    2329           3 :         io.lockx.in.ulock_cnt = 1;
    2330           3 :         io.lockx.in.lock_cnt = 0;
    2331           3 :         io.lockx.in.locks = &lock[0];
    2332           3 :         lock[0].pid = cli->session->pid;
    2333           3 :         status = smb_raw_lock(cli->tree, &io);
    2334           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2335             : 
    2336             :         /* Start the clock. */
    2337           3 :         t = time_mono(NULL);
    2338             : 
    2339             :         /* Unlock lock[1] */
    2340           3 :         io.lockx.in.timeout = 0;
    2341           3 :         io.lockx.in.ulock_cnt = 1;
    2342           3 :         io.lockx.in.lock_cnt = 0;
    2343           3 :         io.lockx.in.locks = &lock[1];
    2344           3 :         lock[1].pid = cli->session->pid;
    2345           3 :         status = smb_raw_lock(cli->tree, &io);
    2346           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2347             : 
    2348             :         /* receive the successful blocked lock requests */
    2349           3 :         status = smbcli_request_simple_recv(req);
    2350           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2351             : 
    2352             :         /* Fail if this took more than 2 seconds. */
    2353           3 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    2354             :                        "Blocking locks were not granted immediately (%s)\n",
    2355             :                        __location__));
    2356           3 : done:
    2357           3 :         smb_raw_exit(cli->session);
    2358           3 :         smbcli_deltree(cli->tree, BASEDIR);
    2359           3 :         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 satisfied 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           3 : static bool test_multilock2(struct torture_context *tctx,
    2383             :                                            struct smbcli_state *cli)
    2384             : {
    2385           0 :         union smb_lock io;
    2386           0 :         struct smb_lock_entry lock[2];
    2387           0 :         NTSTATUS status;
    2388           3 :         bool ret = true;
    2389           0 :         int fnum;
    2390           3 :         const char *fname = BASEDIR "\\multilock2_test.txt";
    2391           0 :         time_t t;
    2392           0 :         struct smbcli_request *req;
    2393           0 :         struct smbcli_request *req2;
    2394           0 :         struct smbcli_session_options options;
    2395             : 
    2396           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
    2397             : 
    2398           3 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
    2399             : 
    2400           3 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 2\n");
    2401           3 :         io.generic.level = RAW_LOCK_LOCKX;
    2402             : 
    2403             :         /* Create the test file. */
    2404           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2405           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    2414           3 :         io.lockx.in.file.fnum = fnum;
    2415           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2416           3 :         io.lockx.in.timeout = 0;
    2417           3 :         io.lockx.in.ulock_cnt = 0;
    2418           3 :         io.lockx.in.lock_cnt = 2;
    2419           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2420           3 :         lock[0].pid = cli->session->pid;
    2421           3 :         lock[0].offset = 100;
    2422           3 :         lock[0].count = 10;
    2423           3 :         lock[1].pid = cli->session->pid;
    2424           3 :         lock[1].offset = 120;
    2425           3 :         lock[1].count = 10;
    2426           3 :         io.lockx.in.locks = &lock[0];
    2427           3 :         status = smb_raw_lock(cli->tree, &io);
    2428           3 :         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           3 :         io.lockx.in.timeout = 20000;
    2436           3 :         lock[0].pid = cli->session->pid+1;
    2437           3 :         lock[1].pid = cli->session->pid+1;
    2438           3 :         req = smb_raw_lock_send(cli->tree, &io);
    2439           3 :         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           3 :         io.lockx.in.timeout = 2000;
    2449           3 :         lock[0].pid = cli->session->pid+2;
    2450           3 :         io.lockx.in.lock_cnt = 1;
    2451           3 :         req2 = smb_raw_lock_send(cli->tree, &io);
    2452           3 :         torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
    2453             :                        "Failed to setup timed locks (%s)\n", __location__));
    2454             : 
    2455             :         /* Unlock lock[0] */
    2456           3 :         io.lockx.in.timeout = 0;
    2457           3 :         io.lockx.in.ulock_cnt = 1;
    2458           3 :         io.lockx.in.lock_cnt = 0;
    2459           3 :         io.lockx.in.locks = &lock[0];
    2460           3 :         lock[0].pid = cli->session->pid;
    2461           3 :         status = smb_raw_lock(cli->tree, &io);
    2462           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2463             : 
    2464             :         /* Did the second lock complete (should time out) ? */
    2465           3 :         status = smbcli_request_simple_recv(req2);
    2466           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2467             : 
    2468           3 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2469             :                        "req should still wait");
    2470             : 
    2471             :         /* Start the clock. */
    2472           3 :         t = time_mono(NULL);
    2473             : 
    2474             :         /* Unlock lock[1] */
    2475           3 :         io.lockx.in.timeout = 0;
    2476           3 :         io.lockx.in.ulock_cnt = 1;
    2477           3 :         io.lockx.in.lock_cnt = 0;
    2478           3 :         io.lockx.in.locks = &lock[1];
    2479           3 :         lock[1].pid = cli->session->pid;
    2480           3 :         status = smb_raw_lock(cli->tree, &io);
    2481           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2482             : 
    2483             :         /* receive the successful blocked lock requests */
    2484           3 :         status = smbcli_request_simple_recv(req);
    2485           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2486             : 
    2487             :         /* Fail if this took more than 2 seconds. */
    2488           3 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    2489             :                        "Blocking locks were not granted immediately (%s)\n",
    2490             :                        __location__));
    2491           3 : done:
    2492           3 :         smb_raw_exit(cli->session);
    2493           3 :         smbcli_deltree(cli->tree, BASEDIR);
    2494           3 :         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 satisfied 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           3 : static bool test_multilock3(struct torture_context *tctx,
    2536             :                             struct smbcli_state *cli)
    2537             : {
    2538           0 :         union smb_lock io;
    2539           0 :         struct smb_lock_entry lock[2];
    2540           0 :         union smb_lock io3;
    2541           0 :         struct smb_lock_entry lock3[1];
    2542           0 :         NTSTATUS status;
    2543           3 :         bool ret = true;
    2544           0 :         int fnum;
    2545           3 :         const char *fname = BASEDIR "\\multilock3_test.txt";
    2546           0 :         time_t t;
    2547           3 :         struct smbcli_request *req = NULL;
    2548           3 :         struct smbcli_request *req2 = NULL;
    2549           3 :         struct smbcli_request *req4 = NULL;
    2550             : 
    2551           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    2552             :                        "Failed to setup up test directory: " BASEDIR);
    2553             : 
    2554           3 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 3\n");
    2555           3 :         io.generic.level = RAW_LOCK_LOCKX;
    2556             : 
    2557             :         /* Create the test file. */
    2558           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2559           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    2569           3 :         io.lockx.in.file.fnum = fnum;
    2570           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2571           3 :         io.lockx.in.timeout = 0;
    2572           3 :         io.lockx.in.ulock_cnt = 0;
    2573           3 :         io.lockx.in.lock_cnt = 2;
    2574           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2575           3 :         lock[0].pid = cli->session->pid;
    2576           3 :         lock[0].offset = 100;
    2577           3 :         lock[0].count = 10;
    2578           3 :         lock[1].pid = cli->session->pid;
    2579           3 :         lock[1].offset = 120;
    2580           3 :         lock[1].count = 10;
    2581           3 :         io.lockx.in.locks = &lock[0];
    2582           3 :         status = smb_raw_lock(cli->tree, &io);
    2583           3 :         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           3 :         io.lockx.in.timeout = 20000;
    2591           3 :         lock[0].pid = cli->session->pid+1;
    2592           3 :         lock[1].pid = cli->session->pid+1;
    2593           3 :         req = smb_raw_lock_send(cli->tree, &io);
    2594           3 :         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           3 :         io.lockx.in.timeout = 2000;
    2604           3 :         lock[0].pid = cli->session->pid+2;
    2605           3 :         io.lockx.in.lock_cnt = 1;
    2606           3 :         req2 = smb_raw_lock_send(cli->tree, &io);
    2607           3 :         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           3 :         io3.lockx.level = RAW_LOCK_LOCKX;
    2615           3 :         io3.lockx.in.file.fnum = fnum;
    2616           3 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2617           3 :         io3.lockx.in.timeout = 0;
    2618           3 :         io3.lockx.in.ulock_cnt = 0;
    2619           3 :         io3.lockx.in.lock_cnt = 1;
    2620           3 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2621           3 :         lock3[0].pid = cli->session->pid+3;
    2622           3 :         lock3[0].offset = 110;
    2623           3 :         lock3[0].count = 10;
    2624           3 :         io3.lockx.in.locks = &lock3[0];
    2625           3 :         status = smb_raw_lock(cli->tree, &io3);
    2626           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2627             : 
    2628             :         /*
    2629             :          * e)
    2630             :          * try 110-119 again
    2631             :          */
    2632           3 :         io3.lockx.in.timeout = 20000;
    2633           3 :         lock3[0].pid = cli->session->pid+4;
    2634           3 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    2635           3 :         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           3 :         io.lockx.in.timeout = 0;
    2643           3 :         io.lockx.in.ulock_cnt = 1;
    2644           3 :         io.lockx.in.lock_cnt = 0;
    2645           3 :         io.lockx.in.locks = &lock[0];
    2646           3 :         lock[0].pid = cli->session->pid;
    2647           3 :         status = smb_raw_lock(cli->tree, &io);
    2648           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2649             : 
    2650             :         /*
    2651             :          * g)
    2652             :          * try to lock lock[0] 100-109 again
    2653             :          */
    2654           3 :         lock[0].pid = cli->session->pid+5;
    2655           3 :         io.lockx.in.ulock_cnt = 0;
    2656           3 :         io.lockx.in.lock_cnt = 1;
    2657           3 :         status = smb_raw_lock(cli->tree, &io);
    2658           3 :         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           3 :         lock[0].pid = cli->session->pid+1;
    2666           3 :         io.lockx.in.ulock_cnt = 0;
    2667           3 :         io.lockx.in.lock_cnt = 1;
    2668           3 :         status = smb_raw_lock(cli->tree, &io);
    2669           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2670             : 
    2671           3 :         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           3 :         status = smbcli_request_simple_recv(req2);
    2679           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2680             : 
    2681           3 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2682             :                        "req should still wait");
    2683           3 :         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           3 :         io3.lockx.in.timeout = 0;
    2691           3 :         io3.lockx.in.ulock_cnt = 1;
    2692           3 :         io3.lockx.in.lock_cnt = 0;
    2693           3 :         lock3[0].pid = cli->session->pid+3;
    2694           3 :         status = smb_raw_lock(cli->tree, &io3);
    2695           3 :         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           3 :         status = smbcli_request_simple_recv(req4);
    2703           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2704             : 
    2705             :         /*
    2706             :          * l)
    2707             :          * try to lock lock[0] 100-109 again
    2708             :          */
    2709           3 :         lock[0].pid = cli->session->pid+6;
    2710           3 :         io.lockx.in.ulock_cnt = 0;
    2711           3 :         io.lockx.in.lock_cnt = 1;
    2712           3 :         status = smb_raw_lock(cli->tree, &io);
    2713           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2714             : 
    2715           3 :         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           3 :         lock[0].pid = cli->session->pid+1;
    2724           3 :         io.lockx.in.ulock_cnt = 0;
    2725           3 :         io.lockx.in.lock_cnt = 1;
    2726           3 :         status = smb_raw_lock(cli->tree, &io);
    2727           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2728             : 
    2729           3 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2730             :                        "req should still wait");
    2731             : 
    2732             :         /* Start the clock. */
    2733           3 :         t = time_mono(NULL);
    2734             : 
    2735             :         /*
    2736             :          * n)
    2737             :          * Unlock lock[1] 120-129 */
    2738           3 :         io.lockx.in.timeout = 0;
    2739           3 :         io.lockx.in.ulock_cnt = 1;
    2740           3 :         io.lockx.in.lock_cnt = 0;
    2741           3 :         io.lockx.in.locks = &lock[1];
    2742           3 :         lock[1].pid = cli->session->pid;
    2743           3 :         status = smb_raw_lock(cli->tree, &io);
    2744           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2745             : 
    2746             :         /*
    2747             :          * o)
    2748             :          * receive the successful blocked lock request (b)
    2749             :          */
    2750           3 :         status = smbcli_request_simple_recv(req);
    2751           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2752             : 
    2753             :         /* Fail if this took more than 2 seconds. */
    2754           3 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    2755             :                        "Blocking locks were not granted immediately (%s)\n",
    2756             :                        __location__));
    2757           3 : done:
    2758           3 :         smb_raw_exit(cli->session);
    2759           3 :         smbcli_deltree(cli->tree, BASEDIR);
    2760           3 :         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           3 : static bool test_multilock4(struct torture_context *tctx,
    2802             :                             struct smbcli_state *cli)
    2803             : {
    2804           0 :         union smb_lock io;
    2805           0 :         struct smb_lock_entry lock[2];
    2806           0 :         union smb_lock io3;
    2807           0 :         struct smb_lock_entry lock3[1];
    2808           0 :         NTSTATUS status;
    2809           3 :         bool ret = true;
    2810           0 :         int fnum;
    2811           3 :         const char *fname = BASEDIR "\\multilock4_test.txt";
    2812           0 :         time_t t;
    2813           3 :         struct smbcli_request *req = NULL;
    2814           3 :         struct smbcli_request *req2 = NULL;
    2815           3 :         struct smbcli_request *req4 = NULL;
    2816             : 
    2817           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    2818             :                        "Failed to setup up test directory: " BASEDIR);
    2819             : 
    2820           3 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 4\n");
    2821           3 :         io.generic.level = RAW_LOCK_LOCKX;
    2822             : 
    2823             :         /* Create the test file. */
    2824           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    2825           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    2835           3 :         io.lockx.in.file.fnum = fnum;
    2836           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2837           3 :         io.lockx.in.timeout = 0;
    2838           3 :         io.lockx.in.ulock_cnt = 0;
    2839           3 :         io.lockx.in.lock_cnt = 2;
    2840           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2841           3 :         lock[0].pid = cli->session->pid;
    2842           3 :         lock[0].offset = 100;
    2843           3 :         lock[0].count = 10;
    2844           3 :         lock[1].pid = cli->session->pid;
    2845           3 :         lock[1].offset = 120;
    2846           3 :         lock[1].count = 10;
    2847           3 :         io.lockx.in.locks = &lock[0];
    2848           3 :         status = smb_raw_lock(cli->tree, &io);
    2849           3 :         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           3 :         io.lockx.in.timeout = 20000;
    2857           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    2858           3 :         lock[0].pid = cli->session->pid+1;
    2859           3 :         lock[1].pid = cli->session->pid+1;
    2860           3 :         req = smb_raw_lock_send(cli->tree, &io);
    2861           3 :         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           3 :         io.lockx.in.timeout = UINT32_MAX;
    2871           3 :         lock[0].pid = cli->session->pid+2;
    2872           3 :         io.lockx.in.lock_cnt = 1;
    2873           3 :         req2 = smb_raw_lock_send(cli->tree, &io);
    2874           3 :         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           3 :         io3.lockx.level = RAW_LOCK_LOCKX;
    2882           3 :         io3.lockx.in.file.fnum = fnum;
    2883           3 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    2884           3 :         io3.lockx.in.timeout = 0;
    2885           3 :         io3.lockx.in.ulock_cnt = 0;
    2886           3 :         io3.lockx.in.lock_cnt = 1;
    2887           3 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2888           3 :         lock3[0].pid = cli->session->pid+3;
    2889           3 :         lock3[0].offset = 110;
    2890           3 :         lock3[0].count = 10;
    2891           3 :         io3.lockx.in.locks = &lock3[0];
    2892           3 :         status = smb_raw_lock(cli->tree, &io3);
    2893           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2894             : 
    2895             :         /*
    2896             :          * e)
    2897             :          * try 110-119 again
    2898             :          */
    2899           3 :         io3.lockx.in.timeout = 20000;
    2900           3 :         lock3[0].pid = cli->session->pid+4;
    2901           3 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    2902           3 :         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           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    2910           3 :         io.lockx.in.timeout = 0;
    2911           3 :         io.lockx.in.ulock_cnt = 1;
    2912           3 :         io.lockx.in.lock_cnt = 0;
    2913           3 :         io.lockx.in.locks = &lock[0];
    2914           3 :         lock[0].pid = cli->session->pid;
    2915           3 :         status = smb_raw_lock(cli->tree, &io);
    2916           3 :         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           3 :         status = smbcli_request_simple_recv(req2);
    2924           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2925             : 
    2926             :         /*
    2927             :          * h)
    2928             :          * try to lock lock[0] 100-109 again
    2929             :          * (read/write)
    2930             :          */
    2931           3 :         lock[0].pid = cli->session->pid+5;
    2932           3 :         io.lockx.in.ulock_cnt = 0;
    2933           3 :         io.lockx.in.lock_cnt = 1;
    2934           3 :         status = smb_raw_lock(cli->tree, &io);
    2935           3 :         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           3 :         lock[0].pid = cli->session->pid+1;
    2943           3 :         io.lockx.in.ulock_cnt = 0;
    2944           3 :         io.lockx.in.lock_cnt = 1;
    2945           3 :         status = smb_raw_lock(cli->tree, &io);
    2946           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2947             : 
    2948           3 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2949             :                        "req should still wait");
    2950           3 :         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           3 :         io3.lockx.in.timeout = 0;
    2958           3 :         io3.lockx.in.ulock_cnt = 1;
    2959           3 :         io3.lockx.in.lock_cnt = 0;
    2960           3 :         lock3[0].pid = cli->session->pid+3;
    2961           3 :         status = smb_raw_lock(cli->tree, &io3);
    2962           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2963             : 
    2964             :         /*
    2965             :          * k)
    2966             :          * receive the successful blocked
    2967             :          * lock request (e) on 110-119.
    2968             :          */
    2969           3 :         status = smbcli_request_simple_recv(req4);
    2970           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    2971             : 
    2972             :         /*
    2973             :          * l)
    2974             :          * try to lock lock[0] 100-109 again
    2975             :          */
    2976           3 :         lock[0].pid = cli->session->pid+6;
    2977           3 :         io.lockx.in.ulock_cnt = 0;
    2978           3 :         io.lockx.in.lock_cnt = 1;
    2979           3 :         status = smb_raw_lock(cli->tree, &io);
    2980           3 :         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           3 :         lock[0].pid = cli->session->pid+1;
    2988           3 :         io.lockx.in.ulock_cnt = 0;
    2989           3 :         io.lockx.in.lock_cnt = 1;
    2990           3 :         status = smb_raw_lock(cli->tree, &io);
    2991           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    2992             : 
    2993           3 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    2994             :                        "req should still wait");
    2995             : 
    2996             :         /* Start the clock. */
    2997           3 :         t = time_mono(NULL);
    2998             : 
    2999             :         /*
    3000             :          * n)
    3001             :          * Unlock (a) lock[1] 120-129
    3002             :          */
    3003           3 :         io.lockx.in.timeout = 0;
    3004           3 :         io.lockx.in.ulock_cnt = 1;
    3005           3 :         io.lockx.in.lock_cnt = 0;
    3006           3 :         io.lockx.in.locks = &lock[1];
    3007           3 :         lock[1].pid = cli->session->pid;
    3008           3 :         status = smb_raw_lock(cli->tree, &io);
    3009           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3010             : 
    3011             :         /*
    3012             :          * o)
    3013             :          * receive the successful blocked lock request (b)
    3014             :          */
    3015           3 :         status = smbcli_request_simple_recv(req);
    3016           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3017             : 
    3018             :         /* Fail if this took more than 2 seconds. */
    3019           3 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    3020             :                        "Blocking locks were not granted immediately (%s)\n",
    3021             :                        __location__));
    3022           3 : done:
    3023           3 :         smb_raw_exit(cli->session);
    3024           3 :         smbcli_deltree(cli->tree, BASEDIR);
    3025           3 :         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           3 : static bool test_multilock5(struct torture_context *tctx,
    3062             :                             struct smbcli_state *cli)
    3063             : {
    3064           0 :         union smb_lock io;
    3065           0 :         struct smb_lock_entry lock[2];
    3066           0 :         union smb_lock io3;
    3067           0 :         struct smb_lock_entry lock3[1];
    3068           0 :         NTSTATUS status;
    3069           3 :         bool ret = true;
    3070           0 :         int fnum;
    3071           3 :         const char *fname = BASEDIR "\\multilock5_test.txt";
    3072           0 :         time_t t;
    3073           3 :         struct smbcli_request *req = NULL;
    3074           3 :         struct smbcli_request *req2 = NULL;
    3075           3 :         struct smbcli_request *req4 = NULL;
    3076             : 
    3077           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    3078             :                        "Failed to setup up test directory: " BASEDIR);
    3079             : 
    3080           3 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 5\n");
    3081           3 :         io.generic.level = RAW_LOCK_LOCKX;
    3082             : 
    3083             :         /* Create the test file. */
    3084           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    3085           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    3096           3 :         io.lockx.in.file.fnum = fnum;
    3097           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3098           3 :         io.lockx.in.timeout = 0;
    3099           3 :         io.lockx.in.ulock_cnt = 0;
    3100           3 :         io.lockx.in.lock_cnt = 2;
    3101           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    3102           3 :         lock[0].pid = cli->session->pid;
    3103           3 :         lock[0].offset = 100;
    3104           3 :         lock[0].count = 10;
    3105           3 :         lock[1].pid = cli->session->pid;
    3106           3 :         lock[1].offset = 120;
    3107           3 :         lock[1].count = 10;
    3108           3 :         io.lockx.in.locks = &lock[0];
    3109           3 :         status = smb_raw_lock(cli->tree, &io);
    3110           3 :         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           3 :         io.lockx.in.timeout = 20000;
    3119           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3120           3 :         lock[0].pid = cli->session->pid+1;
    3121           3 :         lock[1].pid = cli->session->pid+1;
    3122           3 :         req = smb_raw_lock_send(cli->tree, &io);
    3123           3 :         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           3 :         io.lockx.in.timeout = 2000;
    3134           3 :         lock[0].pid = cli->session->pid+2;
    3135           3 :         io.lockx.in.lock_cnt = 1;
    3136           3 :         req2 = smb_raw_lock_send(cli->tree, &io);
    3137           3 :         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           3 :         io3.lockx.level = RAW_LOCK_LOCKX;
    3145           3 :         io3.lockx.in.file.fnum = fnum;
    3146           3 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3147           3 :         io3.lockx.in.timeout = 0;
    3148           3 :         io3.lockx.in.ulock_cnt = 0;
    3149           3 :         io3.lockx.in.lock_cnt = 1;
    3150           3 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3151           3 :         lock3[0].pid = cli->session->pid+3;
    3152           3 :         lock3[0].offset = 110;
    3153           3 :         lock3[0].count = 10;
    3154           3 :         io3.lockx.in.locks = &lock3[0];
    3155           3 :         status = smb_raw_lock(cli->tree, &io3);
    3156           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3157             : 
    3158             :         /*
    3159             :          * e)
    3160             :          * try 110-119 again
    3161             :          */
    3162           3 :         io3.lockx.in.timeout = 20000;
    3163           3 :         lock3[0].pid = cli->session->pid+4;
    3164           3 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    3165           3 :         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           3 :         io.lockx.in.timeout = 0;
    3177           3 :         io.lockx.in.ulock_cnt = 1;
    3178           3 :         io.lockx.in.lock_cnt = 0;
    3179           3 :         io.lockx.in.locks = &lock[0];
    3180           3 :         lock[0].pid = cli->session->pid;
    3181           3 :         status = smb_raw_lock(cli->tree, &io);
    3182           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3183             : 
    3184             :         /*
    3185             :          * g)
    3186             :          * try to lock lock[0] 100-109 again
    3187             :          */
    3188           3 :         lock[0].pid = cli->session->pid+5;
    3189           3 :         io.lockx.in.ulock_cnt = 0;
    3190           3 :         io.lockx.in.lock_cnt = 1;
    3191           3 :         status = smb_raw_lock(cli->tree, &io);
    3192           3 :         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           3 :         lock[0].pid = cli->session->pid+1;
    3201           3 :         io.lockx.in.ulock_cnt = 0;
    3202           3 :         io.lockx.in.lock_cnt = 1;
    3203           3 :         status = smb_raw_lock(cli->tree, &io);
    3204           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3205             : 
    3206           3 :         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           3 :         status = smbcli_request_simple_recv(req2);
    3214           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3215             : 
    3216           3 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3217             :                        "req should still wait");
    3218           3 :         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           3 :         io3.lockx.in.timeout = 0;
    3226           3 :         io3.lockx.in.ulock_cnt = 1;
    3227           3 :         io3.lockx.in.lock_cnt = 0;
    3228           3 :         lock3[0].pid = cli->session->pid+3;
    3229           3 :         status = smb_raw_lock(cli->tree, &io3);
    3230           3 :         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           3 :         status = smbcli_request_simple_recv(req4);
    3238           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3239             : 
    3240             :         /*
    3241             :          * l)
    3242             :          * try to lock lock[0] 100-109 again
    3243             :          */
    3244           3 :         lock[0].pid = cli->session->pid+6;
    3245           3 :         io.lockx.in.ulock_cnt = 0;
    3246           3 :         io.lockx.in.lock_cnt = 1;
    3247           3 :         status = smb_raw_lock(cli->tree, &io);
    3248           3 :         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           3 :         lock[0].pid = cli->session->pid+1;
    3256           3 :         io.lockx.in.ulock_cnt = 0;
    3257           3 :         io.lockx.in.lock_cnt = 1;
    3258           3 :         status = smb_raw_lock(cli->tree, &io);
    3259           3 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3260             : 
    3261           3 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3262             :                        "req should still wait");
    3263             : 
    3264             :         /* Start the clock. */
    3265           3 :         t = time_mono(NULL);
    3266             : 
    3267             :         /*
    3268             :          * n)
    3269             :          * Unlock (a) lock[1] 120-129
    3270             :          */
    3271           3 :         io.lockx.in.timeout = 0;
    3272           3 :         io.lockx.in.ulock_cnt = 1;
    3273           3 :         io.lockx.in.lock_cnt = 0;
    3274           3 :         io.lockx.in.locks = &lock[1];
    3275           3 :         lock[1].pid = cli->session->pid;
    3276           3 :         status = smb_raw_lock(cli->tree, &io);
    3277           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3278             : 
    3279             :         /*
    3280             :          * o)
    3281             :          * receive the successful blocked lock request (b)
    3282             :          */
    3283           3 :         status = smbcli_request_simple_recv(req);
    3284           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3285             : 
    3286             :         /* Fail if this took more than 2 seconds. */
    3287           3 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    3288             :                        "Blocking locks were not granted immediately (%s)\n",
    3289             :                        __location__));
    3290           3 : done:
    3291           3 :         smb_raw_exit(cli->session);
    3292           3 :         smbcli_deltree(cli->tree, BASEDIR);
    3293           3 :         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           3 : static bool test_multilock6(struct torture_context *tctx,
    3330             :                             struct smbcli_state *cli)
    3331             : {
    3332           0 :         union smb_lock io;
    3333           0 :         struct smb_lock_entry lock[2];
    3334           0 :         union smb_lock io3;
    3335           0 :         struct smb_lock_entry lock3[1];
    3336           0 :         NTSTATUS status;
    3337           3 :         bool ret = true;
    3338           0 :         int fnum;
    3339           3 :         const char *fname = BASEDIR "\\multilock6_test.txt";
    3340           0 :         time_t t;
    3341           3 :         struct smbcli_request *req = NULL;
    3342           3 :         struct smbcli_request *req2 = NULL;
    3343           3 :         struct smbcli_request *req4 = NULL;
    3344             : 
    3345           3 :         torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
    3346             :                        "Failed to setup up test directory: " BASEDIR);
    3347             : 
    3348           3 :         torture_comment(tctx, "Testing LOCKING_ANDX multi-lock 6\n");
    3349           3 :         io.generic.level = RAW_LOCK_LOCKX;
    3350             : 
    3351             :         /* Create the test file. */
    3352           3 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
    3353           3 :         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           3 :         io.lockx.level = RAW_LOCK_LOCKX;
    3363           3 :         io.lockx.in.file.fnum = fnum;
    3364           3 :         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3365           3 :         io.lockx.in.timeout = 0;
    3366           3 :         io.lockx.in.ulock_cnt = 0;
    3367           3 :         io.lockx.in.lock_cnt = 2;
    3368           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3369           3 :         lock[0].pid = cli->session->pid;
    3370           3 :         lock[0].offset = 100;
    3371           3 :         lock[0].count = 10;
    3372           3 :         lock[1].pid = cli->session->pid;
    3373           3 :         lock[1].offset = 120;
    3374           3 :         lock[1].count = 10;
    3375           3 :         io.lockx.in.locks = &lock[0];
    3376           3 :         status = smb_raw_lock(cli->tree, &io);
    3377           3 :         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           3 :         io.lockx.in.timeout = 20000;
    3386           3 :         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
    3387           3 :         lock[0].pid = cli->session->pid+1;
    3388           3 :         lock[1].pid = cli->session->pid+1;
    3389           3 :         req = smb_raw_lock_send(cli->tree, &io);
    3390           3 :         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           3 :         io.lockx.in.timeout = 2000;
    3400           3 :         io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3401           3 :         lock[0].pid = cli->session->pid+2;
    3402           3 :         io.lockx.in.lock_cnt = 1;
    3403           3 :         req2 = smb_raw_lock_send(cli->tree, &io);
    3404           3 :         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           3 :         io3.lockx.level = RAW_LOCK_LOCKX;
    3412           3 :         io3.lockx.in.file.fnum = fnum;
    3413           3 :         io3.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
    3414           3 :         io3.lockx.in.timeout = 0;
    3415           3 :         io3.lockx.in.ulock_cnt = 0;
    3416           3 :         io3.lockx.in.lock_cnt = 1;
    3417           3 :         io3.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
    3418           3 :         lock3[0].pid = cli->session->pid+3;
    3419           3 :         lock3[0].offset = 110;
    3420           3 :         lock3[0].count = 10;
    3421           3 :         io3.lockx.in.locks = &lock3[0];
    3422           3 :         status = smb_raw_lock(cli->tree, &io3);
    3423           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3424             : 
    3425             :         /*
    3426             :          * e)
    3427             :          * try 110-119 again
    3428             :          */
    3429           3 :         io3.lockx.in.timeout = 20000;
    3430           3 :         lock3[0].pid = cli->session->pid+4;
    3431           3 :         req4 = smb_raw_lock_send(cli->tree, &io3);
    3432           3 :         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           3 :         io.lockx.in.timeout = 0;
    3440           3 :         io.lockx.in.ulock_cnt = 1;
    3441           3 :         io.lockx.in.lock_cnt = 0;
    3442           3 :         io.lockx.in.locks = &lock[0];
    3443           3 :         lock[0].pid = cli->session->pid;
    3444           3 :         status = smb_raw_lock(cli->tree, &io);
    3445           3 :         CHECK_STATUS(status, NT_STATUS_OK);
    3446             : 
    3447             :         /*
    3448             :          * g)
    3449             :          * try to lock lock[0] 100-109 again
    3450             :          */
    3451           3 :         lock[0].pid = cli->session->pid+5;
    3452           3 :         io.lockx.in.ulock_cnt = 0;
    3453           3 :         io.lockx.in.lock_cnt = 1;
    3454           3 :         status = smb_raw_lock(cli->tree, &io);
    3455           3 :         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           2 :         lock[0].pid = cli->session->pid+1;
    3463           2 :         io.lockx.in.ulock_cnt = 0;
    3464           2 :         io.lockx.in.lock_cnt = 1;
    3465           2 :         status = smb_raw_lock(cli->tree, &io);
    3466           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3467             : 
    3468           2 :         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           2 :         status = smbcli_request_simple_recv(req2);
    3476           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3477             : 
    3478           2 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3479             :                        "req should still wait");
    3480           2 :         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           2 :         io3.lockx.in.timeout = 0;
    3488           2 :         io3.lockx.in.ulock_cnt = 1;
    3489           2 :         io3.lockx.in.lock_cnt = 0;
    3490           2 :         lock3[0].pid = cli->session->pid+3;
    3491           2 :         status = smb_raw_lock(cli->tree, &io3);
    3492           2 :         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           2 :         status = smbcli_request_simple_recv(req4);
    3500           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    3501             : 
    3502             :         /*
    3503             :          * l)
    3504             :          * try to lock lock[0] 100-109 again
    3505             :          */
    3506           2 :         lock[0].pid = cli->session->pid+6;
    3507           2 :         io.lockx.in.ulock_cnt = 0;
    3508           2 :         io.lockx.in.lock_cnt = 1;
    3509           2 :         status = smb_raw_lock(cli->tree, &io);
    3510           2 :         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           2 :         lock[0].pid = cli->session->pid+1;
    3518           2 :         io.lockx.in.ulock_cnt = 0;
    3519           2 :         io.lockx.in.lock_cnt = 1;
    3520           2 :         status = smb_raw_lock(cli->tree, &io);
    3521           2 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
    3522             : 
    3523           2 :         torture_assert(tctx, req->state <= SMBCLI_REQUEST_RECV,
    3524             :                        "req should still wait");
    3525             : 
    3526             :         /* Start the clock. */
    3527           2 :         t = time_mono(NULL);
    3528             : 
    3529             :         /*
    3530             :          * n)
    3531             :          * Unlock (a) lock[1] 120-129
    3532             :          */
    3533           2 :         io.lockx.in.timeout = 0;
    3534           2 :         io.lockx.in.ulock_cnt = 1;
    3535           2 :         io.lockx.in.lock_cnt = 0;
    3536           2 :         io.lockx.in.locks = &lock[1];
    3537           2 :         lock[1].pid = cli->session->pid;
    3538           2 :         status = smb_raw_lock(cli->tree, &io);
    3539           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    3540             : 
    3541             :         /*
    3542             :          * o)
    3543             :          * receive the successful blocked lock request (b)
    3544             :          */
    3545           2 :         status = smbcli_request_simple_recv(req);
    3546           2 :         CHECK_STATUS(status, NT_STATUS_OK);
    3547             : 
    3548             :         /* Fail if this took more than 2 seconds. */
    3549           2 :         torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
    3550             :                        "Blocking locks were not granted immediately (%s)\n",
    3551             :                        __location__));
    3552           2 : done:
    3553           3 :         smb_raw_exit(cli->session);
    3554           3 :         smbcli_deltree(cli->tree, BASEDIR);
    3555           3 :         return ret;
    3556             : }
    3557             : 
    3558             : /*
    3559             :    basic testing of lock calls
    3560             : */
    3561        2379 : struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
    3562             : {
    3563        2379 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "lock");
    3564             : 
    3565        2379 :         torture_suite_add_1smb_test(suite, "lockx", test_lockx);
    3566        2379 :         torture_suite_add_1smb_test(suite, "lock", test_lock);
    3567        2379 :         torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
    3568        2379 :         torture_suite_add_1smb_test(suite, "async", test_async);
    3569        2379 :         torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
    3570        2379 :         torture_suite_add_1smb_test(suite, "changetype", test_changetype);
    3571             : 
    3572        2379 :         torture_suite_add_1smb_test(suite, "stacking", test_stacking);
    3573        2379 :         torture_suite_add_1smb_test(suite, "unlock", test_unlock);
    3574        2379 :         torture_suite_add_1smb_test(suite, "multiple_unlock",
    3575             :             test_multiple_unlock);
    3576        2379 :         torture_suite_add_1smb_test(suite, "zerobytelocks", test_zerobytelocks);
    3577        2379 :         torture_suite_add_1smb_test(suite, "zerobyteread", test_zerobyteread);
    3578        2379 :         torture_suite_add_1smb_test(suite, "multilock", test_multilock);
    3579        2379 :         torture_suite_add_1smb_test(suite, "multilock2", test_multilock2);
    3580        2379 :         torture_suite_add_1smb_test(suite, "multilock3", test_multilock3);
    3581        2379 :         torture_suite_add_1smb_test(suite, "multilock4", test_multilock4);
    3582        2379 :         torture_suite_add_1smb_test(suite, "multilock5", test_multilock5);
    3583        2379 :         torture_suite_add_1smb_test(suite, "multilock6", test_multilock6);
    3584             : 
    3585        2379 :         return suite;
    3586             : }

Generated by: LCOV version 1.14