Cope with API changes.
[gd/samba-autobuild/.git] / source4 / torture / raw / oplock.c
index 51e6a5de6cadbfb10fbb63a7ddbd95fd54e0122d..7e964b4d426ed66f83e1c445233855972da93d6d 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "torture/torture.h"
+#include "librpc/gen_ndr/security.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "libcli/libcli.h"
+#include "torture/util.h"
+#include "lib/events/events.h"
+#include "param/param.h"
+#include "lib/cmdline/popt_common.h"
+#include "libcli/resolve/resolve.h"
 
 #define CHECK_VAL(v, correct) do { \
        if ((v) != (correct)) { \
-               printf("(%d) wrong value for %s  got 0x%x - should be 0x%x\n", \
-                      __LINE__, #v, (int)v, (int)correct); \
-               ret = False; \
+               torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
+                               __location__, #v, (int)v, (int)correct); \
+               ret = false; \
        }} while (0)
 
-#define CHECK_STATUS(status, correct) do { \
+#define CHECK_RANGE(v, min, max) do { \
+       if ((v) < (min) || (v) > (max)) { \
+               torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got %d - should be between %d and %d\n", \
+                               __location__, #v, (int)v, (int)min, (int)max); \
+               ret = false; \
+       }} while (0)
+
+#define CHECK_STRMATCH(v, correct) do { \
+       if (!v || strstr((v),(correct)) == NULL) { \
+               torture_result(tctx, TORTURE_FAIL,  "(%s): wrong value for %s got '%s' - should be '%s'\n", \
+                               __location__, #v, v?v:"NULL", correct); \
+               ret = false; \
+       } \
+} while (0)
+
+#define CHECK_STATUS(tctx, status, correct) do { \
        if (!NT_STATUS_EQUAL(status, correct)) { \
-               printf("(%d) Incorrect status %s - should be %s\n", \
-                      __LINE__, nt_errstr(status), nt_errstr(correct)); \
-               ret = False; \
+               torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
+                      nt_errstr(status), nt_errstr(correct)); \
+               ret = false; \
                goto done; \
        }} while (0)
 
@@ -40,74 +64,164 @@ static struct {
        int fnum;
        uint8_t level;
        int count;
+       int failures;
 } break_info;
 
+#define BASEDIR "\\test_oplock"
+
 /*
-  a handler function for oplock break requests
+  a handler function for oplock break requests. Ack it as a break to level II if possible
 */
-static BOOL oplock_handler_ack(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
+static bool oplock_handler_ack_to_given(struct smbcli_transport *transport,
+                                       uint16_t tid, uint16_t fnum,
+                                       uint8_t level, void *private)
 {
-       struct smbcli_tree *tree = private;
+       struct smbcli_tree *tree = (struct smbcli_tree *)private;
+       const char *name;
+
        break_info.fnum = fnum;
        break_info.level = level;
        break_info.count++;
 
-       printf("Acking in oplock handler\n");
+       switch (level) {
+       case OPLOCK_BREAK_TO_LEVEL_II:
+               name = "level II";
+               break;
+       case OPLOCK_BREAK_TO_NONE:
+               name = "none";
+               break;
+       default:
+               name = "unknown";
+               break_info.failures++;
+       }
+       printf("Acking to %s [0x%02X] in oplock handler\n",
+               name, level);
 
        return smbcli_oplock_ack(tree, fnum, level);
 }
 
+/*
+  a handler function for oplock break requests. Ack it as a break to none
+*/
+static bool oplock_handler_ack_to_none(struct smbcli_transport *transport, 
+                                      uint16_t tid, uint16_t fnum, 
+                                      uint8_t level, void *private)
+{
+       struct smbcli_tree *tree = (struct smbcli_tree *)private;
+       break_info.fnum = fnum;
+       break_info.level = level;
+       break_info.count++;
+
+       printf("Acking to none in oplock handler\n");
+
+       return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
+}
+
+/*
+  a handler function for oplock break requests. Let it timeout
+*/
+static bool oplock_handler_timeout(struct smbcli_transport *transport,
+                                  uint16_t tid, uint16_t fnum,
+                                  uint8_t level, void *private)
+{
+       break_info.fnum = fnum;
+       break_info.level = level;
+       break_info.count++;
+
+       printf("Let oplock break timeout\n");
+       return true;
+}
+
+static void oplock_handler_close_recv(struct smbcli_request *req)
+{
+       NTSTATUS status;
+       status = smbcli_request_simple_recv(req);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("close failed in oplock_handler_close\n");
+               break_info.failures++;
+       }
+}
+
 /*
   a handler function for oplock break requests - close the file
 */
