summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsource3/script/tests/test_smbtorture_s3.sh2
-rw-r--r--source3/torture/torture.c146
2 files changed, 147 insertions, 1 deletions
diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh
index 4680f64039..2a26131704 100755
--- a/source3/script/tests/test_smbtorture_s3.sh
+++ b/source3/script/tests/test_smbtorture_s3.sh
@@ -27,7 +27,7 @@ export SMB_CONF_PATH
tests="FDPASS LOCK1 LOCK2 LOCK3 LOCK4 LOCK5 LOCK6 LOCK7 LOCK9"
#tests="$tests UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE "
tests="$tests UNLINK BROWSE ATTR TRANS2 TORTURE "
-tests="$tests OPLOCK1 OPLOCK2 OPLOCK3 STREAMERROR"
+tests="$tests OPLOCK1 OPLOCK2 OPLOCK3 OPLOCK4 STREAMERROR"
tests="$tests DIR DIR1 DIR-CREATETIME TCON TCONDEV RW1 RW2 RW3 RW-SIGNING"
tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K"
tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE CHAIN1"
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 2eb2566681..ba0e6b883f 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -3415,6 +3415,151 @@ static bool run_oplock3(int dummy)
/* What are we looking for here? What's sucess and what's FAILURE? */
}
+/* handler for oplock 4 tests */
+bool *oplock4_shared_correct;
+
+static NTSTATUS oplock4_handler(struct cli_state *cli, uint16_t fnum, unsigned char level)
+{
+ printf("got oplock break fnum=%d level=%d\n",
+ fnum, level);
+ *oplock4_shared_correct = true;
+ cli_oplock_ack(cli, fnum, level);
+ return NT_STATUS_UNSUCCESSFUL; /* Cause cli_receive_smb to return. */
+}
+
+static bool run_oplock4(int dummy)
+{
+ struct cli_state *cli1, *cli2;
+ const char *fname = "\\lockt4.lck";
+ const char *fname_ln = "\\lockt4_ln.lck";
+ uint16_t fnum1, fnum2;
+ int saved_use_oplocks = use_oplocks;
+ NTSTATUS status;
+ bool correct = true;
+
+ oplock4_shared_correct = (bool *)shm_setup(sizeof(bool));
+ *oplock4_shared_correct = false;
+
+ printf("starting oplock test 4\n");
+
+ if (!torture_open_connection(&cli1, 0)) {
+ use_level_II_oplocks = false;
+ use_oplocks = saved_use_oplocks;
+ return false;
+ }
+
+ if (!torture_open_connection(&cli2, 1)) {
+ use_level_II_oplocks = false;
+ use_oplocks = saved_use_oplocks;
+ return false;
+ }
+
+ cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
+ cli_unlink(cli1, fname_ln, aSYSTEM | aHIDDEN);
+
+ cli_sockopt(cli1, sockops);
+ cli_sockopt(cli2, sockops);
+
+ /* Create the file. */
+ if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
+ printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
+ return false;
+ }
+
+ if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
+ printf("close1 failed (%s)\n", cli_errstr(cli1));
+ return false;
+ }
+
+ /* Now create a hardlink. */
+ if (!NT_STATUS_IS_OK(cli_nt_hardlink(cli1, fname, fname_ln))) {
+ printf("nt hardlink failed (%s)\n", cli_errstr(cli1));
+ return false;
+ }
+
+ /* Prove that opening hardlinks cause deny modes to conflict. */
+ if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1))) {
+ printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
+ return false;
+ }
+
+ status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
+ if (NT_STATUS_IS_OK(status)) {
+ printf("open of %s succeeded - should fail with sharing violation.\n",
+ fname_ln);
+ return false;
+ }
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ printf("open of %s should fail with sharing violation. Got %s\n",
+ fname_ln, nt_errstr(status));
+ return false;
+ }
+
+ if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
+ printf("close1 failed (%s)\n", cli_errstr(cli1));
+ return false;
+ }
+
+ cli1->use_oplocks = true;
+ cli1->use_level_II_oplocks = true;
+
+ cli2->use_oplocks = true;
+ cli2->use_level_II_oplocks = true;
+
+ cli_oplock_handler(cli1, oplock4_handler);
+ if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
+ printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
+ return false;
+ }
+
+ if (fork() == 0) {
+ /* Child code */
+ if (!NT_STATUS_IS_OK(cli_open(cli2, fname_ln, O_RDWR, DENY_NONE, &fnum2))) {
+ printf("open of %s failed (%s)\n", fname_ln, cli_errstr(cli1));
+ *oplock4_shared_correct = false;
+ exit(0);
+ }
+
+ if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
+ printf("close2 failed (%s)\n", cli_errstr(cli1));
+ *oplock4_shared_correct = false;
+ }
+
+ exit(0);
+ }
+
+ sleep(2);
+
+ /* Process the oplock break. */
+ cli_receive_smb(cli1);
+
+ if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
+ printf("close1 failed (%s)\n", cli_errstr(cli1));
+ correct = false;
+ }
+
+ if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
+ printf("unlink failed (%s)\n", cli_errstr(cli1));
+ correct = false;
+ }
+ if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname_ln, aSYSTEM | aHIDDEN))) {
+ printf("unlink failed (%s)\n", cli_errstr(cli1));
+ correct = false;
+ }
+
+ if (!torture_close_connection(cli1)) {
+ correct = false;
+ }
+
+ if (!*oplock4_shared_correct) {
+ correct = false;
+ }
+
+ printf("finished oplock test 4\n");
+
+ return correct;
+}
/*
@@ -7801,6 +7946,7 @@ static struct {
{"OPLOCK1", run_oplock1, 0},
{"OPLOCK2", run_oplock2, 0},
{"OPLOCK3", run_oplock3, 0},
+ {"OPLOCK4", run_oplock4, 0},
{"DIR", run_dirtest, 0},
{"DIR1", run_dirtest1, 0},
{"DIR-CREATETIME", run_dir_createtime, 0},