root/source4/torture/raw/lock.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_lock
  2. test_lockx
  3. test_pidhigh
  4. test_async
  5. test_errorcode
  6. test_changetype
  7. test_zerobytelocks
  8. test_unlock
  9. test_multiple_unlock
  10. test_stacking
  11. torture_raw_lock

   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/popt_common.h"
  31 #include "param/param.h"
  32 
  33 #define CHECK_STATUS(status, correct) do { \
  34         if (!NT_STATUS_EQUAL(status, correct)) { \
  35                 printf("(%s) Incorrect status %s - should be %s\n", \
  36                        __location__, nt_errstr(status), nt_errstr(correct)); \
  37                 ret = false; \
  38                 goto done; \
  39         }} while (0)
  40 
  41 #define CHECK_STATUS_CONT(status, correct) do { \
  42         if (!NT_STATUS_EQUAL(status, correct)) { \
  43                 printf("(%s) Incorrect status %s - should be %s\n", \
  44                        __location__, nt_errstr(status), nt_errstr(correct)); \
  45                 ret = false; \
  46         }} while (0)
  47 
  48 #define CHECK_STATUS_OR(status, correct1, correct2) do { \
  49         if ((!NT_STATUS_EQUAL(status, correct1)) && \
  50             (!NT_STATUS_EQUAL(status, correct2))) { \
  51                 printf("(%s) Incorrect status %s - should be %s or %s\n", \
  52                        __location__, nt_errstr(status), nt_errstr(correct1), \
  53                        nt_errstr(correct2)); \
  54                 ret = false; \
  55                 goto done; \
  56         }} while (0)
  57 
  58 #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
  59         if ((!NT_STATUS_EQUAL(status, correct1)) && \
  60             (!NT_STATUS_EQUAL(status, correct2))) { \
  61                 printf("(%s) Incorrect status %s - should be %s or %s\n", \
  62                        __location__, nt_errstr(status), nt_errstr(correct1), \
  63                        nt_errstr(correct2)); \
  64                 ret = false; \
  65         }} while (0)
  66 #define BASEDIR "\\testlock"
  67 
  68 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
  69 
  70 /*
  71   test SMBlock and SMBunlock ops
  72 */
  73 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75         union smb_lock io;
  76         NTSTATUS status;
  77         bool ret = true;
  78         int fnum;
  79         const char *fname = BASEDIR "\\test.txt";
  80 
  81         if (!torture_setup_dir(cli, BASEDIR)) {
  82                 return false;
  83         }
  84 
  85         printf("Testing RAW_LOCK_LOCK\n");
  86         io.generic.level = RAW_LOCK_LOCK;
  87         
  88         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
  89         if (fnum == -1) {
  90                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
  91                 ret = false;
  92                 goto done;
  93         }
  94 
  95         printf("Trying 0/0 lock\n");
  96         io.lock.level = RAW_LOCK_LOCK;
  97         io.lock.in.file.fnum = fnum;
  98         io.lock.in.count = 0;
  99         io.lock.in.offset = 0;
 100         status = smb_raw_lock(cli->tree, &io);
 101         CHECK_STATUS(status, NT_STATUS_OK);
 102         cli->session->pid++;
 103         status = smb_raw_lock(cli->tree, &io);
 104         CHECK_STATUS(status, NT_STATUS_OK);
 105         cli->session->pid--;
 106         io.lock.level = RAW_LOCK_UNLOCK;
 107         status = smb_raw_lock(cli->tree, &io);
 108         CHECK_STATUS(status, NT_STATUS_OK);
 109 
 110         printf("Trying 0/1 lock\n");
 111         io.lock.level = RAW_LOCK_LOCK;
 112         io.lock.in.file.fnum = fnum;
 113         io.lock.in.count = 1;
 114         io.lock.in.offset = 0;
 115         status = smb_raw_lock(cli->tree, &io);
 116         CHECK_STATUS(status, NT_STATUS_OK);
 117         cli->session->pid++;
 118         status = smb_raw_lock(cli->tree, &io);
 119         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 120         cli->session->pid--;
 121         io.lock.level = RAW_LOCK_UNLOCK;
 122         status = smb_raw_lock(cli->tree, &io);
 123         CHECK_STATUS(status, NT_STATUS_OK);
 124         io.lock.level = RAW_LOCK_UNLOCK;
 125         status = smb_raw_lock(cli->tree, &io);
 126         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 127 
 128         printf("Trying 0xEEFFFFFF lock\n");
 129         io.lock.level = RAW_LOCK_LOCK;
 130         io.lock.in.file.fnum = fnum;
 131         io.lock.in.count = 4000;
 132         io.lock.in.offset = 0xEEFFFFFF;
 133         status = smb_raw_lock(cli->tree, &io);
 134         CHECK_STATUS(status, NT_STATUS_OK);
 135         cli->session->pid++;
 136         status = smb_raw_lock(cli->tree, &io);
 137         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 138         cli->session->pid--;
 139         io.lock.level = RAW_LOCK_UNLOCK;
 140         status = smb_raw_lock(cli->tree, &io);
 141         CHECK_STATUS(status, NT_STATUS_OK);
 142         io.lock.level = RAW_LOCK_UNLOCK;
 143         status = smb_raw_lock(cli->tree, &io);
 144         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 145 
 146         printf("Trying 0xEF000000 lock\n");
 147         io.lock.level = RAW_LOCK_LOCK;
 148         io.lock.in.file.fnum = fnum;
 149         io.lock.in.count = 4000;
 150         io.lock.in.offset = 0xEEFFFFFF;
 151         status = smb_raw_lock(cli->tree, &io);
 152         CHECK_STATUS(status, NT_STATUS_OK);
 153         cli->session->pid++;
 154         status = smb_raw_lock(cli->tree, &io);
 155         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 156         cli->session->pid--;
 157         io.lock.level = RAW_LOCK_UNLOCK;
 158         status = smb_raw_lock(cli->tree, &io);
 159         CHECK_STATUS(status, NT_STATUS_OK);
 160         io.lock.level = RAW_LOCK_UNLOCK;
 161         status = smb_raw_lock(cli->tree, &io);
 162         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 163 
 164         printf("Trying max lock\n");
 165         io.lock.level = RAW_LOCK_LOCK;
 166         io.lock.in.file.fnum = fnum;
 167         io.lock.in.count = 4000;
 168         io.lock.in.offset = 0xEF000000;
 169         status = smb_raw_lock(cli->tree, &io);
 170         CHECK_STATUS(status, NT_STATUS_OK);
 171         cli->session->pid++;
 172         status = smb_raw_lock(cli->tree, &io);
 173         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 174         cli->session->pid--;
 175         io.lock.level = RAW_LOCK_UNLOCK;
 176         status = smb_raw_lock(cli->tree, &io);
 177         CHECK_STATUS(status, NT_STATUS_OK);
 178         io.lock.level = RAW_LOCK_UNLOCK;
 179         status = smb_raw_lock(cli->tree, &io);
 180         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 181 
 182         printf("Trying wrong pid unlock\n");
 183         io.lock.level = RAW_LOCK_LOCK;
 184         io.lock.in.file.fnum = fnum;
 185         io.lock.in.count = 4002;
 186         io.lock.in.offset = 10001;
 187         status = smb_raw_lock(cli->tree, &io);
 188         CHECK_STATUS(status, NT_STATUS_OK);
 189         cli->session->pid++;
 190         io.lock.level = RAW_LOCK_UNLOCK;
 191         status = smb_raw_lock(cli->tree, &io);
 192         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 193         cli->session->pid--;
 194         status = smb_raw_lock(cli->tree, &io);
 195         CHECK_STATUS(status, NT_STATUS_OK);
 196 
 197 done:
 198         smbcli_close(cli->tree, fnum);
 199         smb_raw_exit(cli->session);
 200         smbcli_deltree(cli->tree, BASEDIR);
 201         return ret;
 202 }
 203 
 204 
 205 /*
 206   test locking&X ops
 207 */
 208 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
 209 {
 210         union smb_lock io;
 211         struct smb_lock_entry lock[1];
 212         NTSTATUS status;
 213         bool ret = true;
 214         int fnum;
 215         const char *fname = BASEDIR "\\test.txt";
 216 
 217         if (!torture_setup_dir(cli, BASEDIR)) {
 218                 return false;
 219         }
 220 
 221         printf("Testing RAW_LOCK_LOCKX\n");
 222         io.generic.level = RAW_LOCK_LOCKX;
 223         
 224         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 225         if (fnum == -1) {
 226                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
 227                 ret = false;
 228                 goto done;
 229         }
 230 
 231         io.lockx.level = RAW_LOCK_LOCKX;
 232         io.lockx.in.file.fnum = fnum;
 233         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 234         io.lockx.in.timeout = 0;
 235         io.lockx.in.ulock_cnt = 0;
 236         io.lockx.in.lock_cnt = 1;
 237         lock[0].pid = cli->session->pid;
 238         lock[0].offset = 10;
 239         lock[0].count = 1;
 240         io.lockx.in.locks = &lock[0];
 241         status = smb_raw_lock(cli->tree, &io);
 242         CHECK_STATUS(status, NT_STATUS_OK);
 243 
 244 
 245         printf("Trying 0xEEFFFFFF lock\n");
 246         io.lockx.in.ulock_cnt = 0;
 247         io.lockx.in.lock_cnt = 1;
 248         lock[0].count = 4000;
 249         lock[0].offset = 0xEEFFFFFF;
 250         status = smb_raw_lock(cli->tree, &io);
 251         CHECK_STATUS(status, NT_STATUS_OK);
 252         lock[0].pid++;
 253         status = smb_raw_lock(cli->tree, &io);
 254         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 255         lock[0].pid--;
 256         io.lockx.in.ulock_cnt = 1;
 257         io.lockx.in.lock_cnt = 0;
 258         status = smb_raw_lock(cli->tree, &io);
 259         CHECK_STATUS(status, NT_STATUS_OK);
 260         status = smb_raw_lock(cli->tree, &io);
 261         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 262 
 263         printf("Trying 0xEF000000 lock\n");
 264         io.lockx.in.ulock_cnt = 0;
 265         io.lockx.in.lock_cnt = 1;
 266         lock[0].count = 4000;
 267         lock[0].offset = 0xEF000000;
 268         status = smb_raw_lock(cli->tree, &io);
 269         CHECK_STATUS(status, NT_STATUS_OK);
 270         lock[0].pid++;
 271         status = smb_raw_lock(cli->tree, &io);
 272         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 273         lock[0].pid--;
 274         io.lockx.in.ulock_cnt = 1;
 275         io.lockx.in.lock_cnt = 0;
 276         status = smb_raw_lock(cli->tree, &io);
 277         CHECK_STATUS(status, NT_STATUS_OK);
 278         status = smb_raw_lock(cli->tree, &io);
 279         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 280 
 281         printf("Trying zero lock\n");
 282         io.lockx.in.ulock_cnt = 0;
 283         io.lockx.in.lock_cnt = 1;
 284         lock[0].count = 0;
 285         lock[0].offset = ~0;
 286         status = smb_raw_lock(cli->tree, &io);
 287         CHECK_STATUS(status, NT_STATUS_OK);
 288         lock[0].pid++;
 289         status = smb_raw_lock(cli->tree, &io);
 290         CHECK_STATUS(status, NT_STATUS_OK);
 291         lock[0].pid--;
 292         io.lockx.in.ulock_cnt = 1;
 293         io.lockx.in.lock_cnt = 0;
 294         status = smb_raw_lock(cli->tree, &io);
 295         CHECK_STATUS(status, NT_STATUS_OK);
 296         status = smb_raw_lock(cli->tree, &io);
 297         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 298 
 299         printf("Trying max lock\n");
 300         io.lockx.in.ulock_cnt = 0;
 301         io.lockx.in.lock_cnt = 1;
 302         lock[0].count = 0;
 303         lock[0].offset = ~0;
 304         status = smb_raw_lock(cli->tree, &io);
 305         CHECK_STATUS(status, NT_STATUS_OK);
 306         lock[0].pid++;
 307         status = smb_raw_lock(cli->tree, &io);
 308         CHECK_STATUS(status, NT_STATUS_OK);
 309         lock[0].pid--;
 310         io.lockx.in.ulock_cnt = 1;
 311         io.lockx.in.lock_cnt = 0;
 312         status = smb_raw_lock(cli->tree, &io);
 313         CHECK_STATUS(status, NT_STATUS_OK);
 314         status = smb_raw_lock(cli->tree, &io);
 315         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 316 
 317         printf("Trying 2^63\n");
 318         io.lockx.in.ulock_cnt = 0;
 319         io.lockx.in.lock_cnt = 1;
 320         lock[0].count = 1;
 321         lock[0].offset = 1;
 322         lock[0].offset <<= 63;
 323         status = smb_raw_lock(cli->tree, &io);
 324         CHECK_STATUS(status, NT_STATUS_OK);
 325         lock[0].pid++;
 326         status = smb_raw_lock(cli->tree, &io);
 327         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 328         lock[0].pid--;
 329         io.lockx.in.ulock_cnt = 1;
 330         io.lockx.in.lock_cnt = 0;
 331         status = smb_raw_lock(cli->tree, &io);
 332         CHECK_STATUS(status, NT_STATUS_OK);
 333         status = smb_raw_lock(cli->tree, &io);
 334         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 335 
 336         printf("Trying 2^63 - 1\n");
 337         io.lockx.in.ulock_cnt = 0;
 338         io.lockx.in.lock_cnt = 1;
 339         lock[0].count = 1;
 340         lock[0].offset = 1;
 341         lock[0].offset <<= 63;
 342         lock[0].offset--;
 343         status = smb_raw_lock(cli->tree, &io);
 344         CHECK_STATUS(status, NT_STATUS_OK);
 345         lock[0].pid++;
 346         status = smb_raw_lock(cli->tree, &io);
 347         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 348         lock[0].pid--;
 349         io.lockx.in.ulock_cnt = 1;
 350         io.lockx.in.lock_cnt = 0;
 351         status = smb_raw_lock(cli->tree, &io);
 352         CHECK_STATUS(status, NT_STATUS_OK);
 353         status = smb_raw_lock(cli->tree, &io);
 354         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 355 
 356         printf("Trying max lock 2\n");
 357         io.lockx.in.ulock_cnt = 0;
 358         io.lockx.in.lock_cnt = 1;
 359         lock[0].count = 1;
 360         lock[0].offset = ~0;
 361         status = smb_raw_lock(cli->tree, &io);
 362         CHECK_STATUS(status, NT_STATUS_OK);
 363         lock[0].pid++;
 364         lock[0].count = 2;
 365         status = smb_raw_lock(cli->tree, &io);
 366         if (TARGET_IS_WIN7(tctx))
 367                 CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE);
 368         else
 369                 CHECK_STATUS(status, NT_STATUS_OK);
 370         lock[0].pid--;
 371         io.lockx.in.ulock_cnt = 1;
 372         io.lockx.in.lock_cnt = 0;
 373         lock[0].count = 1;
 374         status = smb_raw_lock(cli->tree, &io);
 375 
 376         /* XXX This is very strange - Win7 gives us an invalid range when we
 377          * unlock the range even though the range is locked! Win7 bug? */
 378         if (TARGET_IS_WIN7(tctx))
 379                 CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE);
 380         else {
 381                 CHECK_STATUS(status, NT_STATUS_OK);
 382                 status = smb_raw_lock(cli->tree, &io);
 383                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 384         }
 385 
 386 done:
 387         smbcli_close(cli->tree, fnum);
 388         smb_raw_exit(cli->session);
 389         smbcli_deltree(cli->tree, BASEDIR);
 390         return ret;
 391 }
 392 
 393 /*
 394   test high pid
 395 */
 396 static bool test_pidhigh(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 397                                                  struct smbcli_state *cli)
 398 {
 399         union smb_lock io;
 400         struct smb_lock_entry lock[1];
 401         NTSTATUS status;
 402         bool ret = true;
 403         int fnum;
 404         const char *fname = BASEDIR "\\test.txt";
 405         uint8_t c = 1;
 406 
 407         if (!torture_setup_dir(cli, BASEDIR)) {
 408                 return false;
 409         }
 410 
 411         printf("Testing high pid\n");
 412         io.generic.level = RAW_LOCK_LOCKX;
 413 
 414         cli->session->pid = 1;
 415         
 416         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 417         if (fnum == -1) {
 418                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
 419                 ret = false;
 420                 goto done;
 421         }
 422 
 423         if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
 424                 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
 425                 ret = false;
 426                 goto done;
 427         }
 428 
 429         io.lockx.level = RAW_LOCK_LOCKX;
 430         io.lockx.in.file.fnum = fnum;
 431         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 432         io.lockx.in.timeout = 0;
 433         io.lockx.in.ulock_cnt = 0;
 434         io.lockx.in.lock_cnt = 1;
 435         lock[0].pid = cli->session->pid;
 436         lock[0].offset = 0;
 437         lock[0].count = 0xFFFFFFFF;
 438         io.lockx.in.locks = &lock[0];
 439         status = smb_raw_lock(cli->tree, &io);
 440         CHECK_STATUS(status, NT_STATUS_OK);
 441 
 442         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
 443                 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
 444                 ret = false;
 445                 goto done;
 446         }
 447 
 448         cli->session->pid = 2;
 449 
 450         if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
 451                 printf("pid is incorrect handled for read with lock!\n");
 452                 ret = false;
 453                 goto done;
 454         }
 455 
 456         cli->session->pid = 0x10001;
 457 
 458         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
 459                 printf("High pid is used on this server!\n");
 460                 ret = false;
 461         } else {
 462                 printf("High pid is not used on this server (correct)\n");
 463         }
 464 
 465 done:
 466         smbcli_close(cli->tree, fnum);
 467         smb_raw_exit(cli->session);
 468         smbcli_deltree(cli->tree, BASEDIR);
 469         return ret;
 470 }
 471 
 472 
 473 /*
 474   test locking&X async operation
 475 */
 476 static bool test_async(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 477                                            struct smbcli_state *cli)
 478 {
 479         struct smbcli_session *session;
 480         struct smb_composite_sesssetup setup;
 481         struct smbcli_tree *tree;
 482         union smb_tcon tcon;
 483         const char *host, *share;
 484         union smb_lock io;
 485         struct smb_lock_entry lock[2];
 486         NTSTATUS status;
 487         bool ret = true;
 488         int fnum;
 489         const char *fname = BASEDIR "\\test.txt";
 490         time_t t;
 491         struct smbcli_request *req;
 492         struct smbcli_session_options options;
 493 
 494         if (!torture_setup_dir(cli, BASEDIR)) {
 495                 return false;
 496         }
 497 
 498         lp_smbcli_session_options(tctx->lp_ctx, &options);
 499 
 500         printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
 501         io.generic.level = RAW_LOCK_LOCKX;
 502 
 503         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 504         if (fnum == -1) {
 505                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
 506                 ret = false;
 507                 goto done;
 508         }
 509 
 510         io.lockx.level = RAW_LOCK_LOCKX;
 511         io.lockx.in.file.fnum = fnum;
 512         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 513         io.lockx.in.timeout = 0;
 514         io.lockx.in.ulock_cnt = 0;
 515         io.lockx.in.lock_cnt = 1;
 516         lock[0].pid = cli->session->pid;
 517         lock[0].offset = 100;
 518         lock[0].count = 10;
 519         io.lockx.in.locks = &lock[0];
 520         status = smb_raw_lock(cli->tree, &io);
 521         CHECK_STATUS(status, NT_STATUS_OK);
 522 
 523         t = time(NULL);
 524 
 525         printf("testing cancel by CANCEL_LOCK\n");
 526 
 527         /* setup a timed lock */
 528         io.lockx.in.timeout = 10000;
 529         req = smb_raw_lock_send(cli->tree, &io);
 530         if (req == NULL) {
 531                 printf("Failed to setup timed lock (%s)\n", __location__);
 532                 ret = false;
 533                 goto done;
 534         }
 535 
 536         /* cancel the wrong range */
 537         lock[0].offset = 0;
 538         io.lockx.in.timeout = 0;
 539         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
 540         status = smb_raw_lock(cli->tree, &io);
 541         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
 542 
 543         /* cancel with the wrong bits set */
 544         lock[0].offset = 100;
 545         io.lockx.in.timeout = 0;
 546         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
 547         status = smb_raw_lock(cli->tree, &io);
 548         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
 549 
 550         /* cancel the right range */
 551         lock[0].offset = 100;
 552         io.lockx.in.timeout = 0;
 553         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
 554         status = smb_raw_lock(cli->tree, &io);
 555         CHECK_STATUS(status, NT_STATUS_OK);
 556 
 557         /* receive the failed lock request */
 558         status = smbcli_request_simple_recv(req);
 559         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 560 
 561         if (time(NULL) > t+2) {
 562                 printf("lock cancel was not immediate (%s)\n", __location__);
 563                 ret = false;
 564                 goto done;
 565         }
 566 
 567         printf("testing cancel by unlock\n");
 568         io.lockx.in.ulock_cnt = 0;
 569         io.lockx.in.lock_cnt = 1;
 570         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 571         io.lockx.in.timeout = 0;
 572         status = smb_raw_lock(cli->tree, &io);
 573         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 574 
 575         io.lockx.in.timeout = 5000;
 576         req = smb_raw_lock_send(cli->tree, &io);
 577         if (req == NULL) {
 578                 printf("Failed to setup timed lock (%s)\n", __location__);
 579                 ret = false;
 580                 goto done;
 581         }
 582 
 583         io.lockx.in.ulock_cnt = 1;
 584         io.lockx.in.lock_cnt = 0;
 585         status = smb_raw_lock(cli->tree, &io);
 586         CHECK_STATUS(status, NT_STATUS_OK);
 587 
 588         t = time(NULL);
 589         status = smbcli_request_simple_recv(req);
 590         CHECK_STATUS(status, NT_STATUS_OK);
 591 
 592         if (time(NULL) > t+2) {
 593                 printf("lock cancel by unlock was not immediate (%s) - took %d secs\n", 
 594                        __location__, (int)(time(NULL)-t));
 595                 ret = false;
 596                 goto done;
 597         }
 598 
 599         printf("testing cancel by close\n");
 600         io.lockx.in.ulock_cnt = 0;
 601         io.lockx.in.lock_cnt = 1;
 602         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 603         io.lockx.in.timeout = 0;
 604         status = smb_raw_lock(cli->tree, &io);
 605         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 606 
 607         t = time(NULL);
 608         io.lockx.in.timeout = 10000;
 609         req = smb_raw_lock_send(cli->tree, &io);
 610         if (req == NULL) {
 611                 printf("Failed to setup timed lock (%s)\n", __location__);
 612                 ret = false;
 613                 goto done;
 614         }
 615 
 616         status = smbcli_close(cli->tree, fnum);
 617         CHECK_STATUS(status, NT_STATUS_OK);
 618 
 619         status = smbcli_request_simple_recv(req);
 620         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 621 
 622         if (time(NULL) > t+2) {
 623                 printf("lock cancel by close was not immediate (%s)\n", __location__);
 624                 ret = false;
 625                 goto done;
 626         }
 627 
 628         printf("create a new sessions\n");
 629         session = smbcli_session_init(cli->transport, tctx, false, options);
 630         setup.in.sesskey = cli->transport->negotiate.sesskey;
 631         setup.in.capabilities = cli->transport->negotiate.capabilities;
 632         setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
 633         setup.in.credentials = cmdline_credentials;
 634         setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
 635         status = smb_composite_sesssetup(session, &setup);
 636         CHECK_STATUS(status, NT_STATUS_OK);
 637         session->vuid = setup.out.vuid;
 638 
 639         printf("create new tree context\n");
 640         share = torture_setting_string(tctx, "share", NULL);
 641         host  = torture_setting_string(tctx, "host", NULL);
 642         tree = smbcli_tree_init(session, tctx, false);
 643         tcon.generic.level = RAW_TCON_TCONX;
 644         tcon.tconx.in.flags = 0;
 645         tcon.tconx.in.password = data_blob(NULL, 0);
 646         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
 647         tcon.tconx.in.device = "A:";
 648         status = smb_raw_tcon(tree, tctx, &tcon);
 649         CHECK_STATUS(status, NT_STATUS_OK);
 650         tree->tid = tcon.tconx.out.tid;
 651 
 652         printf("testing cancel by exit\n");
 653         fname = BASEDIR "\\test_exit.txt";
 654         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 655         if (fnum == -1) {
 656                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
 657                 ret = false;
 658                 goto done;
 659         }
 660         io.lockx.level = RAW_LOCK_LOCKX;
 661         io.lockx.in.file.fnum = fnum;
 662         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 663         io.lockx.in.timeout = 0;
 664         io.lockx.in.ulock_cnt = 0;
 665         io.lockx.in.lock_cnt = 1;
 666         lock[0].pid = session->pid;
 667         lock[0].offset = 100;
 668         lock[0].count = 10;
 669         io.lockx.in.locks = &lock[0];
 670         status = smb_raw_lock(tree, &io);
 671         CHECK_STATUS(status, NT_STATUS_OK);
 672 
 673         io.lockx.in.ulock_cnt = 0;
 674         io.lockx.in.lock_cnt = 1;
 675         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 676         io.lockx.in.timeout = 0;
 677         status = smb_raw_lock(tree, &io);
 678         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 679 
 680         io.lockx.in.timeout = 10000;
 681         t = time(NULL);
 682         req = smb_raw_lock_send(tree, &io);
 683         if (req == NULL) {
 684                 printf("Failed to setup timed lock (%s)\n", __location__);
 685                 ret = false;
 686                 goto done;
 687         }
 688 
 689         status = smb_raw_exit(session);
 690         CHECK_STATUS(status, NT_STATUS_OK);
 691 
 692         status = smbcli_request_simple_recv(req);
 693         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 694 
 695         if (time(NULL) > t+2) {
 696                 printf("lock cancel by exit was not immediate (%s)\n", __location__);
 697                 ret = false;
 698                 goto done;
 699         }
 700 
 701         printf("testing cancel by ulogoff\n");
 702         fname = BASEDIR "\\test_ulogoff.txt";
 703         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 704         if (fnum == -1) {
 705                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
 706                 ret = false;
 707                 goto done;
 708         }
 709         io.lockx.level = RAW_LOCK_LOCKX;
 710         io.lockx.in.file.fnum = fnum;
 711         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 712         io.lockx.in.timeout = 0;
 713         io.lockx.in.ulock_cnt = 0;
 714         io.lockx.in.lock_cnt = 1;
 715         lock[0].pid = session->pid;
 716         lock[0].offset = 100;
 717         lock[0].count = 10;
 718         io.lockx.in.locks = &lock[0];
 719         status = smb_raw_lock(tree, &io);
 720         CHECK_STATUS(status, NT_STATUS_OK);
 721 
 722         io.lockx.in.ulock_cnt = 0;
 723         io.lockx.in.lock_cnt = 1;
 724         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 725         io.lockx.in.timeout = 0;
 726         status = smb_raw_lock(tree, &io);
 727         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 728 
 729         io.lockx.in.timeout = 10000;
 730         t = time(NULL);
 731         req = smb_raw_lock_send(tree, &io);
 732         if (req == NULL) {
 733                 printf("Failed to setup timed lock (%s)\n", __location__);
 734                 ret = false;
 735                 goto done;
 736         }
 737 
 738         status = smb_raw_ulogoff(session);
 739         CHECK_STATUS(status, NT_STATUS_OK);
 740 
 741         status = smbcli_request_simple_recv(req);
 742         if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
 743                 printf("lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
 744                         nt_errstr(status));
 745                 smb_tree_disconnect(tree);
 746                 smb_raw_exit(session);
 747                 goto done;
 748         }
 749         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 750 
 751         if (time(NULL) > t+2) {
 752                 printf("lock cancel by ulogoff was not immediate (%s)\n", __location__);
 753                 ret = false;
 754                 goto done;
 755         }
 756 
 757         printf("testing cancel by tdis\n");
 758         tree->session = cli->session;
 759 
 760         fname = BASEDIR "\\test_tdis.txt";
 761         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 762         if (fnum == -1) {
 763                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
 764                 ret = false;
 765                 goto done;
 766         }
 767         io.lockx.level = RAW_LOCK_LOCKX;
 768         io.lockx.in.file.fnum = fnum;
 769         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 770         io.lockx.in.timeout = 0;
 771         io.lockx.in.ulock_cnt = 0;
 772         io.lockx.in.lock_cnt = 1;
 773         lock[0].pid = cli->session->pid;
 774         lock[0].offset = 100;
 775         lock[0].count = 10;
 776         io.lockx.in.locks = &lock[0];
 777         status = smb_raw_lock(tree, &io);
 778         CHECK_STATUS(status, NT_STATUS_OK);
 779 
 780         status = smb_raw_lock(tree, &io);
 781         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
 782 
 783         io.lockx.in.timeout = 10000;
 784         t = time(NULL);
 785         req = smb_raw_lock_send(tree, &io);
 786         if (req == NULL) {
 787                 printf("Failed to setup timed lock (%s)\n", __location__);
 788                 ret = false;
 789                 goto done;
 790         }
 791 
 792         status = smb_tree_disconnect(tree);
 793         CHECK_STATUS(status, NT_STATUS_OK);
 794 
 795         status = smbcli_request_simple_recv(req);
 796         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
 797 
 798         if (time(NULL) > t+2) {
 799                 printf("lock cancel by tdis was not immediate (%s)\n", __location__);
 800                 ret = false;
 801                 goto done;
 802         }
 803 
 804 done:
 805         smb_raw_exit(cli->session);
 806         smbcli_deltree(cli->tree, BASEDIR);
 807         return ret;
 808 }
 809 
 810 /*
 811   test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
 812 */
 813 static bool test_errorcode(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 814                                                    struct smbcli_state *cli)
 815 {
 816         union smb_lock io;
 817         union smb_open op;
 818         struct smb_lock_entry lock[2];
 819         NTSTATUS status;
 820         bool ret = true;
 821         int fnum, fnum2;
 822         const char *fname;
 823         struct smbcli_request *req;
 824         time_t start;
 825         int t;
 826 
 827         if (!torture_setup_dir(cli, BASEDIR)) {
 828                 return false;
 829         }
 830 
 831         printf("Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
 832 
 833         printf("testing with timeout = 0\n");
 834         fname = BASEDIR "\\test0.txt";
 835         t = 0;
 836 
 837         /*
 838          * the first run is with t = 0,
 839          * the second with t > 0 (=1)
 840          */
 841 next_run:
 842         /* 
 843          * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
 844          * this demonstrates that the cache is per fnum
 845          */
 846         op.openx.level = RAW_OPEN_OPENX;
 847         op.openx.in.fname = fname;
 848         op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
 849         op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
 850         op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
 851         op.openx.in.search_attrs = 0;
 852         op.openx.in.file_attrs = 0;
 853         op.openx.in.write_time = 0;
 854         op.openx.in.size = 0;
 855         op.openx.in.timeout = 0;
 856 
 857         status = smb_raw_open(cli->tree, tctx, &op);
 858         CHECK_STATUS(status, NT_STATUS_OK);
 859         fnum = op.openx.out.file.fnum;
 860 
 861         status = smb_raw_open(cli->tree, tctx, &op);
 862         CHECK_STATUS(status, NT_STATUS_OK);
 863         fnum2 = op.openx.out.file.fnum;
 864 
 865         io.lockx.level = RAW_LOCK_LOCKX;
 866         io.lockx.in.file.fnum = fnum;
 867         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 868         io.lockx.in.timeout = t;
 869         io.lockx.in.ulock_cnt = 0;
 870         io.lockx.in.lock_cnt = 1;
 871         lock[0].pid = cli->session->pid;
 872         lock[0].offset = 100;
 873         lock[0].count = 10;
 874         io.lockx.in.locks = &lock[0];
 875         status = smb_raw_lock(cli->tree, &io);
 876         CHECK_STATUS(status, NT_STATUS_OK);
 877 
 878         /*
 879          * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
 880          * this also demonstrates that the error code cache is per file handle
 881          * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
 882          */
 883         io.lockx.in.file.fnum = fnum2;
 884         status = smb_raw_lock(cli->tree, &io);
 885         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 886 
 887         io.lockx.in.file.fnum = fnum;
 888         status = smb_raw_lock(cli->tree, &io);
 889         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
 890 
 891         /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
 892         io.lockx.in.file.fnum = fnum;
 893         status = smb_raw_lock(cli->tree, &io);
 894         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 895 
 896         io.lockx.in.file.fnum = fnum2;
 897         status = smb_raw_lock(cli->tree, &io);
 898         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 899 
 900         io.lockx.in.file.fnum = fnum;
 901         status = smb_raw_lock(cli->tree, &io);
 902         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 903 
 904         io.lockx.in.file.fnum = fnum2;
 905         status = smb_raw_lock(cli->tree, &io);
 906         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 907 
 908         /* demonstrate that the smbpid doesn't matter */
 909         lock[0].pid++;
 910         io.lockx.in.file.fnum = fnum;
 911         status = smb_raw_lock(cli->tree, &io);
 912         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 913 
 914         io.lockx.in.file.fnum = fnum2;
 915         status = smb_raw_lock(cli->tree, &io);
 916         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 917         lock[0].pid--;
 918 
 919         /* 
 920          * demonstrate the a successful lock with count = 0 and the same offset,
 921          * doesn't reset the error cache
 922          */
 923         lock[0].offset = 100;
 924         lock[0].count = 0;
 925         io.lockx.in.file.fnum = fnum;
 926         status = smb_raw_lock(cli->tree, &io);
 927         CHECK_STATUS(status, NT_STATUS_OK);
 928 
 929         io.lockx.in.file.fnum = fnum2;
 930         status = smb_raw_lock(cli->tree, &io);
 931         CHECK_STATUS(status, NT_STATUS_OK);
 932 
 933         lock[0].offset = 100;
 934         lock[0].count = 10;
 935         io.lockx.in.file.fnum = fnum;
 936         status = smb_raw_lock(cli->tree, &io);
 937         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 938 
 939         io.lockx.in.file.fnum = fnum2;
 940         status = smb_raw_lock(cli->tree, &io);
 941         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 942 
 943         /* 
 944          * demonstrate the a successful lock with count = 0 and outside the locked range,
 945          * doesn't reset the error cache
 946          */
 947         lock[0].offset = 110;
 948         lock[0].count = 0;
 949         io.lockx.in.file.fnum = fnum;
 950         status = smb_raw_lock(cli->tree, &io);
 951         CHECK_STATUS(status, NT_STATUS_OK);
 952 
 953         io.lockx.in.file.fnum = fnum2;
 954         status = smb_raw_lock(cli->tree, &io);
 955         CHECK_STATUS(status, NT_STATUS_OK);
 956 
 957         lock[0].offset = 100;
 958         lock[0].count = 10;
 959         io.lockx.in.file.fnum = fnum;
 960         status = smb_raw_lock(cli->tree, &io);
 961         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 962 
 963         io.lockx.in.file.fnum = fnum2;
 964         status = smb_raw_lock(cli->tree, &io);
 965         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 966 
 967         lock[0].offset = 99;
 968         lock[0].count = 0;
 969         io.lockx.in.file.fnum = fnum;
 970         status = smb_raw_lock(cli->tree, &io);
 971         CHECK_STATUS(status, NT_STATUS_OK);
 972 
 973         io.lockx.in.file.fnum = fnum2;
 974         status = smb_raw_lock(cli->tree, &io);
 975         CHECK_STATUS(status, NT_STATUS_OK);
 976 
 977         lock[0].offset = 100;
 978         lock[0].count = 10;
 979         io.lockx.in.file.fnum = fnum;
 980         status = smb_raw_lock(cli->tree, &io);
 981         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 982 
 983         io.lockx.in.file.fnum = fnum2;
 984         status = smb_raw_lock(cli->tree, &io);
 985         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 986 
 987         /* demonstrate that a changing count doesn't reset the error cache */
 988         lock[0].offset = 100;
 989         lock[0].count = 5;
 990         io.lockx.in.file.fnum = fnum;
 991         status = smb_raw_lock(cli->tree, &io);
 992         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 993 
 994         io.lockx.in.file.fnum = fnum2;
 995         status = smb_raw_lock(cli->tree, &io);
 996         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
 997 
 998         lock[0].offset = 100;
 999         lock[0].count = 15;
1000         io.lockx.in.file.fnum = fnum;
1001         status = smb_raw_lock(cli->tree, &io);
1002         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1003 
1004         io.lockx.in.file.fnum = fnum2;
1005         status = smb_raw_lock(cli->tree, &io);
1006         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1007 
1008         /* 
1009          * demonstrate the a lock with count = 0 and inside the locked range,
1010          * fails and resets the error cache
1011          */
1012         lock[0].offset = 101;
1013         lock[0].count = 0;
1014         io.lockx.in.file.fnum = fnum;
1015         status = smb_raw_lock(cli->tree, &io);
1016         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1017         status = smb_raw_lock(cli->tree, &io);
1018         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1019 
1020         io.lockx.in.file.fnum = fnum2;
1021         status = smb_raw_lock(cli->tree, &io);
1022         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1023         status = smb_raw_lock(cli->tree, &io);
1024         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1025 
1026         lock[0].offset = 100;
1027         lock[0].count = 10;
1028         io.lockx.in.file.fnum = fnum;
1029         status = smb_raw_lock(cli->tree, &io);
1030         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1031         status = smb_raw_lock(cli->tree, &io);
1032         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1033 
1034         io.lockx.in.file.fnum = fnum2;
1035         status = smb_raw_lock(cli->tree, &io);
1036         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1037         status = smb_raw_lock(cli->tree, &io);
1038         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1039 
1040         /* demonstrate the a changing offset, resets the error cache */
1041         lock[0].offset = 105;
1042         lock[0].count = 10;
1043         io.lockx.in.file.fnum = fnum;
1044         status = smb_raw_lock(cli->tree, &io);
1045         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1046         status = smb_raw_lock(cli->tree, &io);
1047         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1048 
1049         io.lockx.in.file.fnum = fnum2;
1050         status = smb_raw_lock(cli->tree, &io);
1051         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1052         status = smb_raw_lock(cli->tree, &io);
1053         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1054 
1055         lock[0].offset = 100;
1056         lock[0].count = 10;
1057         io.lockx.in.file.fnum = fnum;
1058         status = smb_raw_lock(cli->tree, &io);
1059         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1060         status = smb_raw_lock(cli->tree, &io);
1061         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1062 
1063         io.lockx.in.file.fnum = fnum2;
1064         status = smb_raw_lock(cli->tree, &io);
1065         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1066         status = smb_raw_lock(cli->tree, &io);
1067         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1068 
1069         lock[0].offset = 95;
1070         lock[0].count = 9;
1071         io.lockx.in.file.fnum = fnum;
1072         status = smb_raw_lock(cli->tree, &io);
1073         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1074         status = smb_raw_lock(cli->tree, &io);
1075         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1076 
1077         io.lockx.in.file.fnum = fnum2;
1078         status = smb_raw_lock(cli->tree, &io);
1079         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1080         status = smb_raw_lock(cli->tree, &io);
1081         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1082 
1083         lock[0].offset = 100;
1084         lock[0].count = 10;
1085         io.lockx.in.file.fnum = fnum;
1086         status = smb_raw_lock(cli->tree, &io);
1087         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1088         status = smb_raw_lock(cli->tree, &io);
1089         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1090 
1091         io.lockx.in.file.fnum = fnum2;
1092         status = smb_raw_lock(cli->tree, &io);
1093         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1094         status = smb_raw_lock(cli->tree, &io);
1095         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1096 
1097         /* 
1098          * demonstrate the a successful lock in a different range, 
1099          * doesn't reset the cache, the failing lock on the 2nd handle
1100          * resets the resets the cache
1101          */
1102         lock[0].offset = 120;
1103         lock[0].count = 15;
1104         io.lockx.in.file.fnum = fnum;
1105         status = smb_raw_lock(cli->tree, &io);
1106         CHECK_STATUS(status, NT_STATUS_OK);
1107 
1108         io.lockx.in.file.fnum = fnum2;
1109         status = smb_raw_lock(cli->tree, &io);
1110         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1111 
1112         lock[0].offset = 100;
1113         lock[0].count = 10;
1114         io.lockx.in.file.fnum = fnum;
1115         status = smb_raw_lock(cli->tree, &io);
1116         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1117         status = smb_raw_lock(cli->tree, &io);
1118         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1119 
1120         io.lockx.in.file.fnum = fnum2;
1121         status = smb_raw_lock(cli->tree, &io);
1122         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1123         status = smb_raw_lock(cli->tree, &io);
1124         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1125 
1126         /* end of the loop */
1127         if (t == 0) {
1128                 smb_raw_exit(cli->session);
1129                 printf("testing with timeout > 0 (=1)\n");
1130                 fname = BASEDIR "\\test1.txt";
1131                 t = 1;
1132                 goto next_run;
1133         }
1134 
1135         /*
1136          * the following 3 test sections demonstrate that
1137          * the cache is only set when the error is reported
1138          * to the client (after the timeout went by)
1139          */
1140         smb_raw_exit(cli->session);
1141         printf("testing a conflict while a lock is pending\n");
1142         fname = BASEDIR "\\test2.txt";
1143         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1144         if (fnum == -1) {
1145                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1146                 ret = false;
1147                 goto done;
1148         }
1149         io.lockx.level = RAW_LOCK_LOCKX;
1150         io.lockx.in.file.fnum = fnum;
1151         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1152         io.lockx.in.timeout = 0;
1153         io.lockx.in.ulock_cnt = 0;
1154         io.lockx.in.lock_cnt = 1;
1155         lock[0].pid = cli->session->pid;
1156         lock[0].offset = 100;
1157         lock[0].count = 10;
1158         io.lockx.in.locks = &lock[0];
1159         status = smb_raw_lock(cli->tree, &io);
1160         CHECK_STATUS(status, NT_STATUS_OK);
1161 
1162         start = time(NULL);
1163         io.lockx.in.timeout = 1000;
1164         req = smb_raw_lock_send(cli->tree, &io);
1165         if (req == NULL) {
1166                 printf("Failed to setup timed lock (%s)\n", __location__);
1167                 ret = false;
1168                 goto done;
1169         }
1170 
1171         io.lockx.in.timeout = 0;
1172         lock[0].offset = 105;
1173         lock[0].count = 10;
1174         status = smb_raw_lock(cli->tree, &io);
1175         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1176 
1177         status = smbcli_request_simple_recv(req);
1178         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1179 
1180         status = smb_raw_lock(cli->tree, &io);
1181         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1182 
1183         if (time(NULL) < start+1) {
1184                 printf("lock comes back to early (%s)\n", __location__);
1185                 ret = false;
1186                 goto done;
1187         }
1188 
1189         smbcli_close(cli->tree, fnum);
1190         fname = BASEDIR "\\test3.txt";
1191         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1192         if (fnum == -1) {
1193                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1194                 ret = false;
1195                 goto done;
1196         }
1197         io.lockx.level = RAW_LOCK_LOCKX;
1198         io.lockx.in.file.fnum = fnum;
1199         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1200         io.lockx.in.timeout = 0;
1201         io.lockx.in.ulock_cnt = 0;
1202         io.lockx.in.lock_cnt = 1;
1203         lock[0].pid = cli->session->pid;
1204         lock[0].offset = 100;
1205         lock[0].count = 10;
1206         io.lockx.in.locks = &lock[0];
1207         status = smb_raw_lock(cli->tree, &io);
1208         CHECK_STATUS(status, NT_STATUS_OK);
1209 
1210         start = time(NULL);
1211         io.lockx.in.timeout = 1000;
1212         req = smb_raw_lock_send(cli->tree, &io);
1213         if (req == NULL) {
1214                 printf("Failed to setup timed lock (%s)\n", __location__);
1215                 ret = false;
1216                 goto done;
1217         }
1218 
1219         io.lockx.in.timeout = 0;
1220         lock[0].offset = 105;
1221         lock[0].count = 10;
1222         status = smb_raw_lock(cli->tree, &io);
1223         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1224 
1225         status = smbcli_request_simple_recv(req);
1226         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1227 
1228         lock[0].offset = 100;
1229         lock[0].count = 10;
1230         status = smb_raw_lock(cli->tree, &io);
1231         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1232 
1233         if (time(NULL) < start+1) {
1234                 printf("lock comes back to early (%s)\n", __location__);
1235                 ret = false;
1236                 goto done;
1237         }
1238 
1239         smbcli_close(cli->tree, fnum);
1240         fname = BASEDIR "\\test4.txt";
1241         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1242         if (fnum == -1) {
1243                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1244                 ret = false;
1245                 goto done;
1246         }
1247         io.lockx.level = RAW_LOCK_LOCKX;
1248         io.lockx.in.file.fnum = fnum;
1249         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1250         io.lockx.in.timeout = 0;
1251         io.lockx.in.ulock_cnt = 0;
1252         io.lockx.in.lock_cnt = 1;
1253         lock[0].pid = cli->session->pid;
1254         lock[0].offset = 100;
1255         lock[0].count = 10;
1256         io.lockx.in.locks = &lock[0];
1257         status = smb_raw_lock(cli->tree, &io);
1258         CHECK_STATUS(status, NT_STATUS_OK);
1259 
1260         start = time(NULL);
1261         io.lockx.in.timeout = 1000;
1262         req = smb_raw_lock_send(cli->tree, &io);
1263         if (req == NULL) {
1264                 printf("Failed to setup timed lock (%s)\n", __location__);
1265                 ret = false;
1266                 goto done;
1267         }
1268 
1269         io.lockx.in.timeout = 0;
1270         status = smb_raw_lock(cli->tree, &io);
1271         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1272 
1273         status = smbcli_request_simple_recv(req);
1274         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1275 
1276         status = smb_raw_lock(cli->tree, &io);
1277         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1278 
1279         if (time(NULL) < start+1) {
1280                 printf("lock comes back to early (%s)\n", __location__);
1281                 ret = false;
1282                 goto done;
1283         }
1284 
1285 done:
1286         smb_raw_exit(cli->session);
1287         smbcli_deltree(cli->tree, BASEDIR);
1288         return ret;
1289 }
1290 
1291 
1292 /*
1293   test LOCKING_ANDX_CHANGE_LOCKTYPE
1294 */
1295 static bool test_changetype(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1296                                                         struct smbcli_state *cli)
1297 {
1298         union smb_lock io;
1299         struct smb_lock_entry lock[2];
1300         NTSTATUS status;
1301         bool ret = true;
1302         int fnum;
1303         uint8_t c = 0;
1304         const char *fname = BASEDIR "\\test.txt";
1305 
1306         if (!torture_setup_dir(cli, BASEDIR)) {
1307                 return false;
1308         }
1309 
1310         printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1311         io.generic.level = RAW_LOCK_LOCKX;
1312         
1313         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1314         if (fnum == -1) {
1315                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1316                 ret = false;
1317                 goto done;
1318         }
1319 
1320         io.lockx.level = RAW_LOCK_LOCKX;
1321         io.lockx.in.file.fnum = fnum;
1322         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1323         io.lockx.in.timeout = 0;
1324         io.lockx.in.ulock_cnt = 0;
1325         io.lockx.in.lock_cnt = 1;
1326         lock[0].pid = cli->session->pid;
1327         lock[0].offset = 100;
1328         lock[0].count = 10;
1329         io.lockx.in.locks = &lock[0];
1330         status = smb_raw_lock(cli->tree, &io);
1331         CHECK_STATUS(status, NT_STATUS_OK);
1332 
1333         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1334                 printf("allowed write on read locked region (%s)\n", __location__);
1335                 ret = false;
1336                 goto done;
1337         }
1338 
1339         /* windows server don't seem to support this */
1340         io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1341         status = smb_raw_lock(cli->tree, &io);
1342         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1343 
1344         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1345                 printf("allowed write after lock change (%s)\n", __location__);
1346                 ret = false;
1347                 goto done;
1348         }
1349 
1350 done:
1351         smbcli_close(cli->tree, fnum);
1352         smb_raw_exit(cli->session);
1353         smbcli_deltree(cli->tree, BASEDIR);
1354         return ret;
1355 }
1356 
1357 struct double_lock_test {
1358         struct smb_lock_entry lock1;
1359         struct smb_lock_entry lock2;
1360         NTSTATUS exp_status;
1361 };
1362 
1363 /**
1364  * Tests zero byte locks.
1365  */
1366 struct double_lock_test zero_byte_tests[] = {
1367         /* {pid, offset, count}, {pid, offset, count}, status */
1368 
1369         /** First, takes a zero byte lock at offset 10. Then:
1370         *   - Taking 0 byte lock at 10 should succeed.
1371         *   - Taking 1 byte locks at 9,10,11 should succeed.
1372         *   - Taking 2 byte lock at 9 should fail.
1373         *   - Taking 2 byte lock at 10 should succeed.
1374         *   - Taking 3 byte lock at 9 should fail.
1375         */
1376         {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1377         {{1000, 10, 0}, {1001, 9, 1},  NT_STATUS_OK},
1378         {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1379         {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1380         {{1000, 10, 0}, {1001, 9, 2},  NT_STATUS_LOCK_NOT_GRANTED},
1381         {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1382         {{1000, 10, 0}, {1001, 9, 3},  NT_STATUS_LOCK_NOT_GRANTED},
1383 
1384         /** Same, but opposite order. */
1385         {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1386         {{1001, 9, 1},  {1000, 10, 0}, NT_STATUS_OK},
1387         {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1388         {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1389         {{1001, 9, 2},  {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1390         {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1391         {{1001, 9, 3},  {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1392 
1393         /** Zero zero case. */
1394         {{1000, 0, 0},  {1001, 0, 0},  NT_STATUS_OK},
1395 };
1396 
1397 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1398 {
1399         union smb_lock io;
1400         struct smb_lock_entry zerozero;
1401         NTSTATUS status;
1402         bool ret = true;
1403         int fnum, i;
1404         const char *fname = BASEDIR "\\zero.txt";
1405 
1406         printf("Testing zero length byte range locks:\n");
1407 
1408         if (!torture_setup_dir(cli, BASEDIR)) {
1409                 return false;
1410         }
1411 
1412         io.generic.level = RAW_LOCK_LOCKX;
1413 
1414         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1415         if (fnum == -1) {
1416                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1417                 ret = false;
1418                 goto done;
1419         }
1420 
1421         /* Setup initial parameters */
1422         io.lockx.level = RAW_LOCK_LOCKX;
1423         io.lockx.in.file.fnum = fnum;
1424         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1425         io.lockx.in.timeout = 0;
1426 
1427         /* Try every combination of locks in zero_byte_tests. The first lock is
1428          * assumed to succeed. The second lock may contend, depending on the
1429          * expected status. */
1430         for (i = 0;
1431              i < sizeof(zero_byte_tests) / sizeof(struct double_lock_test);
1432              i++) {
1433                 printf("  ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1434                     zero_byte_tests[i].lock1.pid,
1435                     zero_byte_tests[i].lock1.offset,
1436                     zero_byte_tests[i].lock1.count,
1437                     zero_byte_tests[i].lock2.pid,
1438                     zero_byte_tests[i].lock2.offset,
1439                     zero_byte_tests[i].lock2.count,
1440                     nt_errstr(zero_byte_tests[i].exp_status));
1441 
1442                 /* Lock both locks. */
1443                 io.lockx.in.ulock_cnt = 0;
1444                 io.lockx.in.lock_cnt = 1;
1445 
1446                 io.lockx.in.locks = &zero_byte_tests[i].lock1;
1447                 status = smb_raw_lock(cli->tree, &io);
1448                 CHECK_STATUS(status, NT_STATUS_OK);
1449 
1450                 io.lockx.in.locks = &zero_byte_tests[i].lock2;
1451                 status = smb_raw_lock(cli->tree, &io);
1452 
1453                 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1454                         NT_STATUS_LOCK_NOT_GRANTED)) {
1455                         /* Allow either of the failure messages and keep going
1456                          * if we see the wrong status. */
1457                         CHECK_STATUS_OR_CONT(status,
1458                             NT_STATUS_LOCK_NOT_GRANTED,
1459                             NT_STATUS_FILE_LOCK_CONFLICT);
1460 
1461                 } else {
1462                         CHECK_STATUS_CONT(status,
1463                             zero_byte_tests[i].exp_status);
1464                 }
1465 
1466                 /* Unlock both locks. */
1467                 io.lockx.in.ulock_cnt = 1;
1468                 io.lockx.in.lock_cnt = 0;
1469 
1470                 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1471                         status = smb_raw_lock(cli->tree, &io);
1472                         CHECK_STATUS(status, NT_STATUS_OK);
1473                 }
1474 
1475                 io.lockx.in.locks = &zero_byte_tests[i].lock1;
1476                 status = smb_raw_lock(cli->tree, &io);
1477                 CHECK_STATUS(status, NT_STATUS_OK);
1478         }
1479 
1480 done:
1481         smbcli_close(cli->tree, fnum);
1482         smb_raw_exit(cli->session);
1483         smbcli_deltree(cli->tree, BASEDIR);
1484         return ret;
1485 }
1486 
1487 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1488 {
1489         union smb_lock io;
1490         NTSTATUS status;
1491         bool ret = true;
1492         int fnum1, fnum2;
1493         const char *fname = BASEDIR "\\unlock.txt";
1494         struct smb_lock_entry lock1;
1495         struct smb_lock_entry lock2;
1496 
1497         printf("Testing LOCKX unlock:\n");
1498 
1499         if (!torture_setup_dir(cli, BASEDIR)) {
1500                 return false;
1501         }
1502 
1503         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1504         if (fnum1 == -1) {
1505                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1506                 ret = false;
1507                 goto done;
1508         }
1509         fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1510         if (fnum2 == -1) {
1511                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1512                 ret = false;
1513                 goto done;
1514         }
1515 
1516         /* Setup initial parameters */
1517         io.lockx.level = RAW_LOCK_LOCKX;
1518         io.lockx.in.timeout = 0;
1519 
1520         lock1.pid = cli->session->pid;
1521         lock1.offset = 0;
1522         lock1.count = 10;
1523         lock2.pid = cli->session->pid - 1;
1524         lock2.offset = 0;
1525         lock2.count = 10;
1526 
1527         /**
1528          * Take exclusive lock, then unlock it with a shared-unlock call.
1529          */
1530         printf("  taking exclusive lock.\n");
1531         io.lockx.in.ulock_cnt = 0;
1532         io.lockx.in.lock_cnt = 1;
1533         io.lockx.in.mode = 0;
1534         io.lockx.in.file.fnum = fnum1;
1535         io.lockx.in.locks = &lock1;
1536         status = smb_raw_lock(cli->tree, &io);
1537         CHECK_STATUS(status, NT_STATUS_OK);
1538 
1539         printf("  unlock the exclusive with a shared unlock call.\n");
1540         io.lockx.in.ulock_cnt = 1;
1541         io.lockx.in.lock_cnt = 0;
1542         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1543         io.lockx.in.file.fnum = fnum1;
1544         io.lockx.in.locks = &lock1;
1545         status = smb_raw_lock(cli->tree, &io);
1546         CHECK_STATUS(status, NT_STATUS_OK);
1547 
1548         printf("  try shared lock on pid2/fnum2, testing the unlock.\n");
1549         io.lockx.in.ulock_cnt = 0;
1550         io.lockx.in.lock_cnt = 1;
1551         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1552         io.lockx.in.file.fnum = fnum2;
1553         io.lockx.in.locks = &lock2;
1554         status = smb_raw_lock(cli->tree, &io);
1555         CHECK_STATUS(status, NT_STATUS_OK);
1556 
1557         /**
1558          * Unlock a shared lock with an exclusive-unlock call.
1559          */
1560         printf("  unlock new shared lock with exclusive unlock call.\n");
1561         io.lockx.in.ulock_cnt = 1;
1562         io.lockx.in.lock_cnt = 0;
1563         io.lockx.in.mode = 0;
1564         io.lockx.in.file.fnum = fnum2;
1565         io.lockx.in.locks = &lock2;
1566         status = smb_raw_lock(cli->tree, &io);
1567         CHECK_STATUS(status, NT_STATUS_OK);
1568 
1569         printf("  try exclusive lock on pid1, testing the unlock.\n");
1570         io.lockx.in.ulock_cnt = 0;
1571         io.lockx.in.lock_cnt = 1;
1572         io.lockx.in.mode = 0;
1573         io.lockx.in.file.fnum = fnum1;
1574         io.lockx.in.locks = &lock1;
1575         status = smb_raw_lock(cli->tree, &io);
1576         CHECK_STATUS(status, NT_STATUS_OK);
1577 
1578         /* cleanup */
1579         io.lockx.in.ulock_cnt = 1;
1580         io.lockx.in.lock_cnt = 0;
1581         status = smb_raw_lock(cli->tree, &io);
1582         CHECK_STATUS(status, NT_STATUS_OK);
1583 
1584         /**
1585          * Test unlocking of 0-byte locks.
1586          */
1587 
1588         printf("  lock shared and exclusive 0-byte locks, testing that Windows "
1589             "always unlocks the exclusive first.\n");
1590         lock1.pid = cli->session->pid;
1591         lock1.offset = 10;
1592         lock1.count = 0;
1593         lock2.pid = cli->session->pid;
1594         lock2.offset = 5;
1595         lock2.count = 10;
1596         io.lockx.in.ulock_cnt = 0;
1597         io.lockx.in.lock_cnt = 1;
1598         io.lockx.in.file.fnum = fnum1;
1599         io.lockx.in.locks = &lock1;
1600 
1601         /* lock 0-byte shared
1602          * Note: Order of the shared/exclusive locks doesn't matter. */
1603         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1604         status = smb_raw_lock(cli->tree, &io);
1605         CHECK_STATUS(status, NT_STATUS_OK);
1606 
1607         /* lock 0-byte exclusive */
1608         io.lockx.in.mode = 0;
1609         status = smb_raw_lock(cli->tree, &io);
1610         CHECK_STATUS(status, NT_STATUS_OK);
1611 
1612         /* test contention */
1613         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1614         io.lockx.in.locks = &lock2;
1615         io.lockx.in.file.fnum = fnum2;
1616         status = smb_raw_lock(cli->tree, &io);
1617         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1618             NT_STATUS_FILE_LOCK_CONFLICT);
1619 
1620         /* unlock */
1621         io.lockx.in.ulock_cnt = 1;
1622         io.lockx.in.lock_cnt = 0;
1623         io.lockx.in.file.fnum = fnum1;
1624         io.lockx.in.locks = &lock1;
1625         status = smb_raw_lock(cli->tree, &io);
1626         CHECK_STATUS(status, NT_STATUS_OK);
1627 
1628         /* test - can we take a shared lock? */
1629         io.lockx.in.ulock_cnt = 0;
1630         io.lockx.in.lock_cnt = 1;
1631         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1632         io.lockx.in.file.fnum = fnum2;
1633         io.lockx.in.locks = &lock2;
1634         status = smb_raw_lock(cli->tree, &io);
1635 
1636         /* XXX Samba will fail this test. This is temporary(because this isn't
1637          * new to Win7, it succeeds in WinXP too), until I can come to a
1638          * resolution as to whether Samba should support this or not. There is
1639          * code to preference unlocking exclusive locks before shared locks,
1640          * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1641         if (TARGET_IS_WIN7(tctx))
1642                 CHECK_STATUS(status, NT_STATUS_OK);
1643         else {
1644                 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1645                     NT_STATUS_FILE_LOCK_CONFLICT);
1646         }
1647 
1648         /* cleanup */
1649         io.lockx.in.ulock_cnt = 1;
1650         io.lockx.in.lock_cnt = 0;
1651         status = smb_raw_lock(cli->tree, &io);
1652 
1653         /* XXX Same as above. */
1654         if (TARGET_IS_WIN7(tctx))
1655                 CHECK_STATUS(status, NT_STATUS_OK);
1656         else
1657                 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1658 
1659         io.lockx.in.file.fnum = fnum1;
1660         io.lockx.in.locks = &lock1;
1661         status = smb_raw_lock(cli->tree, &io);
1662         CHECK_STATUS(status, NT_STATUS_OK);
1663 
1664 done:
1665         smbcli_close(cli->tree, fnum1);
1666         smbcli_close(cli->tree, fnum2);
1667         smb_raw_exit(cli->session);
1668         smbcli_deltree(cli->tree, BASEDIR);
1669         return ret;
1670 }
1671 
1672 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1673 {
1674         union smb_lock io;
1675         NTSTATUS status;
1676         bool ret = true;
1677         int fnum1;
1678         const char *fname = BASEDIR "\\unlock_multiple.txt";
1679         struct smb_lock_entry lock1;
1680         struct smb_lock_entry lock2;
1681         struct smb_lock_entry locks[2];
1682 
1683         printf("Testing LOCKX multiple unlock:\n");
1684 
1685         if (!torture_setup_dir(cli, BASEDIR)) {
1686                 return false;
1687         }
1688 
1689         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1690         if (fnum1 == -1) {
1691                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1692                 ret = false;
1693                 goto done;
1694         }
1695 
1696         /* Setup initial parameters */
1697         io.lockx.level = RAW_LOCK_LOCKX;
1698         io.lockx.in.timeout = 0;
1699 
1700         lock1.pid = cli->session->pid;
1701         lock1.offset = 0;
1702         lock1.count = 10;
1703         lock2.pid = cli->session->pid;
1704         lock2.offset = 10;
1705         lock2.count = 10;
1706 
1707         locks[0] = lock1;
1708         locks[1] = lock2;
1709 
1710         io.lockx.in.file.fnum = fnum1;
1711         io.lockx.in.mode = 0; /* exclusive */
1712 
1713         /** Test1: Take second lock, but not first. */
1714         printf("  unlock 2 locks, first one not locked. Expect no locks "
1715             "unlocked. \n");
1716 
1717         io.lockx.in.ulock_cnt = 0;
1718         io.lockx.in.lock_cnt = 1;
1719         io.lockx.in.locks = &lock2;
1720         status = smb_raw_lock(cli->tree, &io);
1721         CHECK_STATUS(status, NT_STATUS_OK);
1722 
1723         /* Try to unlock both locks. */
1724         io.lockx.in.ulock_cnt = 2;
1725         io.lockx.in.lock_cnt = 0;
1726         io.lockx.in.locks = locks;
1727 
1728         status = smb_raw_lock(cli->tree, &io);
1729         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1730 
1731         /* Second lock should not be unlocked. */
1732         io.lockx.in.ulock_cnt = 0;
1733         io.lockx.in.lock_cnt = 1;
1734         io.lockx.in.locks = &lock2;
1735         status = smb_raw_lock(cli->tree, &io);
1736         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1737 
1738         /* cleanup */
1739         io.lockx.in.ulock_cnt = 1;
1740         io.lockx.in.lock_cnt = 0;
1741         io.lockx.in.locks = &lock2;
1742         status = smb_raw_lock(cli->tree, &io);
1743         CHECK_STATUS(status, NT_STATUS_OK);
1744 
1745         /** Test2: Take first lock, but not second. */
1746         printf("  unlock 2 locks, second one not locked. Expect first lock "
1747             "unlocked.\n");
1748 
1749         io.lockx.in.ulock_cnt = 0;
1750         io.lockx.in.lock_cnt = 1;
1751         io.lockx.in.locks = &lock1;
1752         status = smb_raw_lock(cli->tree, &io);
1753         CHECK_STATUS(status, NT_STATUS_OK);
1754 
1755         /* Try to unlock both locks. */
1756         io.lockx.in.ulock_cnt = 2;
1757         io.lockx.in.lock_cnt = 0;
1758         io.lockx.in.locks = locks;
1759 
1760         status = smb_raw_lock(cli->tree, &io);
1761         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1762 
1763         /* First lock should be unlocked. */
1764         io.lockx.in.ulock_cnt = 0;
1765         io.lockx.in.lock_cnt = 1;
1766         io.lockx.in.locks = &lock1;
1767         status = smb_raw_lock(cli->tree, &io);
1768         CHECK_STATUS(status, NT_STATUS_OK);
1769 
1770         /* cleanup */
1771         io.lockx.in.ulock_cnt = 1;
1772         io.lockx.in.lock_cnt = 0;
1773         io.lockx.in.locks = &lock1;
1774         status = smb_raw_lock(cli->tree, &io);
1775         CHECK_STATUS(status, NT_STATUS_OK);
1776 
1777 done:
1778         smbcli_close(cli->tree, fnum1);
1779         smb_raw_exit(cli->session);
1780         smbcli_deltree(cli->tree, BASEDIR);
1781         return ret;
1782 }
1783 
1784 /**
1785  * torture_locktest5 covers stacking pretty well, but its missing two tests:
1786  * - stacking an exclusive on top of shared fails
1787  * - stacking two exclusives fail
1788  */
1789 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1790 {
1791         union smb_lock io;
1792         NTSTATUS status;
1793         bool ret = true;
1794         int fnum1;
1795         const char *fname = BASEDIR "\\stacking.txt";
1796         struct smb_lock_entry lock1;
1797         struct smb_lock_entry lock2;
1798 
1799         printf("Testing stacking:\n");
1800 
1801         if (!torture_setup_dir(cli, BASEDIR)) {
1802                 return false;
1803         }
1804 
1805         io.generic.level = RAW_LOCK_LOCKX;
1806 
1807         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1808         if (fnum1 == -1) {
1809                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1810                 ret = false;
1811                 goto done;
1812         }
1813 
1814         /* Setup initial parameters */
1815         io.lockx.level = RAW_LOCK_LOCKX;
1816         io.lockx.in.timeout = 0;
1817 
1818         lock1.pid = cli->session->pid;
1819         lock1.offset = 0;
1820         lock1.count = 10;
1821         lock2.pid = cli->session->pid - 1;
1822         lock2.offset = 0;
1823         lock2.count = 10;
1824 
1825         /**
1826          * Try to take a shared lock, then stack an exclusive.
1827          */
1828         printf("  stacking an exclusive on top of a shared lock fails.\n");
1829         io.lockx.in.file.fnum = fnum1;
1830         io.lockx.in.locks = &lock1;
1831 
1832         io.lockx.in.ulock_cnt = 0;
1833         io.lockx.in.lock_cnt = 1;
1834         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1835         status = smb_raw_lock(cli->tree, &io);
1836         CHECK_STATUS(status, NT_STATUS_OK);
1837 
1838         io.lockx.in.ulock_cnt = 0;
1839         io.lockx.in.lock_cnt = 1;
1840         io.lockx.in.mode = 0;
1841         status = smb_raw_lock(cli->tree, &io);
1842         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1843             NT_STATUS_FILE_LOCK_CONFLICT);
1844 
1845         /* cleanup */
1846         io.lockx.in.ulock_cnt = 1;
1847         io.lockx.in.lock_cnt = 0;
1848         status = smb_raw_lock(cli->tree, &io);
1849         CHECK_STATUS(status, NT_STATUS_OK);
1850 
1851         /**
1852          * Prove that two exclusive locks do not stack.
1853          */
1854         printf("  two exclusive locks do not stack.\n");
1855         io.lockx.in.ulock_cnt = 0;
1856         io.lockx.in.lock_cnt = 1;
1857         io.lockx.in.mode = 0;
1858         status = smb_raw_lock(cli->tree, &io);
1859         CHECK_STATUS(status, NT_STATUS_OK);
1860         status = smb_raw_lock(cli->tree, &io);
1861         CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1862             NT_STATUS_FILE_LOCK_CONFLICT);
1863 
1864         /* cleanup */
1865         io.lockx.in.ulock_cnt = 1;
1866         io.lockx.in.lock_cnt = 0;
1867         status = smb_raw_lock(cli->tree, &io);
1868         CHECK_STATUS(status, NT_STATUS_OK);
1869 
1870 done:
1871         smbcli_close(cli->tree, fnum1);
1872         smb_raw_exit(cli->session);
1873         smbcli_deltree(cli->tree, BASEDIR);
1874         return ret;
1875 }
1876 
1877 /* 
1878    basic testing of lock calls
1879 */
1880 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
1881 {
1882         struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
1883 
1884         torture_suite_add_1smb_test(suite, "lockx", test_lockx);
1885         torture_suite_add_1smb_test(suite, "lock", test_lock);
1886         torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
1887         torture_suite_add_1smb_test(suite, "async", test_async);
1888         torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
1889         torture_suite_add_1smb_test(suite, "changetype", test_changetype);
1890 
1891         torture_suite_add_1smb_test(suite, "stacking", test_stacking);
1892         torture_suite_add_1smb_test(suite, "unlock", test_unlock);
1893         torture_suite_add_1smb_test(suite, "multiple_unlock",
1894             test_multiple_unlock);
1895         torture_suite_add_1smb_test(suite, "zerobytelocks",
1896             test_zerobytelocks);
1897 
1898         return suite;
1899 }

/* [<][>][^][v][top][bottom][index][help] */