summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2009-02-12 16:00:46 +0100
committerJelmer Vernooij <jelmer@samba.org>2009-02-12 16:00:46 +0100
commit082ba6a1ad3a68aff118d96f855a2aa65eaeb359 (patch)
treed70b7e8012e787a11ea1c12224318643cdd552c3 /source4
parent762fdc8c5c2db304f3dc4536c19d69366d1399df (diff)
parent4f6d1728254c8503e71c6fdd008fb7264dec26c5 (diff)
downloadsamba-082ba6a1ad3a68aff118d96f855a2aa65eaeb359.tar.gz
samba-082ba6a1ad3a68aff118d96f855a2aa65eaeb359.tar.bz2
samba-082ba6a1ad3a68aff118d96f855a2aa65eaeb359.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source4')
-rw-r--r--source4/rpc_server/spoolss/dcesrv_spoolss.c12
-rw-r--r--source4/torture/basic/locking.c2
-rw-r--r--source4/torture/ndr/spoolss.c8
-rw-r--r--source4/torture/raw/lock.c573
-rw-r--r--source4/torture/smbtorture.c2
5 files changed, 579 insertions, 18 deletions
diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.c b/source4/rpc_server/spoolss/dcesrv_spoolss.c
index d127837382..c0330c0ae8 100644
--- a/source4/rpc_server/spoolss/dcesrv_spoolss.c
+++ b/source4/rpc_server/spoolss/dcesrv_spoolss.c
@@ -1197,20 +1197,20 @@ static WERROR dcesrv_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_
/*
- spoolss_RouterRefreshPrinterChangeNotification
+ spoolss_RouterReplyPrinterEx
*/
-static WERROR dcesrv_spoolss_RouterRefreshPrinterChangeNotification(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct spoolss_RouterRefreshPrinterChangeNotification *r)
+static WERROR dcesrv_spoolss_RouterReplyPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RouterReplyPrinterEx *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
- spoolss_RemoteFindNextPrinterChangeNotifyEx
+ spoolss_RouterRefreshPrinterChangeNotify
*/
-static WERROR dcesrv_spoolss_RemoteFindNextPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct spoolss_RemoteFindNextPrinterChangeNotifyEx *r)
+static WERROR dcesrv_spoolss_RouterRefreshPrinterChangeNotify(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RouterRefreshPrinterChangeNotify *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
diff --git a/source4/torture/basic/locking.c b/source4/torture/basic/locking.c
index fcac52ca6a..06a960bc81 100644
--- a/source4/torture/basic/locking.c
+++ b/source4/torture/basic/locking.c
@@ -610,7 +610,7 @@ ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
EXPECTED(ret, true);
- torture_comment(tctx, "the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
+ torture_comment(tctx, "the same process %s unlock the stack of 3 locks\n", ret?"can":"cannot");
/* Ensure the next unlock fails. */
ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
diff --git a/source4/torture/ndr/spoolss.c b/source4/torture/ndr/spoolss.c
index eecd91edba..c1ca0c20c9 100644
--- a/source4/torture/ndr/spoolss.c
+++ b/source4/torture/ndr/spoolss.c
@@ -109,14 +109,14 @@ static const uint8_t RFFPCNEX_out_data[] = {
0x00, 0x00, 0x00, 0x00
};
-static const uint8_t RFNPCNEX_in_data[] = {
+static const uint8_t RRPCN_in_data[] = {
0x00, 0x00, 0x00, 0x00, 0x1e, 0x9b, 0x8b, 0xe5, 0x32, 0x9a, 0xd5, 0x45,
0xa8, 0x0a, 0x10, 0x30, 0x5b, 0x87, 0x6f, 0x69, 0x01, 0x00, 0x00, 0x00,
0x44, 0x0d, 0x0b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-static const uint8_t RFNPCNEX_out_data[] = {
+static const uint8_t RRPCN_out_data[] = {
0x00, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
@@ -459,8 +459,8 @@ struct torture_suite *ndr_spoolss_suite(TALLOC_CTX *ctx)
torture_suite_add_ndr_pull_fn_test(suite, spoolss_RemoteFindFirstPrinterChangeNotifyEx, RFFPCNEX_in_data, NDR_IN, NULL );
torture_suite_add_ndr_pull_fn_test(suite, spoolss_RemoteFindFirstPrinterChangeNotifyEx, RFFPCNEX_out_data, NDR_OUT, NULL );
- torture_suite_add_ndr_pull_fn_test(suite, spoolss_RemoteFindNextPrinterChangeNotifyEx, RFNPCNEX_in_data, NDR_IN, NULL );
- torture_suite_add_ndr_pull_fn_test(suite, spoolss_RemoteFindNextPrinterChangeNotifyEx, RFNPCNEX_out_data, NDR_OUT, NULL );
+ torture_suite_add_ndr_pull_fn_test(suite, spoolss_RouterRefreshPrinterChangeNotify, RRPCN_in_data, NDR_IN, NULL );
+ torture_suite_add_ndr_pull_fn_test(suite, spoolss_RouterRefreshPrinterChangeNotify, RRPCN_out_data, NDR_OUT, NULL );
torture_suite_add_ndr_pull_fn_test(suite, spoolss_EnumForms, enumforms_in_data, NDR_IN, NULL );
torture_suite_add_ndr_pull_fn_test(suite, spoolss_EnumForms, enumforms_out_data, NDR_OUT, NULL );
diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c
index 2d1eae3a69..72a03e1623 100644
--- a/source4/torture/raw/lock.c
+++ b/source4/torture/raw/lock.c
@@ -38,8 +38,34 @@
goto done; \
}} while (0)
+#define CHECK_STATUS_CONT(status, correct) do { \
+ if (!NT_STATUS_EQUAL(status, correct)) { \
+ printf("(%s) Incorrect status %s - should be %s\n", \
+ __location__, nt_errstr(status), nt_errstr(correct)); \
+ ret = false; \
+ }} while (0)
+
+#define CHECK_STATUS_OR(status, correct1, correct2) do { \
+ if ((!NT_STATUS_EQUAL(status, correct1)) && \
+ (!NT_STATUS_EQUAL(status, correct2))) { \
+ printf("(%s) Incorrect status %s - should be %s or %s\n", \
+ __location__, nt_errstr(status), nt_errstr(correct1), \
+ nt_errstr(correct2)); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+#define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
+ if ((!NT_STATUS_EQUAL(status, correct1)) && \
+ (!NT_STATUS_EQUAL(status, correct2))) { \
+ printf("(%s) Incorrect status %s - should be %s or %s\n", \
+ __location__, nt_errstr(status), nt_errstr(correct1), \
+ nt_errstr(correct2)); \
+ ret = false; \
+ }} while (0)
#define BASEDIR "\\testlock"
+#define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
/*
test SMBlock and SMBunlock ops
@@ -337,15 +363,25 @@ static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
lock[0].pid++;
lock[0].count = 2;
status = smb_raw_lock(cli->tree, &io);
- CHECK_STATUS(status, NT_STATUS_OK);
+ if (TARGET_IS_WIN7(tctx))
+ CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE);
+ else
+ CHECK_STATUS(status, NT_STATUS_OK);
lock[0].pid--;
io.lockx.in.ulock_cnt = 1;
io.lockx.in.lock_cnt = 0;
lock[0].count = 1;
status = smb_raw_lock(cli->tree, &io);
- CHECK_STATUS(status, NT_STATUS_OK);
- status = smb_raw_lock(cli->tree, &io);
- CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
+ /* XXX This is very strange - Win7 gives us an invalid range when we
+ * unlock the range even though the range is locked! Win7 bug? */
+ if (TARGET_IS_WIN7(tctx))
+ CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE);
+ else {
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ }
done:
smbcli_close(cli->tree, fnum);
@@ -354,7 +390,6 @@ done:
return ret;
}
-
/*
test high pid
*/
@@ -410,8 +445,6 @@ static bool test_pidhigh(struct torture_context *tctx,
goto done;
}
- cli->session->pid |= 0x10000;
-
cli->session->pid = 2;
if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
@@ -1321,6 +1354,525 @@ done:
return ret;
}
+struct double_lock_test {
+ struct smb_lock_entry lock1;
+ struct smb_lock_entry lock2;
+ NTSTATUS exp_status;
+};
+
+/**
+ * Tests zero byte locks.
+ */
+struct double_lock_test zero_byte_tests[] = {
+ /* {pid, offset, count}, {pid, offset, count}, status */
+
+ /** First, takes a zero byte lock at offset 10. Then:
+ * - Taking 0 byte lock at 10 should succeed.
+ * - Taking 1 byte locks at 9,10,11 should succeed.
+ * - Taking 2 byte lock at 9 should fail.
+ * - Taking 2 byte lock at 10 should succeed.
+ * - Taking 3 byte lock at 9 should fail.
+ */
+ {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
+ {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
+ {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
+ {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
+ {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
+ {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
+ {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
+
+ /** Same, but opposite order. */
+ {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
+ {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
+ {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
+ {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
+ {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
+ {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
+ {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
+
+ /** Zero zero case. */
+ {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
+};
+
+static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
+{
+ union smb_lock io;
+ struct smb_lock_entry zerozero;
+ NTSTATUS status;
+ bool ret = true;
+ int fnum, i;
+ const char *fname = BASEDIR "\\zero.txt";
+
+ printf("Testing zero length byte range locks:\n");
+
+ if (!torture_setup_dir(cli, BASEDIR)) {
+ return false;
+ }
+
+ io.generic.level = RAW_LOCK_LOCKX;
+
+ fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+ if (fnum == -1) {
+ printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
+ ret = false;
+ goto done;
+ }
+
+ /* Setup initial parameters */
+ io.lockx.level = RAW_LOCK_LOCKX;
+ io.lockx.in.file.fnum = fnum;
+ io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
+ io.lockx.in.timeout = 0;
+
+ /* Try every combination of locks in zero_byte_tests. The first lock is
+ * assumed to succeed. The second lock may contend, depending on the
+ * expected status. */
+ for (i = 0;
+ i < sizeof(zero_byte_tests) / sizeof(struct double_lock_test);
+ i++) {
+ printf(" ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
+ zero_byte_tests[i].lock1.pid,
+ zero_byte_tests[i].lock1.offset,
+ zero_byte_tests[i].lock1.count,
+ zero_byte_tests[i].lock2.pid,
+ zero_byte_tests[i].lock2.offset,
+ zero_byte_tests[i].lock2.count,
+ nt_errstr(zero_byte_tests[i].exp_status));
+
+ /* Lock both locks. */
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+
+ io.lockx.in.locks = &zero_byte_tests[i].lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ io.lockx.in.locks = &zero_byte_tests[i].lock2;
+ status = smb_raw_lock(cli->tree, &io);
+
+ if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
+ NT_STATUS_LOCK_NOT_GRANTED)) {
+ /* Allow either of the failure messages and keep going
+ * if we see the wrong status. */
+ CHECK_STATUS_OR_CONT(status,
+ NT_STATUS_LOCK_NOT_GRANTED,
+ NT_STATUS_FILE_LOCK_CONFLICT);
+
+ } else {
+ CHECK_STATUS_CONT(status,
+ zero_byte_tests[i].exp_status);
+ }
+
+ /* Unlock both locks. */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ }
+
+ io.lockx.in.locks = &zero_byte_tests[i].lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ }
+
+done:
+ smbcli_close(cli->tree, fnum);
+ smb_raw_exit(cli->session);
+ smbcli_deltree(cli->tree, BASEDIR);
+ return ret;
+}
+
+static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
+{
+ union smb_lock io;
+ NTSTATUS status;
+ bool ret = true;
+ int fnum1, fnum2;
+ const char *fname = BASEDIR "\\unlock.txt";
+ struct smb_lock_entry lock1;
+ struct smb_lock_entry lock2;
+
+ printf("Testing LOCKX unlock:\n");
+
+ if (!torture_setup_dir(cli, BASEDIR)) {
+ return false;
+ }
+
+ fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+ if (fnum1 == -1) {
+ printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
+ ret = false;
+ goto done;
+ }
+ fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+ if (fnum2 == -1) {
+ printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
+ ret = false;
+ goto done;
+ }
+
+ /* Setup initial parameters */
+ io.lockx.level = RAW_LOCK_LOCKX;
+ io.lockx.in.timeout = 0;
+
+ lock1.pid = cli->session->pid;
+ lock1.offset = 0;
+ lock1.count = 10;
+ lock2.pid = cli->session->pid - 1;
+ lock2.offset = 0;
+ lock2.count = 10;
+
+ /**
+ * Take exclusive lock, then unlock it with a shared-unlock call.
+ */
+ printf(" taking exclusive lock.\n");
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.mode = 0;
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ printf(" unlock the exclusive with a shared unlock call.\n");
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ printf(" try shared lock on pid2/fnum2, testing the unlock.\n");
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ io.lockx.in.file.fnum = fnum2;
+ io.lockx.in.locks = &lock2;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /**
+ * Unlock a shared lock with an exclusive-unlock call.
+ */
+ printf(" unlock new shared lock with exclusive unlock call.\n");
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ io.lockx.in.mode = 0;
+ io.lockx.in.file.fnum = fnum2;
+ io.lockx.in.locks = &lock2;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ printf(" try exclusive lock on pid1, testing the unlock.\n");
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.mode = 0;
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* cleanup */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /**
+ * Test unlocking of 0-byte locks.
+ */
+
+ printf(" lock shared and exclusive 0-byte locks, testing that Windows "
+ "always unlocks the exclusive first.\n");
+ lock1.pid = cli->session->pid;
+ lock1.offset = 10;
+ lock1.count = 0;
+ lock2.pid = cli->session->pid;
+ lock2.offset = 5;
+ lock2.count = 10;
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.locks = &lock1;
+
+ /* lock 0-byte shared
+ * Note: Order of the shared/exclusive locks doesn't matter. */
+ io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* lock 0-byte exclusive */
+ io.lockx.in.mode = 0;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* test contention */
+ io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ io.lockx.in.locks = &lock2;
+ io.lockx.in.file.fnum = fnum2;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
+ NT_STATUS_FILE_LOCK_CONFLICT);
+
+ /* unlock */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* test - can we take a shared lock? */
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ io.lockx.in.file.fnum = fnum2;
+ io.lockx.in.locks = &lock2;
+ status = smb_raw_lock(cli->tree, &io);
+
+ /* XXX Samba will fail this test. This is temporary(because this isn't
+ * new to Win7, it succeeds in WinXP too), until I can come to a
+ * resolution as to whether Samba should support this or not. There is
+ * code to preference unlocking exclusive locks before shared locks,
+ * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
+ if (TARGET_IS_WIN7(tctx))
+ CHECK_STATUS(status, NT_STATUS_OK);
+ else {
+ CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
+ NT_STATUS_FILE_LOCK_CONFLICT);
+ }
+
+ /* cleanup */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ status = smb_raw_lock(cli->tree, &io);
+
+ /* XXX Same as above. */
+ if (TARGET_IS_WIN7(tctx))
+ CHECK_STATUS(status, NT_STATUS_OK);
+ else
+ CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+done:
+ smbcli_close(cli->tree, fnum1);
+ smbcli_close(cli->tree, fnum2);
+ smb_raw_exit(cli->session);
+ smbcli_deltree(cli->tree, BASEDIR);
+ return ret;
+}
+
+static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
+{
+ union smb_lock io;
+ NTSTATUS status;
+ bool ret = true;
+ int fnum1;
+ const char *fname = BASEDIR "\\unlock_multiple.txt";
+ struct smb_lock_entry lock1;
+ struct smb_lock_entry lock2;
+ struct smb_lock_entry locks[2];
+
+ printf("Testing LOCKX multiple unlock:\n");
+
+ if (!torture_setup_dir(cli, BASEDIR)) {
+ return false;
+ }
+
+ fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+ if (fnum1 == -1) {
+ printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
+ ret = false;
+ goto done;
+ }
+
+ /* Setup initial parameters */
+ io.lockx.level = RAW_LOCK_LOCKX;
+ io.lockx.in.timeout = 0;
+
+ lock1.pid = cli->session->pid;
+ lock1.offset = 0;
+ lock1.count = 10;
+ lock2.pid = cli->session->pid;
+ lock2.offset = 10;
+ lock2.count = 10;
+
+ locks[0] = lock1;
+ locks[1] = lock2;
+
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.mode = 0; /* exclusive */
+
+ /** Test1: Take second lock, but not first. */
+ printf(" unlock 2 locks, first one not locked. Expect no locks "
+ "unlocked. \n");
+
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.locks = &lock2;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Try to unlock both locks. */
+ io.lockx.in.ulock_cnt = 2;
+ io.lockx.in.lock_cnt = 0;
+ io.lockx.in.locks = locks;
+
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
+ /* Second lock should not be unlocked. */
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.locks = &lock2;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
+
+ /* cleanup */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ io.lockx.in.locks = &lock2;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /** Test2: Take first lock, but not second. */
+ printf(" unlock 2 locks, second one not locked. Expect first lock "
+ "unlocked.\n");
+
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* Try to unlock both locks. */
+ io.lockx.in.ulock_cnt = 2;
+ io.lockx.in.lock_cnt = 0;
+ io.lockx.in.locks = locks;
+
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+
+ /* First lock should be unlocked. */
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* cleanup */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ io.lockx.in.locks = &lock1;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+done:
+ smbcli_close(cli->tree, fnum1);
+ smb_raw_exit(cli->session);
+ smbcli_deltree(cli->tree, BASEDIR);
+ return ret;
+}
+
+/**
+ * torture_locktest5 covers stacking pretty well, but its missing two tests:
+ * - stacking an exclusive on top of shared fails
+ * - stacking two exclusives fail
+ */
+static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
+{
+ union smb_lock io;
+ NTSTATUS status;
+ bool ret = true;
+ int fnum1;
+ const char *fname = BASEDIR "\\stacking.txt";
+ struct smb_lock_entry lock1;
+ struct smb_lock_entry lock2;
+
+ printf("Testing stacking:\n");
+
+ if (!torture_setup_dir(cli, BASEDIR)) {
+ return false;
+ }
+
+ io.generic.level = RAW_LOCK_LOCKX;
+
+ fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+ if (fnum1 == -1) {
+ printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
+ ret = false;
+ goto done;
+ }
+
+ /* Setup initial parameters */
+ io.lockx.level = RAW_LOCK_LOCKX;
+ io.lockx.in.timeout = 0;
+
+ lock1.pid = cli->session->pid;
+ lock1.offset = 0;
+ lock1.count = 10;
+ lock2.pid = cli->session->pid - 1;
+ lock2.offset = 0;
+ lock2.count = 10;
+
+ /**
+ * Try to take a shared lock, then stack an exclusive.
+ */
+ printf(" stacking an exclusive on top of a shared lock fails.\n");
+ io.lockx.in.file.fnum = fnum1;
+ io.lockx.in.locks = &lock1;
+
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.mode = 0;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
+ NT_STATUS_FILE_LOCK_CONFLICT);
+
+ /* cleanup */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /**
+ * Prove that two exclusive locks do not stack.
+ */
+ printf(" two exclusive locks do not stack.\n");
+ io.lockx.in.ulock_cnt = 0;
+ io.lockx.in.lock_cnt = 1;
+ io.lockx.in.mode = 0;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
+ NT_STATUS_FILE_LOCK_CONFLICT);
+
+ /* cleanup */
+ io.lockx.in.ulock_cnt = 1;
+ io.lockx.in.lock_cnt = 0;
+ status = smb_raw_lock(cli->tree, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+done:
+ smbcli_close(cli->tree, fnum1);
+ smb_raw_exit(cli->session);
+ smbcli_deltree(cli->tree, BASEDIR);
+ return ret;
+}
/*
basic testing of lock calls
@@ -1336,5 +1888,12 @@ struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
torture_suite_add_1smb_test(suite, "changetype", test_changetype);
+ torture_suite_add_1smb_test(suite, "stacking", test_stacking);
+ torture_suite_add_1smb_test(suite, "unlock", test_unlock);
+ torture_suite_add_1smb_test(suite, "multiple_unlock",
+ test_multiple_unlock);
+ torture_suite_add_1smb_test(suite, "zerobytelocks",
+ test_zerobytelocks);
+
return suite;
}
diff --git a/source4/torture/smbtorture.c b/source4/torture/smbtorture.c
index 635990354c..d01dc9a856 100644
--- a/source4/torture/smbtorture.c
+++ b/source4/torture/smbtorture.c
@@ -559,6 +559,8 @@ int main(int argc,char *argv[])
lp_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
} else if (strcmp(target, "samba4") == 0) {
lp_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
+ } else if (strcmp(target, "win7") == 0) {
+ lp_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
}
if (max_runtime) {