s3:librpc: add smbXsrv.idl
[Samba/gebeck_regimport.git] / source4 / torture / raw / lock.c
blob0092a94c12329082aa0ca23a09a55aac0a0bb461
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"
32 #include "torture/raw/proto.h"
34 #define CHECK_STATUS(status, correct) do { \
35 if (!NT_STATUS_EQUAL(status, correct)) { \
36 torture_result(tctx, TORTURE_FAIL, \
37 "(%s) Incorrect status %s - should be %s\n", \
38 __location__, nt_errstr(status), nt_errstr(correct)); \
39 ret = false; \
40 goto done; \
41 }} while (0)
43 #define CHECK_STATUS_CONT(status, correct) do { \
44 if (!NT_STATUS_EQUAL(status, correct)) { \
45 torture_result(tctx, TORTURE_FAIL, \
46 "(%s) Incorrect status %s - should be %s\n", \
47 __location__, nt_errstr(status), nt_errstr(correct)); \
48 ret = false; \
49 }} while (0)
51 #define CHECK_STATUS_OR(status, correct1, correct2) do { \
52 if ((!NT_STATUS_EQUAL(status, correct1)) && \
53 (!NT_STATUS_EQUAL(status, correct2))) { \
54 torture_result(tctx, TORTURE_FAIL, \
55 "(%s) Incorrect status %s - should be %s or %s\n", \
56 __location__, nt_errstr(status), nt_errstr(correct1), \
57 nt_errstr(correct2)); \
58 ret = false; \
59 goto done; \
60 }} while (0)
62 #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
63 if ((!NT_STATUS_EQUAL(status, correct1)) && \
64 (!NT_STATUS_EQUAL(status, correct2))) { \
65 torture_result(tctx, TORTURE_FAIL, \
66 "(%s) Incorrect status %s - should be %s or %s\n", \
67 __location__, nt_errstr(status), nt_errstr(correct1), \
68 nt_errstr(correct2)); \
69 ret = false; \
70 }} while (0)
71 #define BASEDIR "\\testlock"
73 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
74 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
75 #define TARGET_IS_WINDOWS(_tctx) \
76 ((torture_setting_bool(_tctx, "w2k3", false)) || \
77 (torture_setting_bool(_tctx, "w2k8", false)) || \
78 (torture_setting_bool(_tctx, "win7", false)))
79 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
80 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
82 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
83 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
84 #define TARGET_SUPPORTS_SMBEXIT(_tctx) \
85 (torture_setting_bool(_tctx, "smbexit_pdu_support", true))
86 #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
87 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
88 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
89 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
90 #define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \
91 (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true))
93 test SMBlock and SMBunlock ops
95 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
97 union smb_lock io;
98 NTSTATUS status;
99 bool ret = true;
100 int fnum;
101 const char *fname = BASEDIR "\\test.txt";
103 if (!TARGET_SUPPORTS_SMBLOCK(tctx))
104 torture_skip(tctx, "Target does not support the SMBlock PDU");
106 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
108 torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
109 io.generic.level = RAW_LOCK_LOCK;
111 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
112 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
113 "Failed to create %s - %s\n",
114 fname, smbcli_errstr(cli->tree)));
116 torture_comment(tctx, "Trying 0/0 lock\n");
117 io.lock.level = RAW_LOCK_LOCK;
118 io.lock.in.file.fnum = fnum;
119 io.lock.in.count = 0;
120 io.lock.in.offset = 0;
121 status = smb_raw_lock(cli->tree, &io);
122 CHECK_STATUS(status, NT_STATUS_OK);
123 cli->session->pid++;
124 status = smb_raw_lock(cli->tree, &io);
125 CHECK_STATUS(status, NT_STATUS_OK);
126 cli->session->pid--;
127 io.lock.level = RAW_LOCK_UNLOCK;
128 status = smb_raw_lock(cli->tree, &io);
129 CHECK_STATUS(status, NT_STATUS_OK);
131 torture_comment(tctx, "Trying 0/1 lock\n");
132 io.lock.level = RAW_LOCK_LOCK;
133 io.lock.in.file.fnum = fnum;
134 io.lock.in.count = 1;
135 io.lock.in.offset = 0;
136 status = smb_raw_lock(cli->tree, &io);
137 CHECK_STATUS(status, NT_STATUS_OK);
138 cli->session->pid++;
139 status = smb_raw_lock(cli->tree, &io);
140 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
141 cli->session->pid--;
142 io.lock.level = RAW_LOCK_UNLOCK;
143 status = smb_raw_lock(cli->tree, &io);
144 CHECK_STATUS(status, NT_STATUS_OK);
145 io.lock.level = RAW_LOCK_UNLOCK;
146 status = smb_raw_lock(cli->tree, &io);
147 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
149 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
150 io.lock.level = RAW_LOCK_LOCK;
151 io.lock.in.file.fnum = fnum;
152 io.lock.in.count = 4000;
153 io.lock.in.offset = 0xEEFFFFFF;
154 status = smb_raw_lock(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_OK);
156 cli->session->pid++;
157 status = smb_raw_lock(cli->tree, &io);
158 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
159 cli->session->pid--;
160 io.lock.level = RAW_LOCK_UNLOCK;
161 status = smb_raw_lock(cli->tree, &io);
162 CHECK_STATUS(status, NT_STATUS_OK);
163 io.lock.level = RAW_LOCK_UNLOCK;
164 status = smb_raw_lock(cli->tree, &io);
165 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
167 torture_comment(tctx, "Trying 0xEF000000 lock\n");
168 io.lock.level = RAW_LOCK_LOCK;
169 io.lock.in.file.fnum = fnum;
170 io.lock.in.count = 4000;
171 io.lock.in.offset = 0xEEFFFFFF;
172 status = smb_raw_lock(cli->tree, &io);
173 CHECK_STATUS(status, NT_STATUS_OK);
174 cli->session->pid++;
175 status = smb_raw_lock(cli->tree, &io);
176 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
177 cli->session->pid--;
178 io.lock.level = RAW_LOCK_UNLOCK;
179 status = smb_raw_lock(cli->tree, &io);
180 CHECK_STATUS(status, NT_STATUS_OK);
181 io.lock.level = RAW_LOCK_UNLOCK;
182 status = smb_raw_lock(cli->tree, &io);
183 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
185 torture_comment(tctx, "Trying max lock\n");
186 io.lock.level = RAW_LOCK_LOCK;
187 io.lock.in.file.fnum = fnum;
188 io.lock.in.count = 4000;
189 io.lock.in.offset = 0xEF000000;
190 status = smb_raw_lock(cli->tree, &io);
191 CHECK_STATUS(status, NT_STATUS_OK);
192 cli->session->pid++;
193 status = smb_raw_lock(cli->tree, &io);
194 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
195 cli->session->pid--;
196 io.lock.level = RAW_LOCK_UNLOCK;
197 status = smb_raw_lock(cli->tree, &io);
198 CHECK_STATUS(status, NT_STATUS_OK);
199 io.lock.level = RAW_LOCK_UNLOCK;
200 status = smb_raw_lock(cli->tree, &io);
201 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
203 torture_comment(tctx, "Trying wrong pid unlock\n");
204 io.lock.level = RAW_LOCK_LOCK;
205 io.lock.in.file.fnum = fnum;
206 io.lock.in.count = 4002;
207 io.lock.in.offset = 10001;
208 status = smb_raw_lock(cli->tree, &io);
209 CHECK_STATUS(status, NT_STATUS_OK);
210 cli->session->pid++;
211 io.lock.level = RAW_LOCK_UNLOCK;
212 status = smb_raw_lock(cli->tree, &io);
213 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
214 cli->session->pid--;
215 status = smb_raw_lock(cli->tree, &io);
216 CHECK_STATUS(status, NT_STATUS_OK);
218 done:
219 smbcli_close(cli->tree, fnum);
220 smb_raw_exit(cli->session);
221 smbcli_deltree(cli->tree, BASEDIR);
222 return ret;
227 test locking&X ops
229 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
231 union smb_lock io;
232 struct smb_lock_entry lock[1];
233 NTSTATUS status;
234 bool ret = true;
235 int fnum;
236 const char *fname = BASEDIR "\\test.txt";
238 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
240 torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
241 io.generic.level = RAW_LOCK_LOCKX;
243 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
244 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
245 "Failed to create %s - %s\n",
246 fname, smbcli_errstr(cli->tree)));
248 io.lockx.level = RAW_LOCK_LOCKX;
249 io.lockx.in.file.fnum = fnum;
250 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
251 io.lockx.in.timeout = 0;
252 io.lockx.in.ulock_cnt = 0;
253 io.lockx.in.lock_cnt = 1;
254 lock[0].pid = cli->session->pid;
255 lock[0].offset = 10;
256 lock[0].count = 1;
257 io.lockx.in.locks = &lock[0];
258 status = smb_raw_lock(cli->tree, &io);
259 CHECK_STATUS(status, NT_STATUS_OK);
262 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
263 io.lockx.in.ulock_cnt = 0;
264 io.lockx.in.lock_cnt = 1;
265 lock[0].count = 4000;
266 lock[0].offset = 0xEEFFFFFF;
267 status = smb_raw_lock(cli->tree, &io);
268 CHECK_STATUS(status, NT_STATUS_OK);
269 lock[0].pid++;
270 status = smb_raw_lock(cli->tree, &io);
271 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
272 lock[0].pid--;
273 io.lockx.in.ulock_cnt = 1;
274 io.lockx.in.lock_cnt = 0;
275 status = smb_raw_lock(cli->tree, &io);
276 CHECK_STATUS(status, NT_STATUS_OK);
277 status = smb_raw_lock(cli->tree, &io);
278 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
280 torture_comment(tctx, "Trying 0xEF000000 lock\n");
281 io.lockx.in.ulock_cnt = 0;
282 io.lockx.in.lock_cnt = 1;
283 lock[0].count = 4000;
284 lock[0].offset = 0xEF000000;
285 status = smb_raw_lock(cli->tree, &io);
286 CHECK_STATUS(status, NT_STATUS_OK);
287 lock[0].pid++;
288 status = smb_raw_lock(cli->tree, &io);
289 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
290 lock[0].pid--;
291 io.lockx.in.ulock_cnt = 1;
292 io.lockx.in.lock_cnt = 0;
293 status = smb_raw_lock(cli->tree, &io);
294 CHECK_STATUS(status, NT_STATUS_OK);
295 status = smb_raw_lock(cli->tree, &io);
296 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
298 torture_comment(tctx, "Trying zero lock\n");
299 io.lockx.in.ulock_cnt = 0;
300 io.lockx.in.lock_cnt = 1;
301 lock[0].count = 0;
302 lock[0].offset = ~0;
303 status = smb_raw_lock(cli->tree, &io);
304 CHECK_STATUS(status, NT_STATUS_OK);
305 lock[0].pid++;
306 status = smb_raw_lock(cli->tree, &io);
307 CHECK_STATUS(status, NT_STATUS_OK);
308 lock[0].pid--;
309 io.lockx.in.ulock_cnt = 1;
310 io.lockx.in.lock_cnt = 0;
311 status = smb_raw_lock(cli->tree, &io);
312 CHECK_STATUS(status, NT_STATUS_OK);
313 status = smb_raw_lock(cli->tree, &io);
314 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
316 torture_comment(tctx, "Trying max lock\n");
317 io.lockx.in.ulock_cnt = 0;
318 io.lockx.in.lock_cnt = 1;
319 lock[0].count = 0;
320 lock[0].offset = ~0;
321 status = smb_raw_lock(cli->tree, &io);
322 CHECK_STATUS(status, NT_STATUS_OK);
323 lock[0].pid++;
324 status = smb_raw_lock(cli->tree, &io);
325 CHECK_STATUS(status, NT_STATUS_OK);
326 lock[0].pid--;
327 io.lockx.in.ulock_cnt = 1;
328 io.lockx.in.lock_cnt = 0;
329 status = smb_raw_lock(cli->tree, &io);
330 CHECK_STATUS(status, NT_STATUS_OK);
331 status = smb_raw_lock(cli->tree, &io);
332 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
334 torture_comment(tctx, "Trying 2^63\n");
335 io.lockx.in.ulock_cnt = 0;
336 io.lockx.in.lock_cnt = 1;
337 lock[0].count = 1;
338 lock[0].offset = 1;
339 lock[0].offset <<= 63;
340 status = smb_raw_lock(cli->tree, &io);
341 CHECK_STATUS(status, NT_STATUS_OK);
342 lock[0].pid++;
343 status = smb_raw_lock(cli->tree, &io);
344 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
345 lock[0].pid--;
346 io.lockx.in.ulock_cnt = 1;
347 io.lockx.in.lock_cnt = 0;
348 status = smb_raw_lock(cli->tree, &io);
349 CHECK_STATUS(status, NT_STATUS_OK);
350 status = smb_raw_lock(cli->tree, &io);
351 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
353 torture_comment(tctx, "Trying 2^63 - 1\n");
354 io.lockx.in.ulock_cnt = 0;
355 io.lockx.in.lock_cnt = 1;
356 lock[0].count = 1;
357 lock[0].offset = 1;
358 lock[0].offset <<= 63;
359 lock[0].offset--;
360 status = smb_raw_lock(cli->tree, &io);
361 CHECK_STATUS(status, NT_STATUS_OK);
362 lock[0].pid++;
363 status = smb_raw_lock(cli->tree, &io);
364 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
365 lock[0].pid--;
366 io.lockx.in.ulock_cnt = 1;
367 io.lockx.in.lock_cnt = 0;
368 status = smb_raw_lock(cli->tree, &io);
369 CHECK_STATUS(status, NT_STATUS_OK);
370 status = smb_raw_lock(cli->tree, &io);
371 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
373 torture_comment(tctx, "Trying max lock 2\n");
374 io.lockx.in.ulock_cnt = 0;
375 io.lockx.in.lock_cnt = 1;
376 lock[0].count = 1;
377 lock[0].offset = ~0;
378 status = smb_raw_lock(cli->tree, &io);
379 CHECK_STATUS(status, NT_STATUS_OK);
380 lock[0].pid++;
381 lock[0].count = 2;
382 status = smb_raw_lock(cli->tree, &io);
383 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
384 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
385 else
386 CHECK_STATUS(status, NT_STATUS_OK);
387 lock[0].pid--;
388 io.lockx.in.ulock_cnt = 1;
389 io.lockx.in.lock_cnt = 0;
390 lock[0].count = 1;
391 status = smb_raw_lock(cli->tree, &io);
393 CHECK_STATUS(status, NT_STATUS_OK);
394 status = smb_raw_lock(cli->tree, &io);
395 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
397 done:
398 smbcli_close(cli->tree, fnum);
399 smb_raw_exit(cli->session);
400 smbcli_deltree(cli->tree, BASEDIR);
401 return ret;
405 test high pid
407 static bool test_pidhigh(struct torture_context *tctx,
408 struct smbcli_state *cli)
410 union smb_lock io;
411 struct smb_lock_entry lock[1];
412 NTSTATUS status;
413 bool ret = true;
414 int fnum;
415 const char *fname = BASEDIR "\\test.txt";
416 uint8_t c = 1;
418 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
420 torture_comment(tctx, "Testing high pid\n");
421 io.generic.level = RAW_LOCK_LOCKX;
423 cli->session->pid = 1;
425 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
426 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
427 "Failed to create %s - %s\n",
428 fname, smbcli_errstr(cli->tree)));
430 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
431 torture_result(tctx, TORTURE_FAIL,
432 "Failed to write 1 byte - %s\n",
433 smbcli_errstr(cli->tree));
434 ret = false;
435 goto done;
438 io.lockx.level = RAW_LOCK_LOCKX;
439 io.lockx.in.file.fnum = fnum;
440 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
441 io.lockx.in.timeout = 0;
442 io.lockx.in.ulock_cnt = 0;
443 io.lockx.in.lock_cnt = 1;
444 lock[0].pid = cli->session->pid;
445 lock[0].offset = 0;
446 lock[0].count = 0xFFFFFFFF;
447 io.lockx.in.locks = &lock[0];
448 status = smb_raw_lock(cli->tree, &io);
449 CHECK_STATUS(status, NT_STATUS_OK);
451 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
452 torture_result(tctx, TORTURE_FAIL,
453 "Failed to read 1 byte - %s\n",
454 smbcli_errstr(cli->tree));
455 ret = false;
456 goto done;
459 cli->session->pid = 2;
461 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
462 torture_result(tctx, TORTURE_FAIL,
463 "pid is incorrect handled for read with lock!\n");
464 ret = false;
465 goto done;
468 cli->session->pid = 0x10001;
470 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
471 torture_result(tctx, TORTURE_FAIL,
472 "High pid is used on this server!\n");
473 ret = false;
474 } else {
475 torture_warning(tctx, "High pid is not used on this server (correct)\n");
478 done:
479 smbcli_close(cli->tree, fnum);
480 smb_raw_exit(cli->session);
481 smbcli_deltree(cli->tree, BASEDIR);
482 return ret;
487 test locking&X async operation
489 static bool test_async(struct torture_context *tctx,
490 struct smbcli_state *cli)
492 struct smbcli_session *session;
493 struct smb_composite_sesssetup setup;
494 struct smbcli_tree *tree;
495 union smb_tcon tcon;
496 const char *host, *share;
497 union smb_lock io;
498 struct smb_lock_entry lock[2];
499 NTSTATUS status;
500 bool ret = true;
501 int fnum;
502 const char *fname = BASEDIR "\\test.txt";
503 time_t t;
504 struct smbcli_request *req, *req2;
505 struct smbcli_session_options options;
507 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
509 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
511 torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
512 io.generic.level = RAW_LOCK_LOCKX;
514 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
515 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
516 "Failed to create %s - %s\n",
517 fname, smbcli_errstr(cli->tree)));
519 io.lockx.level = RAW_LOCK_LOCKX;
520 io.lockx.in.file.fnum = fnum;
521 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
522 io.lockx.in.timeout = 0;
523 io.lockx.in.ulock_cnt = 0;
524 io.lockx.in.lock_cnt = 1;
525 lock[0].pid = cli->session->pid;
526 lock[0].offset = 100;
527 lock[0].count = 10;
528 lock[1].pid = cli->session->pid;
529 lock[1].offset = 110;
530 lock[1].count = 10;
531 io.lockx.in.locks = &lock[0];
532 status = smb_raw_lock(cli->tree, &io);
533 CHECK_STATUS(status, NT_STATUS_OK);
535 t = time_mono(NULL);
537 torture_comment(tctx, "Testing cancel by CANCEL_LOCK\n");
539 /* setup a timed lock */
540 io.lockx.in.timeout = 10000;
541 req = smb_raw_lock_send(cli->tree, &io);
542 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
543 "Failed to setup timed lock (%s)\n", __location__));
545 /* cancel the wrong range */
546 lock[0].offset = 0;
547 io.lockx.in.timeout = 0;
548 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
549 status = smb_raw_lock(cli->tree, &io);
550 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
552 /* cancel with the wrong bits set */
553 lock[0].offset = 100;
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 the right range */
560 lock[0].offset = 100;
561 io.lockx.in.timeout = 0;
562 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
563 status = smb_raw_lock(cli->tree, &io);
564 CHECK_STATUS(status, NT_STATUS_OK);
566 /* receive the failed lock request */
567 status = smbcli_request_simple_recv(req);
568 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
570 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
571 "lock cancel was not immediate (%s)\n", __location__));
573 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
574 * if the lock vector contains one entry. When given mutliple cancel
575 * requests in a single PDU we expect the server to return an
576 * error. Samba4 handles this correctly. Windows servers seem to
577 * accept the request but only cancel the first lock. Samba3
578 * now does what Windows does (JRA).
580 torture_comment(tctx, "Testing multiple cancel\n");
582 /* acquire second lock */
583 io.lockx.in.timeout = 0;
584 io.lockx.in.ulock_cnt = 0;
585 io.lockx.in.lock_cnt = 1;
586 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
587 io.lockx.in.locks = &lock[1];
588 status = smb_raw_lock(cli->tree, &io);
589 CHECK_STATUS(status, NT_STATUS_OK);
591 /* setup 2 timed locks */
592 t = time_mono(NULL);
593 io.lockx.in.timeout = 10000;
594 io.lockx.in.lock_cnt = 1;
595 io.lockx.in.locks = &lock[0];
596 req = smb_raw_lock_send(cli->tree, &io);
597 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
598 "Failed to setup timed lock (%s)\n", __location__));
599 io.lockx.in.locks = &lock[1];
600 req2 = smb_raw_lock_send(cli->tree, &io);
601 torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
602 "Failed to setup timed lock (%s)\n", __location__));
604 /* try to cancel both locks in the same packet */
605 io.lockx.in.timeout = 0;
606 io.lockx.in.lock_cnt = 2;
607 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
608 io.lockx.in.locks = lock;
609 status = smb_raw_lock(cli->tree, &io);
610 CHECK_STATUS(status, NT_STATUS_OK);
612 torture_warning(tctx, "Target server accepted a lock cancel "
613 "request with multiple locks. This violates "
614 "MS-CIFS 2.2.4.32.1.\n");
616 /* receive the failed lock requests */
617 status = smbcli_request_simple_recv(req);
618 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
620 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
621 "first lock was not cancelled immediately (%s)\n",
622 __location__));
624 /* send cancel to second lock */
625 io.lockx.in.timeout = 0;
626 io.lockx.in.lock_cnt = 1;
627 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK |
628 LOCKING_ANDX_LARGE_FILES;
629 io.lockx.in.locks = &lock[1];
630 status = smb_raw_lock(cli->tree, &io);
631 CHECK_STATUS(status, NT_STATUS_OK);
633 status = smbcli_request_simple_recv(req2);
634 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
636 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
637 "second lock was not cancelled immediately (%s)\n",
638 __location__));
640 /* cleanup the second lock */
641 io.lockx.in.ulock_cnt = 1;
642 io.lockx.in.lock_cnt = 0;
643 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
644 io.lockx.in.locks = &lock[1];
645 status = smb_raw_lock(cli->tree, &io);
646 CHECK_STATUS(status, NT_STATUS_OK);
648 /* If a lock request contained multiple ranges and we are cancelling
649 * one while it's still pending, what happens? */
650 torture_comment(tctx, "Testing cancel 1/2 lock request\n");
652 /* Send request with two ranges */
653 io.lockx.in.timeout = -1;
654 io.lockx.in.ulock_cnt = 0;
655 io.lockx.in.lock_cnt = 2;
656 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
657 io.lockx.in.locks = lock;
658 req = smb_raw_lock_send(cli->tree, &io);
659 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
660 "Failed to setup pending lock (%s)\n", __location__));
662 /* Try to cancel the first lock range */
663 io.lockx.in.timeout = 0;
664 io.lockx.in.lock_cnt = 1;
665 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
666 io.lockx.in.locks = &lock[0];
667 status = smb_raw_lock(cli->tree, &io);
668 CHECK_STATUS(status, NT_STATUS_OK);
670 /* Locking request should've failed and second range should be
671 * unlocked */
672 status = smbcli_request_simple_recv(req);
673 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
675 io.lockx.in.timeout = 0;
676 io.lockx.in.ulock_cnt = 0;
677 io.lockx.in.lock_cnt = 1;
678 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
679 io.lockx.in.locks = &lock[1];
680 status = smb_raw_lock(cli->tree, &io);
681 CHECK_STATUS(status, NT_STATUS_OK);
683 /* Cleanup both locks */
684 io.lockx.in.ulock_cnt = 2;
685 io.lockx.in.lock_cnt = 0;
686 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
687 io.lockx.in.locks = lock;
688 status = smb_raw_lock(cli->tree, &io);
689 CHECK_STATUS(status, NT_STATUS_OK);
691 torture_comment(tctx, "Testing cancel 2/2 lock request\n");
693 /* Lock second range so it contends */
694 io.lockx.in.timeout = 0;
695 io.lockx.in.ulock_cnt = 0;
696 io.lockx.in.lock_cnt = 1;
697 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
698 io.lockx.in.locks = &lock[1];
699 status = smb_raw_lock(cli->tree, &io);
700 CHECK_STATUS(status, NT_STATUS_OK);
702 /* Send request with two ranges */
703 io.lockx.in.timeout = -1;
704 io.lockx.in.ulock_cnt = 0;
705 io.lockx.in.lock_cnt = 2;
706 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
707 io.lockx.in.locks = lock;
708 req = smb_raw_lock_send(cli->tree, &io);
709 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
710 "Failed to setup pending lock (%s)\n", __location__));
712 /* Try to cancel the second lock range */
713 io.lockx.in.timeout = 0;
714 io.lockx.in.lock_cnt = 1;
715 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
716 io.lockx.in.locks = &lock[1];
717 status = smb_raw_lock(cli->tree, &io);
718 CHECK_STATUS(status, NT_STATUS_OK);
720 /* Locking request should've failed and first range should be
721 * unlocked */
722 status = smbcli_request_simple_recv(req);
723 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
725 io.lockx.in.timeout = 0;
726 io.lockx.in.ulock_cnt = 0;
727 io.lockx.in.lock_cnt = 1;
728 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
729 io.lockx.in.locks = &lock[0];
730 status = smb_raw_lock(cli->tree, &io);
731 CHECK_STATUS(status, NT_STATUS_OK);
733 /* Cleanup both locks */
734 io.lockx.in.ulock_cnt = 2;
735 io.lockx.in.lock_cnt = 0;
736 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
737 io.lockx.in.locks = lock;
738 status = smb_raw_lock(cli->tree, &io);
739 CHECK_STATUS(status, NT_STATUS_OK);
741 torture_comment(tctx, "Testing cancel by unlock\n");
742 io.lockx.in.ulock_cnt = 0;
743 io.lockx.in.lock_cnt = 1;
744 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
745 io.lockx.in.timeout = 0;
746 io.lockx.in.locks = &lock[0];
747 status = smb_raw_lock(cli->tree, &io);
748 CHECK_STATUS(status, NT_STATUS_OK);
750 io.lockx.in.timeout = 5000;
751 req = smb_raw_lock_send(cli->tree, &io);
752 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
753 "Failed to setup timed lock (%s)\n", __location__));
755 io.lockx.in.ulock_cnt = 1;
756 io.lockx.in.lock_cnt = 0;
757 status = smb_raw_lock(cli->tree, &io);
758 CHECK_STATUS(status, NT_STATUS_OK);
760 t = time_mono(NULL);
761 status = smbcli_request_simple_recv(req);
762 CHECK_STATUS(status, NT_STATUS_OK);
764 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
765 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
766 __location__, (int)(time_mono(NULL)-t)));
768 torture_comment(tctx, "Testing cancel by close\n");
769 io.lockx.in.ulock_cnt = 0;
770 io.lockx.in.lock_cnt = 1;
771 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
772 io.lockx.in.timeout = 0;
773 status = smb_raw_lock(cli->tree, &io);
774 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
776 t = time_mono(NULL);
777 io.lockx.in.timeout = 10000;
778 req = smb_raw_lock_send(cli->tree, &io);
779 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
780 "Failed to setup timed lock (%s)\n", __location__));
782 status = smbcli_close(cli->tree, fnum);
783 CHECK_STATUS(status, NT_STATUS_OK);
785 status = smbcli_request_simple_recv(req);
786 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
787 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
788 else
789 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
791 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
792 "lock cancel by close was not immediate (%s)\n", __location__));
794 torture_comment(tctx, "create a new sessions\n");
795 session = smbcli_session_init(cli->transport, tctx, false, options);
796 setup.in.sesskey = cli->transport->negotiate.sesskey;
797 setup.in.capabilities = cli->transport->negotiate.capabilities;
798 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
799 setup.in.credentials = cmdline_credentials;
800 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
801 status = smb_composite_sesssetup(session, &setup);
802 CHECK_STATUS(status, NT_STATUS_OK);
803 session->vuid = setup.out.vuid;
805 torture_comment(tctx, "create new tree context\n");
806 share = torture_setting_string(tctx, "share", NULL);
807 host = torture_setting_string(tctx, "host", NULL);
808 tree = smbcli_tree_init(session, tctx, false);
809 tcon.generic.level = RAW_TCON_TCONX;
810 tcon.tconx.in.flags = 0;
811 tcon.tconx.in.password = data_blob(NULL, 0);
812 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
813 tcon.tconx.in.device = "A:";
814 status = smb_raw_tcon(tree, tctx, &tcon);
815 CHECK_STATUS(status, NT_STATUS_OK);
816 tree->tid = tcon.tconx.out.tid;
818 torture_comment(tctx, "Testing cancel by exit\n");
819 if (TARGET_SUPPORTS_SMBEXIT(tctx)) {
820 fname = BASEDIR "\\test_exit.txt";
821 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
822 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
823 "Failed to reopen %s - %s\n",
824 fname, smbcli_errstr(tree)));
826 io.lockx.level = RAW_LOCK_LOCKX;
827 io.lockx.in.file.fnum = fnum;
828 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
829 io.lockx.in.timeout = 0;
830 io.lockx.in.ulock_cnt = 0;
831 io.lockx.in.lock_cnt = 1;
832 lock[0].pid = session->pid;
833 lock[0].offset = 100;
834 lock[0].count = 10;
835 io.lockx.in.locks = &lock[0];
836 status = smb_raw_lock(tree, &io);
837 CHECK_STATUS(status, NT_STATUS_OK);
839 io.lockx.in.ulock_cnt = 0;
840 io.lockx.in.lock_cnt = 1;
841 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
842 io.lockx.in.timeout = 0;
843 status = smb_raw_lock(tree, &io);
844 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
846 io.lockx.in.timeout = 10000;
847 t = time_mono(NULL);
848 req = smb_raw_lock_send(tree, &io);
849 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
850 "Failed to setup timed lock (%s)\n",
851 __location__));
853 status = smb_raw_exit(session);
854 CHECK_STATUS(status, NT_STATUS_OK);
856 status = smbcli_request_simple_recv(req);
857 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
858 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
859 else
860 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
862 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
863 "lock cancel by exit was not immediate (%s)\n",
864 __location__));
866 else {
867 torture_comment(tctx,
868 " skipping test, SMBExit not supported\n");
871 torture_comment(tctx, "Testing cancel by ulogoff\n");
872 fname = BASEDIR "\\test_ulogoff.txt";
873 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
874 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
875 "Failed to reopen %s - %s\n",
876 fname, smbcli_errstr(tree)));
878 io.lockx.level = RAW_LOCK_LOCKX;
879 io.lockx.in.file.fnum = fnum;
880 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
881 io.lockx.in.timeout = 0;
882 io.lockx.in.ulock_cnt = 0;
883 io.lockx.in.lock_cnt = 1;
884 lock[0].pid = session->pid;
885 lock[0].offset = 100;
886 lock[0].count = 10;
887 io.lockx.in.locks = &lock[0];
888 status = smb_raw_lock(tree, &io);
889 CHECK_STATUS(status, NT_STATUS_OK);
891 io.lockx.in.ulock_cnt = 0;
892 io.lockx.in.lock_cnt = 1;
893 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
894 io.lockx.in.timeout = 0;
895 status = smb_raw_lock(tree, &io);
896 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
898 io.lockx.in.timeout = 10000;
899 t = time_mono(NULL);
900 req = smb_raw_lock_send(tree, &io);
901 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
902 "Failed to setup timed lock (%s)\n", __location__));
904 status = smb_raw_ulogoff(session);
905 CHECK_STATUS(status, NT_STATUS_OK);
907 status = smbcli_request_simple_recv(req);
908 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx)) {
909 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
910 torture_result(tctx, TORTURE_FAIL,
911 "lock not canceled by ulogoff - %s "
912 "(ignored because of vfs_vifs fails it)\n",
913 nt_errstr(status));
914 smb_tree_disconnect(tree);
915 smb_raw_exit(session);
916 goto done;
918 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
919 } else {
920 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
923 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
924 "lock cancel by ulogoff was not immediate (%s)\n", __location__));
926 torture_comment(tctx, "Testing cancel by tdis\n");
927 tree->session = cli->session;
929 fname = BASEDIR "\\test_tdis.txt";
930 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
931 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
932 "Failed to reopen %s - %s\n",
933 fname, smbcli_errstr(tree)));
935 io.lockx.level = RAW_LOCK_LOCKX;
936 io.lockx.in.file.fnum = fnum;
937 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
938 io.lockx.in.timeout = 0;
939 io.lockx.in.ulock_cnt = 0;
940 io.lockx.in.lock_cnt = 1;
941 lock[0].pid = cli->session->pid;
942 lock[0].offset = 100;
943 lock[0].count = 10;
944 io.lockx.in.locks = &lock[0];
945 status = smb_raw_lock(tree, &io);
946 CHECK_STATUS(status, NT_STATUS_OK);
948 status = smb_raw_lock(tree, &io);
949 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
951 io.lockx.in.timeout = 10000;
952 t = time_mono(NULL);
953 req = smb_raw_lock_send(tree, &io);
954 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
955 "Failed to setup timed lock (%s)\n", __location__));
957 status = smb_tree_disconnect(tree);
958 CHECK_STATUS(status, NT_STATUS_OK);
960 status = smbcli_request_simple_recv(req);
961 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx))
962 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
963 else
964 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
966 torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
967 "lock cancel by tdis was not immediate (%s)\n", __location__));
969 done:
970 smb_raw_exit(cli->session);
971 smbcli_deltree(cli->tree, BASEDIR);
972 return ret;
976 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
978 static bool test_errorcode(struct torture_context *tctx,
979 struct smbcli_state *cli)
981 union smb_lock io;
982 union smb_open op;
983 struct smb_lock_entry lock[2];
984 NTSTATUS status;
985 bool ret = true;
986 int fnum, fnum2;
987 const char *fname;
988 struct smbcli_request *req;
989 time_t start;
990 int t;
991 int delay;
992 uint16_t deny_mode = 0;
994 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
996 torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
998 torture_comment(tctx, "Testing with timeout = 0\n");
999 fname = BASEDIR "\\test0.txt";
1000 t = 0;
1003 * the first run is with t = 0,
1004 * the second with t > 0 (=1)
1006 next_run:
1008 * use the DENY_DOS mode, that creates two fnum's of one low-level
1009 * file handle, this demonstrates that the cache is per fnum, not
1010 * per file handle
1012 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
1013 deny_mode = OPENX_MODE_DENY_DOS;
1014 else
1015 deny_mode = OPENX_MODE_DENY_NONE;
1017 op.openx.level = RAW_OPEN_OPENX;
1018 op.openx.in.fname = fname;
1019 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1020 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
1021 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
1022 op.openx.in.search_attrs = 0;
1023 op.openx.in.file_attrs = 0;
1024 op.openx.in.write_time = 0;
1025 op.openx.in.size = 0;
1026 op.openx.in.timeout = 0;
1028 status = smb_raw_open(cli->tree, tctx, &op);
1029 CHECK_STATUS(status, NT_STATUS_OK);
1030 fnum = op.openx.out.file.fnum;
1032 status = smb_raw_open(cli->tree, tctx, &op);
1033 CHECK_STATUS(status, NT_STATUS_OK);
1034 fnum2 = op.openx.out.file.fnum;
1036 io.lockx.level = RAW_LOCK_LOCKX;
1037 io.lockx.in.file.fnum = fnum;
1038 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1039 io.lockx.in.timeout = t;
1040 io.lockx.in.ulock_cnt = 0;
1041 io.lockx.in.lock_cnt = 1;
1042 lock[0].pid = cli->session->pid;
1043 lock[0].offset = 100;
1044 lock[0].count = 10;
1045 io.lockx.in.locks = &lock[0];
1046 status = smb_raw_lock(cli->tree, &io);
1047 CHECK_STATUS(status, NT_STATUS_OK);
1050 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
1051 * this also demonstrates that the error code cache is per file handle
1052 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
1054 io.lockx.in.file.fnum = fnum2;
1055 status = smb_raw_lock(cli->tree, &io);
1056 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1058 io.lockx.in.file.fnum = fnum;
1059 status = smb_raw_lock(cli->tree, &io);
1060 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1062 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
1063 io.lockx.in.file.fnum = fnum;
1064 status = smb_raw_lock(cli->tree, &io);
1065 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1067 io.lockx.in.file.fnum = fnum2;
1068 status = smb_raw_lock(cli->tree, &io);
1069 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1071 io.lockx.in.file.fnum = fnum;
1072 status = smb_raw_lock(cli->tree, &io);
1073 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1075 io.lockx.in.file.fnum = fnum2;
1076 status = smb_raw_lock(cli->tree, &io);
1077 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1079 /* demonstrate that the smbpid doesn't matter */
1080 lock[0].pid++;
1081 io.lockx.in.file.fnum = fnum;
1082 status = smb_raw_lock(cli->tree, &io);
1083 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1085 io.lockx.in.file.fnum = fnum2;
1086 status = smb_raw_lock(cli->tree, &io);
1087 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1088 lock[0].pid--;
1091 * demonstrate the a successful lock with count = 0 and the same offset,
1092 * doesn't reset the error cache
1094 lock[0].offset = 100;
1095 lock[0].count = 0;
1096 io.lockx.in.file.fnum = fnum;
1097 status = smb_raw_lock(cli->tree, &io);
1098 CHECK_STATUS(status, NT_STATUS_OK);
1100 io.lockx.in.file.fnum = fnum2;
1101 status = smb_raw_lock(cli->tree, &io);
1102 CHECK_STATUS(status, NT_STATUS_OK);
1104 lock[0].offset = 100;
1105 lock[0].count = 10;
1106 io.lockx.in.file.fnum = fnum;
1107 status = smb_raw_lock(cli->tree, &io);
1108 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1110 io.lockx.in.file.fnum = fnum2;
1111 status = smb_raw_lock(cli->tree, &io);
1112 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1115 * demonstrate the a successful lock with count = 0 and outside the locked range,
1116 * doesn't reset the error cache
1118 lock[0].offset = 110;
1119 lock[0].count = 0;
1120 io.lockx.in.file.fnum = fnum;
1121 status = smb_raw_lock(cli->tree, &io);
1122 CHECK_STATUS(status, NT_STATUS_OK);
1124 io.lockx.in.file.fnum = fnum2;
1125 status = smb_raw_lock(cli->tree, &io);
1126 CHECK_STATUS(status, NT_STATUS_OK);
1128 lock[0].offset = 100;
1129 lock[0].count = 10;
1130 io.lockx.in.file.fnum = fnum;
1131 status = smb_raw_lock(cli->tree, &io);
1132 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1134 io.lockx.in.file.fnum = fnum2;
1135 status = smb_raw_lock(cli->tree, &io);
1136 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1138 lock[0].offset = 99;
1139 lock[0].count = 0;
1140 io.lockx.in.file.fnum = fnum;
1141 status = smb_raw_lock(cli->tree, &io);
1142 CHECK_STATUS(status, NT_STATUS_OK);
1144 io.lockx.in.file.fnum = fnum2;
1145 status = smb_raw_lock(cli->tree, &io);
1146 CHECK_STATUS(status, NT_STATUS_OK);
1148 lock[0].offset = 100;
1149 lock[0].count = 10;
1150 io.lockx.in.file.fnum = fnum;
1151 status = smb_raw_lock(cli->tree, &io);
1152 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1154 io.lockx.in.file.fnum = fnum2;
1155 status = smb_raw_lock(cli->tree, &io);
1156 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1158 /* demonstrate that a changing count doesn't reset the error cache */
1159 lock[0].offset = 100;
1160 lock[0].count = 5;
1161 io.lockx.in.file.fnum = fnum;
1162 status = smb_raw_lock(cli->tree, &io);
1163 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1165 io.lockx.in.file.fnum = fnum2;
1166 status = smb_raw_lock(cli->tree, &io);
1167 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1169 lock[0].offset = 100;
1170 lock[0].count = 15;
1171 io.lockx.in.file.fnum = fnum;
1172 status = smb_raw_lock(cli->tree, &io);
1173 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1175 io.lockx.in.file.fnum = fnum2;
1176 status = smb_raw_lock(cli->tree, &io);
1177 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1180 * demonstrate the a lock with count = 0 and inside the locked range,
1181 * fails and resets the error cache
1183 lock[0].offset = 101;
1184 lock[0].count = 0;
1185 io.lockx.in.file.fnum = fnum;
1186 status = smb_raw_lock(cli->tree, &io);
1187 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1188 status = smb_raw_lock(cli->tree, &io);
1189 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1191 io.lockx.in.file.fnum = fnum2;
1192 status = smb_raw_lock(cli->tree, &io);
1193 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1194 status = smb_raw_lock(cli->tree, &io);
1195 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1197 lock[0].offset = 100;
1198 lock[0].count = 10;
1199 io.lockx.in.file.fnum = fnum;
1200 status = smb_raw_lock(cli->tree, &io);
1201 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1202 status = smb_raw_lock(cli->tree, &io);
1203 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1205 io.lockx.in.file.fnum = fnum2;
1206 status = smb_raw_lock(cli->tree, &io);
1207 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1208 status = smb_raw_lock(cli->tree, &io);
1209 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1211 /* demonstrate the a changing offset, resets the error cache */
1212 lock[0].offset = 105;
1213 lock[0].count = 10;
1214 io.lockx.in.file.fnum = fnum;
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 io.lockx.in.file.fnum = fnum2;
1221 status = smb_raw_lock(cli->tree, &io);
1222 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1223 status = smb_raw_lock(cli->tree, &io);
1224 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1226 lock[0].offset = 100;
1227 lock[0].count = 10;
1228 io.lockx.in.file.fnum = fnum;
1229 status = smb_raw_lock(cli->tree, &io);
1230 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1231 status = smb_raw_lock(cli->tree, &io);
1232 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1234 io.lockx.in.file.fnum = fnum2;
1235 status = smb_raw_lock(cli->tree, &io);
1236 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1237 status = smb_raw_lock(cli->tree, &io);
1238 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1240 lock[0].offset = 95;
1241 lock[0].count = 9;
1242 io.lockx.in.file.fnum = fnum;
1243 status = smb_raw_lock(cli->tree, &io);
1244 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1245 status = smb_raw_lock(cli->tree, &io);
1246 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1248 io.lockx.in.file.fnum = fnum2;
1249 status = smb_raw_lock(cli->tree, &io);
1250 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1251 status = smb_raw_lock(cli->tree, &io);
1252 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1254 lock[0].offset = 100;
1255 lock[0].count = 10;
1256 io.lockx.in.file.fnum = fnum;
1257 status = smb_raw_lock(cli->tree, &io);
1258 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1259 status = smb_raw_lock(cli->tree, &io);
1260 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1262 io.lockx.in.file.fnum = fnum2;
1263 status = smb_raw_lock(cli->tree, &io);
1264 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1265 status = smb_raw_lock(cli->tree, &io);
1266 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1269 * demonstrate the a successful lock in a different range,
1270 * doesn't reset the cache, the failing lock on the 2nd handle
1271 * resets the cache
1273 lock[0].offset = 120;
1274 lock[0].count = 15;
1275 io.lockx.in.file.fnum = fnum;
1276 status = smb_raw_lock(cli->tree, &io);
1277 CHECK_STATUS(status, NT_STATUS_OK);
1279 io.lockx.in.file.fnum = fnum2;
1280 status = smb_raw_lock(cli->tree, &io);
1281 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1283 lock[0].offset = 100;
1284 lock[0].count = 10;
1285 io.lockx.in.file.fnum = fnum;
1286 status = smb_raw_lock(cli->tree, &io);
1287 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1288 status = smb_raw_lock(cli->tree, &io);
1289 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1291 io.lockx.in.file.fnum = fnum2;
1292 status = smb_raw_lock(cli->tree, &io);
1293 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1294 status = smb_raw_lock(cli->tree, &io);
1295 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1297 /* end of the loop */
1298 if (t == 0) {
1299 smb_raw_exit(cli->session);
1300 t = 1;
1301 torture_comment(tctx, "Testing with timeout > 0 (=%d)\n",
1303 fname = BASEDIR "\\test1.txt";
1304 goto next_run;
1307 t = 4000;
1308 torture_comment(tctx, "Testing special cases with timeout > 0 (=%d)\n",
1312 * the following 3 test sections demonstrate that
1313 * the cache is only set when the error is reported
1314 * to the client (after the timeout went by)
1316 smb_raw_exit(cli->session);
1317 torture_comment(tctx, "Testing a conflict while a lock is pending\n");
1318 fname = BASEDIR "\\test2.txt";
1319 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1320 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1321 "Failed to reopen %s - %s\n",
1322 fname, smbcli_errstr(cli->tree)));
1324 io.lockx.level = RAW_LOCK_LOCKX;
1325 io.lockx.in.file.fnum = fnum;
1326 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1327 io.lockx.in.timeout = 0;
1328 io.lockx.in.ulock_cnt = 0;
1329 io.lockx.in.lock_cnt = 1;
1330 lock[0].pid = cli->session->pid;
1331 lock[0].offset = 100;
1332 lock[0].count = 10;
1333 io.lockx.in.locks = &lock[0];
1334 status = smb_raw_lock(cli->tree, &io);
1335 CHECK_STATUS(status, NT_STATUS_OK);
1337 start = time_mono(NULL);
1338 io.lockx.in.timeout = t;
1339 req = smb_raw_lock_send(cli->tree, &io);
1340 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1341 "Failed to setup timed lock (%s)\n", __location__));
1343 io.lockx.in.timeout = 0;
1344 lock[0].offset = 105;
1345 lock[0].count = 10;
1346 status = smb_raw_lock(cli->tree, &io);
1347 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1349 status = smbcli_request_simple_recv(req);
1350 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1352 delay = t / 1000;
1353 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1354 delay /= 2;
1357 torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
1358 "lock comes back to early timeout[%d] delay[%d]"
1359 "(%s)\n", t, delay, __location__));
1361 status = smb_raw_lock(cli->tree, &io);
1362 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1364 smbcli_close(cli->tree, fnum);
1365 fname = BASEDIR "\\test3.txt";
1366 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1367 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1368 "Failed to reopen %s - %s\n",
1369 fname, smbcli_errstr(cli->tree)));
1371 io.lockx.level = RAW_LOCK_LOCKX;
1372 io.lockx.in.file.fnum = fnum;
1373 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1374 io.lockx.in.timeout = 0;
1375 io.lockx.in.ulock_cnt = 0;
1376 io.lockx.in.lock_cnt = 1;
1377 lock[0].pid = cli->session->pid;
1378 lock[0].offset = 100;
1379 lock[0].count = 10;
1380 io.lockx.in.locks = &lock[0];
1381 status = smb_raw_lock(cli->tree, &io);
1382 CHECK_STATUS(status, NT_STATUS_OK);
1384 start = time_mono(NULL);
1385 io.lockx.in.timeout = t;
1386 req = smb_raw_lock_send(cli->tree, &io);
1387 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1388 "Failed to setup timed lock (%s)\n", __location__));
1390 io.lockx.in.timeout = 0;
1391 lock[0].offset = 105;
1392 lock[0].count = 10;
1393 status = smb_raw_lock(cli->tree, &io);
1394 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1396 status = smbcli_request_simple_recv(req);
1397 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1399 delay = t / 1000;
1400 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1401 delay /= 2;
1404 torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
1405 "lock comes back to early timeout[%d] delay[%d]"
1406 "(%s)\n", t, delay, __location__));
1408 lock[0].offset = 100;
1409 lock[0].count = 10;
1410 status = smb_raw_lock(cli->tree, &io);
1411 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1413 smbcli_close(cli->tree, fnum);
1414 fname = BASEDIR "\\test4.txt";
1415 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1416 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1417 "Failed to reopen %s - %s\n",
1418 fname, smbcli_errstr(cli->tree)));
1420 io.lockx.level = RAW_LOCK_LOCKX;
1421 io.lockx.in.file.fnum = fnum;
1422 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1423 io.lockx.in.timeout = 0;
1424 io.lockx.in.ulock_cnt = 0;
1425 io.lockx.in.lock_cnt = 1;
1426 lock[0].pid = cli->session->pid;
1427 lock[0].offset = 100;
1428 lock[0].count = 10;
1429 io.lockx.in.locks = &lock[0];
1430 status = smb_raw_lock(cli->tree, &io);
1431 CHECK_STATUS(status, NT_STATUS_OK);
1433 start = time_mono(NULL);
1434 io.lockx.in.timeout = t;
1435 req = smb_raw_lock_send(cli->tree, &io);
1436 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1437 "Failed to setup timed lock (%s)\n", __location__));
1439 io.lockx.in.timeout = 0;
1440 status = smb_raw_lock(cli->tree, &io);
1441 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1443 status = smbcli_request_simple_recv(req);
1444 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1446 delay = t / 1000;
1447 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1448 delay /= 2;
1451 torture_assert(tctx,!(time_mono(NULL) < start+delay), talloc_asprintf(tctx,
1452 "lock comes back to early timeout[%d] delay[%d]"
1453 "(%s)\n", t, delay, __location__));
1455 status = smb_raw_lock(cli->tree, &io);
1456 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1458 done:
1459 smb_raw_exit(cli->session);
1460 smbcli_deltree(cli->tree, BASEDIR);
1461 return ret;
1466 test LOCKING_ANDX_CHANGE_LOCKTYPE
1468 static bool test_changetype(struct torture_context *tctx,
1469 struct smbcli_state *cli)
1471 union smb_lock io;
1472 struct smb_lock_entry lock[2];
1473 NTSTATUS status;
1474 bool ret = true;
1475 int fnum;
1476 uint8_t c = 0;
1477 const char *fname = BASEDIR "\\test.txt";
1479 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1481 torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1482 io.generic.level = RAW_LOCK_LOCKX;
1484 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1485 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1486 "Failed to create %s - %s\n",
1487 fname, smbcli_errstr(cli->tree)));
1489 io.lockx.level = RAW_LOCK_LOCKX;
1490 io.lockx.in.file.fnum = fnum;
1491 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1492 io.lockx.in.timeout = 0;
1493 io.lockx.in.ulock_cnt = 0;
1494 io.lockx.in.lock_cnt = 1;
1495 lock[0].pid = cli->session->pid;
1496 lock[0].offset = 100;
1497 lock[0].count = 10;
1498 io.lockx.in.locks = &lock[0];
1499 status = smb_raw_lock(cli->tree, &io);
1500 CHECK_STATUS(status, NT_STATUS_OK);
1502 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1503 torture_result(tctx, TORTURE_FAIL,
1504 "allowed write on read locked region (%s)\n", __location__);
1505 ret = false;
1506 goto done;
1509 /* windows server don't seem to support this */
1510 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1511 status = smb_raw_lock(cli->tree, &io);
1512 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1514 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1515 torture_result(tctx, TORTURE_FAIL,
1516 "allowed write after lock change (%s)\n", __location__);
1517 ret = false;
1518 goto done;
1521 done:
1522 smbcli_close(cli->tree, fnum);
1523 smb_raw_exit(cli->session);
1524 smbcli_deltree(cli->tree, BASEDIR);
1525 return ret;
1528 struct double_lock_test {
1529 struct smb_lock_entry lock1;
1530 struct smb_lock_entry lock2;
1531 NTSTATUS exp_status;
1535 * Tests zero byte locks.
1537 static struct double_lock_test zero_byte_tests[] = {
1538 /* {pid, offset, count}, {pid, offset, count}, status */
1540 /** First, takes a zero byte lock at offset 10. Then:
1541 * - Taking 0 byte lock at 10 should succeed.
1542 * - Taking 1 byte locks at 9,10,11 should succeed.
1543 * - Taking 2 byte lock at 9 should fail.
1544 * - Taking 2 byte lock at 10 should succeed.
1545 * - Taking 3 byte lock at 9 should fail.
1547 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1548 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
1549 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1550 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1551 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
1552 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1553 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
1555 /** Same, but opposite order. */
1556 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1557 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
1558 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1559 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1560 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1561 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1562 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1564 /** Zero zero case. */
1565 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
1568 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
1570 union smb_lock io;
1571 NTSTATUS status;
1572 bool ret = true;
1573 int fnum, i;
1574 const char *fname = BASEDIR "\\zero.txt";
1576 torture_comment(tctx, "Testing zero length byte range locks:\n");
1578 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1580 io.generic.level = RAW_LOCK_LOCKX;
1582 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1583 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1584 "Failed to create %s - %s\n",
1585 fname, smbcli_errstr(cli->tree)));
1587 /* Setup initial parameters */
1588 io.lockx.level = RAW_LOCK_LOCKX;
1589 io.lockx.in.file.fnum = fnum;
1590 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1591 io.lockx.in.timeout = 0;
1593 /* Try every combination of locks in zero_byte_tests. The first lock is
1594 * assumed to succeed. The second lock may contend, depending on the
1595 * expected status. */
1596 for (i = 0;
1597 i < ARRAY_SIZE(zero_byte_tests);
1598 i++) {
1599 torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1600 zero_byte_tests[i].lock1.pid,
1601 (unsigned long long) zero_byte_tests[i].lock1.offset,
1602 (unsigned long long) zero_byte_tests[i].lock1.count,
1603 zero_byte_tests[i].lock2.pid,
1604 (unsigned long long) zero_byte_tests[i].lock2.offset,
1605 (unsigned long long) zero_byte_tests[i].lock2.count,
1606 nt_errstr(zero_byte_tests[i].exp_status));
1608 /* Lock both locks. */
1609 io.lockx.in.ulock_cnt = 0;
1610 io.lockx.in.lock_cnt = 1;
1612 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1613 &zero_byte_tests[i].lock1);
1614 status = smb_raw_lock(cli->tree, &io);
1615 CHECK_STATUS(status, NT_STATUS_OK);
1617 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1618 &zero_byte_tests[i].lock2);
1619 status = smb_raw_lock(cli->tree, &io);
1621 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1622 NT_STATUS_LOCK_NOT_GRANTED)) {
1623 /* Allow either of the failure messages and keep going
1624 * if we see the wrong status. */
1625 CHECK_STATUS_OR_CONT(status,
1626 NT_STATUS_LOCK_NOT_GRANTED,
1627 NT_STATUS_FILE_LOCK_CONFLICT);
1629 } else {
1630 CHECK_STATUS_CONT(status,
1631 zero_byte_tests[i].exp_status);
1634 /* Unlock both locks. */
1635 io.lockx.in.ulock_cnt = 1;
1636 io.lockx.in.lock_cnt = 0;
1638 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1639 status = smb_raw_lock(cli->tree, &io);
1640 CHECK_STATUS(status, NT_STATUS_OK);
1643 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1644 &zero_byte_tests[i].lock1);
1645 status = smb_raw_lock(cli->tree, &io);
1646 CHECK_STATUS(status, NT_STATUS_OK);
1649 done:
1650 smbcli_close(cli->tree, fnum);
1651 smb_raw_exit(cli->session);
1652 smbcli_deltree(cli->tree, BASEDIR);
1653 return ret;
1656 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1658 union smb_lock io;
1659 NTSTATUS status;
1660 bool ret = true;
1661 int fnum1, fnum2;
1662 const char *fname = BASEDIR "\\unlock.txt";
1663 struct smb_lock_entry lock1;
1664 struct smb_lock_entry lock2;
1666 torture_comment(tctx, "Testing LOCKX unlock:\n");
1668 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1670 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1671 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1672 "Failed to create %s - %s\n",
1673 fname, smbcli_errstr(cli->tree)));
1675 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1676 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
1677 "Failed to create %s - %s\n",
1678 fname, smbcli_errstr(cli->tree)));
1680 /* Setup initial parameters */
1681 io.lockx.level = RAW_LOCK_LOCKX;
1682 io.lockx.in.timeout = 0;
1684 lock1.pid = cli->session->pid;
1685 lock1.offset = 0;
1686 lock1.count = 10;
1687 lock2.pid = cli->session->pid - 1;
1688 lock2.offset = 0;
1689 lock2.count = 10;
1692 * Take exclusive lock, then unlock it with a shared-unlock call.
1694 torture_comment(tctx, " taking exclusive lock.\n");
1695 io.lockx.in.ulock_cnt = 0;
1696 io.lockx.in.lock_cnt = 1;
1697 io.lockx.in.mode = 0;
1698 io.lockx.in.file.fnum = fnum1;
1699 io.lockx.in.locks = &lock1;
1700 status = smb_raw_lock(cli->tree, &io);
1701 CHECK_STATUS(status, NT_STATUS_OK);
1703 torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
1704 io.lockx.in.ulock_cnt = 1;
1705 io.lockx.in.lock_cnt = 0;
1706 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1707 io.lockx.in.file.fnum = fnum1;
1708 io.lockx.in.locks = &lock1;
1709 status = smb_raw_lock(cli->tree, &io);
1710 CHECK_STATUS(status, NT_STATUS_OK);
1712 torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
1713 io.lockx.in.ulock_cnt = 0;
1714 io.lockx.in.lock_cnt = 1;
1715 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1716 io.lockx.in.file.fnum = fnum2;
1717 io.lockx.in.locks = &lock2;
1718 status = smb_raw_lock(cli->tree, &io);
1719 CHECK_STATUS(status, NT_STATUS_OK);
1722 * Unlock a shared lock with an exclusive-unlock call.
1724 torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
1725 io.lockx.in.ulock_cnt = 1;
1726 io.lockx.in.lock_cnt = 0;
1727 io.lockx.in.mode = 0;
1728 io.lockx.in.file.fnum = fnum2;
1729 io.lockx.in.locks = &lock2;
1730 status = smb_raw_lock(cli->tree, &io);
1731 CHECK_STATUS(status, NT_STATUS_OK);
1733 torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
1734 io.lockx.in.ulock_cnt = 0;
1735 io.lockx.in.lock_cnt = 1;
1736 io.lockx.in.mode = 0;
1737 io.lockx.in.file.fnum = fnum1;
1738 io.lockx.in.locks = &lock1;
1739 status = smb_raw_lock(cli->tree, &io);
1740 CHECK_STATUS(status, NT_STATUS_OK);
1742 /* cleanup */
1743 io.lockx.in.ulock_cnt = 1;
1744 io.lockx.in.lock_cnt = 0;
1745 status = smb_raw_lock(cli->tree, &io);
1746 CHECK_STATUS(status, NT_STATUS_OK);
1749 * Test unlocking of 0-byte locks.
1752 torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
1753 "always unlocks the exclusive first.\n");
1754 lock1.pid = cli->session->pid;
1755 lock1.offset = 10;
1756 lock1.count = 0;
1757 lock2.pid = cli->session->pid;
1758 lock2.offset = 5;
1759 lock2.count = 10;
1760 io.lockx.in.ulock_cnt = 0;
1761 io.lockx.in.lock_cnt = 1;
1762 io.lockx.in.file.fnum = fnum1;
1763 io.lockx.in.locks = &lock1;
1765 /* lock 0-byte shared
1766 * Note: Order of the shared/exclusive locks doesn't matter. */
1767 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1768 status = smb_raw_lock(cli->tree, &io);
1769 CHECK_STATUS(status, NT_STATUS_OK);
1771 /* lock 0-byte exclusive */
1772 io.lockx.in.mode = 0;
1773 status = smb_raw_lock(cli->tree, &io);
1774 CHECK_STATUS(status, NT_STATUS_OK);
1776 /* test contention */
1777 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1778 io.lockx.in.locks = &lock2;
1779 io.lockx.in.file.fnum = fnum2;
1780 status = smb_raw_lock(cli->tree, &io);
1781 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1782 NT_STATUS_FILE_LOCK_CONFLICT);
1784 /* unlock */
1785 io.lockx.in.ulock_cnt = 1;
1786 io.lockx.in.lock_cnt = 0;
1787 io.lockx.in.file.fnum = fnum1;
1788 io.lockx.in.locks = &lock1;
1789 status = smb_raw_lock(cli->tree, &io);
1790 CHECK_STATUS(status, NT_STATUS_OK);
1792 /* test - can we take a shared lock? */
1793 io.lockx.in.ulock_cnt = 0;
1794 io.lockx.in.lock_cnt = 1;
1795 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1796 io.lockx.in.file.fnum = fnum2;
1797 io.lockx.in.locks = &lock2;
1798 status = smb_raw_lock(cli->tree, &io);
1800 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1801 * new to Win7, it succeeds in WinXP too), until I can come to a
1802 * resolution as to whether Samba should support this or not. There is
1803 * code to preference unlocking exclusive locks before shared locks,
1804 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1805 if (TARGET_IS_SAMBA3(tctx)) {
1806 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1807 NT_STATUS_FILE_LOCK_CONFLICT);
1808 } else {
1809 CHECK_STATUS(status, NT_STATUS_OK);
1812 /* cleanup */
1813 io.lockx.in.ulock_cnt = 1;
1814 io.lockx.in.lock_cnt = 0;
1815 status = smb_raw_lock(cli->tree, &io);
1817 /* XXX Same as above. */
1818 if (TARGET_IS_SAMBA3(tctx)) {
1819 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1820 } else {
1821 CHECK_STATUS(status, NT_STATUS_OK);
1824 io.lockx.in.file.fnum = fnum1;
1825 io.lockx.in.locks = &lock1;
1826 status = smb_raw_lock(cli->tree, &io);
1827 CHECK_STATUS(status, NT_STATUS_OK);
1829 done:
1830 smbcli_close(cli->tree, fnum1);
1831 smbcli_close(cli->tree, fnum2);
1832 smb_raw_exit(cli->session);
1833 smbcli_deltree(cli->tree, BASEDIR);
1834 return ret;
1837 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1839 union smb_lock io;
1840 NTSTATUS status;
1841 bool ret = true;
1842 int fnum1;
1843 const char *fname = BASEDIR "\\unlock_multiple.txt";
1844 struct smb_lock_entry lock1;
1845 struct smb_lock_entry lock2;
1846 struct smb_lock_entry locks[2];
1848 torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
1850 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1852 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1853 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1854 "Failed to create %s - %s\n",
1855 fname, smbcli_errstr(cli->tree)));
1857 /* Setup initial parameters */
1858 io.lockx.level = RAW_LOCK_LOCKX;
1859 io.lockx.in.timeout = 0;
1861 lock1.pid = cli->session->pid;
1862 lock1.offset = 0;
1863 lock1.count = 10;
1864 lock2.pid = cli->session->pid;
1865 lock2.offset = 10;
1866 lock2.count = 10;
1868 locks[0] = lock1;
1869 locks[1] = lock2;
1871 io.lockx.in.file.fnum = fnum1;
1872 io.lockx.in.mode = 0; /* exclusive */
1874 /** Test1: Take second lock, but not first. */
1875 torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
1876 "unlocked. \n");
1878 io.lockx.in.ulock_cnt = 0;
1879 io.lockx.in.lock_cnt = 1;
1880 io.lockx.in.locks = &lock2;
1881 status = smb_raw_lock(cli->tree, &io);
1882 CHECK_STATUS(status, NT_STATUS_OK);
1884 /* Try to unlock both locks. */
1885 io.lockx.in.ulock_cnt = 2;
1886 io.lockx.in.lock_cnt = 0;
1887 io.lockx.in.locks = locks;
1889 status = smb_raw_lock(cli->tree, &io);
1890 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1892 /* Second lock should not be unlocked. */
1893 io.lockx.in.ulock_cnt = 0;
1894 io.lockx.in.lock_cnt = 1;
1895 io.lockx.in.locks = &lock2;
1896 status = smb_raw_lock(cli->tree, &io);
1897 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1899 /* cleanup */
1900 io.lockx.in.ulock_cnt = 1;
1901 io.lockx.in.lock_cnt = 0;
1902 io.lockx.in.locks = &lock2;
1903 status = smb_raw_lock(cli->tree, &io);
1904 CHECK_STATUS(status, NT_STATUS_OK);
1906 /** Test2: Take first lock, but not second. */
1907 torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
1908 "unlocked.\n");
1910 io.lockx.in.ulock_cnt = 0;
1911 io.lockx.in.lock_cnt = 1;
1912 io.lockx.in.locks = &lock1;
1913 status = smb_raw_lock(cli->tree, &io);
1914 CHECK_STATUS(status, NT_STATUS_OK);
1916 /* Try to unlock both locks. */
1917 io.lockx.in.ulock_cnt = 2;
1918 io.lockx.in.lock_cnt = 0;
1919 io.lockx.in.locks = locks;
1921 status = smb_raw_lock(cli->tree, &io);
1922 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1924 /* First lock should be unlocked. */
1925 io.lockx.in.ulock_cnt = 0;
1926 io.lockx.in.lock_cnt = 1;
1927 io.lockx.in.locks = &lock1;
1928 status = smb_raw_lock(cli->tree, &io);
1929 CHECK_STATUS(status, NT_STATUS_OK);
1931 /* cleanup */
1932 io.lockx.in.ulock_cnt = 1;
1933 io.lockx.in.lock_cnt = 0;
1934 io.lockx.in.locks = &lock1;
1935 status = smb_raw_lock(cli->tree, &io);
1936 CHECK_STATUS(status, NT_STATUS_OK);
1938 /* Test3: Request 2 locks, second will contend. What happens to the
1939 * first? */
1940 torture_comment(tctx, " request 2 locks, second one will contend. "
1941 "Expect both to fail.\n");
1943 /* Lock the second range */
1944 io.lockx.in.ulock_cnt = 0;
1945 io.lockx.in.lock_cnt = 1;
1946 io.lockx.in.locks = &lock2;
1947 status = smb_raw_lock(cli->tree, &io);
1948 CHECK_STATUS(status, NT_STATUS_OK);
1950 /* Request both locks */
1951 io.lockx.in.ulock_cnt = 0;
1952 io.lockx.in.lock_cnt = 2;
1953 io.lockx.in.locks = locks;
1955 status = smb_raw_lock(cli->tree, &io);
1956 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1958 /* First lock should be unlocked. */
1959 io.lockx.in.ulock_cnt = 0;
1960 io.lockx.in.lock_cnt = 1;
1961 io.lockx.in.locks = &lock1;
1962 status = smb_raw_lock(cli->tree, &io);
1963 CHECK_STATUS(status, NT_STATUS_OK);
1965 /* cleanup */
1966 io.lockx.in.ulock_cnt = 2;
1967 io.lockx.in.lock_cnt = 0;
1968 io.lockx.in.locks = locks;
1969 status = smb_raw_lock(cli->tree, &io);
1970 CHECK_STATUS(status, NT_STATUS_OK);
1972 /* Test4: Request unlock and lock. The lock contends, is the unlock
1973 * then re-locked? */
1974 torture_comment(tctx, " request unlock and lock, second one will "
1975 "contend. Expect the unlock to succeed.\n");
1977 /* Lock both ranges */
1978 io.lockx.in.ulock_cnt = 0;
1979 io.lockx.in.lock_cnt = 2;
1980 io.lockx.in.locks = locks;
1981 status = smb_raw_lock(cli->tree, &io);
1982 CHECK_STATUS(status, NT_STATUS_OK);
1984 /* Attempt to unlock the first range and lock the second */
1985 io.lockx.in.ulock_cnt = 1;
1986 io.lockx.in.lock_cnt = 1;
1987 io.lockx.in.locks = locks;
1988 status = smb_raw_lock(cli->tree, &io);
1989 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1991 /* The first lock should've been unlocked */
1992 io.lockx.in.ulock_cnt = 0;
1993 io.lockx.in.lock_cnt = 1;
1994 io.lockx.in.locks = &lock1;
1995 status = smb_raw_lock(cli->tree, &io);
1996 CHECK_STATUS(status, NT_STATUS_OK);
1998 /* cleanup */
1999 io.lockx.in.ulock_cnt = 2;
2000 io.lockx.in.lock_cnt = 0;
2001 io.lockx.in.locks = locks;
2002 status = smb_raw_lock(cli->tree, &io);
2003 CHECK_STATUS(status, NT_STATUS_OK);
2005 done:
2006 smbcli_close(cli->tree, fnum1);
2007 smb_raw_exit(cli->session);
2008 smbcli_deltree(cli->tree, BASEDIR);
2009 return ret;
2013 * torture_locktest5 covers stacking pretty well, but its missing two tests:
2014 * - stacking an exclusive on top of shared fails
2015 * - stacking two exclusives fail
2017 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
2019 union smb_lock io;
2020 NTSTATUS status;
2021 bool ret = true;
2022 int fnum1;
2023 const char *fname = BASEDIR "\\stacking.txt";
2024 struct smb_lock_entry lock1;
2026 torture_comment(tctx, "Testing stacking:\n");
2028 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
2030 io.generic.level = RAW_LOCK_LOCKX;
2032 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2033 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
2034 "Failed to create %s - %s\n",
2035 fname, smbcli_errstr(cli->tree)));
2037 /* Setup initial parameters */
2038 io.lockx.level = RAW_LOCK_LOCKX;
2039 io.lockx.in.timeout = 0;
2041 lock1.pid = cli->session->pid;
2042 lock1.offset = 0;
2043 lock1.count = 10;
2046 * Try to take a shared lock, then stack an exclusive.
2048 torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
2049 io.lockx.in.file.fnum = fnum1;
2050 io.lockx.in.locks = &lock1;
2052 io.lockx.in.ulock_cnt = 0;
2053 io.lockx.in.lock_cnt = 1;
2054 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
2055 status = smb_raw_lock(cli->tree, &io);
2056 CHECK_STATUS(status, NT_STATUS_OK);
2058 io.lockx.in.ulock_cnt = 0;
2059 io.lockx.in.lock_cnt = 1;
2060 io.lockx.in.mode = 0;
2061 status = smb_raw_lock(cli->tree, &io);
2062 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
2063 NT_STATUS_FILE_LOCK_CONFLICT);
2065 /* cleanup */
2066 io.lockx.in.ulock_cnt = 1;
2067 io.lockx.in.lock_cnt = 0;
2068 status = smb_raw_lock(cli->tree, &io);
2069 CHECK_STATUS(status, NT_STATUS_OK);
2072 * Prove that two exclusive locks do not stack.
2074 torture_comment(tctx, " two exclusive locks do not stack.\n");
2075 io.lockx.in.ulock_cnt = 0;
2076 io.lockx.in.lock_cnt = 1;
2077 io.lockx.in.mode = 0;
2078 status = smb_raw_lock(cli->tree, &io);
2079 CHECK_STATUS(status, NT_STATUS_OK);
2080 status = smb_raw_lock(cli->tree, &io);
2081 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
2082 NT_STATUS_FILE_LOCK_CONFLICT);
2084 /* cleanup */
2085 io.lockx.in.ulock_cnt = 1;
2086 io.lockx.in.lock_cnt = 0;
2087 status = smb_raw_lock(cli->tree, &io);
2088 CHECK_STATUS(status, NT_STATUS_OK);
2090 done:
2091 smbcli_close(cli->tree, fnum1);
2092 smb_raw_exit(cli->session);
2093 smbcli_deltree(cli->tree, BASEDIR);
2094 return ret;
2098 * Test how 0-byte read requests contend with byte range locks
2100 static bool test_zerobyteread(struct torture_context *tctx,
2101 struct smbcli_state *cli)
2103 union smb_lock io;
2104 union smb_read rd;
2105 NTSTATUS status;
2106 bool ret = true;
2107 int fnum1, fnum2;
2108 const char *fname = BASEDIR "\\zerobyteread.txt";
2109 struct smb_lock_entry lock1;
2110 uint8_t c = 1;
2112 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
2114 io.generic.level = RAW_LOCK_LOCKX;
2116 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2117 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
2118 "Failed to create %s - %s\n",
2119 fname, smbcli_errstr(cli->tree)));
2121 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2122 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
2123 "Failed to create %s - %s\n",
2124 fname, smbcli_errstr(cli->tree)));
2126 /* Setup initial parameters */
2127 io.lockx.level = RAW_LOCK_LOCKX;
2128 io.lockx.in.timeout = 0;
2130 lock1.pid = cli->session->pid;
2131 lock1.offset = 0;
2132 lock1.count = 10;
2134 ZERO_STRUCT(rd);
2135 rd.readx.level = RAW_READ_READX;
2137 torture_comment(tctx, "Testing zero byte read on lock range:\n");
2139 /* Take an exclusive lock */
2140 torture_comment(tctx, " taking exclusive lock.\n");
2141 io.lockx.in.ulock_cnt = 0;
2142 io.lockx.in.lock_cnt = 1;
2143 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2144 io.lockx.in.file.fnum = fnum1;
2145 io.lockx.in.locks = &lock1;
2146 status = smb_raw_lock(cli->tree, &io);
2147 CHECK_STATUS(status, NT_STATUS_OK);
2149 /* Try a zero byte read */
2150 torture_comment(tctx, " reading 0 bytes.\n");
2151 rd.readx.in.file.fnum = fnum2;
2152 rd.readx.in.offset = 5;
2153 rd.readx.in.mincnt = 0;
2154 rd.readx.in.maxcnt = 0;
2155 rd.readx.in.remaining = 0;
2156 rd.readx.in.read_for_execute = false;
2157 rd.readx.out.data = &c;
2158 status = smb_raw_read(cli->tree, &rd);
2159 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2160 "zero byte read did not return 0 bytes");
2161 CHECK_STATUS(status, NT_STATUS_OK);
2163 /* Unlock lock */
2164 io.lockx.in.ulock_cnt = 1;
2165 io.lockx.in.lock_cnt = 0;
2166 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2167 io.lockx.in.file.fnum = fnum1;
2168 io.lockx.in.locks = &lock1;
2169 status = smb_raw_lock(cli->tree, &io);
2170 CHECK_STATUS(status, NT_STATUS_OK);
2172 torture_comment(tctx, "Testing zero byte read on zero byte lock "
2173 "range:\n");
2175 /* Take an exclusive lock */
2176 torture_comment(tctx, " taking exclusive 0-byte lock.\n");
2177 io.lockx.in.ulock_cnt = 0;
2178 io.lockx.in.lock_cnt = 1;
2179 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2180 io.lockx.in.file.fnum = fnum1;
2181 io.lockx.in.locks = &lock1;
2182 lock1.offset = 5;
2183 lock1.count = 0;
2184 status = smb_raw_lock(cli->tree, &io);
2185 CHECK_STATUS(status, NT_STATUS_OK);
2187 /* Try a zero byte read before the lock */
2188 torture_comment(tctx, " reading 0 bytes before the lock.\n");
2189 rd.readx.in.file.fnum = fnum2;
2190 rd.readx.in.offset = 4;
2191 rd.readx.in.mincnt = 0;
2192 rd.readx.in.maxcnt = 0;
2193 rd.readx.in.remaining = 0;
2194 rd.readx.in.read_for_execute = false;
2195 rd.readx.out.data = &c;
2196 status = smb_raw_read(cli->tree, &rd);
2197 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2198 "zero byte read did not return 0 bytes");
2199 CHECK_STATUS(status, NT_STATUS_OK);
2201 /* Try a zero byte read on the lock */
2202 torture_comment(tctx, " reading 0 bytes on the lock.\n");
2203 rd.readx.in.file.fnum = fnum2;
2204 rd.readx.in.offset = 5;
2205 rd.readx.in.mincnt = 0;
2206 rd.readx.in.maxcnt = 0;
2207 rd.readx.in.remaining = 0;
2208 rd.readx.in.read_for_execute = false;
2209 rd.readx.out.data = &c;
2210 status = smb_raw_read(cli->tree, &rd);
2211 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2212 "zero byte read did not return 0 bytes");
2213 CHECK_STATUS(status, NT_STATUS_OK);
2215 /* Try a zero byte read after the lock */
2216 torture_comment(tctx, " reading 0 bytes after the lock.\n");
2217 rd.readx.in.file.fnum = fnum2;
2218 rd.readx.in.offset = 6;
2219 rd.readx.in.mincnt = 0;
2220 rd.readx.in.maxcnt = 0;
2221 rd.readx.in.remaining = 0;
2222 rd.readx.in.read_for_execute = false;
2223 rd.readx.out.data = &c;
2224 status = smb_raw_read(cli->tree, &rd);
2225 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2226 "zero byte read did not return 0 bytes");
2227 CHECK_STATUS(status, NT_STATUS_OK);
2229 /* Unlock lock */
2230 io.lockx.in.ulock_cnt = 1;
2231 io.lockx.in.lock_cnt = 0;
2232 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2233 io.lockx.in.file.fnum = fnum1;
2234 io.lockx.in.locks = &lock1;
2235 status = smb_raw_lock(cli->tree, &io);
2236 CHECK_STATUS(status, NT_STATUS_OK);
2238 done:
2239 smbcli_close(cli->tree, fnum1);
2240 smbcli_close(cli->tree, fnum2);
2241 smb_raw_exit(cli->session);
2242 smbcli_deltree(cli->tree, BASEDIR);
2243 return ret;
2247 basic testing of lock calls
2249 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
2251 struct torture_suite *suite = torture_suite_create(mem_ctx, "lock");
2253 torture_suite_add_1smb_test(suite, "lockx", test_lockx);
2254 torture_suite_add_1smb_test(suite, "lock", test_lock);
2255 torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
2256 torture_suite_add_1smb_test(suite, "async", test_async);
2257 torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
2258 torture_suite_add_1smb_test(suite, "changetype", test_changetype);
2260 torture_suite_add_1smb_test(suite, "stacking", test_stacking);
2261 torture_suite_add_1smb_test(suite, "unlock", test_unlock);
2262 torture_suite_add_1smb_test(suite, "multiple_unlock",
2263 test_multiple_unlock);
2264 torture_suite_add_1smb_test(suite, "zerobytelocks", test_zerobytelocks);
2265 torture_suite_add_1smb_test(suite, "zerobyteread", test_zerobyteread);
2267 return suite;