-static BOOL oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
+static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, 
+                                uint16_t fnum, uint8_t level, void *private)
 {
        union smb_close io;
-       NTSTATUS status;
-       struct smbcli_tree *tree = private;
+       struct smbcli_tree *tree = (struct smbcli_tree *)private;
+       struct smbcli_request *req;
 
        break_info.fnum = fnum;
        break_info.level = level;
        break_info.count++;
 
        io.close.level = RAW_CLOSE_CLOSE;
-       io.close.in.fnum = fnum;
+       io.close.in.file.fnum = fnum;
        io.close.in.write_time = 0;
-       status = smb_raw_close(tree, &io);
+       req = smb_raw_close_send(tree, &io);
+       if (req == NULL) {
+               printf("failed to send close in oplock_handler_close\n");
+               return false;
+       }
+
+       req->async.fn = oplock_handler_close_recv;
+       req->async.private = NULL;
+
+       return true;
+}
+
+static bool open_connection_no_level2_oplocks(struct torture_context *tctx,
+                                             struct smbcli_state **c)
+{
+       NTSTATUS status;
+       struct smbcli_options options;
+       struct smbcli_session_options session_options;
 
-       printf("Closing in oplock handler\n");
+       lp_smbcli_options(tctx->lp_ctx, &options);
+       lp_smbcli_session_options(tctx->lp_ctx, &session_options);
 
+       options.use_level2_oplocks = false;
+
+       status = smbcli_full_connection(tctx, c,
+                                       torture_setting_string(tctx, "host", NULL),
+                                       lp_smb_ports(tctx->lp_ctx),
+                                       torture_setting_string(tctx, "share", NULL),
+                                       NULL, cmdline_credentials,
+                                       lp_resolve_context(tctx->lp_ctx),
+                                       tctx->ev, &options, &session_options);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("close failed in oplock_handler_close\n");
-               return False;
+               printf("Failed to open connection - %s\n", nt_errstr(status));
+               return false;
        }
-       return True;
+
+       return true;
 }
 
