diff options
-rw-r--r-- | source4/torture/raw/lock.c | 673 |
1 files changed, 668 insertions, 5 deletions
diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c index e6930f2b33..0a2ed5260b 100644 --- a/source4/torture/raw/lock.c +++ b/source4/torture/raw/lock.c @@ -25,6 +25,9 @@ #include "system/filesys.h" #include "libcli/libcli.h" #include "torture/util.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "lib/cmdline/popt_common.h" #define CHECK_STATUS(status, correct) do { \ if (!NT_STATUS_EQUAL(status, correct)) { \ @@ -445,6 +448,11 @@ done: */ static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { + struct smbcli_session *session; + struct smb_composite_sesssetup setup; + struct smbcli_tree *tree; + union smb_tcon tcon; + const char *host, *share; union smb_lock io; struct smb_lock_entry lock[2]; NTSTATUS status; @@ -460,7 +468,7 @@ static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) printf("Testing LOCKING_ANDX_CANCEL_LOCK\n"); 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)); @@ -557,7 +565,6 @@ static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) goto done; } - printf("testing cancel by close\n"); io.lockx.in.ulock_cnt = 0; io.lockx.in.lock_cnt = 1; @@ -566,6 +573,7 @@ static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) status = smb_raw_lock(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + t = time(NULL); io.lockx.in.timeout = 10000; req = smb_raw_lock_send(cli->tree, &io); if (req == NULL) { @@ -574,20 +582,674 @@ static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) goto done; } - smbcli_close(cli->tree, fnum); + status = smbcli_close(cli->tree, fnum); + CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_request_simple_recv(req); CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); if (time(NULL) > t+2) { - printf("lock cancel by unlock was not immediate (%s)\n", __location__); + printf("lock cancel by close was not immediate (%s)\n", __location__); + ret = False; + goto done; + } + + printf("create a new sessions\n"); + session = smbcli_session_init(cli->transport, mem_ctx, False); + setup.in.sesskey = cli->transport->negotiate.sesskey; + setup.in.capabilities = cli->transport->negotiate.capabilities; + setup.in.workgroup = lp_workgroup(); + setup.in.credentials = cmdline_credentials; + status = smb_composite_sesssetup(session, &setup); + CHECK_STATUS(status, NT_STATUS_OK); + session->vuid = setup.out.vuid; + + printf("create new tree context\n"); + share = lp_parm_string(-1, "torture", "share"); + host = lp_parm_string(-1, "torture", "host"); + tree = smbcli_tree_init(session, mem_ctx, False); + tcon.generic.level = RAW_TCON_TCONX; + tcon.tconx.in.flags = 0; + tcon.tconx.in.password = data_blob(NULL, 0); + tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share); + tcon.tconx.in.device = "A:"; + status = smb_raw_tcon(tree, mem_ctx, &tcon); + CHECK_STATUS(status, NT_STATUS_OK); + tree->tid = tcon.tconx.out.tid; + + printf("testing cancel by exit\n"); + fname = BASEDIR "\\test_exit.txt"; + fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE); + if (fnum == -1) { + printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree)); + ret = False; + goto done; + } + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + io.lockx.in.timeout = 10000; + t = time(NULL); + req = smb_raw_lock_send(tree, &io); + if (req == NULL) { + printf("Failed to setup timed lock (%s)\n", __location__); + ret = False; + goto done; + } + + status = smb_raw_exit(session); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + + if (time(NULL) > t+2) { + printf("lock cancel by exit was not immediate (%s)\n", __location__); + ret = False; + goto done; + } + + printf("testing cancel by ulogoff\n"); + fname = BASEDIR "\\test_ulogoff.txt"; + fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE); + if (fnum == -1) { + printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree)); + ret = False; + goto done; + } + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + io.lockx.in.timeout = 10000; + t = time(NULL); + req = smb_raw_lock_send(tree, &io); + if (req == NULL) { + printf("Failed to setup timed lock (%s)\n", __location__); + ret = False; + goto done; + } + + status = smb_raw_ulogoff(session); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smbcli_request_simple_recv(req); + if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) { + printf("lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n", + nt_errstr(status)); + smb_tree_disconnect(tree); + smb_raw_exit(session); + goto done; + } + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + + if (time(NULL) > t+2) { + printf("lock cancel by ulogoff was not immediate (%s)\n", __location__); + ret = False; + goto done; + } + + printf("testing cancel by tdis\n"); + tree->session = cli->session; + + fname = BASEDIR "\\test_tdis.txt"; + fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE); + if (fnum == -1) { + printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree)); + ret = False; + goto done; + } + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smb_raw_lock(tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + io.lockx.in.timeout = 10000; + t = time(NULL); + req = smb_raw_lock_send(tree, &io); + if (req == NULL) { + printf("Failed to setup timed lock (%s)\n", __location__); + ret = False; + goto done; + } + + status = smb_tree_disconnect(tree); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); + + if (time(NULL) > t+2) { + printf("lock cancel by tdis was not immediate (%s)\n", __location__); ret = False; goto done; } - done: + smb_raw_exit(cli->session); + smbcli_deltree(cli->tree, BASEDIR); + return ret; +} + +/* + test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT +*/ +static BOOL test_errorcode(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) +{ + union smb_lock io; + union smb_open op; + struct smb_lock_entry lock[2]; + NTSTATUS status; + BOOL ret = True; + int fnum, fnum2; + const char *fname; + struct smbcli_request *req; + time_t start; + int t; + + if (!torture_setup_dir(cli, BASEDIR)) { + return False; + } + + printf("Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n"); + + printf("testing with timeout = 0\n"); + fname = BASEDIR "\\test0.txt"; + t = 0; + + /* + * the first run is with t = 0, + * the second with t > 0 (=1) + */ +next_run: + /* + * use the DENY_DOS mode, that creates two fnum's of one low-level file handle, + * this demonstrates that the cache is per fnum + */ + op.openx.level = RAW_OPEN_OPENX; + op.openx.in.fname = fname; + op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO; + op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS; + op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE; + op.openx.in.search_attrs = 0; + op.openx.in.file_attrs = 0; + op.openx.in.write_time = 0; + op.openx.in.size = 0; + op.openx.in.timeout = 0; + + status = smb_raw_open(cli->tree, mem_ctx, &op); + CHECK_STATUS(status, NT_STATUS_OK); + fnum = op.openx.out.file.fnum; + + status = smb_raw_open(cli->tree, mem_ctx, &op); + CHECK_STATUS(status, NT_STATUS_OK); + fnum2 = op.openx.out.file.fnum; + + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = t; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED + * this also demonstrates that the error code cache is per file handle + * (LOCK_NOT_GRANTED is only be used when timeout is 0!) + */ + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + + /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */ + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* demonstrate that the smbpid doesn't matter */ + lock[0].pid++; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + lock[0].pid--; + + /* + * demonstrate the a successful lock with count = 0 and the same offset, + * doesn't reset the error cache + */ + lock[0].offset = 100; + lock[0].count = 0; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* + * demonstrate the a successful lock with count = 0 and outside the locked range, + * doesn't reset the error cache + */ + lock[0].offset = 110; + lock[0].count = 0; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + lock[0].offset = 99; + lock[0].count = 0; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* demonstrate that a changing count doesn't reset the error cache */ + lock[0].offset = 100; + lock[0].count = 5; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + lock[0].offset = 100; + lock[0].count = 15; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* + * demonstrate the a lock with count = 0 and inside the locked range, + * fails and resets the error cache + */ + lock[0].offset = 101; + lock[0].count = 0; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* demonstrate the a changing offset, resets the error cache */ + lock[0].offset = 105; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + lock[0].offset = 95; + lock[0].count = 9; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* + * demonstrate the a successful lock in a different range, + * doesn't reset the cache, the failing lock on the 2nd handle + * resets the resets the cache + */ + lock[0].offset = 120; + lock[0].count = 15; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.file.fnum = fnum; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + io.lockx.in.file.fnum = fnum2; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED)); + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + /* end of the loop */ + if (t == 0) { + smb_raw_exit(cli->session); + printf("testing with timeout > 0 (=1)\n"); + fname = BASEDIR "\\test1.txt"; + t = 1; + goto next_run; + } + + /* + * the following 3 test sections demonstrate that + * the cache is only set when the error is reported + * to the client (after the timeout went by) + */ + smb_raw_exit(cli->session); + printf("testing a conflict while a lock is pending\n"); + fname = BASEDIR "\\test2.txt"; + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); + if (fnum == -1) { + printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree)); + ret = False; + goto done; + } + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + start = time(NULL); + io.lockx.in.timeout = 1000; + req = smb_raw_lock_send(cli->tree, &io); + if (req == NULL) { + printf("Failed to setup timed lock (%s)\n", __location__); + ret = False; + goto done; + } + + io.lockx.in.timeout = 0; + lock[0].offset = 105; + lock[0].count = 10; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + if (time(NULL) < start+1) { + printf("lock comes back to early (%s)\n", __location__); + ret = False; + goto done; + } + smbcli_close(cli->tree, fnum); + fname = BASEDIR "\\test3.txt"; + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); + if (fnum == -1) { + printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree)); + ret = False; + goto done; + } + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + start = time(NULL); + io.lockx.in.timeout = 1000; + req = smb_raw_lock_send(cli->tree, &io); + if (req == NULL) { + printf("Failed to setup timed lock (%s)\n", __location__); + ret = False; + goto done; + } + + io.lockx.in.timeout = 0; + lock[0].offset = 105; + lock[0].count = 10; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + lock[0].offset = 100; + lock[0].count = 10; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + if (time(NULL) < start+1) { + printf("lock comes back to early (%s)\n", __location__); + ret = False; + goto done; + } + + smbcli_close(cli->tree, fnum); + fname = BASEDIR "\\test4.txt"; + fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); + if (fnum == -1) { + printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree)); + ret = False; + goto done; + } + io.lockx.level = RAW_LOCK_LOCKX; + io.lockx.in.file.fnum = fnum; + io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + io.lockx.in.timeout = 0; + io.lockx.in.ulock_cnt = 0; + io.lockx.in.lock_cnt = 1; + lock[0].pid = cli->session->pid; + lock[0].offset = 100; + lock[0].count = 10; + io.lockx.in.locks = &lock[0]; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + start = time(NULL); + io.lockx.in.timeout = 1000; + req = smb_raw_lock_send(cli->tree, &io); + if (req == NULL) { + printf("Failed to setup timed lock (%s)\n", __location__); + ret = False; + goto done; + } + + io.lockx.in.timeout = 0; + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + + status = smbcli_request_simple_recv(req); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + status = smb_raw_lock(cli->tree, &io); + CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); + + if (time(NULL) < start+1) { + printf("lock comes back to early (%s)\n", __location__); + ret = False; + goto done; + } + +done: smb_raw_exit(cli->session); smbcli_deltree(cli->tree, BASEDIR); return ret; @@ -678,6 +1340,7 @@ BOOL torture_raw_lock(struct torture_context *torture) ret &= test_lock(cli, mem_ctx); ret &= test_pidhigh(cli, mem_ctx); ret &= test_async(cli, mem_ctx); + ret &= test_errorcode(cli, mem_ctx); ret &= test_changetype(cli, mem_ctx); torture_close_connection(cli); |