summaryrefslogtreecommitdiff
path: root/source4/torture/raw
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/raw')
-rw-r--r--source4/torture/raw/chkpath.c77
-rw-r--r--source4/torture/raw/composite.c2
-rw-r--r--source4/torture/raw/oplock.c872
-rw-r--r--source4/torture/raw/qfsinfo.c29
-rw-r--r--source4/torture/raw/setfileinfo.c115
5 files changed, 1056 insertions, 39 deletions
diff --git a/source4/torture/raw/chkpath.c b/source4/torture/raw/chkpath.c
index 42a3c3cebe..fa69c92caa 100644
--- a/source4/torture/raw/chkpath.c
+++ b/source4/torture/raw/chkpath.c
@@ -54,24 +54,68 @@ static NTSTATUS single_search(struct smbcli_state *cli,
return status;
}
-static bool test_path(struct smbcli_state *cli, const char *path, NTSTATUS expected, NTSTATUS dos_expected)
+static bool test_path_ex(struct smbcli_state *cli, struct torture_context *tctx,
+ const char *path, const char *path_expected,
+ NTSTATUS expected, NTSTATUS dos_expected)
{
union smb_chkpath io;
+ union smb_fileinfo finfo;
NTSTATUS status;
+
io.chkpath.in.path = path;
status = smb_raw_chkpath(cli->tree, &io);
if (!NT_STATUS_EQUAL(status, expected) && !NT_STATUS_EQUAL(status, dos_expected)) {
- printf("%-40s FAILED %s should be %s or %s\n",
+ printf("FAILED %-30s chkpath %s should be %s or %s\n",
path, nt_errstr(status), nt_errstr(expected), nt_errstr(dos_expected));
return false;
} else {
- printf("%-40s correct (%s)\n", path, nt_errstr(status));
+ printf("%-30s chkpath correct (%s)\n", path, nt_errstr(status));
+ }
+
+ if (NT_STATUS_EQUAL(expected, NT_STATUS_NOT_A_DIRECTORY)) {
+ expected = NT_STATUS_OK;
+ }
+
+ ZERO_STRUCT(finfo);
+ finfo.generic.level = RAW_FILEINFO_NAME_INFO;
+ finfo.generic.in.file.path = path;
+ status = smb_raw_pathinfo(cli->tree, cli, &finfo);
+ if (!NT_STATUS_EQUAL(status, expected) && !NT_STATUS_EQUAL(status, dos_expected)) {
+ printf("FAILED: %-30s pathinfo %s should be %s or %s\n",
+ path, nt_errstr(status), nt_errstr(expected), nt_errstr(dos_expected));
+ return false;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("%-30s chkpath correct (%s)\n", path, nt_errstr(status));
+ return true;
+ }
+ if (path_expected &&
+ (!finfo.name_info.out.fname.s ||
+ strcmp(finfo.name_info.out.fname.s, path_expected) != 0)) {
+ if (tctx && torture_setting_bool(tctx, "samba4", false)) {
+ printf("IGNORE: %-30s => %-20s should be %s\n",
+ path, finfo.name_info.out.fname.s, path_expected);
+ return true;
+ }
+ printf("FAILED: %-30s => %-20s should be %s\n",
+ path, finfo.name_info.out.fname.s, path_expected);
+ return false;
}
+ printf("%-30s => %-20s correct\n",
+ path, finfo.name_info.out.fname.s);
+
return true;
}
-static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_path(struct smbcli_state *cli, const char *path,
+ NTSTATUS expected, NTSTATUS dos_expected)
+{
+ return test_path_ex(cli, NULL, path, path, expected, dos_expected);
+}
+
+static bool test_chkpath(struct smbcli_state *cli, struct torture_context *tctx)
{
union smb_chkpath io;
NTSTATUS status;
@@ -86,7 +130,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
ret &= test_path(cli, BASEDIR "\\nodir", NT_STATUS_OBJECT_NAME_NOT_FOUND, NT_STATUS_DOS(ERRDOS,ERRbadpath));
- fnum = create_complex_file(cli, mem_ctx, BASEDIR "\\test.txt..");
+ fnum = create_complex_file(cli, tctx, BASEDIR "\\test.txt..");
if (fnum == -1) {
printf("failed to open test.txt - %s\n", smbcli_errstr(cli->tree));
ret = false;
@@ -101,9 +145,20 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
goto done;
}
- ret &= test_path(cli, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
- ret &= test_path(cli, BASEDIR "\\foo\\..\\test.txt..", NT_STATUS_NOT_A_DIRECTORY, NT_STATUS_DOS(ERRDOS,ERRbadpath));
- ret &= test_path(cli, "", NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, ((char *)BASEDIR) + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\\\") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\foo\\..") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\f\\o\\o\\..\\..\\..") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\foo\\\\\..\\\\") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, BASEDIR"\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, BASEDIR"\\\\..\\"BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, BASEDIR"\\\\\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, "\\\\\\\\"BASEDIR"\\\\\\\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, "\\\\\\\\"BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, BASEDIR "\\foo\\..\\test.txt..", BASEDIR "\\test.txt..",
+ NT_STATUS_NOT_A_DIRECTORY, NT_STATUS_DOS(ERRDOS,ERRbadpath));
+ ret &= test_path_ex(cli, tctx, "", "\\", NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path(cli, ".", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path(cli, ".\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path(cli, "\\\\\\.\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
@@ -122,7 +177,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
give different NT status returns for chkpth and findfirst. */
printf("testing findfirst on %s\n", "\\.\\\\\\\\\\\\.");
- status = single_search(cli, mem_ctx, "\\.\\\\\\\\\\\\.");
+ status = single_search(cli, tctx, "\\.\\\\\\\\\\\\.");
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRinvalidname));
ret &= test_path(cli, "\\.\\\\\\\\\\\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
@@ -164,7 +219,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
ret &= test_path(cli, "\\..\\", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath));
ret &= test_path(cli, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath));
ret &= test_path(cli, BASEDIR "\\.", NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRbadpath));
- ret &= test_path(cli, BASEDIR "\\..", NT_STATUS_OK,NT_STATUS_OK);
+ ret &= test_path_ex(cli, tctx, BASEDIR "\\..", "\\", NT_STATUS_OK,NT_STATUS_OK);
ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb600", NT_STATUS_OBJECT_NAME_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb6.exe", NT_STATUS_NOT_A_DIRECTORY,NT_STATUS_DOS(ERRDOS,ERRbadpath));
@@ -183,7 +238,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
printf("testing findfirst on %s\n", BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
- status = single_search(cli, mem_ctx, BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
+ status = single_search(cli, tctx, BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
/* We expect this open to fail with the same error code as the chkpath below. */
diff --git a/source4/torture/raw/composite.c b/source4/torture/raw/composite.c
index 7238a2fd46..1f31fbc515 100644
--- a/source4/torture/raw/composite.c
+++ b/source4/torture/raw/composite.c
@@ -31,6 +31,7 @@
#include "lib/cmdline/popt_common.h"
#include "torture/util.h"
#include "param/param.h"
+#include "libcli/resolve/resolve.h"
#define BASEDIR "\\composite"
@@ -161,6 +162,7 @@ static bool test_fetchfile(struct smbcli_state *cli, struct torture_context *tct
io2.in.credentials = cmdline_credentials;
io2.in.workgroup = lp_workgroup(tctx->lp_ctx);
io2.in.filename = fname;
+ io2.in.resolve_ctx = lp_resolve_context(tctx->lp_ctx);
lp_smbcli_options(tctx->lp_ctx, &io2.in.options);
printf("testing parallel fetchfile with %d ops\n", torture_numops);
diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c
index e81b634161..7ac88c0996 100644
--- a/source4/torture/raw/oplock.c
+++ b/source4/torture/raw/oplock.c
@@ -27,11 +27,19 @@
#define CHECK_VAL(v, correct) do { \
if ((v) != (correct)) { \
- torture_comment(tctx, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
+ 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_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)) { \
torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
@@ -123,9 +131,9 @@ static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t ti
return true;
}
-static bool test_raw_oplock_normal(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
{
- const char *fname = BASEDIR "\\test_normal.dat";
+ const char *fname = BASEDIR "\\test_exclusive1.dat";
NTSTATUS status;
bool ret = true;
union smb_open io;
@@ -156,7 +164,7 @@ static bool test_raw_oplock_normal(struct torture_context *tctx, struct smbcli_s
io.ntcreatex.in.security_flags = 0;
io.ntcreatex.in.fname = fname;
- torture_comment(tctx, "open a file with a normal oplock\n");
+ 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;
@@ -188,6 +196,381 @@ done:
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_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, 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, "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;
+ 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);
+
+ 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);
+
+ torture_comment(tctx, "close 1st handle\n");
+ smbcli_close(cli1->tree, fnum);
+
+ 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);
+
+ torture_comment(tctx, "close 1st handle\n");
+ smbcli_close(cli2->tree, fnum2);
+
+ 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);
+
+done:
+ smb_raw_exit(cli1->session);
+ smb_raw_exit(cli2->session);
+ smbcli_deltree(cli1->tree, BASEDIR);
+ return ret;
+}
+
+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;
+ bool s3 = torture_setting_bool(tctx, "samba3", false);
+
+ if (!torture_setup_dir(cli1, BASEDIR)) {
+ return false;
+ }
+
+ /* cleanup */
+ smbcli_unlink(cli1->tree, fname);
+
+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, 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, "open a file with an exclusive oplock (share mode: %s)\n",
+ s3?"all":"none");
+ ZERO_STRUCT(break_info);
+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+ if (s3) {
+ 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);
+
+ 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.failures, 0);
+ CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
+
+ 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_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;
+
+ if (!torture_setup_dir(cli1, BASEDIR)) {
+ return false;
+ }
+
+ /* cleanup */
+ smbcli_unlink(cli1->tree, fname);
+
+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, 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, "open with exclusive oplock\n");
+ ZERO_STRUCT(break_info);
+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
+
+ 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);
+ 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;
+ 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_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_levelII, cli1->tree);
+ smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, 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, "open with exclusive oplock\n");
+ ZERO_STRUCT(break_info);
+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
+
+
+ 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);
+
+ 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:
+ smb_raw_exit(cli1->session);
+ smb_raw_exit(cli2->session);
+ smbcli_deltree(cli1->tree, BASEDIR);
+ return ret;
+}
+
+static bool test_raw_oplock_exclusive6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+ 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;
+ bool s3 = torture_setting_bool(tctx, "samba3", false);
+
+ 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_levelII, 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;
+
+ /* we should use no share mode, when samba3 passes this */
+ torture_comment(tctx, "open a file with an exclusive oplock (share mode: %s)\n",
+ s3?"all":"none");
+ ZERO_STRUCT(break_info);
+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
+ if (s3) {
+ 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);
+
+ 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";
@@ -1352,6 +1735,475 @@ done:
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_levelII, cli1->tree);
+ smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, 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, "open with batch oplock\n");
+ ZERO_STRUCT(break_info);
+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, 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;
+ bool s3 = torture_setting_bool(tctx, "samba3", false);
+
+ 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_levelII, 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;
+
+ /* we should use no share mode, when samba3 passes this */
+ torture_comment(tctx, "open a file with an batch oplock (share mode: %s)\n",
+ s3?"all":"none");
+ ZERO_STRUCT(break_info);
+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+ NTCREATEX_FLAGS_REQUEST_OPLOCK |
+ NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+ if (s3) {
+ 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, "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;
+ bool s3 = torture_setting_bool(tctx, "samba3", false);
+
+ 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_levelII, 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;
+
+ /* we should use no share mode, when samba3 passes this */
+ torture_comment(tctx, "open a file with an batch oplock (share mode: %s)\n",
+ s3?"all":"none");
+ ZERO_STRUCT(break_info);
+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+ NTCREATEX_FLAGS_REQUEST_OPLOCK |
+ NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+ if (s3) {
+ 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, "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_setting_bool(tctx, "samba3", false)) {
+ torture_skip(tctx, "BACHT19 disabled against samba3\n");
+ }
+
+ 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_levelII, 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 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;
+}
+
+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_setting_bool(tctx, "samba3", false)) {
+ torture_skip(tctx, "BACHT20 disabled against samba3\n");
+ }
+
+ 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_levelII, 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 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);
+
+ /* we should use no share mode, when samba3 passes this */
+ 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;
+}
+
/*
basic testing of oplocks
*/
@@ -1359,7 +2211,12 @@ 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, "NORMAL", test_raw_oplock_normal);
+ 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);
@@ -1375,6 +2232,11 @@ struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx)
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);
return suite;
}
diff --git a/source4/torture/raw/qfsinfo.c b/source4/torture/raw/qfsinfo.c
index 3207558624..c1c77edba9 100644
--- a/source4/torture/raw/qfsinfo.c
+++ b/source4/torture/raw/qfsinfo.c
@@ -38,7 +38,7 @@ static struct {
{"SIZE_INFO", RAW_QFS_SIZE_INFO, },
{"DEVICE_INFO", RAW_QFS_DEVICE_INFO, },
{"ATTRIBUTE_INFO", RAW_QFS_ATTRIBUTE_INFO, },
- {"UNIX_INFO", RAW_QFS_UNIX_INFO, CAP_UNIX},
+ {"UNIX_INFO", RAW_QFS_UNIX_INFO, CAP_UNIX},
{"VOLUME_INFORMATION", RAW_QFS_VOLUME_INFORMATION, },
{"SIZE_INFORMATION", RAW_QFS_SIZE_INFORMATION, },
{"DEVICE_INFORMATION", RAW_QFS_DEVICE_INFORMATION, },
@@ -130,7 +130,7 @@ bool torture_raw_qfsinfo(struct torture_context *torture,
/* scan all the levels, pulling the results */
for (i=0; levels[i].name; i++) {
- printf("Running level %s\n", levels[i].name);
+ torture_comment(torture, "Running level %s\n", levels[i].name);
levels[i].fsinfo.generic.level = levels[i].level;
levels[i].status = smb_raw_fsinfo(cli->tree, torture, &levels[i].fsinfo);
}
@@ -151,14 +151,11 @@ bool torture_raw_qfsinfo(struct torture_context *torture,
}
if (count != 0) {
- printf("%d levels failed\n", count);
- if (count > 13) {
- printf("too many level failures - giving up\n");
- return false;
- }
+ torture_comment(torture, "%d levels failed\n", count);
+ torture_assert(torture, count > 13, "too many level failures - giving up");
}
- printf("check for correct aliases\n");
+ torture_comment(torture, "check for correct aliases\n");
s1 = find("SIZE_INFO");
s2 = find("SIZE_INFORMATION");
if (s1 && s2) {
@@ -181,7 +178,7 @@ bool torture_raw_qfsinfo(struct torture_context *torture,
STRUCT_EQUAL(volume_info, create_time, volume_info, create_time);
VAL_EQUAL (volume_info, serial_number, volume_info, serial_number);
STR_EQUAL (volume_info, volume_name.s, volume_info, volume_name.s);
- printf("volume_info.volume_name = '%s'\n", s1->volume_info.out.volume_name.s);
+ torture_comment(torture, "volume_info.volume_name = '%s'\n", s1->volume_info.out.volume_name.s);
}
s1 = find("ATTRIBUTE_INFO");
@@ -192,10 +189,10 @@ bool torture_raw_qfsinfo(struct torture_context *torture,
VAL_EQUAL(attribute_info, max_file_component_length,
attribute_info, max_file_component_length);
STR_EQUAL(attribute_info, fs_type.s, attribute_info, fs_type.s);
- printf("attribute_info.fs_type = '%s'\n", s1->attribute_info.out.fs_type.s);
+ torture_comment(torture, "attribute_info.fs_type = '%s'\n", s1->attribute_info.out.fs_type.s);
}
- printf("check for consistent disk sizes\n");
+ torture_comment(torture, "check for consistent disk sizes\n");
s1 = find("DSKATTR");
s2 = find("ALLOCATION");
if (s1 && s2) {
@@ -214,10 +211,10 @@ bool torture_raw_qfsinfo(struct torture_context *torture,
size1, size2);
ret = false;
}
- printf("total disk = %.0f MB\n", size1*scale/1.0e6);
+ torture_comment(torture, "total disk = %.0f MB\n", size1*scale/1.0e6);
}
- printf("check consistent free disk space\n");
+ torture_comment(torture, "check consistent free disk space\n");
s1 = find("DSKATTR");
s2 = find("ALLOCATION");
if (s1 && s2) {
@@ -236,10 +233,10 @@ bool torture_raw_qfsinfo(struct torture_context *torture,
size1, size2);
ret = false;
}
- printf("free disk = %.0f MB\n", size1*scale/1.0e6);
+ torture_comment(torture, "free disk = %.0f MB\n", size1*scale/1.0e6);
}
- printf("volume info consistency\n");
+ torture_comment(torture, "volume info consistency\n");
s1 = find("VOLUME");
s2 = find("VOLUME_INFO");
if (s1 && s2) {
@@ -287,7 +284,7 @@ bool torture_raw_qfsinfo(struct torture_context *torture,
} \
}} while (0)
- printf("check for correct termination\n");
+ torture_comment(torture, "check for correct termination\n");
STR_CHECK("VOLUME", volume, volume_name, 0);
STR_CHECK("VOLUME_INFO", volume_info, volume_name, STR_UNICODE);
diff --git a/source4/torture/raw/setfileinfo.c b/source4/torture/raw/setfileinfo.c
index e58b3fd760..90ccde7213 100644
--- a/source4/torture/raw/setfileinfo.c
+++ b/source4/torture/raw/setfileinfo.c
@@ -453,6 +453,10 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
char *fnum_fname_new;
char *path_fname;
char *path_fname_new;
+ char *path_dname;
+ char *path_dname_new;
+ char *saved_name;
+ char *saved_name_new;
union smb_fileinfo finfo1, finfo2;
union smb_setfileinfo sfinfo;
NTSTATUS status, status2;
@@ -464,6 +468,8 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n);
asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n);
asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n);
+ asprintf(&path_dname, BASEDIR "\\dname_test_%d", n);
+ asprintf(&path_dname_new, BASEDIR "\\dname_test_new_%d", n);
if (!torture_setup_dir(cli, BASEDIR)) {
return false;
@@ -553,17 +559,112 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
sfinfo.rename_information.in.root_fid = d_fnum;
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_INVALID_PARAMETER);
CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
+ smbcli_close(cli->tree, d_fnum);
-done:
- smb_raw_exit(cli->session);
- smbcli_close(cli->tree, fnum);
- if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) {
- printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree));
+ printf("Trying rename directory\n");
+ if (!torture_setup_dir(cli, path_dname)) {
+ ret = false;
+ goto done;
}
- if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
- printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
+ saved_name = path_fname;
+ saved_name_new = path_fname_new;
+ path_fname = path_dname;
+ path_fname_new = path_dname_new;
+ sfinfo.rename_information.in.new_name = path_dname_new+strlen(BASEDIR)+1;
+ sfinfo.rename_information.in.overwrite = 0;
+ sfinfo.rename_information.in.root_fid = 0;
+ CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
+ path_fname = saved_name;
+ path_fname_new = saved_name_new;
+
+ if (torture_setting_bool(torture, "samba3", false)) {
+ printf("SKIP: Trying rename directory with a handle\n");
+ printf("SKIP: Trying rename by path while a handle is open\n");
+ printf("SKIP: Trying rename directory by path while a handle is open\n");
+ goto done;
}
+ printf("Trying rename directory with a handle\n");
+ status = create_directory_handle(cli->tree, path_dname_new, &d_fnum);
+ fnum_saved = fnum;
+ fnum = d_fnum;
+ saved_name = fnum_fname;
+ saved_name_new = fnum_fname_new;
+ fnum_fname = path_dname;
+ fnum_fname_new = path_dname_new;
+ sfinfo.rename_information.in.new_name = path_dname+strlen(BASEDIR)+1;
+ sfinfo.rename_information.in.overwrite = 0;
+ sfinfo.rename_information.in.root_fid = 0;
+ CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
+ smbcli_close(cli->tree, d_fnum);
+ fnum = fnum_saved;
+ fnum_fname = saved_name;
+ fnum_fname_new = saved_name_new;
+
+ printf("Trying rename by path while a handle is open\n");
+ fnum_saved = fnum;
+ fnum = create_complex_file(cli, torture, path_fname);
+ sfinfo.rename_information.in.new_name = path_fname_new+strlen(BASEDIR)+1;
+ sfinfo.rename_information.in.overwrite = 0;
+ sfinfo.rename_information.in.root_fid = 0;
+ CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
+ /* check that the handle returns the same name */
+ check_fnum = true;
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
+ /* rename it back on the handle */
+ sfinfo.rename_information.in.new_name = path_fname+strlen(BASEDIR)+1;
+ CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
+ check_fnum = false;
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
+ smbcli_close(cli->tree, fnum);
+ fnum = fnum_saved;
+
+ printf("Trying rename directory by path while a handle is open\n");
+ status = create_directory_handle(cli->tree, path_dname, &d_fnum);
+ fnum_saved = fnum;
+ fnum = d_fnum;
+ saved_name = path_fname;
+ saved_name_new = path_fname_new;
+ path_fname = path_dname;
+ path_fname_new = path_dname_new;
+ sfinfo.rename_information.in.new_name = path_dname_new+strlen(BASEDIR)+1;
+ sfinfo.rename_information.in.overwrite = 0;
+ sfinfo.rename_information.in.root_fid = 0;
+ CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
+ path_fname = saved_name;
+ path_fname_new = saved_name_new;
+ saved_name = fnum_fname;
+ saved_name_new = fnum_fname_new;
+ fnum_fname = path_dname;
+ fnum_fname_new = path_dname_new;
+ /* check that the handle returns the same name */
+ check_fnum = true;
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
+ /* rename it back on the handle */
+ sfinfo.rename_information.in.new_name = path_dname+strlen(BASEDIR)+1;
+ CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
+ fnum_fname = saved_name;
+ fnum_fname_new = saved_name_new;
+ saved_name = path_fname;
+ saved_name_new = path_fname_new;
+ path_fname = path_dname;
+ path_fname_new = path_dname_new;
+ check_fnum = false;
+ CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
+ smbcli_close(cli->tree, d_fnum);
+ fnum = fnum_saved;
+ path_fname = saved_name;
+ path_fname_new = saved_name_new;
+
+done:
+ smb_raw_exit(cli->session);
+ smbcli_deltree(cli->tree, BASEDIR);
return ret;
}