-/*
-  test oplock ops
-*/
-static BOOL test_oplock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 {
-       const char *fname = "\\test_oplock.dat";
+       const char *fname = BASEDIR "\\test_exclusive1.dat";
        NTSTATUS status;
-       BOOL ret = True;
+       bool ret = true;
        union smb_open io;
-       struct smb_unlink unl;
-       union smb_read rd;
-       uint16_t fnum=0, fnum2=0;
+       union smb_unlink unl;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
 
        /* cleanup */
-       smbcli_unlink(cli->tree, fname);
+       smbcli_unlink(cli1->tree, fname);
 
-       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
        /*
          base ntcreatex parms
        */
        io.generic.level = RAW_OPEN_NTCREATEX;
        io.ntcreatex.in.root_fid = 0;
-       io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
        io.ntcreatex.in.alloc_size = 0;
        io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
@@ -117,233 +231,2801 @@ static BOOL test_oplock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        io.ntcreatex.in.security_flags = 0;
        io.ntcreatex.in.fname = fname;
 
-       printf("open a file with a normal oplock\n");
+       torture_comment(tctx, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
        ZERO_STRUCT(break_info);
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
 
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
 
-       printf("unlink it - should be no break\n");
-       unl.in.pattern = fname;
-       unl.in.attrib = 0;
-       status = smb_raw_unlink(cli->tree, &unl);
-       CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
+       torture_comment(tctx, "a 2nd open should not cause a break\n");
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       torture_comment(tctx, "unlink it - should also be no break\n");
+       unl.unlink.in.pattern = fname;
+       unl.unlink.in.attrib = 0;
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
        CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_exclusive2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_exclusive2.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_unlink unl;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
 
-       smbcli_close(cli->tree, fnum);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
        /*
-         with a batch oplock we get a break
+         base ntcreatex parms
        */
-       printf("open with batch oplock\n");
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
        ZERO_STRUCT(break_info);
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
 
-       printf("unlink should generate a break\n");
-       unl.in.pattern = fname;
-       unl.in.attrib = 0;
-       status = smb_raw_unlink(cli->tree, &unl);
-       CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
 
-       CHECK_VAL(break_info.fnum, fnum);
-       CHECK_VAL(break_info.level, 1);
+       torture_comment(tctx, "a 2nd open should cause a break to level 2\n");
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
        CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+       CHECK_VAL(break_info.failures, 0);
+       ZERO_STRUCT(break_info);
 
+       /* now we have 2 level II oplocks... */
+       torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
+       unl.unlink.in.pattern = fname;
+       unl.unlink.in.attrib = 0;
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
 
-       smbcli_close(cli->tree, fnum);
+       torture_comment(tctx, "close 1st handle\n");
+       smbcli_close(cli1->tree, fnum);
 
-       printf("if we close on break then the unlink can succeed\n");
-       ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+       torture_comment(tctx, "try to unlink it - should not cause a break, but a sharing violation\n");
+       unl.unlink.in.pattern = fname;
+       unl.unlink.in.attrib = 0;
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
 
-       unl.in.pattern = fname;
-       unl.in.attrib = 0;
-       ZERO_STRUCT(break_info);
-       status = smb_raw_unlink(cli->tree, &unl);
-       CHECK_STATUS(status, NT_STATUS_OK);
+       torture_comment(tctx, "close 1st handle\n");
+       smbcli_close(cli2->tree, fnum2);
 
-       CHECK_VAL(break_info.fnum, fnum);
-       CHECK_VAL(break_info.level, 1);
-       CHECK_VAL(break_info.count, 1);
+       torture_comment(tctx, "unlink it\n");
+       unl.unlink.in.pattern = fname;
+       unl.unlink.in.attrib = 0;
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
 
-       printf("a self read should not cause a break\n");
-       ZERO_STRUCT(break_info);
-       smbcli_close(cli->tree, fnum);
-       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_exclusive3.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_setfileinfo sfi;
+       uint16_t fnum=0;
 
-       rd.read.level = RAW_READ_READ;
-       rd.read.in.fnum = fnum;
-       rd.read.in.count = 1;
-       rd.read.in.offset = 0;
-       rd.read.in.remaining = 0;
-       status = smb_raw_read(cli->tree, &rd);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       CHECK_VAL(break_info.count, 0);
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
 
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
 
-       printf("a 2nd open should give a break\n");
-       ZERO_STRUCT(break_info);
-       smbcli_close(cli->tree, fnum);
-       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
 
        ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
+
+       torture_comment(tctx, "setpathinfo EOF should trigger a break to none\n");
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+       sfi.generic.in.file.path = fname;
+       sfi.end_of_file_info.in.size = 100;
 
+       status = smb_raw_setpathinfo(cli2->tree, &sfi);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
        CHECK_VAL(break_info.count, 1);
-       CHECK_VAL(break_info.fnum, fnum);
-       CHECK_VAL(break_info.level, 1);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
 
-       printf("a 2nd open should get an oplock when we close instead of ack\n");
-       ZERO_STRUCT(break_info);
-       smbcli_close(cli->tree, fnum);
-       smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
+       smbcli_close(cli1->tree, fnum);
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum2 = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
 
-       ZERO_STRUCT(break_info);
+static bool test_raw_oplock_exclusive4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_exclusive4.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
 
-       CHECK_VAL(break_info.count, 1);
-       CHECK_VAL(break_info.fnum, fnum2);
-       CHECK_VAL(break_info.level, 1);
-       
-       smbcli_close(cli->tree, fnum);
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
 
-       printf("open with batch oplock\n");
+       torture_comment(tctx, "EXCLUSIVE4: open with exclusive oplock\n");
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
 
        ZERO_STRUCT(break_info);
-       printf("second open with attributes only shouldn't cause oplock break\n");
+       torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       io.ntcreatex.in.access_mask = SA_RIGHT_FILE_READ_ATTRIBUTES|SA_RIGHT_FILE_WRITE_ATTRIBUTES|STD_RIGHT_SYNCHRONIZE_ACCESS;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum2 = io.ntcreatex.out.fnum;
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
        CHECK_VAL(break_info.count, 0);
-       CHECK_VAL(break_info.fnum, 0);
-       CHECK_VAL(break_info.level, 0);
+       CHECK_VAL(break_info.failures, 0);
 
-       smbcli_close(cli->tree, fnum);
-       smbcli_close(cli->tree, fnum2);
-       smbcli_unlink(cli->tree, fname);
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
 
-       printf("open with attributes only can create file\n");
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       io.ntcreatex.in.access_mask = SA_RIGHT_FILE_READ_ATTRIBUTES|SA_RIGHT_FILE_WRITE_ATTRIBUTES|STD_RIGHT_SYNCHRONIZE_ACCESS;
-       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
-       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_exclusive5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_exclusive5.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "EXCLUSIVE5: open with exclusive oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
-       printf("Subsequent normal open should break oplock on attribute only open to level II\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
 
        ZERO_STRUCT(break_info);
-       smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
 
-       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
-               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
-               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
-       io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
-       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
-       status = smb_raw_open(cli->tree, mem_ctx, &io);
-       CHECK_STATUS(status, NT_STATUS_OK);
-       fnum2 = io.ntcreatex.out.fnum;
-       CHECK_VAL(break_info.count, 1);
-       CHECK_VAL(break_info.fnum, fnum);
+       torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
        CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
 
 done:
-       smbcli_close(cli->tree, fnum);
-       smbcli_close(cli->tree, fnum2);
-       smbcli_unlink(cli->tree, fname);
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
        return ret;
 }
 
-
-/* 
-   basic testing of oplocks
-*/
-BOOL torture_raw_oplock(void)
+static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 {
-       struct smbcli_state *cli1;
-       BOOL ret = True;
-       TALLOC_CTX *mem_ctx;
+       const char *fname1 = BASEDIR "\\test_exclusive6_1.dat";
+       const char *fname2 = BASEDIR "\\test_exclusive6_2.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_rename rn;
+       uint16_t fnum=0;
 
-       if (!torture_open_connection(&cli1)) {
-               return False;
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
        }
 
-       mem_ctx = talloc_init("torture_raw_oplock");
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname1);
+       smbcli_unlink(cli1->tree, fname2);
 
-       if (!test_oplock(cli1, mem_ctx)) {
-               ret = False;
-       }
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
 
-       torture_close_connection(cli1);
-       talloc_destroy(mem_ctx);
-       return ret;
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname1;
+
+       torture_comment(tctx, "EXCLUSIVE6: open a file with an exclusive oplock (share mode: none)\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
+
+       torture_comment(tctx, "rename should not generate a break but get a sharing violation\n");
+       ZERO_STRUCT(rn);
+       rn.generic.level = RAW_RENAME_RENAME;
+       rn.rename.in.pattern1 = fname1;
+       rn.rename.in.pattern2 = fname2;
+       rn.rename.in.attrib = 0;
+
+       printf("trying rename while first file open\n");
+       status = smb_raw_rename(cli2->tree, &rn);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch1.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_unlink unl;
+       uint16_t fnum=0;
+       char c = 0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       /*
+         with a batch oplock we get a break
+       */
+       torture_comment(tctx, "BATCH1: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "unlink should generate a break\n");
+       unl.unlink.in.pattern = fname;
+       unl.unlink.in.attrib = 0;
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+       CHECK_VAL(break_info.failures, 0);
+
+       torture_comment(tctx, "2nd unlink should not generate a break\n");
+       ZERO_STRUCT(break_info);
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+
+       CHECK_VAL(break_info.count, 0);
+
+       torture_comment(tctx, "writing should generate a self break to none\n");
+       smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
+       msleep(100);
+       smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch2.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_unlink unl;
+       uint16_t fnum=0;
+       char c = 0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH2: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
+       unl.unlink.in.pattern = fname;
+       unl.unlink.in.attrib = 0;
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+       CHECK_VAL(break_info.failures, 0);
+
+       torture_comment(tctx, "2nd unlink should not generate a break\n");
+       ZERO_STRUCT(break_info);
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+
+       CHECK_VAL(break_info.count, 0);
+
+       torture_comment(tctx, "writing should not generate a break\n");
+       smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
+       msleep(100);
+       smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
+
+       CHECK_VAL(break_info.count, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch3.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_unlink unl;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH3: if we close on break then the unlink can succeed\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       unl.unlink.in.pattern = fname;
+       unl.unlink.in.attrib = 0;
+       ZERO_STRUCT(break_info);
+       status = smb_raw_unlink(cli2->tree, &unl);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, 1);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch4.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_read rd;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH4: a self read should not cause a break\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       rd.read.level = RAW_READ_READ;
+       rd.read.in.file.fnum = fnum;
+       rd.read.in.count = 1;
+       rd.read.in.offset = 0;
+       rd.read.in.remaining = 0;
+       status = smb_raw_read(cli1->tree, &rd);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch5.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH5: a 2nd open should give a break\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, 1);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch6.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+       char c = 0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
+
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, 1);
+       CHECK_VAL(break_info.failures, 0);
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "write should trigger a break to none on both\n");
+       smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
+       msleep(100);
+       smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
+
+       CHECK_VAL(break_info.count, 2);
+       CHECK_VAL(break_info.level, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch7.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
+
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum2);
+       CHECK_VAL(break_info.level, 1);
+       CHECK_VAL(break_info.failures, 0);
+       
+       smbcli_close(cli2->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch8.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH8: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+       torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch9.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+       char c = 0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH9: open with attributes only can create file\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
+
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       smbcli_close(cli2->tree, fnum2);
+
+       torture_comment(tctx, "third oplocked open should grant level2 without break\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "write should trigger a break to none on both\n");
+       smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
+
+       /* Now the oplock break request comes in. But right now we can't
+        * answer it. Do another write */
+
+       msleep(100);
+       smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
+
+       CHECK_VAL(break_info.count, 2);
+       CHECK_VAL(break_info.level, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch10.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
+
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       torture_comment(tctx, "write should trigger a break to none\n");
+       {
+               union smb_write wr;
+               wr.write.level = RAW_WRITE_WRITE;
+               wr.write.in.file.fnum = fnum;
+               wr.write.in.count = 1;
+               wr.write.in.offset = 0;
+               wr.write.in.remaining = 0;
+               wr.write.in.data = (const uint8_t *)"x";
+               status = smb_raw_write(cli1->tree, &wr);
+               CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       }
+
+       /* Now the oplock break request comes in. But right now we can't
+        * answer it. Do another write */
+
+       msleep(100);
+       
+       {
+               union smb_write wr;
+               wr.write.level = RAW_WRITE_WRITE;
+               wr.write.in.file.fnum = fnum;
+               wr.write.in.count = 1;
+               wr.write.in.offset = 0;
+               wr.write.in.remaining = 0;
+               wr.write.in.data = (const uint8_t *)"x";
+               status = smb_raw_write(cli1->tree, &wr);
+               CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       }
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum2);
+       CHECK_VAL(break_info.level, 0);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch11.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_setfileinfo sfi;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       /* Test if a set-eof on pathname breaks an exclusive oplock. */
+       torture_comment(tctx, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
+
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+       
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+       sfi.generic.in.file.path = fname;
+       sfi.end_of_file_info.in.size = 100;
+
+        status = smb_raw_setpathinfo(cli2->tree, &sfi);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch12.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_setfileinfo sfi;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
+       torture_comment(tctx, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
+
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+       
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
+       sfi.generic.in.file.path = fname;
+       sfi.allocation_info.in.alloc_size = 65536 * 8;
+
+        status = smb_raw_setpathinfo(cli2->tree, &sfi);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch13.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH13: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch14.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH14: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch15.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_fileinfo qfi;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
+       torture_comment(tctx, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
+
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(break_info.count, 0);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.path = fname;
+
+       status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch16.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH16: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
+
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname1 = BASEDIR "\\test_batch17_1.dat";
+       const char *fname2 = BASEDIR "\\test_batch17_2.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_rename rn;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname1);
+       smbcli_unlink(cli1->tree, fname2);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname1;
+
+       torture_comment(tctx, "BATCH17: open a file with an batch oplock (share mode: none)\n");
+
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "rename should trigger a break\n");
+       ZERO_STRUCT(rn);
+       rn.generic.level = RAW_RENAME_RENAME;
+       rn.rename.in.pattern1 = fname1;
+       rn.rename.in.pattern2 = fname2;
+       rn.rename.in.attrib = 0;
+
+       printf("trying rename while first file open\n");
+       status = smb_raw_rename(cli2->tree, &rn);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname1 = BASEDIR "\\test_batch18_1.dat";
+       const char *fname2 = BASEDIR "\\test_batch18_2.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_rename rn;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname1);
+       smbcli_unlink(cli1->tree, fname2);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname1;
+
+       torture_comment(tctx, "BATCH18: open a file with an batch oplock (share mode: none)\n");
+
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "ntrename should trigger a break\n");
+       ZERO_STRUCT(rn);
+       rn.generic.level = RAW_RENAME_NTRENAME;
+       rn.ntrename.in.attrib   = 0;
+       rn.ntrename.in.flags    = RENAME_FLAG_RENAME;
+       rn.ntrename.in.old_name = fname1;
+       rn.ntrename.in.new_name = fname2;
+       printf("trying rename while first file open\n");
+       status = smb_raw_rename(cli2->tree, &rn);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname1 = BASEDIR "\\test_batch19_1.dat";
+       const char *fname2 = BASEDIR "\\test_batch19_2.dat";
+       const char *fname3 = BASEDIR "\\test_batch19_3.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_fileinfo qfi;
+       union smb_setfileinfo sfi;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname1);
+       smbcli_unlink(cli1->tree, fname2);
+       smbcli_unlink(cli1->tree, fname3);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname1;
+
+       torture_comment(tctx, "BATCH19: open a file with an batch oplock (share mode: none)\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
+       sfi.generic.in.file.path = fname1;
+       sfi.rename_information.in.overwrite     = 0;
+       sfi.rename_information.in.root_fid      = 0;
+       sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
+
+        status = smb_raw_setpathinfo(cli2->tree, &sfi);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum;
+
+       status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
+
+       torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
+       sfi.generic.in.file.fnum = fnum;
+       sfi.rename_information.in.overwrite     = 0;
+       sfi.rename_information.in.root_fid      = 0;
+       sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
+
+       status = smb_raw_setfileinfo(cli1->tree, &sfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum;
+
+       status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+/****************************************************
+ Called from raw-rename - we need oplock handling for
+ this test so this is why it's in oplock.c, not rename.c
+****************************************************/
+
+bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname1 = BASEDIR "\\test_trans2rename_1.dat";
+       const char *fname2 = BASEDIR "\\test_trans2rename_2.dat";
+       const char *fname3 = BASEDIR "\\test_trans2rename_3.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_fileinfo qfi;
+       union smb_setfileinfo sfi;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname1);
+       smbcli_unlink(cli1->tree, fname2);
+       smbcli_unlink(cli1->tree, fname3);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname1;
+
+       torture_comment(tctx, "open a file with an exclusive oplock (share mode: none)\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
+
+       torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
+       sfi.generic.in.file.path = fname1;
+       sfi.rename_information.in.overwrite     = 0;
+       sfi.rename_information.in.root_fid      = 0;
+       sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
+
+        status = smb_raw_setpathinfo(cli2->tree, &sfi);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum;
+
+       status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
+
+       torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
+       sfi.generic.in.file.fnum = fnum;
+       sfi.rename_information.in.overwrite     = 0;
+       sfi.rename_information.in.root_fid      = 0;
+       sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
+
+       status = smb_raw_setfileinfo(cli1->tree, &sfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum;
+
+       status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+/****************************************************
+ Called from raw-rename - we need oplock handling for
+ this test so this is why it's in oplock.c, not rename.c
+****************************************************/
+
+bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1)
+{
+       const char *fname1 = BASEDIR "\\test_nttransrename_1.dat";
+       const char *fname2 = BASEDIR "\\test_nttransrename_2.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_fileinfo qfi, qpi;
+       union smb_rename rn;
+       uint16_t fnum=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname1);
+       smbcli_unlink(cli1->tree, fname2);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = 0;/* ask for no access at all */;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname1;
+
+       torture_comment(tctx, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
+
+       torture_comment(tctx, "nttrans_rename: should not trigger a break nor a share mode violation\n");
+       ZERO_STRUCT(rn);
+       rn.generic.level = RAW_RENAME_NTTRANS;
+       rn.nttrans.in.file.fnum = fnum;
+       rn.nttrans.in.flags     = 0;
+       rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
+
+        status = smb_raw_rename(cli1->tree, &rn);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+
+       /* w2k3 does nothing, it doesn't rename the file */
+       torture_comment(tctx, "nttrans_rename: the server should have done nothing\n");
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum;
+
+       status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname1);
+
+       ZERO_STRUCT(qpi);
+       qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qpi.generic.in.file.path = fname1;
+
+       status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
+
+       ZERO_STRUCT(qpi);
+       qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qpi.generic.in.file.path = fname2;
+
+       status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+       torture_comment(tctx, "nttrans_rename: after closing the file the file is still not renamed\n");
+       status = smbcli_close(cli1->tree, fnum);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       ZERO_STRUCT(qpi);
+       qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qpi.generic.in.file.path = fname1;
+
+       status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qpi.all_info.out.fname.s, fname1);
+
+       ZERO_STRUCT(qpi);
+       qpi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qpi.generic.in.file.path = fname2;
+
+       status = smb_raw_pathinfo(cli1->tree, tctx, &qpi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+       torture_comment(tctx, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
+       ZERO_STRUCT(rn);
+       rn.generic.level = RAW_RENAME_NTTRANS;
+       rn.nttrans.in.file.fnum = fnum+1;
+       rn.nttrans.in.flags     = 0;
+       rn.nttrans.in.new_name  = fname2+strlen(BASEDIR)+1;
+
+       status = smb_raw_rename(cli1->tree, &rn);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_INVALID_HANDLE);
+
+done:
+       smb_raw_exit(cli1->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+
+static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname1 = BASEDIR "\\test_batch20_1.dat";
+       const char *fname2 = BASEDIR "\\test_batch20_2.dat";
+       const char *fname3 = BASEDIR "\\test_batch20_3.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       union smb_fileinfo qfi;
+       union smb_setfileinfo sfi;
+       uint16_t fnum=0,fnum2=0;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname1);
+       smbcli_unlink(cli1->tree, fname2);
+       smbcli_unlink(cli1->tree, fname3);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname1;
+
+       torture_comment(tctx, "BATCH20: open a file with an batch oplock (share mode: all)\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "setpathinfo rename info should not trigger a break nor a violation\n");
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
+       sfi.generic.in.file.path = fname1;
+       sfi.rename_information.in.overwrite     = 0;
+       sfi.rename_information.in.root_fid      = 0;
+       sfi.rename_information.in.new_name      = fname2+strlen(BASEDIR)+1;
+
+       status = smb_raw_setpathinfo(cli2->tree, &sfi);
+
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 0);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum;
+
+       status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname2);
+
+       torture_comment(tctx, "open a file with the new name an batch oplock (share mode: all)\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       io.ntcreatex.in.fname = fname2;
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+
+       torture_comment(tctx, "setfileinfo rename info should not trigger a break nor a violation\n");
+       ZERO_STRUCT(sfi);
+       sfi.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
+       sfi.generic.in.file.fnum = fnum;
+       sfi.rename_information.in.overwrite     = 0;
+       sfi.rename_information.in.root_fid      = 0;
+       sfi.rename_information.in.new_name      = fname3+strlen(BASEDIR)+1;
+
+       status = smb_raw_setfileinfo(cli1->tree, &sfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.failures, 0);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum;
+
+       status = smb_raw_fileinfo(cli1->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
+
+       ZERO_STRUCT(qfi);
+       qfi.generic.level = RAW_FILEINFO_ALL_INFORMATION;
+       qfi.generic.in.file.fnum = fnum2;
+
+       status = smb_raw_fileinfo(cli2->tree, tctx, &qfi);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_STRMATCH(qfi.all_info.out.fname.s, fname3);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch21(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch21.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       struct smb_echo e;
+       uint16_t fnum=0;
+       char c = 0;
+       ssize_t wr;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       /*
+         with a batch oplock we get a break
+       */
+       torture_comment(tctx, "BATCH21: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "writing should not generate a break\n");
+       wr = smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
+       CHECK_VAL(wr, 1);
+       CHECK_STATUS(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_OK);
+
+       ZERO_STRUCT(e);
+       e.in.repeat_count = 1;
+       status = smb_raw_echo(cli1->transport, &e);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+
+       CHECK_VAL(break_info.count, 0);
+
+       smbcli_close(cli1->tree, fnum);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch22(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch22.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0;
+       struct timeval tv;
+       int timeout = torture_setting_int(tctx, "oplocktimeout", 30);
+       int te;
+
+       if (torture_setting_bool(tctx, "samba3", false)) {
+               torture_skip(tctx, "BATCH22 disabled against samba3\n");
+       }
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       /*
+         with a batch oplock we get a break
+       */
+       torture_comment(tctx, "BATCH22: open with batch oplock\n");
+       ZERO_STRUCT(break_info);
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+               NTCREATEX_SHARE_ACCESS_WRITE|
+               NTCREATEX_SHARE_ACCESS_DELETE;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       torture_comment(tctx, "a 2nd open shoud not succeed after the oplock break timeout\n");
+       tv = timeval_current();
+       smbcli_oplock_handler(cli1->transport, oplock_handler_timeout, cli1->tree);
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
+       te = (int)timeval_elapsed(&tv);
+       CHECK_RANGE(te, timeout - 1, timeout + 15);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+       CHECK_VAL(break_info.failures, 0);
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "a 2nd open shoud succeed after the oplock release without break\n");
+       tv = timeval_current();
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+       te = (int)timeval_elapsed(&tv);
+       /* it should come in without delay */
+       CHECK_RANGE(te+1, 0, timeout);
+       fnum2 = io.ntcreatex.out.file.fnum;
+
+       CHECK_VAL(break_info.count, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli1->tree, fnum2);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch23(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch23.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum=0, fnum2=0,fnum3=0;
+       struct smbcli_state *cli3 = NULL;
+
+       if (torture_setting_bool(tctx, "samba3", false)) {
+               torture_skip(tctx, "BATCH23 disabled against samba3\n");
+       }
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       ret = open_connection_no_level2_oplocks(tctx, &cli3);
+       CHECK_VAL(ret, true);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH23: a open and ask for a batch oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
+       smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
+
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli1->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "a 2nd open without level2 oplock support should generate a break to level2\n");
+       status = smb_raw_open(cli3->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum3 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
+       CHECK_VAL(break_info.failures, 0);
+
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "a 3rd open with level2 oplock support should not generate a break\n");
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       CHECK_VAL(break_info.count, 0);
+
+       smbcli_close(cli1->tree, fnum);
+       smbcli_close(cli2->tree, fnum2);
+       smbcli_close(cli3->tree, fnum3);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smb_raw_exit(cli3->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+static bool test_raw_oplock_batch24(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       const char *fname = BASEDIR "\\test_batch24.dat";
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       uint16_t fnum2=0,fnum3=0;
+       struct smbcli_state *cli3 = NULL;
+
+       if (!torture_setup_dir(cli1, BASEDIR)) {
+               return false;
+       }
+
+       /* cleanup */
+       smbcli_unlink(cli1->tree, fname);
+
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+
+       ret = open_connection_no_level2_oplocks(tctx, &cli3);
+       CHECK_VAL(ret, true);
+
+       /*
+         base ntcreatex parms
+       */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       torture_comment(tctx, "BATCH24: a open without level support and ask for a batch oplock\n");
+       ZERO_STRUCT(break_info);
+       smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree);
+       smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree);
+       smbcli_oplock_handler(cli3->transport, oplock_handler_ack_to_given, cli3->tree);
+
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+               NTCREATEX_FLAGS_REQUEST_OPLOCK |
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+       status = smb_raw_open(cli3->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum3 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
+
+       ZERO_STRUCT(break_info);
+
+       torture_comment(tctx, "a 2nd open with level2 oplock support should generate a break to none\n");
+       status = smb_raw_open(cli2->tree, tctx, &io);
+       CHECK_STATUS(tctx, status, NT_STATUS_OK);
+       fnum2 = io.ntcreatex.out.file.fnum;
+       CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
+
+       CHECK_VAL(break_info.count, 1);
+       CHECK_VAL(break_info.fnum, fnum3);
+       CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
+       CHECK_VAL(break_info.failures, 0);
+
+       smbcli_close(cli3->tree, fnum3);
+       smbcli_close(cli2->tree, fnum2);
+
+done:
+       smb_raw_exit(cli1->session);
+       smb_raw_exit(cli2->session);
+       smb_raw_exit(cli3->session);
+       smbcli_deltree(cli1->tree, BASEDIR);
+       return ret;
+}
+
+/* 
+   basic testing of oplocks
+*/
+struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "OPLOCK");
+
+       torture_suite_add_2smb_test(suite, "EXCLUSIVE1", test_raw_oplock_exclusive1);
+       torture_suite_add_2smb_test(suite, "EXCLUSIVE2", test_raw_oplock_exclusive2);
+       torture_suite_add_2smb_test(suite, "EXCLUSIVE3", test_raw_oplock_exclusive3);
+       torture_suite_add_2smb_test(suite, "EXCLUSIVE4", test_raw_oplock_exclusive4);
+       torture_suite_add_2smb_test(suite, "EXCLUSIVE5", test_raw_oplock_exclusive5);
+       torture_suite_add_2smb_test(suite, "EXCLUSIVE6", test_raw_oplock_exclusive6);
+       torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
+       torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
+       torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
+       torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
+       torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
+       torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
+       torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
+       torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
+       torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
+       torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
+       torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
+       torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
+       torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
+       torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
+       torture_suite_add_2smb_test(suite, "BATCH15", test_raw_oplock_batch15);
+       torture_suite_add_2smb_test(suite, "BATCH16", test_raw_oplock_batch16);
+       torture_suite_add_2smb_test(suite, "BATCH17", test_raw_oplock_batch17);
+       torture_suite_add_2smb_test(suite, "BATCH18", test_raw_oplock_batch18);
+       torture_suite_add_2smb_test(suite, "BATCH19", test_raw_oplock_batch19);
+       torture_suite_add_2smb_test(suite, "BATCH20", test_raw_oplock_batch20);
+       torture_suite_add_2smb_test(suite, "BATCH21", test_raw_oplock_batch21);
+       torture_suite_add_2smb_test(suite, "BATCH22", test_raw_oplock_batch22);
+       torture_suite_add_2smb_test(suite, "BATCH23", test_raw_oplock_batch23);
+       torture_suite_add_2smb_test(suite, "BATCH24", test_raw_oplock_batch24);
+
+       return suite;
+}
+
+/* 
+   stress testing of oplocks
+*/
+bool torture_bench_oplock(struct torture_context *torture)
+{
+       struct smbcli_state **cli;
+       bool ret = true;
+       TALLOC_CTX *mem_ctx = talloc_new(torture);
+       int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
+       int i, count=0;
+       int timelimit = torture_setting_int(torture, "timelimit", 10);
+       union smb_open io;
+       struct timeval tv;
+
+       cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
+
+       torture_comment(torture, "Opening %d connections\n", torture_nprocs);
+       for (i=0;i<torture_nprocs;i++) {
+               if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
+                       return false;
+               }
+               talloc_steal(mem_ctx, cli[i]);
+               smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
+                                     cli[i]->tree);
+       }
+
+       if (!torture_setup_dir(cli[0], BASEDIR)) {
+               ret = false;
+               goto done;
+       }
+
+       io.ntcreatex.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = BASEDIR "\\test.dat";
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+               NTCREATEX_FLAGS_REQUEST_OPLOCK | 
+               NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+
+       tv = timeval_current(); 
+
+       /*
+         we open the same file with SHARE_ACCESS_NONE from all the
+         connections in a round robin fashion. Each open causes an
+         oplock break on the previous connection, which is answered
+         by the oplock_handler_close() to close the file.
+
+         This measures how fast we can pass on oplocks, and stresses
+         the oplock handling code
+       */
+       torture_comment(torture, "Running for %d seconds\n", timelimit);
+       while (timeval_elapsed(&tv) < timelimit) {
+               for (i=0;i<torture_nprocs;i++) {
+                       NTSTATUS status;
+
+                       status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
+                       CHECK_STATUS(torture, status, NT_STATUS_OK);
+                       count++;
+               }
+
+               if (torture_setting_bool(torture, "progress", true)) {
+                       torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
+               }
+       }
+
+       torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
+
+       smb_raw_exit(cli[torture_nprocs-1]->session);
+       
+done:
+       smb_raw_exit(cli[0]->session);
+       smbcli_deltree(cli[0]->tree, BASEDIR);
+       talloc_free(mem_ctx);
+       return ret;
+}
+
+
+static struct hold_oplock_info {
+       const char *fname;
+       bool close_on_break;
+       uint32_t share_access;
+       uint16_t fnum;
+} hold_info[] = {
+       { BASEDIR "\\notshared_close", true,  
+         NTCREATEX_SHARE_ACCESS_NONE, },
+       { BASEDIR "\\notshared_noclose", false, 
+         NTCREATEX_SHARE_ACCESS_NONE, },
+       { BASEDIR "\\shared_close", true,  
+         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
+       { BASEDIR "\\shared_noclose", false,  
+         NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
+};
+
+static bool oplock_handler_hold(struct smbcli_transport *transport, 
+                               uint16_t tid, uint16_t fnum, uint8_t level, 
+                               void *private)
+{
+       struct smbcli_tree *tree = (struct smbcli_tree *)private;
+       struct hold_oplock_info *info;
+       int i;
+
+       for (i=0;i<ARRAY_SIZE(hold_info);i++) {
+               if (hold_info[i].fnum == fnum) break;
+       }
+
+       if (i == ARRAY_SIZE(hold_info)) {
+               printf("oplock break for unknown fnum %u\n", fnum);
+               return false;
+       }
+
+       info = &hold_info[i];
+
+       if (info->close_on_break) {
+               printf("oplock break on %s - closing\n",
+                      info->fname);
+               oplock_handler_close(transport, tid, fnum, level, private);
+               return true;
+       }
+
+       printf("oplock break on %s - acking break\n", info->fname);
+
+       return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
+}
+
+
+/* 
+   used for manual testing of oplocks - especially interaction with
+   other filesystems (such as NFS and local access)
+*/
+bool torture_hold_oplock(struct torture_context *torture, 
+                        struct smbcli_state *cli)
+{
+       struct event_context *ev = 
+               (struct event_context *)cli->transport->socket->event.ctx;
+       int i;
+
+       printf("Setting up open files with oplocks in %s\n", BASEDIR);
+
+       if (!torture_setup_dir(cli, BASEDIR)) {
+               return false;
+       }
+
+       smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
+
+       /* setup the files */
+       for (i=0;i<ARRAY_SIZE(hold_info);i++) {
+               union smb_open io;
+               NTSTATUS status;
+               char c = 1;
+
+               io.generic.level = RAW_OPEN_NTCREATEX;
+               io.ntcreatex.in.root_fid = 0;
+               io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+               io.ntcreatex.in.alloc_size = 0;
+               io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+               io.ntcreatex.in.share_access = hold_info[i].share_access;
+               io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+               io.ntcreatex.in.create_options = 0;
+               io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+               io.ntcreatex.in.security_flags = 0;
+               io.ntcreatex.in.fname = hold_info[i].fname;
+               io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
+                       NTCREATEX_FLAGS_REQUEST_OPLOCK |
+                       NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+               printf("opening %s\n", hold_info[i].fname);
+
+               status = smb_raw_open(cli->tree, cli, &io);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("Failed to open %s - %s\n", 
+                              hold_info[i].fname, nt_errstr(status));
+                       return false;
+               }
+
+               if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
+                       printf("Oplock not granted for %s - expected %d but got %d\n", 
+                              hold_info[i].fname, BATCH_OPLOCK_RETURN, 
+                               io.ntcreatex.out.oplock_level);
+                       return false;
+               }
+               hold_info[i].fnum = io.ntcreatex.out.file.fnum;
+
+               /* make the file non-zero size */
+               if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
+                       printf("Failed to write to file\n");
+                       return false;
+               }
+       }
+
+       printf("Waiting for oplock events\n");
+       event_loop_wait(ev);
+
+       return true;
 }