s4:torture - suppress printf "%llu" on uint64_t variables warnings
[Samba/gebeck_regimport.git] / source4 / torture / raw / lock.c
blob17757e41160f8843065240294509c860be8b25df
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for various lock operations
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/raw/raw_proto.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
28 #include "libcli/composite/composite.h"
29 #include "libcli/smb_composite/smb_composite.h"
30 #include "lib/cmdline/popt_common.h"
31 #include "param/param.h"
33 #define CHECK_STATUS(status, correct) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 torture_result(tctx, TORTURE_FAIL, \
36 "(%s) Incorrect status %s - should be %s\n", \
37 __location__, nt_errstr(status), nt_errstr(correct)); \
38 ret = false; \
39 goto done; \
40 }} while (0)
42 #define CHECK_STATUS_CONT(status, correct) do { \
43 if (!NT_STATUS_EQUAL(status, correct)) { \
44 torture_result(tctx, TORTURE_FAIL, \
45 "(%s) Incorrect status %s - should be %s\n", \
46 __location__, nt_errstr(status), nt_errstr(correct)); \
47 ret = false; \
48 }} while (0)
50 #define CHECK_STATUS_OR(status, correct1, correct2) do { \
51 if ((!NT_STATUS_EQUAL(status, correct1)) && \
52 (!NT_STATUS_EQUAL(status, correct2))) { \
53 torture_result(tctx, TORTURE_FAIL, \
54 "(%s) Incorrect status %s - should be %s or %s\n", \
55 __location__, nt_errstr(status), nt_errstr(correct1), \
56 nt_errstr(correct2)); \
57 ret = false; \
58 goto done; \
59 }} while (0)
61 #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
62 if ((!NT_STATUS_EQUAL(status, correct1)) && \
63 (!NT_STATUS_EQUAL(status, correct2))) { \
64 torture_result(tctx, TORTURE_FAIL, \
65 "(%s) Incorrect status %s - should be %s or %s\n", \
66 __location__, nt_errstr(status), nt_errstr(correct1), \
67 nt_errstr(correct2)); \
68 ret = false; \
69 }} while (0)
70 #define BASEDIR "\\testlock"
72 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
73 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
74 #define TARGET_IS_WINDOWS(_tctx) \
75 ((torture_setting_bool(_tctx, "w2k3", false)) || \
76 (torture_setting_bool(_tctx, "w2k8", false)) || \
77 (torture_setting_bool(_tctx, "win7", false)))
78 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
79 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
81 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
82 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
83 #define TARGET_SUPPORTS_SMBEXIT(_tctx) \
84 (torture_setting_bool(_tctx, "smbexit_pdu_support", true))
85 #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
86 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
87 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
88 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
89 #define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \
90 (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true))
92 test SMBlock and SMBunlock ops
94 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
96 union smb_lock io;
97 NTSTATUS status;
98 bool ret = true;
99 int fnum;
100 const char *fname = BASEDIR "\\test.txt";
102 if (!TARGET_SUPPORTS_SMBLOCK(tctx))
103 torture_skip(tctx, "Target does not support the SMBlock PDU");
105 if (!torture_setup_dir(cli, BASEDIR)) {
106 return false;
109 torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
110 io.generic.level = RAW_LOCK_LOCK;
112 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
113 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
114 "Failed to create %s - %s\n",
115 fname, smbcli_errstr(cli->tree)));
117 torture_comment(tctx, "Trying 0/0 lock\n");
118 io.lock.level = RAW_LOCK_LOCK;
119 io.lock.in.file.fnum = fnum;
120 io.lock.in.count = 0;
121 io.lock.in.offset = 0;
122 status = smb_raw_lock(cli->tree, &io);
123 CHECK_STATUS(status, NT_STATUS_OK);
124 cli->session->pid++;
125 status = smb_raw_lock(cli->tree, &io);
126 CHECK_STATUS(status, NT_STATUS_OK);
127 cli->session->pid--;
128 io.lock.level = RAW_LOCK_UNLOCK;
129 status = smb_raw_lock(cli->tree, &io);
130 CHECK_STATUS(status, NT_STATUS_OK);
132 torture_comment(tctx, "Trying 0/1 lock\n");
133 io.lock.level = RAW_LOCK_LOCK;
134 io.lock.in.file.fnum = fnum;
135 io.lock.in.count = 1;
136 io.lock.in.offset = 0;
137 status = smb_raw_lock(cli->tree, &io);
138 CHECK_STATUS(status, NT_STATUS_OK);
139 cli->session->pid++;
140 status = smb_raw_lock(cli->tree, &io);
141 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
142 cli->session->pid--;
143 io.lock.level = RAW_LOCK_UNLOCK;
144 status = smb_raw_lock(cli->tree, &io);
145 CHECK_STATUS(status, NT_STATUS_OK);
146 io.lock.level = RAW_LOCK_UNLOCK;
147 status = smb_raw_lock(cli->tree, &io);
148 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
150 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
151 io.lock.level = RAW_LOCK_LOCK;
152 io.lock.in.file.fnum = fnum;
153 io.lock.in.count = 4000;
154 io.lock.in.offset = 0xEEFFFFFF;
155 status = smb_raw_lock(cli->tree, &io);
156 CHECK_STATUS(status, NT_STATUS_OK);
157 cli->session->pid++;
158 status = smb_raw_lock(cli->tree, &io);
159 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
160 cli->session->pid--;
161 io.lock.level = RAW_LOCK_UNLOCK;
162 status = smb_raw_lock(cli->tree, &io);
163 CHECK_STATUS(status, NT_STATUS_OK);
164 io.lock.level = RAW_LOCK_UNLOCK;
165 status = smb_raw_lock(cli->tree, &io);
166 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
168 torture_comment(tctx, "Trying 0xEF000000 lock\n");
169 io.lock.level = RAW_LOCK_LOCK;
170 io.lock.in.file.fnum = fnum;
171 io.lock.in.count = 4000;
172 io.lock.in.offset = 0xEEFFFFFF;
173 status = smb_raw_lock(cli->tree, &io);
174 CHECK_STATUS(status, NT_STATUS_OK);
175 cli->session->pid++;
176 status = smb_raw_lock(cli->tree, &io);
177 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
178 cli->session->pid--;
179 io.lock.level = RAW_LOCK_UNLOCK;
180 status = smb_raw_lock(cli->tree, &io);
181 CHECK_STATUS(status, NT_STATUS_OK);
182 io.lock.level = RAW_LOCK_UNLOCK;
183 status = smb_raw_lock(cli->tree, &io);
184 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
186 torture_comment(tctx, "Trying max lock\n");
187 io.lock.level = RAW_LOCK_LOCK;
188 io.lock.in.file.fnum = fnum;
189 io.lock.in.count = 4000;
190 io.lock.in.offset = 0xEF000000;
191 status = smb_raw_lock(cli->tree, &io);
192 CHECK_STATUS(status, NT_STATUS_OK);
193 cli->session->pid++;
194 status = smb_raw_lock(cli->tree, &io);
195 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
196 cli->session->pid--;
197 io.lock.level = RAW_LOCK_UNLOCK;
198 status = smb_raw_lock(cli->tree, &io);
199 CHECK_STATUS(status, NT_STATUS_OK);
200 io.lock.level = RAW_LOCK_UNLOCK;
201 status = smb_raw_lock(cli->tree, &io);
202 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
204 torture_comment(tctx, "Trying wrong pid unlock\n");
205 io.lock.level = RAW_LOCK_LOCK;
206 io.lock.in.file.fnum = fnum;
207 io.lock.in.count = 4002;
208 io.lock.in.offset = 10001;
209 status = smb_raw_lock(cli->tree, &io);
210 CHECK_STATUS(status, NT_STATUS_OK);
211 cli->session->pid++;
212 io.lock.level = RAW_LOCK_UNLOCK;
213 status = smb_raw_lock(cli->tree, &io);
214 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
215 cli->session->pid--;
216 status = smb_raw_lock(cli->tree, &io);
217 CHECK_STATUS(status, NT_STATUS_OK);
219 done:
220 smbcli_close(cli->tree, fnum);
221 smb_raw_exit(cli->session);
222 smbcli_deltree(cli->tree, BASEDIR);
223 return ret;
228 test locking&X ops
230 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
232 union smb_lock io;
233 struct smb_lock_entry lock[1];
234 NTSTATUS status;
235 bool ret = true;
236 int fnum;
237 const char *fname = BASEDIR "\\test.txt";
239 if (!torture_setup_dir(cli, BASEDIR)) {
240 return false;
243 torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
244 io.generic.level = RAW_LOCK_LOCKX;
246 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
247 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
248 "Failed to create %s - %s\n",
249 fname, smbcli_errstr(cli->tree)));
251 io.lockx.level = RAW_LOCK_LOCKX;
252 io.lockx.in.file.fnum = fnum;
253 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
254 io.lockx.in.timeout = 0;
255 io.lockx.in.ulock_cnt = 0;
256 io.lockx.in.lock_cnt = 1;
257 lock[0].pid = cli->session->pid;
258 lock[0].offset = 10;
259 lock[0].count = 1;
260 io.lockx.in.locks = &lock[0];
261 status = smb_raw_lock(cli->tree, &io);
262 CHECK_STATUS(status, NT_STATUS_OK);
265 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
266 io.lockx.in.ulock_cnt = 0;
267 io.lockx.in.lock_cnt = 1;
268 lock[0].count = 4000;
269 lock[0].offset = 0xEEFFFFFF;
270 status = smb_raw_lock(cli->tree, &io);
271 CHECK_STATUS(status, NT_STATUS_OK);
272 lock[0].pid++;
273 status = smb_raw_lock(cli->tree, &io);
274 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
275 lock[0].pid--;
276 io.lockx.in.ulock_cnt = 1;
277 io.lockx.in.lock_cnt = 0;
278 status = smb_raw_lock(cli->tree, &io);
279 CHECK_STATUS(status, NT_STATUS_OK);
280 status = smb_raw_lock(cli->tree, &io);
281 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
283 torture_comment(tctx, "Trying 0xEF000000 lock\n");
284 io.lockx.in.ulock_cnt = 0;
285 io.lockx.in.lock_cnt = 1;
286 lock[0].count = 4000;
287 lock[0].offset = 0xEF000000;
288 status = smb_raw_lock(cli->tree, &io);
289 CHECK_STATUS(status, NT_STATUS_OK);
290 lock[0].pid++;
291 status = smb_raw_lock(cli->tree, &io);
292 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
293 lock[0].pid--;
294 io.lockx.in.ulock_cnt = 1;
295 io.lockx.in.lock_cnt = 0;
296 status = smb_raw_lock(cli->tree, &io);
297 CHECK_STATUS(status, NT_STATUS_OK);
298 status = smb_raw_lock(cli->tree, &io);
299 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
301 torture_comment(tctx, "Trying zero lock\n");
302 io.lockx.in.ulock_cnt = 0;
303 io.lockx.in.lock_cnt = 1;
304 lock[0].count = 0;
305 lock[0].offset = ~0;
306 status = smb_raw_lock(cli->tree, &io);
307 CHECK_STATUS(status, NT_STATUS_OK);
308 lock[0].pid++;
309 status = smb_raw_lock(cli->tree, &io);
310 CHECK_STATUS(status, NT_STATUS_OK);
311 lock[0].pid--;
312 io.lockx.in.ulock_cnt = 1;
313 io.lockx.in.lock_cnt = 0;
314 status = smb_raw_lock(cli->tree, &io);
315 CHECK_STATUS(status, NT_STATUS_OK);
316 status = smb_raw_lock(cli->tree, &io);
317 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
319 torture_comment(tctx, "Trying max lock\n");
320 io.lockx.in.ulock_cnt = 0;
321 io.lockx.in.lock_cnt = 1;
322 lock[0].count = 0;
323 lock[0].offset = ~0;
324 status = smb_raw_lock(cli->tree, &io);
325 CHECK_STATUS(status, NT_STATUS_OK);
326 lock[0].pid++;
327 status = smb_raw_lock(cli->tree, &io);
328 CHECK_STATUS(status, NT_STATUS_OK);
329 lock[0].pid--;
330 io.lockx.in.ulock_cnt = 1;
331 io.lockx.in.lock_cnt = 0;
332 status = smb_raw_lock(cli->tree, &io);
333 CHECK_STATUS(status, NT_STATUS_OK);
334 status = smb_raw_lock(cli->tree, &io);
335 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
337 torture_comment(tctx, "Trying 2^63\n");
338 io.lockx.in.ulock_cnt = 0;
339 io.lockx.in.lock_cnt = 1;
340 lock[0].count = 1;
341 lock[0].offset = 1;
342 lock[0].offset <<= 63;
343 status = smb_raw_lock(cli->tree, &io);
344 CHECK_STATUS(status, NT_STATUS_OK);
345 lock[0].pid++;
346 status = smb_raw_lock(cli->tree, &io);
347 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
348 lock[0].pid--;
349 io.lockx.in.ulock_cnt = 1;
350 io.lockx.in.lock_cnt = 0;
351 status = smb_raw_lock(cli->tree, &io);
352 CHECK_STATUS(status, NT_STATUS_OK);
353 status = smb_raw_lock(cli->tree, &io);
354 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
356 torture_comment(tctx, "Trying 2^63 - 1\n");
357 io.lockx.in.ulock_cnt = 0;
358 io.lockx.in.lock_cnt = 1;
359 lock[0].count = 1;
360 lock[0].offset = 1;
361 lock[0].offset <<= 63;
362 lock[0].offset--;
363 status = smb_raw_lock(cli->tree, &io);
364 CHECK_STATUS(status, NT_STATUS_OK);
365 lock[0].pid++;
366 status = smb_raw_lock(cli->tree, &io);
367 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
368 lock[0].pid--;
369 io.lockx.in.ulock_cnt = 1;
370 io.lockx.in.lock_cnt = 0;
371 status = smb_raw_lock(cli->tree, &io);
372 CHECK_STATUS(status, NT_STATUS_OK);
373 status = smb_raw_lock(cli->tree, &io);
374 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
376 torture_comment(tctx, "Trying max lock 2\n");
377 io.lockx.in.ulock_cnt = 0;
378 io.lockx.in.lock_cnt = 1;
379 lock[0].count = 1;
380 lock[0].offset = ~0;
381 status = smb_raw_lock(cli->tree, &io);
382 CHECK_STATUS(status, NT_STATUS_OK);
383 lock[0].pid++;
384 lock[0].count = 2;
385 status = smb_raw_lock(cli->tree, &io);
386 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
387 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
388 else
389 CHECK_STATUS(status, NT_STATUS_OK);
390 lock[0].pid--;
391 io.lockx.in.ulock_cnt = 1;
392 io.lockx.in.lock_cnt = 0;
393 lock[0].count = 1;
394 status = smb_raw_lock(cli->tree, &io);
396 CHECK_STATUS(status, NT_STATUS_OK);
397 status = smb_raw_lock(cli->tree, &io);
398 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
400 done:
401 smbcli_close(cli->tree, fnum);
402 smb_raw_exit(cli->session);
403 smbcli_deltree(cli->tree, BASEDIR);
404 return ret;
408 test high pid
410 static bool test_pidhigh(struct torture_context *tctx,
411 struct smbcli_state *cli)
413 union smb_lock io;
414 struct smb_lock_entry lock[1];
415 NTSTATUS status;
416 bool ret = true;
417 int fnum;
418 const char *fname = BASEDIR "\\test.txt";
419 uint8_t c = 1;
421 if (!torture_setup_dir(cli, BASEDIR)) {
422 return false;
425 torture_comment(tctx, "Testing high pid\n");
426 io.generic.level = RAW_LOCK_LOCKX;
428 cli->session->pid = 1;
430 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
431 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
432 "Failed to create %s - %s\n",
433 fname, smbcli_errstr(cli->tree)));
435 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
436 torture_result(tctx, TORTURE_FAIL,
437 "Failed to write 1 byte - %s\n",
438 smbcli_errstr(cli->tree));
439 ret = false;
440 goto done;
443 io.lockx.level = RAW_LOCK_LOCKX;
444 io.lockx.in.file.fnum = fnum;
445 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
446 io.lockx.in.timeout = 0;
447 io.lockx.in.ulock_cnt = 0;
448 io.lockx.in.lock_cnt = 1;
449 lock[0].pid = cli->session->pid;
450 lock[0].offset = 0;
451 lock[0].count = 0xFFFFFFFF;
452 io.lockx.in.locks = &lock[0];
453 status = smb_raw_lock(cli->tree, &io);
454 CHECK_STATUS(status, NT_STATUS_OK);
456 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
457 torture_result(tctx, TORTURE_FAIL,
458 "Failed to read 1 byte - %s\n",
459 smbcli_errstr(cli->tree));
460 ret = false;
461 goto done;
464 cli->session->pid = 2;
466 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
467 torture_result(tctx, TORTURE_FAIL,
468 "pid is incorrect handled for read with lock!\n");
469 ret = false;
470 goto done;
473 cli->session->pid = 0x10001;
475 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
476 torture_result(tctx, TORTURE_FAIL,
477 "High pid is used on this server!\n");
478 ret = false;
479 } else {
480 torture_warning(tctx, "High pid is not used on this server (correct)\n");
483 done:
484 smbcli_close(cli->tree, fnum);
485 smb_raw_exit(cli->session);
486 smbcli_deltree(cli->tree, BASEDIR);
487 return ret;
492 test locking&X async operation
494 static bool test_async(struct torture_context *tctx,
495 struct smbcli_state *cli)
497 struct smbcli_session *session;
498 struct smb_composite_sesssetup setup;
499 struct smbcli_tree *tree;
500 union smb_tcon tcon;
501 const char *host, *share;
502 union smb_lock io;
503 struct smb_lock_entry lock[2];
504 NTSTATUS status;
505 bool ret = true;
506 int fnum;
507 const char *fname = BASEDIR "\\test.txt";
508 time_t t;
509 struct smbcli_request *req, *req2;
510 struct smbcli_session_options options;
512 if (!torture_setup_dir(cli, BASEDIR)) {
513 return false;
516 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
518 torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
519 io.generic.level = RAW_LOCK_LOCKX;
521 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
522 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
523 "Failed to create %s - %s\n",
524 fname, smbcli_errstr(cli->tree)));
526 io.lockx.level = RAW_LOCK_LOCKX;
527 io.lockx.in.file.fnum = fnum;
528 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
529 io.lockx.in.timeout = 0;
530 io.lockx.in.ulock_cnt = 0;
531 io.lockx.in.lock_cnt = 1;
532 lock[0].pid = cli->session->pid;
533 lock[0].offset = 100;
534 lock[0].count = 10;
535 lock[1].pid = cli->session->pid;
536 lock[1].offset = 110;
537 lock[1].count = 10;
538 io.lockx.in.locks = &lock[0];
539 status = smb_raw_lock(cli->tree, &io);
540 CHECK_STATUS(status, NT_STATUS_OK);
542 t = time_mono(NULL);
544 torture_comment(tctx, "Testing cancel by CANCEL_LOCK\n");
546 /* setup a timed lock */
547 io.lockx.in.timeout = 10000;
548 req = smb_raw_lock_send(cli->tree, &io);
549 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
550 "Failed to setup timed lock (%s)\n", __location__));
552 /* cancel the wrong range */
553 lock[0].offset = 0;
554 io.lockx.in.timeout = 0;
555 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
556 status = smb_raw_lock(cli->tree, &io);
557 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
559 /* cancel with the wrong bits set */
560 lock[0].offset = 100;
561 io.lockx.in.timeout = 0;
562 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
563 status = smb_raw_lock(cli->tree, &io);
564 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
566 /* cancel the right range */
567 lock[0].offset = 100;
568 io.lockx.in.timeout = 0;
569 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
570 status = smb_raw_lock(cli->tree, &io);
571 CHECK_STATUS(status, NT_STATUS_OK);
573 /* receive the failed lock request */
574 status = smbcli_request_simple_recv(req);
575 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
577 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
578 "lock cancel was not immediate (%s)\n", __location__));
580 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
581 * if the lock vector contains one entry. When given mutliple cancel
582 * requests in a single PDU we expect the server to return an
583 * error. Samba4 handles this correctly. Windows servers seem to
584 * accept the request but only cancel the first lock. Samba3
585 * now does what Windows does (JRA).
587 torture_comment(tctx, "Testing multiple cancel\n");
589 /* acquire second lock */
590 io.lockx.in.timeout = 0;
591 io.lockx.in.ulock_cnt = 0;
592 io.lockx.in.lock_cnt = 1;
593 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
594 io.lockx.in.locks = &lock[1];
595 status = smb_raw_lock(cli->tree, &io);
596 CHECK_STATUS(status, NT_STATUS_OK);
598 /* setup 2 timed locks */
599 t = time_mono(NULL);
600 io.lockx.in.timeout = 10000;
601 io.lockx.in.lock_cnt = 1;
602 io.lockx.in.locks = &lock[0];
603 req = smb_raw_lock_send(cli->tree, &io);
604 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
605 "Failed to setup timed lock (%s)\n", __location__));
606 io.lockx.in.locks = &lock[1];
607 req2 = smb_raw_lock_send(cli->tree, &io);
608 torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
609 "Failed to setup timed lock (%s)\n", __location__));
611 /* try to cancel both locks in the same packet */
612 io.lockx.in.timeout = 0;
613 io.lockx.in.lock_cnt = 2;
614 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
615 io.lockx.in.locks = lock;
616 status = smb_raw_lock(cli->tree, &io);
617 CHECK_STATUS(status, NT_STATUS_OK);
619 torture_warning(tctx, "Target server accepted a lock cancel "
620 "request with multiple locks. This violates "
621 "MS-CIFS 2.2.4.32.1.\n");
623 /* receive the failed lock requests */
624 status = smbcli_request_simple_recv(req);
625 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
627 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
628 "first lock was not cancelled immediately (%s)\n",
629 __location__));
631 /* send cancel to second lock */
632 io.lockx.in.timeout = 0;
633 io.lockx.in.lock_cnt = 1;
634 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK |
635 LOCKING_ANDX_LARGE_FILES;
636 io.lockx.in.locks = &lock[1];
637 status = smb_raw_lock(cli->tree, &io);
638 CHECK_STATUS(status, NT_STATUS_OK);
640 status = smbcli_request_simple_recv(req2);
641 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
643 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
644 "second lock was not cancelled immediately (%s)\n",
645 __location__));
647 /* cleanup the second lock */
648 io.lockx.in.ulock_cnt = 1;
649 io.lockx.in.lock_cnt = 0;
650 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
651 io.lockx.in.locks = &lock[1];
652 status = smb_raw_lock(cli->tree, &io);
653 CHECK_STATUS(status, NT_STATUS_OK);
655 /* If a lock request contained multiple ranges and we are cancelling
656 * one while it's still pending, what happens? */
657 torture_comment(tctx, "Testing cancel 1/2 lock request\n");
659 /* Send request with two ranges */
660 io.lockx.in.timeout = -1;
661 io.lockx.in.ulock_cnt = 0;
662 io.lockx.in.lock_cnt = 2;
663 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
664 io.lockx.in.locks = lock;
665 req = smb_raw_lock_send(cli->tree, &io);
666 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
667 "Failed to setup pending lock (%s)\n", __location__));
669 /* Try to cancel the first lock range */
670 io.lockx.in.timeout = 0;
671 io.lockx.in.lock_cnt = 1;
672 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
673 io.lockx.in.locks = &lock[0];
674 status = smb_raw_lock(cli->tree, &io);
675 CHECK_STATUS(status, NT_STATUS_OK);
677 /* Locking request should've failed and second range should be
678 * unlocked */
679 status = smbcli_request_simple_recv(req);
680 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
682 io.lockx.in.timeout = 0;
683 io.lockx.in.ulock_cnt = 0;
684 io.lockx.in.lock_cnt = 1;
685 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
686 io.lockx.in.locks = &lock[1];
687 status = smb_raw_lock(cli->tree, &io);
688 CHECK_STATUS(status, NT_STATUS_OK);
690 /* Cleanup both locks */
691 io.lockx.in.ulock_cnt = 2;
692 io.lockx.in.lock_cnt = 0;
693 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
694 io.lockx.in.locks = lock;
695 status = smb_raw_lock(cli->tree, &io);
696 CHECK_STATUS(status, NT_STATUS_OK);
698 torture_comment(tctx, "Testing cancel 2/2 lock request\n");
700 /* Lock second range so it contends */
701 io.lockx.in.timeout = 0;
702 io.lockx.in.ulock_cnt = 0;
703 io.lockx.in.lock_cnt = 1;
704 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
705 io.lockx.in.locks = &lock[1];
706 status = smb_raw_lock(cli->tree, &io);
707 CHECK_STATUS(status, NT_STATUS_OK);
709 /* Send request with two ranges */
710 io.lockx.in.timeout = -1;
711 io.lockx.in.ulock_cnt = 0;
712 io.lockx.in.lock_cnt = 2;
713 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
714 io.lockx.in.locks = lock;
715 req = smb_raw_lock_send(cli->tree, &io);
716 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
717 "Failed to setup pending lock (%s)\n", __location__));
719 /* Try to cancel the second lock range */
720 io.lockx.in.timeout = 0;
721 io.lockx.in.lock_cnt = 1;
722 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
723 io.lockx.in.locks = &lock[1];
724 status = smb_raw_lock(cli->tree, &io);
725 CHECK_STATUS(status, NT_STATUS_OK);
727 /* Locking request should've failed and first range should be
728 * unlocked */
729 status = smbcli_request_simple_recv(req);
730 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
732 io.lockx.in.timeout = 0;
733 io.lockx.in.ulock_cnt = 0;
734 io.lockx.in.lock_cnt = 1;
735 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
736 io.lockx.in.locks = &lock[0];
737 status = smb_raw_lock(cli->tree, &io);
738 CHECK_STATUS(status, NT_STATUS_OK);
740 /* Cleanup both locks */
741 io.lockx.in.ulock_cnt = 2;
742 io.lockx.in.lock_cnt = 0;
743 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
744 io.lockx.in.locks = lock;
745 status = smb_raw_lock(cli->tree, &io);
746 CHECK_STATUS(status, NT_STATUS_OK);
748 torture_comment(tctx, "Testing cancel by unlock\n");
749 io.lockx.in.ulock_cnt = 0;
750 io.lockx.in.lock_cnt = 1;
751 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
752 io.lockx.in.timeout = 0;
753 io.lockx.in.locks = &lock[0];
754 status = smb_raw_lock(cli->tree, &io);
755 CHECK_STATUS(status, NT_STATUS_OK);
757 io.lockx.in.timeout = 5000;
758 req = smb_raw_lock_send(cli->tree, &io);
759 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
760 "Failed to setup timed lock (%s)\n", __location__));
762 io.lockx.in.ulock_cnt = 1;
763 io.lockx.in.lock_cnt = 0;
764 status = smb_raw_lock(cli->tree, &io);
765 CHECK_STATUS(status, NT_STATUS_OK);
767 t = time_mono(NULL);
768 status = smbcli_request_simple_recv(req);
769 CHECK_STATUS(status, NT_STATUS_OK);
771 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
772 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
773 __location__, (int)(time_mono(NULL)-t)));
775 torture_comment(tctx, "Testing cancel by close\n");
776 io.lockx.in.ulock_cnt = 0;
777 io.lockx.in.lock_cnt = 1;
778 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
779 io.lockx.in.timeout = 0;
780 status = smb_raw_lock(cli->tree, &io);
781 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
783 t = time_mono(NULL);
784 io.lockx.in.timeout = 10000;
785 req = smb_raw_lock_send(cli->tree, &io);
786 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
787 "Failed to setup timed lock (%s)\n", __location__));
789 status = smbcli_close(cli->tree, fnum);
790 CHECK_STATUS(status, NT_STATUS_OK);
792 status = smbcli_request_simple_recv(req);
793 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
794 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
795 else
796 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
798 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
799 "lock cancel by close was not immediate (%s)\n", __location__));
801 torture_comment(tctx, "create a new sessions\n");
802 session = smbcli_session_init(cli->transport, tctx, false, options);
803 setup.in.sesskey = cli->transport->negotiate.sesskey;
804 setup.in.capabilities = cli->transport->negotiate.capabilities;
805 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
806 setup.in.credentials = cmdline_credentials;
807 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
808 status = smb_composite_sesssetup(session, &setup);
809 CHECK_STATUS(status, NT_STATUS_OK);
810 session->vuid = setup.out.vuid;
812 torture_comment(tctx, "create new tree context\n");
813 share = torture_setting_string(tctx, "share", NULL);
814 host = torture_setting_string(tctx, "host", NULL);
815 tree = smbcli_tree_init(session, tctx, false);
816 tcon.generic.level = RAW_TCON_TCONX;
817 tcon.tconx.in.flags = 0;
818 tcon.tconx.in.password = data_blob(NULL, 0);
819 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
820 tcon.tconx.in.device = "A:";
821 status = smb_raw_tcon(tree, tctx, &tcon);
822 CHECK_STATUS(status, NT_STATUS_OK);
823 tree->tid = tcon.tconx.out.tid;
825 torture_comment(tctx, "Testing cancel by exit\n");
826 if (TARGET_SUPPORTS_SMBEXIT(tctx)) {
827 fname = BASEDIR "\\test_exit.txt";
828 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
829 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
830 "Failed to reopen %s - %s\n",
831 fname, smbcli_errstr(tree)));
833 io.lockx.level = RAW_LOCK_LOCKX;
834 io.lockx.in.file.fnum = fnum;
835 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
836 io.lockx.in.timeout = 0;
837 io.lockx.in.ulock_cnt = 0;
838 io.lockx.in.lock_cnt = 1;
839 lock[0].pid = session->pid;
840 lock[0].offset = 100;
841 lock[0].count = 10;
842 io.lockx.in.locks = &lock[0];
843 status = smb_raw_lock(tree, &io);
844 CHECK_STATUS(status, NT_STATUS_OK);
846 io.lockx.in.ulock_cnt = 0;
847 io.lockx.in.lock_cnt = 1;
848 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
849 io.lockx.in.timeout = 0;
850 status = smb_raw_lock(tree, &io);
851 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
853 io.lockx.in.timeout = 10000;
854 t = time_mono(NULL);
855 req = smb_raw_lock_send(tree, &io);
856 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
857 "Failed to setup timed lock (%s)\n",
858 __location__));
860 status = smb_raw_exit(session);
861 CHECK_STATUS(status, NT_STATUS_OK);
863 status = smbcli_request_simple_recv(req);
864 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
865 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
866 else
867 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
869 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
870 "lock cancel by exit was not immediate (%s)\n",
871 __location__));
873 else {
874 torture_comment(tctx,
875 " skipping test, SMBExit not supported\n");
878 torture_comment(tctx, "Testing cancel by ulogoff\n");
879 fname = BASEDIR "\\test_ulogoff.txt";
880 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
881 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
882 "Failed to reopen %s - %s\n",
883 fname, smbcli_errstr(tree)));
885 io.lockx.level = RAW_LOCK_LOCKX;
886 io.lockx.in.file.fnum = fnum;
887 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
888 io.lockx.in.timeout = 0;
889 io.lockx.in.ulock_cnt = 0;
890 io.lockx.in.lock_cnt = 1;
891 lock[0].pid = session->pid;
892 lock[0].offset = 100;
893 lock[0].count = 10;
894 io.lockx.in.locks = &lock[0];
895 status = smb_raw_lock(tree, &io);
896 CHECK_STATUS(status, NT_STATUS_OK);
898 io.lockx.in.ulock_cnt = 0;
899 io.lockx.in.lock_cnt = 1;
900 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
901 io.lockx.in.timeout = 0;
902 status = smb_raw_lock(tree, &io);
903 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
905 io.lockx.in.timeout = 10000;
906 t = time_mono(NULL);
907 req = smb_raw_lock_send(tree, &io);
908 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
909 "Failed to setup timed lock (%s)\n", __location__));
911 status = smb_raw_ulogoff(session);
912 CHECK_STATUS(status, NT_STATUS_OK);
914 status = smbcli_request_simple_recv(req);
915 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) {
916 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
917 torture_result(tctx, TORTURE_FAIL,
918 "lock not canceled by ulogoff - %s "
919 "(ignored because of vfs_vifs fails it)\n",
920 nt_errstr(status));
921 smb_tree_disconnect(tree);
922 smb_raw_exit(session);
923 goto done;
925 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
926 } else {
927 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
930 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
931 "lock cancel by ulogoff was not immediate (%s)\n", __location__));
933 torture_comment(tctx, "Testing cancel by tdis\n");
934 tree->session = cli->session;
936 fname = BASEDIR "\\test_tdis.txt";
937 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
938 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
939 "Failed to reopen %s - %s\n",
940 fname, smbcli_errstr(tree)));
942 io.lockx.level = RAW_LOCK_LOCKX;
943 io.lockx.in.file.fnum = fnum;
944 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
945 io.lockx.in.timeout = 0;
946 io.lockx.in.ulock_cnt = 0;
947 io.lockx.in.lock_cnt = 1;
948 lock[0].pid = cli->session->pid;
949 lock[0].offset = 100;
950 lock[0].count = 10;
951 io.lockx.in.locks = &lock[0];
952 status = smb_raw_lock(tree, &io);
953 CHECK_STATUS(status, NT_STATUS_OK);
955 status = smb_raw_lock(tree, &io);
956 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
958 io.lockx.in.timeout = 10000;
959 t = time_mono(NULL);
960 req = smb_raw_lock_send(tree, &io);
961 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
962 "Failed to setup timed lock (%s)\n", __location__));
964 status = smb_tree_disconnect(tree);
965 CHECK_STATUS(status, NT_STATUS_OK);
967 status = smbcli_request_simple_recv(req);
968 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
969 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
970 else
971 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
973 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
974 "lock cancel by tdis was not immediate (%s)\n", __location__));
976 done:
977 smb_raw_exit(cli->session);
978 smbcli_deltree(cli->tree, BASEDIR);
979 return ret;
983 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
985 static bool test_errorcode(struct torture_context *tctx,
986 struct smbcli_state *cli)
988 union smb_lock io;
989 union smb_open op;
990 struct smb_lock_entry lock[2];
991 NTSTATUS status;
992 bool ret = true;
993 int fnum, fnum2;
994 const char *fname;
995 struct smbcli_request *req;
996 time_t start;
997 int t;
998 int delay;
999 uint16_t deny_mode = 0;
1001 if (!torture_setup_dir(cli, BASEDIR)) {
1002 return false;
1005 torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
1007 torture_comment(tctx, "Testing with timeout = 0\n");
1008 fname = BASEDIR "\\test0.txt";
1009 t = 0;
1012 * the first run is with t = 0,
1013 * the second with t > 0 (=1)
1015 next_run:
1017 * use the DENY_DOS mode, that creates two fnum's of one low-level
1018 * file handle, this demonstrates that the cache is per fnum, not
1019 * per file handle
1021 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
1022 deny_mode = OPENX_MODE_DENY_DOS;
1023 else
1024 deny_mode = OPENX_MODE_DENY_NONE;
1026 op.openx.level = RAW_OPEN_OPENX;
1027 op.openx.in.fname = fname;
1028 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1029 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
1030 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
1031 op.openx.in.search_attrs = 0;
1032 op.openx.in.file_attrs = 0;
1033 op.openx.in.write_time = 0;
1034 op.openx.in.size = 0;
1035 op.openx.in.timeout = 0;
1037 status = smb_raw_open(cli->tree, tctx, &op);
1038 CHECK_STATUS(status, NT_STATUS_OK);
1039 fnum = op.openx.out.file.fnum;
1041 status = smb_raw_open(cli->tree, tctx, &op);
1042 CHECK_STATUS(status, NT_STATUS_OK);
1043 fnum2 = op.openx.out.file.fnum;
1045 io.lockx.level = RAW_LOCK_LOCKX;
1046 io.lockx.in.file.fnum = fnum;
1047 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1048 io.lockx.in.timeout = t;
1049 io.lockx.in.ulock_cnt = 0;
1050 io.lockx.in.lock_cnt = 1;
1051 lock[0].pid = cli->session->pid;
1052 lock[0].offset = 100;
1053 lock[0].count = 10;
1054 io.lockx.in.locks = &lock[0];
1055 status = smb_raw_lock(cli->tree, &io);
1056 CHECK_STATUS(status, NT_STATUS_OK);
1059 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
1060 * this also demonstrates that the error code cache is per file handle
1061 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
1063 io.lockx.in.file.fnum = fnum2;
1064 status = smb_raw_lock(cli->tree, &io);
1065 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1067 io.lockx.in.file.fnum = fnum;
1068 status = smb_raw_lock(cli->tree, &io);
1069 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1071 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
1072 io.lockx.in.file.fnum = fnum;
1073 status = smb_raw_lock(cli->tree, &io);
1074 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1076 io.lockx.in.file.fnum = fnum2;
1077 status = smb_raw_lock(cli->tree, &io);
1078 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1080 io.lockx.in.file.fnum = fnum;
1081 status = smb_raw_lock(cli->tree, &io);
1082 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1084 io.lockx.in.file.fnum = fnum2;
1085 status = smb_raw_lock(cli->tree, &io);
1086 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1088 /* demonstrate that the smbpid doesn't matter */
1089 lock[0].pid++;
1090 io.lockx.in.file.fnum = fnum;
1091 status = smb_raw_lock(cli->tree, &io);
1092 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1094 io.lockx.in.file.fnum = fnum2;
1095 status = smb_raw_lock(cli->tree, &io);
1096 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1097 lock[0].pid--;
1100 * demonstrate the a successful lock with count = 0 and the same offset,
1101 * doesn't reset the error cache
1103 lock[0].offset = 100;
1104 lock[0].count = 0;
1105 io.lockx.in.file.fnum = fnum;
1106 status = smb_raw_lock(cli->tree, &io);
1107 CHECK_STATUS(status, NT_STATUS_OK);
1109 io.lockx.in.file.fnum = fnum2;
1110 status = smb_raw_lock(cli->tree, &io);
1111 CHECK_STATUS(status, NT_STATUS_OK);
1113 lock[0].offset = 100;
1114 lock[0].count = 10;
1115 io.lockx.in.file.fnum = fnum;
1116 status = smb_raw_lock(cli->tree, &io);
1117 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1119 io.lockx.in.file.fnum = fnum2;
1120 status = smb_raw_lock(cli->tree, &io);
1121 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1124 * demonstrate the a successful lock with count = 0 and outside the locked range,
1125 * doesn't reset the error cache
1127 lock[0].offset = 110;
1128 lock[0].count = 0;
1129 io.lockx.in.file.fnum = fnum;
1130 status = smb_raw_lock(cli->tree, &io);
1131 CHECK_STATUS(status, NT_STATUS_OK);
1133 io.lockx.in.file.fnum = fnum2;
1134 status = smb_raw_lock(cli->tree, &io);
1135 CHECK_STATUS(status, NT_STATUS_OK);
1137 lock[0].offset = 100;
1138 lock[0].count = 10;
1139 io.lockx.in.file.fnum = fnum;
1140 status = smb_raw_lock(cli->tree, &io);
1141 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1143 io.lockx.in.file.fnum = fnum2;
1144 status = smb_raw_lock(cli->tree, &io);
1145 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1147 lock[0].offset = 99;
1148 lock[0].count = 0;
1149 io.lockx.in.file.fnum = fnum;
1150 status = smb_raw_lock(cli->tree, &io);
1151 CHECK_STATUS(status, NT_STATUS_OK);
1153 io.lockx.in.file.fnum = fnum2;
1154 status = smb_raw_lock(cli->tree, &io);
1155 CHECK_STATUS(status, NT_STATUS_OK);
1157 lock[0].offset = 100;
1158 lock[0].count = 10;
1159 io.lockx.in.file.fnum = fnum;
1160 status = smb_raw_lock(cli->tree, &io);
1161 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1163 io.lockx.in.file.fnum = fnum2;
1164 status = smb_raw_lock(cli->tree, &io);
1165 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1167 /* demonstrate that a changing count doesn't reset the error cache */
1168 lock[0].offset = 100;
1169 lock[0].count = 5;
1170 io.lockx.in.file.fnum = fnum;
1171 status = smb_raw_lock(cli->tree, &io);
1172 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1174 io.lockx.in.file.fnum = fnum2;
1175 status = smb_raw_lock(cli->tree, &io);
1176 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1178 lock[0].offset = 100;
1179 lock[0].count = 15;
1180 io.lockx.in.file.fnum = fnum;
1181 status = smb_raw_lock(cli->tree, &io);
1182 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1184 io.lockx.in.file.fnum = fnum2;
1185 status = smb_raw_lock(cli->tree, &io);
1186 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1189 * demonstrate the a lock with count = 0 and inside the locked range,
1190 * fails and resets the error cache
1192 lock[0].offset = 101;
1193 lock[0].count = 0;
1194 io.lockx.in.file.fnum = fnum;
1195 status = smb_raw_lock(cli->tree, &io);
1196 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1197 status = smb_raw_lock(cli->tree, &io);
1198 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1200 io.lockx.in.file.fnum = fnum2;
1201 status = smb_raw_lock(cli->tree, &io);
1202 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1203 status = smb_raw_lock(cli->tree, &io);
1204 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1206 lock[0].offset = 100;
1207 lock[0].count = 10;
1208 io.lockx.in.file.fnum = fnum;
1209 status = smb_raw_lock(cli->tree, &io);
1210 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1211 status = smb_raw_lock(cli->tree, &io);
1212 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1214 io.lockx.in.file.fnum = fnum2;
1215 status = smb_raw_lock(cli->tree, &io);
1216 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1217 status = smb_raw_lock(cli->tree, &io);
1218 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1220 /* demonstrate the a changing offset, resets the error cache */
1221 lock[0].offset = 105;
1222 lock[0].count = 10;
1223 io.lockx.in.file.fnum = fnum;
1224 status = smb_raw_lock(cli->tree, &io);
1225 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1226 status = smb_raw_lock(cli->tree, &io);
1227 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1229 io.lockx.in.file.fnum = fnum2;
1230 status = smb_raw_lock(cli->tree, &io);
1231 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1232 status = smb_raw_lock(cli->tree, &io);
1233 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1235 lock[0].offset = 100;
1236 lock[0].count = 10;
1237 io.lockx.in.file.fnum = fnum;
1238 status = smb_raw_lock(cli->tree, &io);
1239 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1240 status = smb_raw_lock(cli->tree, &io);
1241 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1243 io.lockx.in.file.fnum = fnum2;
1244 status = smb_raw_lock(cli->tree, &io);
1245 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1246 status = smb_raw_lock(cli->tree, &io);
1247 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1249 lock[0].offset = 95;
1250 lock[0].count = 9;
1251 io.lockx.in.file.fnum = fnum;
1252 status = smb_raw_lock(cli->tree, &io);
1253 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1254 status = smb_raw_lock(cli->tree, &io);
1255 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1257 io.lockx.in.file.fnum = fnum2;
1258 status = smb_raw_lock(cli->tree, &io);
1259 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1260 status = smb_raw_lock(cli->tree, &io);
1261 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1263 lock[0].offset = 100;
1264 lock[0].count = 10;
1265 io.lockx.in.file.fnum = fnum;
1266 status = smb_raw_lock(cli->tree, &io);
1267 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1268 status = smb_raw_lock(cli->tree, &io);
1269 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1271 io.lockx.in.file.fnum = fnum2;
1272 status = smb_raw_lock(cli->tree, &io);
1273 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1274 status = smb_raw_lock(cli->tree, &io);
1275 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1278 * demonstrate the a successful lock in a different range,
1279 * doesn't reset the cache, the failing lock on the 2nd handle
1280 * resets the cache
1282 lock[0].offset = 120;
1283 lock[0].count = 15;
1284 io.lockx.in.file.fnum = fnum;
1285 status = smb_raw_lock(cli->tree, &io);
1286 CHECK_STATUS(status, NT_STATUS_OK);
1288 io.lockx.in.file.fnum = fnum2;
1289 status = smb_raw_lock(cli->tree, &io);
1290 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1292 lock[0].offset = 100;
1293 lock[0].count = 10;
1294 io.lockx.in.file.fnum = fnum;
1295 status = smb_raw_lock(cli->tree, &io);
1296 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1297 status = smb_raw_lock(cli->tree, &io);
1298 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1300 io.lockx.in.file.fnum = fnum2;
1301 status = smb_raw_lock(cli->tree, &io);
1302 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1303 status = smb_raw_lock(cli->tree, &io);
1304 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1306 /* end of the loop */
1307 if (t == 0) {
1308 smb_raw_exit(cli->session);
1309 t = 1;
1310 torture_comment(tctx, "Testing with timeout > 0 (=%d)\n",
1312 fname = BASEDIR "\\test1.txt";
1313 goto next_run;
1316 t = 4000;
1317 torture_comment(tctx, "Testing special cases with timeout > 0 (=%d)\n",
1321 * the following 3 test sections demonstrate that
1322 * the cache is only set when the error is reported
1323 * to the client (after the timeout went by)
1325 smb_raw_exit(cli->session);
1326 torture_comment(tctx, "Testing a conflict while a lock is pending\n");
1327 fname = BASEDIR "\\test2.txt";
1328 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1329 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1330 "Failed to reopen %s - %s\n",
1331 fname, smbcli_errstr(cli->tree)));
1333 io.lockx.level = RAW_LOCK_LOCKX;
1334 io.lockx.in.file.fnum = fnum;
1335 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1336 io.lockx.in.timeout = 0;
1337 io.lockx.in.ulock_cnt = 0;
1338 io.lockx.in.lock_cnt = 1;
1339 lock[0].pid = cli->session->pid;
1340 lock[0].offset = 100;
1341 lock[0].count = 10;
1342 io.lockx.in.locks = &lock[0];
1343 status = smb_raw_lock(cli->tree, &io);
1344 CHECK_STATUS(status, NT_STATUS_OK);
1346 start = time_mono(NULL);
1347 io.lockx.in.timeout = t;
1348 req = smb_raw_lock_send(cli->tree, &io);
1349 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1350 "Failed to setup timed lock (%s)\n", __location__));
1352 io.lockx.in.timeout = 0;
1353 lock[0].offset = 105;
1354 lock[0].count = 10;
1355 status = smb_raw_lock(cli->tree, &io);
1356 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1358 status = smbcli_request_simple_recv(req);
1359 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1361 delay = t / 1000;
1362 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1363 delay /= 2;
1366 torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
1367 "lock comes back to early timeout[%d] delay[%d]"
1368 "(%s)\n", t, delay, __location__));
1370 status = smb_raw_lock(cli->tree, &io);
1371 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1373 smbcli_close(cli->tree, fnum);
1374 fname = BASEDIR "\\test3.txt";
1375 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1376 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1377 "Failed to reopen %s - %s\n",
1378 fname, smbcli_errstr(cli->tree)));
1380 io.lockx.level = RAW_LOCK_LOCKX;
1381 io.lockx.in.file.fnum = fnum;
1382 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1383 io.lockx.in.timeout = 0;
1384 io.lockx.in.ulock_cnt = 0;
1385 io.lockx.in.lock_cnt = 1;
1386 lock[0].pid = cli->session->pid;
1387 lock[0].offset = 100;
1388 lock[0].count = 10;
1389 io.lockx.in.locks = &lock[0];
1390 status = smb_raw_lock(cli->tree, &io);
1391 CHECK_STATUS(status, NT_STATUS_OK);
1393 start = time_mono(NULL);
1394 io.lockx.in.timeout = t;
1395 req = smb_raw_lock_send(cli->tree, &io);
1396 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1397 "Failed to setup timed lock (%s)\n", __location__));
1399 io.lockx.in.timeout = 0;
1400 lock[0].offset = 105;
1401 lock[0].count = 10;
1402 status = smb_raw_lock(cli->tree, &io);
1403 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1405 status = smbcli_request_simple_recv(req);
1406 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1408 delay = t / 1000;
1409 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1410 delay /= 2;
1413 torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
1414 "lock comes back to early timeout[%d] delay[%d]"
1415 "(%s)\n", t, delay, __location__));
1417 lock[0].offset = 100;
1418 lock[0].count = 10;
1419 status = smb_raw_lock(cli->tree, &io);
1420 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1422 smbcli_close(cli->tree, fnum);
1423 fname = BASEDIR "\\test4.txt";
1424 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1425 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1426 "Failed to reopen %s - %s\n",
1427 fname, smbcli_errstr(cli->tree)));
1429 io.lockx.level = RAW_LOCK_LOCKX;
1430 io.lockx.in.file.fnum = fnum;
1431 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1432 io.lockx.in.timeout = 0;
1433 io.lockx.in.ulock_cnt = 0;
1434 io.lockx.in.lock_cnt = 1;
1435 lock[0].pid = cli->session->pid;
1436 lock[0].offset = 100;
1437 lock[0].count = 10;
1438 io.lockx.in.locks = &lock[0];
1439 status = smb_raw_lock(cli->tree, &io);
1440 CHECK_STATUS(status, NT_STATUS_OK);
1442 start = time_mono(NULL);
1443 io.lockx.in.timeout = t;
1444 req = smb_raw_lock_send(cli->tree, &io);
1445 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1446 "Failed to setup timed lock (%s)\n", __location__));
1448 io.lockx.in.timeout = 0;
1449 status = smb_raw_lock(cli->tree, &io);
1450 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1452 status = smbcli_request_simple_recv(req);
1453 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1455 delay = t / 1000;
1456 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1457 delay /= 2;
1460 torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
1461 "lock comes back to early timeout[%d] delay[%d]"
1462 "(%s)\n", t, delay, __location__));
1464 status = smb_raw_lock(cli->tree, &io);
1465 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1467 done:
1468 smb_raw_exit(cli->session);
1469 smbcli_deltree(cli->tree, BASEDIR);
1470 return ret;
1475 test LOCKING_ANDX_CHANGE_LOCKTYPE
1477 static bool test_changetype(struct torture_context *tctx,
1478 struct smbcli_state *cli)
1480 union smb_lock io;
1481 struct smb_lock_entry lock[2];
1482 NTSTATUS status;
1483 bool ret = true;
1484 int fnum;
1485 uint8_t c = 0;
1486 const char *fname = BASEDIR "\\test.txt";
1488 if (!torture_setup_dir(cli, BASEDIR)) {
1489 return false;
1492 torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1493 io.generic.level = RAW_LOCK_LOCKX;
1495 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1496 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1497 "Failed to create %s - %s\n",
1498 fname, smbcli_errstr(cli->tree)));
1500 io.lockx.level = RAW_LOCK_LOCKX;
1501 io.lockx.in.file.fnum = fnum;
1502 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1503 io.lockx.in.timeout = 0;
1504 io.lockx.in.ulock_cnt = 0;
1505 io.lockx.in.lock_cnt = 1;
1506 lock[0].pid = cli->session->pid;
1507 lock[0].offset = 100;
1508 lock[0].count = 10;
1509 io.lockx.in.locks = &lock[0];
1510 status = smb_raw_lock(cli->tree, &io);
1511 CHECK_STATUS(status, NT_STATUS_OK);
1513 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1514 torture_result(tctx, TORTURE_FAIL,
1515 "allowed write on read locked region (%s)\n", __location__);
1516 ret = false;
1517 goto done;
1520 /* windows server don't seem to support this */
1521 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1522 status = smb_raw_lock(cli->tree, &io);
1523 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1525 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1526 torture_result(tctx, TORTURE_FAIL,
1527 "allowed write after lock change (%s)\n", __location__);
1528 ret = false;
1529 goto done;
1532 done:
1533 smbcli_close(cli->tree, fnum);
1534 smb_raw_exit(cli->session);
1535 smbcli_deltree(cli->tree, BASEDIR);
1536 return ret;
1539 struct double_lock_test {
1540 struct smb_lock_entry lock1;
1541 struct smb_lock_entry lock2;
1542 NTSTATUS exp_status;
1546 * Tests zero byte locks.
1548 static struct double_lock_test zero_byte_tests[] = {
1549 /* {pid, offset, count}, {pid, offset, count}, status */
1551 /** First, takes a zero byte lock at offset 10. Then:
1552 * - Taking 0 byte lock at 10 should succeed.
1553 * - Taking 1 byte locks at 9,10,11 should succeed.
1554 * - Taking 2 byte lock at 9 should fail.
1555 * - Taking 2 byte lock at 10 should succeed.
1556 * - Taking 3 byte lock at 9 should fail.
1558 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1559 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
1560 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1561 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1562 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
1563 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1564 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
1566 /** Same, but opposite order. */
1567 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1568 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
1569 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1570 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1571 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1572 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1573 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1575 /** Zero zero case. */
1576 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
1579 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
1581 union smb_lock io;
1582 NTSTATUS status;
1583 bool ret = true;
1584 int fnum, i;
1585 const char *fname = BASEDIR "\\zero.txt";
1587 torture_comment(tctx, "Testing zero length byte range locks:\n");
1589 if (!torture_setup_dir(cli, BASEDIR)) {
1590 return false;
1593 io.generic.level = RAW_LOCK_LOCKX;
1595 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1596 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1597 "Failed to create %s - %s\n",
1598 fname, smbcli_errstr(cli->tree)));
1600 /* Setup initial parameters */
1601 io.lockx.level = RAW_LOCK_LOCKX;
1602 io.lockx.in.file.fnum = fnum;
1603 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1604 io.lockx.in.timeout = 0;
1606 /* Try every combination of locks in zero_byte_tests. The first lock is
1607 * assumed to succeed. The second lock may contend, depending on the
1608 * expected status. */
1609 for (i = 0;
1610 i < ARRAY_SIZE(zero_byte_tests);
1611 i++) {
1612 torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1613 zero_byte_tests[i].lock1.pid,
1614 (unsigned long long) zero_byte_tests[i].lock1.offset,
1615 (unsigned long long) zero_byte_tests[i].lock1.count,
1616 zero_byte_tests[i].lock2.pid,
1617 (unsigned long long) zero_byte_tests[i].lock2.offset,
1618 (unsigned long long) zero_byte_tests[i].lock2.count,
1619 nt_errstr(zero_byte_tests[i].exp_status));
1621 /* Lock both locks. */
1622 io.lockx.in.ulock_cnt = 0;
1623 io.lockx.in.lock_cnt = 1;
1625 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1626 &zero_byte_tests[i].lock1);
1627 status = smb_raw_lock(cli->tree, &io);
1628 CHECK_STATUS(status, NT_STATUS_OK);
1630 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1631 &zero_byte_tests[i].lock2);
1632 status = smb_raw_lock(cli->tree, &io);
1634 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1635 NT_STATUS_LOCK_NOT_GRANTED)) {
1636 /* Allow either of the failure messages and keep going
1637 * if we see the wrong status. */
1638 CHECK_STATUS_OR_CONT(status,
1639 NT_STATUS_LOCK_NOT_GRANTED,
1640 NT_STATUS_FILE_LOCK_CONFLICT);
1642 } else {
1643 CHECK_STATUS_CONT(status,
1644 zero_byte_tests[i].exp_status);
1647 /* Unlock both locks. */
1648 io.lockx.in.ulock_cnt = 1;
1649 io.lockx.in.lock_cnt = 0;
1651 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1652 status = smb_raw_lock(cli->tree, &io);
1653 CHECK_STATUS(status, NT_STATUS_OK);
1656 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1657 &zero_byte_tests[i].lock1);
1658 status = smb_raw_lock(cli->tree, &io);
1659 CHECK_STATUS(status, NT_STATUS_OK);
1662 done:
1663 smbcli_close(cli->tree, fnum);
1664 smb_raw_exit(cli->session);
1665 smbcli_deltree(cli->tree, BASEDIR);
1666 return ret;
1669 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1671 union smb_lock io;
1672 NTSTATUS status;
1673 bool ret = true;
1674 int fnum1, fnum2;
1675 const char *fname = BASEDIR "\\unlock.txt";
1676 struct smb_lock_entry lock1;
1677 struct smb_lock_entry lock2;
1679 torture_comment(tctx, "Testing LOCKX unlock:\n");
1681 if (!torture_setup_dir(cli, BASEDIR)) {
1682 return false;
1685 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1686 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1687 "Failed to create %s - %s\n",
1688 fname, smbcli_errstr(cli->tree)));
1690 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1691 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
1692 "Failed to create %s - %s\n",
1693 fname, smbcli_errstr(cli->tree)));
1695 /* Setup initial parameters */
1696 io.lockx.level = RAW_LOCK_LOCKX;
1697 io.lockx.in.timeout = 0;
1699 lock1.pid = cli->session->pid;
1700 lock1.offset = 0;
1701 lock1.count = 10;
1702 lock2.pid = cli->session->pid - 1;
1703 lock2.offset = 0;
1704 lock2.count = 10;
1707 * Take exclusive lock, then unlock it with a shared-unlock call.
1709 torture_comment(tctx, " taking exclusive lock.\n");
1710 io.lockx.in.ulock_cnt = 0;
1711 io.lockx.in.lock_cnt = 1;
1712 io.lockx.in.mode = 0;
1713 io.lockx.in.file.fnum = fnum1;
1714 io.lockx.in.locks = &lock1;
1715 status = smb_raw_lock(cli->tree, &io);
1716 CHECK_STATUS(status, NT_STATUS_OK);
1718 torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
1719 io.lockx.in.ulock_cnt = 1;
1720 io.lockx.in.lock_cnt = 0;
1721 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1722 io.lockx.in.file.fnum = fnum1;
1723 io.lockx.in.locks = &lock1;
1724 status = smb_raw_lock(cli->tree, &io);
1725 CHECK_STATUS(status, NT_STATUS_OK);
1727 torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
1728 io.lockx.in.ulock_cnt = 0;
1729 io.lockx.in.lock_cnt = 1;
1730 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1731 io.lockx.in.file.fnum = fnum2;
1732 io.lockx.in.locks = &lock2;
1733 status = smb_raw_lock(cli->tree, &io);
1734 CHECK_STATUS(status, NT_STATUS_OK);
1737 * Unlock a shared lock with an exclusive-unlock call.
1739 torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
1740 io.lockx.in.ulock_cnt = 1;
1741 io.lockx.in.lock_cnt = 0;
1742 io.lockx.in.mode = 0;
1743 io.lockx.in.file.fnum = fnum2;
1744 io.lockx.in.locks = &lock2;
1745 status = smb_raw_lock(cli->tree, &io);
1746 CHECK_STATUS(status, NT_STATUS_OK);
1748 torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
1749 io.lockx.in.ulock_cnt = 0;
1750 io.lockx.in.lock_cnt = 1;
1751 io.lockx.in.mode = 0;
1752 io.lockx.in.file.fnum = fnum1;
1753 io.lockx.in.locks = &lock1;
1754 status = smb_raw_lock(cli->tree, &io);
1755 CHECK_STATUS(status, NT_STATUS_OK);
1757 /* cleanup */
1758 io.lockx.in.ulock_cnt = 1;
1759 io.lockx.in.lock_cnt = 0;
1760 status = smb_raw_lock(cli->tree, &io);
1761 CHECK_STATUS(status, NT_STATUS_OK);
1764 * Test unlocking of 0-byte locks.
1767 torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
1768 "always unlocks the exclusive first.\n");
1769 lock1.pid = cli->session->pid;
1770 lock1.offset = 10;
1771 lock1.count = 0;
1772 lock2.pid = cli->session->pid;
1773 lock2.offset = 5;
1774 lock2.count = 10;
1775 io.lockx.in.ulock_cnt = 0;
1776 io.lockx.in.lock_cnt = 1;
1777 io.lockx.in.file.fnum = fnum1;
1778 io.lockx.in.locks = &lock1;
1780 /* lock 0-byte shared
1781 * Note: Order of the shared/exclusive locks doesn't matter. */
1782 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1783 status = smb_raw_lock(cli->tree, &io);
1784 CHECK_STATUS(status, NT_STATUS_OK);
1786 /* lock 0-byte exclusive */
1787 io.lockx.in.mode = 0;
1788 status = smb_raw_lock(cli->tree, &io);
1789 CHECK_STATUS(status, NT_STATUS_OK);
1791 /* test contention */
1792 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1793 io.lockx.in.locks = &lock2;
1794 io.lockx.in.file.fnum = fnum2;
1795 status = smb_raw_lock(cli->tree, &io);
1796 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1797 NT_STATUS_FILE_LOCK_CONFLICT);
1799 /* unlock */
1800 io.lockx.in.ulock_cnt = 1;
1801 io.lockx.in.lock_cnt = 0;
1802 io.lockx.in.file.fnum = fnum1;
1803 io.lockx.in.locks = &lock1;
1804 status = smb_raw_lock(cli->tree, &io);
1805 CHECK_STATUS(status, NT_STATUS_OK);
1807 /* test - can we take a shared lock? */
1808 io.lockx.in.ulock_cnt = 0;
1809 io.lockx.in.lock_cnt = 1;
1810 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1811 io.lockx.in.file.fnum = fnum2;
1812 io.lockx.in.locks = &lock2;
1813 status = smb_raw_lock(cli->tree, &io);
1815 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1816 * new to Win7, it succeeds in WinXP too), until I can come to a
1817 * resolution as to whether Samba should support this or not. There is
1818 * code to preference unlocking exclusive locks before shared locks,
1819 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1820 if (TARGET_IS_SAMBA3(tctx)) {
1821 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1822 NT_STATUS_FILE_LOCK_CONFLICT);
1823 } else {
1824 CHECK_STATUS(status, NT_STATUS_OK);
1827 /* cleanup */
1828 io.lockx.in.ulock_cnt = 1;
1829 io.lockx.in.lock_cnt = 0;
1830 status = smb_raw_lock(cli->tree, &io);
1832 /* XXX Same as above. */
1833 if (TARGET_IS_SAMBA3(tctx)) {
1834 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1835 } else {
1836 CHECK_STATUS(status, NT_STATUS_OK);
1839 io.lockx.in.file.fnum = fnum1;
1840 io.lockx.in.locks = &lock1;
1841 status = smb_raw_lock(cli->tree, &io);
1842 CHECK_STATUS(status, NT_STATUS_OK);
1844 done:
1845 smbcli_close(cli->tree, fnum1);
1846 smbcli_close(cli->tree, fnum2);
1847 smb_raw_exit(cli->session);
1848 smbcli_deltree(cli->tree, BASEDIR);
1849 return ret;
1852 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1854 union smb_lock io;
1855 NTSTATUS status;
1856 bool ret = true;
1857 int fnum1;
1858 const char *fname = BASEDIR "\\unlock_multiple.txt";
1859 struct smb_lock_entry lock1;
1860 struct smb_lock_entry lock2;
1861 struct smb_lock_entry locks[2];
1863 torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
1865 if (!torture_setup_dir(cli, BASEDIR)) {
1866 return false;
1869 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1870 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1871 "Failed to create %s - %s\n",
1872 fname, smbcli_errstr(cli->tree)));
1874 /* Setup initial parameters */
1875 io.lockx.level = RAW_LOCK_LOCKX;
1876 io.lockx.in.timeout = 0;
1878 lock1.pid = cli->session->pid;
1879 lock1.offset = 0;
1880 lock1.count = 10;
1881 lock2.pid = cli->session->pid;
1882 lock2.offset = 10;
1883 lock2.count = 10;
1885 locks[0] = lock1;
1886 locks[1] = lock2;
1888 io.lockx.in.file.fnum = fnum1;
1889 io.lockx.in.mode = 0; /* exclusive */
1891 /** Test1: Take second lock, but not first. */
1892 torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
1893 "unlocked. \n");
1895 io.lockx.in.ulock_cnt = 0;
1896 io.lockx.in.lock_cnt = 1;
1897 io.lockx.in.locks = &lock2;
1898 status = smb_raw_lock(cli->tree, &io);
1899 CHECK_STATUS(status, NT_STATUS_OK);
1901 /* Try to unlock both locks. */
1902 io.lockx.in.ulock_cnt = 2;
1903 io.lockx.in.lock_cnt = 0;
1904 io.lockx.in.locks = locks;
1906 status = smb_raw_lock(cli->tree, &io);
1907 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1909 /* Second lock should not be unlocked. */
1910 io.lockx.in.ulock_cnt = 0;
1911 io.lockx.in.lock_cnt = 1;
1912 io.lockx.in.locks = &lock2;
1913 status = smb_raw_lock(cli->tree, &io);
1914 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1916 /* cleanup */
1917 io.lockx.in.ulock_cnt = 1;
1918 io.lockx.in.lock_cnt = 0;
1919 io.lockx.in.locks = &lock2;
1920 status = smb_raw_lock(cli->tree, &io);
1921 CHECK_STATUS(status, NT_STATUS_OK);
1923 /** Test2: Take first lock, but not second. */
1924 torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
1925 "unlocked.\n");
1927 io.lockx.in.ulock_cnt = 0;
1928 io.lockx.in.lock_cnt = 1;
1929 io.lockx.in.locks = &lock1;
1930 status = smb_raw_lock(cli->tree, &io);
1931 CHECK_STATUS(status, NT_STATUS_OK);
1933 /* Try to unlock both locks. */
1934 io.lockx.in.ulock_cnt = 2;
1935 io.lockx.in.lock_cnt = 0;
1936 io.lockx.in.locks = locks;
1938 status = smb_raw_lock(cli->tree, &io);
1939 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1941 /* First lock should be unlocked. */
1942 io.lockx.in.ulock_cnt = 0;
1943 io.lockx.in.lock_cnt = 1;
1944 io.lockx.in.locks = &lock1;
1945 status = smb_raw_lock(cli->tree, &io);
1946 CHECK_STATUS(status, NT_STATUS_OK);
1948 /* cleanup */
1949 io.lockx.in.ulock_cnt = 1;
1950 io.lockx.in.lock_cnt = 0;
1951 io.lockx.in.locks = &lock1;
1952 status = smb_raw_lock(cli->tree, &io);
1953 CHECK_STATUS(status, NT_STATUS_OK);
1955 /* Test3: Request 2 locks, second will contend. What happens to the
1956 * first? */
1957 torture_comment(tctx, " request 2 locks, second one will contend. "
1958 "Expect both to fail.\n");
1960 /* Lock the second range */
1961 io.lockx.in.ulock_cnt = 0;
1962 io.lockx.in.lock_cnt = 1;
1963 io.lockx.in.locks = &lock2;
1964 status = smb_raw_lock(cli->tree, &io);
1965 CHECK_STATUS(status, NT_STATUS_OK);
1967 /* Request both locks */
1968 io.lockx.in.ulock_cnt = 0;
1969 io.lockx.in.lock_cnt = 2;
1970 io.lockx.in.locks = locks;
1972 status = smb_raw_lock(cli->tree, &io);
1973 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1975 /* First lock should be unlocked. */
1976 io.lockx.in.ulock_cnt = 0;
1977 io.lockx.in.lock_cnt = 1;
1978 io.lockx.in.locks = &lock1;
1979 status = smb_raw_lock(cli->tree, &io);
1980 CHECK_STATUS(status, NT_STATUS_OK);
1982 /* cleanup */
1983 io.lockx.in.ulock_cnt = 2;
1984 io.lockx.in.lock_cnt = 0;
1985 io.lockx.in.locks = locks;
1986 status = smb_raw_lock(cli->tree, &io);
1987 CHECK_STATUS(status, NT_STATUS_OK);
1989 /* Test4: Request unlock and lock. The lock contends, is the unlock
1990 * then re-locked? */
1991 torture_comment(tctx, " request unlock and lock, second one will "
1992 "contend. Expect the unlock to succeed.\n");
1994 /* Lock both ranges */
1995 io.lockx.in.ulock_cnt = 0;
1996 io.lockx.in.lock_cnt = 2;
1997 io.lockx.in.locks = locks;
1998 status = smb_raw_lock(cli->tree, &io);
1999 CHECK_STATUS(status, NT_STATUS_OK);
2001 /* Attempt to unlock the first range and lock the second */
2002 io.lockx.in.ulock_cnt = 1;
2003 io.lockx.in.lock_cnt = 1;
2004 io.lockx.in.locks = locks;
2005 status = smb_raw_lock(cli->tree, &io);
2006 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
2008 /* The first lock should've been unlocked */
2009 io.lockx.in.ulock_cnt = 0;
2010 io.lockx.in.lock_cnt = 1;
2011 io.lockx.in.locks = &lock1;
2012 status = smb_raw_lock(cli->tree, &io);
2013 CHECK_STATUS(status, NT_STATUS_OK);
2015 /* cleanup */
2016 io.lockx.in.ulock_cnt = 2;
2017 io.lockx.in.lock_cnt = 0;
2018 io.lockx.in.locks = locks;
2019 status = smb_raw_lock(cli->tree, &io);
2020 CHECK_STATUS(status, NT_STATUS_OK);
2022 done:
2023 smbcli_close(cli->tree, fnum1);
2024 smb_raw_exit(cli->session);
2025 smbcli_deltree(cli->tree, BASEDIR);
2026 return ret;
2030 * torture_locktest5 covers stacking pretty well, but its missing two tests:
2031 * - stacking an exclusive on top of shared fails
2032 * - stacking two exclusives fail
2034 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
2036 union smb_lock io;
2037 NTSTATUS status;
2038 bool ret = true;
2039 int fnum1;
2040 const char *fname = BASEDIR "\\stacking.txt";
2041 struct smb_lock_entry lock1;
2042 struct smb_lock_entry lock2;
2044 torture_comment(tctx, "Testing stacking:\n");
2046 if (!torture_setup_dir(cli, BASEDIR)) {
2047 return false;
2050 io.generic.level = RAW_LOCK_LOCKX;
2052 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2053 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
2054 "Failed to create %s - %s\n",
2055 fname, smbcli_errstr(cli->tree)));
2057 /* Setup initial parameters */
2058 io.lockx.level = RAW_LOCK_LOCKX;
2059 io.lockx.in.timeout = 0;
2061 lock1.pid = cli->session->pid;
2062 lock1.offset = 0;
2063 lock1.count = 10;
2064 lock2.pid = cli->session->pid - 1;
2065 lock2.offset = 0;
2066 lock2.count = 10;
2069 * Try to take a shared lock, then stack an exclusive.
2071 torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
2072 io.lockx.in.file.fnum = fnum1;
2073 io.lockx.in.locks = &lock1;
2075 io.lockx.in.ulock_cnt = 0;
2076 io.lockx.in.lock_cnt = 1;
2077 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
2078 status = smb_raw_lock(cli->tree, &io);
2079 CHECK_STATUS(status, NT_STATUS_OK);
2081 io.lockx.in.ulock_cnt = 0;
2082 io.lockx.in.lock_cnt = 1;
2083 io.lockx.in.mode = 0;
2084 status = smb_raw_lock(cli->tree, &io);
2085 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
2086 NT_STATUS_FILE_LOCK_CONFLICT);
2088 /* cleanup */
2089 io.lockx.in.ulock_cnt = 1;
2090 io.lockx.in.lock_cnt = 0;
2091 status = smb_raw_lock(cli->tree, &io);
2092 CHECK_STATUS(status, NT_STATUS_OK);
2095 * Prove that two exclusive locks do not stack.
2097 torture_comment(tctx, " two exclusive locks do not stack.\n");
2098 io.lockx.in.ulock_cnt = 0;
2099 io.lockx.in.lock_cnt = 1;
2100 io.lockx.in.mode = 0;
2101 status = smb_raw_lock(cli->tree, &io);
2102 CHECK_STATUS(status, NT_STATUS_OK);
2103 status = smb_raw_lock(cli->tree, &io);
2104 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
2105 NT_STATUS_FILE_LOCK_CONFLICT);
2107 /* cleanup */
2108 io.lockx.in.ulock_cnt = 1;
2109 io.lockx.in.lock_cnt = 0;
2110 status = smb_raw_lock(cli->tree, &io);
2111 CHECK_STATUS(status, NT_STATUS_OK);
2113 done:
2114 smbcli_close(cli->tree, fnum1);
2115 smb_raw_exit(cli->session);
2116 smbcli_deltree(cli->tree, BASEDIR);
2117 return ret;
2121 * Test how 0-byte read requests contend with byte range locks
2123 static bool test_zerobyteread(struct torture_context *tctx,
2124 struct smbcli_state *cli)
2126 union smb_lock io;
2127 union smb_read rd;
2128 NTSTATUS status;
2129 bool ret = true;
2130 int fnum1, fnum2;
2131 const char *fname = BASEDIR "\\zerobyteread.txt";
2132 struct smb_lock_entry lock1;
2133 uint8_t c = 1;
2135 if (!torture_setup_dir(cli, BASEDIR)) {
2136 return false;
2139 io.generic.level = RAW_LOCK_LOCKX;
2141 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2142 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
2143 "Failed to create %s - %s\n",
2144 fname, smbcli_errstr(cli->tree)));
2146 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2147 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
2148 "Failed to create %s - %s\n",
2149 fname, smbcli_errstr(cli->tree)));
2151 /* Setup initial parameters */
2152 io.lockx.level = RAW_LOCK_LOCKX;
2153 io.lockx.in.timeout = 0;
2155 lock1.pid = cli->session->pid;
2156 lock1.offset = 0;
2157 lock1.count = 10;
2159 ZERO_STRUCT(rd);
2160 rd.readx.level = RAW_READ_READX;
2162 torture_comment(tctx, "Testing zero byte read on lock range:\n");
2164 /* Take an exclusive lock */
2165 torture_comment(tctx, " taking exclusive lock.\n");
2166 io.lockx.in.ulock_cnt = 0;
2167 io.lockx.in.lock_cnt = 1;
2168 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2169 io.lockx.in.file.fnum = fnum1;
2170 io.lockx.in.locks = &lock1;
2171 status = smb_raw_lock(cli->tree, &io);
2172 CHECK_STATUS(status, NT_STATUS_OK);
2174 /* Try a zero byte read */
2175 torture_comment(tctx, " reading 0 bytes.\n");
2176 rd.readx.in.file.fnum = fnum2;
2177 rd.readx.in.offset = 5;
2178 rd.readx.in.mincnt = 0;
2179 rd.readx.in.maxcnt = 0;
2180 rd.readx.in.remaining = 0;
2181 rd.readx.in.read_for_execute = false;
2182 rd.readx.out.data = &c;
2183 status = smb_raw_read(cli->tree, &rd);
2184 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2185 "zero byte read did not return 0 bytes");
2186 CHECK_STATUS(status, NT_STATUS_OK);
2188 /* Unlock lock */
2189 io.lockx.in.ulock_cnt = 1;
2190 io.lockx.in.lock_cnt = 0;
2191 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2192 io.lockx.in.file.fnum = fnum1;
2193 io.lockx.in.locks = &lock1;
2194 status = smb_raw_lock(cli->tree, &io);
2195 CHECK_STATUS(status, NT_STATUS_OK);
2197 torture_comment(tctx, "Testing zero byte read on zero byte lock "
2198 "range:\n");
2200 /* Take an exclusive lock */
2201 torture_comment(tctx, " taking exclusive 0-byte lock.\n");
2202 io.lockx.in.ulock_cnt = 0;
2203 io.lockx.in.lock_cnt = 1;
2204 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2205 io.lockx.in.file.fnum = fnum1;
2206 io.lockx.in.locks = &lock1;
2207 lock1.offset = 5;
2208 lock1.count = 0;
2209 status = smb_raw_lock(cli->tree, &io);
2210 CHECK_STATUS(status, NT_STATUS_OK);
2212 /* Try a zero byte read before the lock */
2213 torture_comment(tctx, " reading 0 bytes before the lock.\n");
2214 rd.readx.in.file.fnum = fnum2;
2215 rd.readx.in.offset = 4;
2216 rd.readx.in.mincnt = 0;
2217 rd.readx.in.maxcnt = 0;
2218 rd.readx.in.remaining = 0;
2219 rd.readx.in.read_for_execute = false;
2220 rd.readx.out.data = &c;
2221 status = smb_raw_read(cli->tree, &rd);
2222 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2223 "zero byte read did not return 0 bytes");
2224 CHECK_STATUS(status, NT_STATUS_OK);
2226 /* Try a zero byte read on the lock */
2227 torture_comment(tctx, " reading 0 bytes on the lock.\n");
2228 rd.readx.in.file.fnum = fnum2;
2229 rd.readx.in.offset = 5;
2230 rd.readx.in.mincnt = 0;
2231 rd.readx.in.maxcnt = 0;
2232 rd.readx.in.remaining = 0;
2233 rd.readx.in.read_for_execute = false;
2234 rd.readx.out.data = &c;
2235 status = smb_raw_read(cli->tree, &rd);
2236 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2237 "zero byte read did not return 0 bytes");
2238 CHECK_STATUS(status, NT_STATUS_OK);
2240 /* Try a zero byte read after the lock */
2241 torture_comment(tctx, " reading 0 bytes after the lock.\n");
2242 rd.readx.in.file.fnum = fnum2;
2243 rd.readx.in.offset = 6;
2244 rd.readx.in.mincnt = 0;
2245 rd.readx.in.maxcnt = 0;
2246 rd.readx.in.remaining = 0;
2247 rd.readx.in.read_for_execute = false;
2248 rd.readx.out.data = &c;
2249 status = smb_raw_read(cli->tree, &rd);
2250 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2251 "zero byte read did not return 0 bytes");
2252 CHECK_STATUS(status, NT_STATUS_OK);
2254 /* Unlock lock */
2255 io.lockx.in.ulock_cnt = 1;
2256 io.lockx.in.lock_cnt = 0;
2257 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2258 io.lockx.in.file.fnum = fnum1;
2259 io.lockx.in.locks = &lock1;
2260 status = smb_raw_lock(cli->tree, &io);
2261 CHECK_STATUS(status, NT_STATUS_OK);
2263 done:
2264 smbcli_close(cli->tree, fnum1);
2265 smbcli_close(cli->tree, fnum2);
2266 smb_raw_exit(cli->session);
2267 smbcli_deltree(cli->tree, BASEDIR);
2268 return ret;
2272 basic testing of lock calls
2274 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
2276 struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
2278 torture_suite_add_1smb_test(suite, "lockx", test_lockx);
2279 torture_suite_add_1smb_test(suite, "lock", test_lock);
2280 torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
2281 torture_suite_add_1smb_test(suite, "async", test_async);
2282 torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
2283 torture_suite_add_1smb_test(suite, "changetype", test_changetype);
2285 torture_suite_add_1smb_test(suite, "stacking", test_stacking);
2286 torture_suite_add_1smb_test(suite, "unlock", test_unlock);
2287 torture_suite_add_1smb_test(suite, "multiple_unlock",
2288 test_multiple_unlock);
2289 torture_suite_add_1smb_test(suite, "zerobytelocks",
2290 test_zerobytelocks);
2291 torture_suite_add_1smb_test(suite, "zerobyteread",
2292 test_zerobyteread);
2294 return suite;