s4/torture: add more lock cancellation tests
[Samba/fernandojvsilva.git] / source4 / torture / raw / lock.c
blob0af73e503a637b276be95e15726a7c87f126f32c
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_SMBLOCK(_tctx) \
84 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
85 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
86 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
88 test SMBlock and SMBunlock ops
90 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
92 union smb_lock io;
93 NTSTATUS status;
94 bool ret = true;
95 int fnum;
96 const char *fname = BASEDIR "\\test.txt";
98 if (!TARGET_SUPPORTS_SMBLOCK(tctx))
99 torture_skip(tctx, "Target does not support the SMBlock PDU");
101 if (!torture_setup_dir(cli, BASEDIR)) {
102 return false;
105 torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
106 io.generic.level = RAW_LOCK_LOCK;
108 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
109 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
110 "Failed to create %s - %s\n",
111 fname, smbcli_errstr(cli->tree)));
113 torture_comment(tctx, "Trying 0/0 lock\n");
114 io.lock.level = RAW_LOCK_LOCK;
115 io.lock.in.file.fnum = fnum;
116 io.lock.in.count = 0;
117 io.lock.in.offset = 0;
118 status = smb_raw_lock(cli->tree, &io);
119 CHECK_STATUS(status, NT_STATUS_OK);
120 cli->session->pid++;
121 status = smb_raw_lock(cli->tree, &io);
122 CHECK_STATUS(status, NT_STATUS_OK);
123 cli->session->pid--;
124 io.lock.level = RAW_LOCK_UNLOCK;
125 status = smb_raw_lock(cli->tree, &io);
126 CHECK_STATUS(status, NT_STATUS_OK);
128 torture_comment(tctx, "Trying 0/1 lock\n");
129 io.lock.level = RAW_LOCK_LOCK;
130 io.lock.in.file.fnum = fnum;
131 io.lock.in.count = 1;
132 io.lock.in.offset = 0;
133 status = smb_raw_lock(cli->tree, &io);
134 CHECK_STATUS(status, NT_STATUS_OK);
135 cli->session->pid++;
136 status = smb_raw_lock(cli->tree, &io);
137 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
138 cli->session->pid--;
139 io.lock.level = RAW_LOCK_UNLOCK;
140 status = smb_raw_lock(cli->tree, &io);
141 CHECK_STATUS(status, NT_STATUS_OK);
142 io.lock.level = RAW_LOCK_UNLOCK;
143 status = smb_raw_lock(cli->tree, &io);
144 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
146 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
147 io.lock.level = RAW_LOCK_LOCK;
148 io.lock.in.file.fnum = fnum;
149 io.lock.in.count = 4000;
150 io.lock.in.offset = 0xEEFFFFFF;
151 status = smb_raw_lock(cli->tree, &io);
152 CHECK_STATUS(status, NT_STATUS_OK);
153 cli->session->pid++;
154 status = smb_raw_lock(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
156 cli->session->pid--;
157 io.lock.level = RAW_LOCK_UNLOCK;
158 status = smb_raw_lock(cli->tree, &io);
159 CHECK_STATUS(status, NT_STATUS_OK);
160 io.lock.level = RAW_LOCK_UNLOCK;
161 status = smb_raw_lock(cli->tree, &io);
162 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
164 torture_comment(tctx, "Trying 0xEF000000 lock\n");
165 io.lock.level = RAW_LOCK_LOCK;
166 io.lock.in.file.fnum = fnum;
167 io.lock.in.count = 4000;
168 io.lock.in.offset = 0xEEFFFFFF;
169 status = smb_raw_lock(cli->tree, &io);
170 CHECK_STATUS(status, NT_STATUS_OK);
171 cli->session->pid++;
172 status = smb_raw_lock(cli->tree, &io);
173 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
174 cli->session->pid--;
175 io.lock.level = RAW_LOCK_UNLOCK;
176 status = smb_raw_lock(cli->tree, &io);
177 CHECK_STATUS(status, NT_STATUS_OK);
178 io.lock.level = RAW_LOCK_UNLOCK;
179 status = smb_raw_lock(cli->tree, &io);
180 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
182 torture_comment(tctx, "Trying max lock\n");
183 io.lock.level = RAW_LOCK_LOCK;
184 io.lock.in.file.fnum = fnum;
185 io.lock.in.count = 4000;
186 io.lock.in.offset = 0xEF000000;
187 status = smb_raw_lock(cli->tree, &io);
188 CHECK_STATUS(status, NT_STATUS_OK);
189 cli->session->pid++;
190 status = smb_raw_lock(cli->tree, &io);
191 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
192 cli->session->pid--;
193 io.lock.level = RAW_LOCK_UNLOCK;
194 status = smb_raw_lock(cli->tree, &io);
195 CHECK_STATUS(status, NT_STATUS_OK);
196 io.lock.level = RAW_LOCK_UNLOCK;
197 status = smb_raw_lock(cli->tree, &io);
198 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
200 torture_comment(tctx, "Trying wrong pid unlock\n");
201 io.lock.level = RAW_LOCK_LOCK;
202 io.lock.in.file.fnum = fnum;
203 io.lock.in.count = 4002;
204 io.lock.in.offset = 10001;
205 status = smb_raw_lock(cli->tree, &io);
206 CHECK_STATUS(status, NT_STATUS_OK);
207 cli->session->pid++;
208 io.lock.level = RAW_LOCK_UNLOCK;
209 status = smb_raw_lock(cli->tree, &io);
210 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
211 cli->session->pid--;
212 status = smb_raw_lock(cli->tree, &io);
213 CHECK_STATUS(status, NT_STATUS_OK);
215 done:
216 smbcli_close(cli->tree, fnum);
217 smb_raw_exit(cli->session);
218 smbcli_deltree(cli->tree, BASEDIR);
219 return ret;
224 test locking&X ops
226 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
228 union smb_lock io;
229 struct smb_lock_entry lock[1];
230 NTSTATUS status;
231 bool ret = true;
232 int fnum;
233 const char *fname = BASEDIR "\\test.txt";
235 if (!torture_setup_dir(cli, BASEDIR)) {
236 return false;
239 torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
240 io.generic.level = RAW_LOCK_LOCKX;
242 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
243 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
244 "Failed to create %s - %s\n",
245 fname, smbcli_errstr(cli->tree)));
247 io.lockx.level = RAW_LOCK_LOCKX;
248 io.lockx.in.file.fnum = fnum;
249 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
250 io.lockx.in.timeout = 0;
251 io.lockx.in.ulock_cnt = 0;
252 io.lockx.in.lock_cnt = 1;
253 lock[0].pid = cli->session->pid;
254 lock[0].offset = 10;
255 lock[0].count = 1;
256 io.lockx.in.locks = &lock[0];
257 status = smb_raw_lock(cli->tree, &io);
258 CHECK_STATUS(status, NT_STATUS_OK);
261 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
262 io.lockx.in.ulock_cnt = 0;
263 io.lockx.in.lock_cnt = 1;
264 lock[0].count = 4000;
265 lock[0].offset = 0xEEFFFFFF;
266 status = smb_raw_lock(cli->tree, &io);
267 CHECK_STATUS(status, NT_STATUS_OK);
268 lock[0].pid++;
269 status = smb_raw_lock(cli->tree, &io);
270 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
271 lock[0].pid--;
272 io.lockx.in.ulock_cnt = 1;
273 io.lockx.in.lock_cnt = 0;
274 status = smb_raw_lock(cli->tree, &io);
275 CHECK_STATUS(status, NT_STATUS_OK);
276 status = smb_raw_lock(cli->tree, &io);
277 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
279 torture_comment(tctx, "Trying 0xEF000000 lock\n");
280 io.lockx.in.ulock_cnt = 0;
281 io.lockx.in.lock_cnt = 1;
282 lock[0].count = 4000;
283 lock[0].offset = 0xEF000000;
284 status = smb_raw_lock(cli->tree, &io);
285 CHECK_STATUS(status, NT_STATUS_OK);
286 lock[0].pid++;
287 status = smb_raw_lock(cli->tree, &io);
288 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
289 lock[0].pid--;
290 io.lockx.in.ulock_cnt = 1;
291 io.lockx.in.lock_cnt = 0;
292 status = smb_raw_lock(cli->tree, &io);
293 CHECK_STATUS(status, NT_STATUS_OK);
294 status = smb_raw_lock(cli->tree, &io);
295 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
297 torture_comment(tctx, "Trying zero lock\n");
298 io.lockx.in.ulock_cnt = 0;
299 io.lockx.in.lock_cnt = 1;
300 lock[0].count = 0;
301 lock[0].offset = ~0;
302 status = smb_raw_lock(cli->tree, &io);
303 CHECK_STATUS(status, NT_STATUS_OK);
304 lock[0].pid++;
305 status = smb_raw_lock(cli->tree, &io);
306 CHECK_STATUS(status, NT_STATUS_OK);
307 lock[0].pid--;
308 io.lockx.in.ulock_cnt = 1;
309 io.lockx.in.lock_cnt = 0;
310 status = smb_raw_lock(cli->tree, &io);
311 CHECK_STATUS(status, NT_STATUS_OK);
312 status = smb_raw_lock(cli->tree, &io);
313 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
315 torture_comment(tctx, "Trying max lock\n");
316 io.lockx.in.ulock_cnt = 0;
317 io.lockx.in.lock_cnt = 1;
318 lock[0].count = 0;
319 lock[0].offset = ~0;
320 status = smb_raw_lock(cli->tree, &io);
321 CHECK_STATUS(status, NT_STATUS_OK);
322 lock[0].pid++;
323 status = smb_raw_lock(cli->tree, &io);
324 CHECK_STATUS(status, NT_STATUS_OK);
325 lock[0].pid--;
326 io.lockx.in.ulock_cnt = 1;
327 io.lockx.in.lock_cnt = 0;
328 status = smb_raw_lock(cli->tree, &io);
329 CHECK_STATUS(status, NT_STATUS_OK);
330 status = smb_raw_lock(cli->tree, &io);
331 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
333 torture_comment(tctx, "Trying 2^63\n");
334 io.lockx.in.ulock_cnt = 0;
335 io.lockx.in.lock_cnt = 1;
336 lock[0].count = 1;
337 lock[0].offset = 1;
338 lock[0].offset <<= 63;
339 status = smb_raw_lock(cli->tree, &io);
340 CHECK_STATUS(status, NT_STATUS_OK);
341 lock[0].pid++;
342 status = smb_raw_lock(cli->tree, &io);
343 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
344 lock[0].pid--;
345 io.lockx.in.ulock_cnt = 1;
346 io.lockx.in.lock_cnt = 0;
347 status = smb_raw_lock(cli->tree, &io);
348 CHECK_STATUS(status, NT_STATUS_OK);
349 status = smb_raw_lock(cli->tree, &io);
350 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
352 torture_comment(tctx, "Trying 2^63 - 1\n");
353 io.lockx.in.ulock_cnt = 0;
354 io.lockx.in.lock_cnt = 1;
355 lock[0].count = 1;
356 lock[0].offset = 1;
357 lock[0].offset <<= 63;
358 lock[0].offset--;
359 status = smb_raw_lock(cli->tree, &io);
360 CHECK_STATUS(status, NT_STATUS_OK);
361 lock[0].pid++;
362 status = smb_raw_lock(cli->tree, &io);
363 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
364 lock[0].pid--;
365 io.lockx.in.ulock_cnt = 1;
366 io.lockx.in.lock_cnt = 0;
367 status = smb_raw_lock(cli->tree, &io);
368 CHECK_STATUS(status, NT_STATUS_OK);
369 status = smb_raw_lock(cli->tree, &io);
370 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
372 torture_comment(tctx, "Trying max lock 2\n");
373 io.lockx.in.ulock_cnt = 0;
374 io.lockx.in.lock_cnt = 1;
375 lock[0].count = 1;
376 lock[0].offset = ~0;
377 status = smb_raw_lock(cli->tree, &io);
378 CHECK_STATUS(status, NT_STATUS_OK);
379 lock[0].pid++;
380 lock[0].count = 2;
381 status = smb_raw_lock(cli->tree, &io);
382 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
383 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
384 else
385 CHECK_STATUS(status, NT_STATUS_OK);
386 lock[0].pid--;
387 io.lockx.in.ulock_cnt = 1;
388 io.lockx.in.lock_cnt = 0;
389 lock[0].count = 1;
390 status = smb_raw_lock(cli->tree, &io);
392 CHECK_STATUS(status, NT_STATUS_OK);
393 status = smb_raw_lock(cli->tree, &io);
394 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
396 done:
397 smbcli_close(cli->tree, fnum);
398 smb_raw_exit(cli->session);
399 smbcli_deltree(cli->tree, BASEDIR);
400 return ret;
404 test high pid
406 static bool test_pidhigh(struct torture_context *tctx,
407 struct smbcli_state *cli)
409 union smb_lock io;
410 struct smb_lock_entry lock[1];
411 NTSTATUS status;
412 bool ret = true;
413 int fnum;
414 const char *fname = BASEDIR "\\test.txt";
415 uint8_t c = 1;
417 if (!torture_setup_dir(cli, BASEDIR)) {
418 return false;
421 torture_comment(tctx, "Testing high pid\n");
422 io.generic.level = RAW_LOCK_LOCKX;
424 cli->session->pid = 1;
426 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
427 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
428 "Failed to create %s - %s\n",
429 fname, smbcli_errstr(cli->tree)));
431 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
432 torture_result(tctx, TORTURE_FAIL,
433 "Failed to write 1 byte - %s\n",
434 smbcli_errstr(cli->tree));
435 ret = false;
436 goto done;
439 io.lockx.level = RAW_LOCK_LOCKX;
440 io.lockx.in.file.fnum = fnum;
441 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
442 io.lockx.in.timeout = 0;
443 io.lockx.in.ulock_cnt = 0;
444 io.lockx.in.lock_cnt = 1;
445 lock[0].pid = cli->session->pid;
446 lock[0].offset = 0;
447 lock[0].count = 0xFFFFFFFF;
448 io.lockx.in.locks = &lock[0];
449 status = smb_raw_lock(cli->tree, &io);
450 CHECK_STATUS(status, NT_STATUS_OK);
452 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
453 torture_result(tctx, TORTURE_FAIL,
454 "Failed to read 1 byte - %s\n",
455 smbcli_errstr(cli->tree));
456 ret = false;
457 goto done;
460 cli->session->pid = 2;
462 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
463 torture_result(tctx, TORTURE_FAIL,
464 "pid is incorrect handled for read with lock!\n");
465 ret = false;
466 goto done;
469 cli->session->pid = 0x10001;
471 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
472 torture_result(tctx, TORTURE_FAIL,
473 "High pid is used on this server!\n");
474 ret = false;
475 } else {
476 torture_warning(tctx, "High pid is not used on this server (correct)\n");
479 done:
480 smbcli_close(cli->tree, fnum);
481 smb_raw_exit(cli->session);
482 smbcli_deltree(cli->tree, BASEDIR);
483 return ret;
488 test locking&X async operation
490 static bool test_async(struct torture_context *tctx,
491 struct smbcli_state *cli)
493 struct smbcli_session *session;
494 struct smb_composite_sesssetup setup;
495 struct smbcli_tree *tree;
496 union smb_tcon tcon;
497 const char *host, *share;
498 union smb_lock io;
499 struct smb_lock_entry lock[2];
500 NTSTATUS status;
501 bool ret = true;
502 int fnum;
503 const char *fname = BASEDIR "\\test.txt";
504 time_t t;
505 struct smbcli_request *req, *req2;
506 struct smbcli_session_options options;
508 if (!torture_setup_dir(cli, BASEDIR)) {
509 return false;
512 lp_smbcli_session_options(tctx->lp_ctx, &options);
514 torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
515 io.generic.level = RAW_LOCK_LOCKX;
517 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
518 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
519 "Failed to create %s - %s\n",
520 fname, smbcli_errstr(cli->tree)));
522 io.lockx.level = RAW_LOCK_LOCKX;
523 io.lockx.in.file.fnum = fnum;
524 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
525 io.lockx.in.timeout = 0;
526 io.lockx.in.ulock_cnt = 0;
527 io.lockx.in.lock_cnt = 1;
528 lock[0].pid = cli->session->pid;
529 lock[0].offset = 100;
530 lock[0].count = 10;
531 lock[1].pid = cli->session->pid;
532 lock[1].offset = 110;
533 lock[1].count = 10;
534 io.lockx.in.locks = &lock[0];
535 status = smb_raw_lock(cli->tree, &io);
536 CHECK_STATUS(status, NT_STATUS_OK);
538 t = time(NULL);
540 torture_comment(tctx, "testing cancel by CANCEL_LOCK\n");
542 /* setup a timed lock */
543 io.lockx.in.timeout = 10000;
544 req = smb_raw_lock_send(cli->tree, &io);
545 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
546 "Failed to setup timed lock (%s)\n", __location__));
548 /* cancel the wrong range */
549 lock[0].offset = 0;
550 io.lockx.in.timeout = 0;
551 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
552 status = smb_raw_lock(cli->tree, &io);
553 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
555 /* cancel with the wrong bits set */
556 lock[0].offset = 100;
557 io.lockx.in.timeout = 0;
558 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
559 status = smb_raw_lock(cli->tree, &io);
560 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
562 /* cancel the right range */
563 lock[0].offset = 100;
564 io.lockx.in.timeout = 0;
565 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
566 status = smb_raw_lock(cli->tree, &io);
567 CHECK_STATUS(status, NT_STATUS_OK);
569 /* receive the failed lock request */
570 status = smbcli_request_simple_recv(req);
571 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
573 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
574 "lock cancel was not immediate (%s)\n", __location__));
576 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
577 * if the lock vector contains one entry. When given mutliple cancel
578 * requests in a single PDU we expect the server to return an
579 * error. Samba4 handles this correctly. Windows servers seem to
580 * accept the request but only cancel the first lock. Samba3
581 * now does what Windows does (JRA).
583 torture_comment(tctx, "testing multiple cancel\n");
585 /* acquire second lock */
586 io.lockx.in.timeout = 0;
587 io.lockx.in.ulock_cnt = 0;
588 io.lockx.in.lock_cnt = 1;
589 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
590 io.lockx.in.locks = &lock[1];
591 status = smb_raw_lock(cli->tree, &io);
592 CHECK_STATUS(status, NT_STATUS_OK);
594 /* setup 2 timed locks */
595 t = time(NULL);
596 io.lockx.in.timeout = 10000;
597 io.lockx.in.lock_cnt = 1;
598 io.lockx.in.locks = &lock[0];
599 req = smb_raw_lock_send(cli->tree, &io);
600 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
601 "Failed to setup timed lock (%s)\n", __location__));
602 io.lockx.in.locks = &lock[1];
603 req2 = smb_raw_lock_send(cli->tree, &io);
604 torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
605 "Failed to setup timed lock (%s)\n", __location__));
607 /* try to cancel both locks in the same packet */
608 io.lockx.in.timeout = 0;
609 io.lockx.in.lock_cnt = 2;
610 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
611 io.lockx.in.locks = lock;
612 status = smb_raw_lock(cli->tree, &io);
613 CHECK_STATUS(status, NT_STATUS_OK);
615 torture_warning(tctx, "Target server accepted a lock cancel "
616 "request with multiple locks. This violates "
617 "MS-CIFS 2.2.4.32.1.\n");
619 /* receive the failed lock requests */
620 status = smbcli_request_simple_recv(req);
621 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
623 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
624 "first lock was not cancelled immediately (%s)\n",
625 __location__));
627 /* send cancel to second lock */
628 io.lockx.in.timeout = 0;
629 io.lockx.in.lock_cnt = 1;
630 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK |
631 LOCKING_ANDX_LARGE_FILES;
632 io.lockx.in.locks = &lock[1];
633 status = smb_raw_lock(cli->tree, &io);
634 CHECK_STATUS(status, NT_STATUS_OK);
636 status = smbcli_request_simple_recv(req2);
637 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
639 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
640 "second lock was not cancelled immediately (%s)\n",
641 __location__));
643 /* cleanup the second lock */
644 io.lockx.in.ulock_cnt = 1;
645 io.lockx.in.lock_cnt = 0;
646 io.lockx.in.locks = &lock[1];
647 status = smb_raw_lock(cli->tree, &io);
648 CHECK_STATUS(status, NT_STATUS_OK);
650 /* If a lock request contained multiple ranges and we are cancelling
651 * one while it's still pending, what happens? */
652 torture_comment(tctx, "testing cancel 1/2 lock request\n");
654 /* Send request with two ranges */
655 io.lockx.in.timeout = -1;
656 io.lockx.in.ulock_cnt = 0;
657 io.lockx.in.lock_cnt = 2;
658 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
659 io.lockx.in.locks = lock;
660 req = smb_raw_lock_send(cli->tree, &io);
661 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
662 "Failed to setup pending lock (%s)\n", __location__));
664 /* Try to cancel the first lock range */
665 io.lockx.in.timeout = 0;
666 io.lockx.in.lock_cnt = 1;
667 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
668 io.lockx.in.locks = &lock[0];
669 status = smb_raw_lock(cli->tree, &io);
670 CHECK_STATUS(status, NT_STATUS_OK);
672 /* Locking request should've failed and second range should be
673 * unlocked */
674 status = smbcli_request_simple_recv(req);
675 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
677 io.lockx.in.timeout = 0;
678 io.lockx.in.ulock_cnt = 0;
679 io.lockx.in.lock_cnt = 1;
680 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
681 io.lockx.in.locks = &lock[1];
682 status = smb_raw_lock(cli->tree, &io);
683 CHECK_STATUS(status, NT_STATUS_OK);
685 /* Cleanup both locks */
686 io.lockx.in.ulock_cnt = 2;
687 io.lockx.in.lock_cnt = 0;
688 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
689 io.lockx.in.locks = lock;
690 status = smb_raw_lock(cli->tree, &io);
691 CHECK_STATUS(status, NT_STATUS_OK);
693 torture_comment(tctx, "testing cancel 2/2 lock request\n");
695 /* Lock second range so it contends */
696 io.lockx.in.timeout = 0;
697 io.lockx.in.ulock_cnt = 0;
698 io.lockx.in.lock_cnt = 1;
699 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
700 io.lockx.in.locks = &lock[1];
701 status = smb_raw_lock(cli->tree, &io);
702 CHECK_STATUS(status, NT_STATUS_OK);
704 /* Send request with two ranges */
705 io.lockx.in.timeout = -1;
706 io.lockx.in.ulock_cnt = 0;
707 io.lockx.in.lock_cnt = 2;
708 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
709 io.lockx.in.locks = lock;
710 req = smb_raw_lock_send(cli->tree, &io);
711 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
712 "Failed to setup pending lock (%s)\n", __location__));
714 /* Try to cancel the second lock range */
715 io.lockx.in.timeout = 0;
716 io.lockx.in.lock_cnt = 1;
717 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
718 io.lockx.in.locks = &lock[1];
719 status = smb_raw_lock(cli->tree, &io);
720 CHECK_STATUS(status, NT_STATUS_OK);
722 /* Locking request should've failed and first range should be
723 * unlocked */
724 status = smbcli_request_simple_recv(req);
725 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
727 io.lockx.in.timeout = 0;
728 io.lockx.in.ulock_cnt = 0;
729 io.lockx.in.lock_cnt = 1;
730 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
731 io.lockx.in.locks = &lock[0];
732 status = smb_raw_lock(cli->tree, &io);
733 CHECK_STATUS(status, NT_STATUS_OK);
735 /* Cleanup both locks */
736 io.lockx.in.ulock_cnt = 2;
737 io.lockx.in.lock_cnt = 0;
738 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
739 io.lockx.in.locks = lock;
740 status = smb_raw_lock(cli->tree, &io);
741 CHECK_STATUS(status, NT_STATUS_OK);
743 torture_comment(tctx, "testing cancel by unlock\n");
744 io.lockx.in.ulock_cnt = 0;
745 io.lockx.in.lock_cnt = 1;
746 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
747 io.lockx.in.timeout = 0;
748 io.lockx.in.locks = &lock[0];
749 status = smb_raw_lock(cli->tree, &io);
750 CHECK_STATUS(status, NT_STATUS_OK);
752 io.lockx.in.timeout = 5000;
753 req = smb_raw_lock_send(cli->tree, &io);
754 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
755 "Failed to setup timed lock (%s)\n", __location__));
757 io.lockx.in.ulock_cnt = 1;
758 io.lockx.in.lock_cnt = 0;
759 status = smb_raw_lock(cli->tree, &io);
760 CHECK_STATUS(status, NT_STATUS_OK);
762 t = time(NULL);
763 status = smbcli_request_simple_recv(req);
764 CHECK_STATUS(status, NT_STATUS_OK);
766 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
767 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
768 __location__, (int)(time(NULL)-t)));
770 torture_comment(tctx, "testing cancel by close\n");
771 io.lockx.in.ulock_cnt = 0;
772 io.lockx.in.lock_cnt = 1;
773 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
774 io.lockx.in.timeout = 0;
775 status = smb_raw_lock(cli->tree, &io);
776 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
778 t = time(NULL);
779 io.lockx.in.timeout = 10000;
780 req = smb_raw_lock_send(cli->tree, &io);
781 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
782 "Failed to setup timed lock (%s)\n", __location__));
784 status = smbcli_close(cli->tree, fnum);
785 CHECK_STATUS(status, NT_STATUS_OK);
787 status = smbcli_request_simple_recv(req);
788 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
790 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
791 "lock cancel by close was not immediate (%s)\n", __location__));
793 torture_comment(tctx, "create a new sessions\n");
794 session = smbcli_session_init(cli->transport, tctx, false, options);
795 setup.in.sesskey = cli->transport->negotiate.sesskey;
796 setup.in.capabilities = cli->transport->negotiate.capabilities;
797 setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
798 setup.in.credentials = cmdline_credentials;
799 setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
800 status = smb_composite_sesssetup(session, &setup);
801 CHECK_STATUS(status, NT_STATUS_OK);
802 session->vuid = setup.out.vuid;
804 torture_comment(tctx, "create new tree context\n");
805 share = torture_setting_string(tctx, "share", NULL);
806 host = torture_setting_string(tctx, "host", NULL);
807 tree = smbcli_tree_init(session, tctx, false);
808 tcon.generic.level = RAW_TCON_TCONX;
809 tcon.tconx.in.flags = 0;
810 tcon.tconx.in.password = data_blob(NULL, 0);
811 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
812 tcon.tconx.in.device = "A:";
813 status = smb_raw_tcon(tree, tctx, &tcon);
814 CHECK_STATUS(status, NT_STATUS_OK);
815 tree->tid = tcon.tconx.out.tid;
817 torture_comment(tctx, "testing cancel by exit\n");
818 fname = BASEDIR "\\test_exit.txt";
819 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
820 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
821 "Failed to reopen %s - %s\n",
822 fname, smbcli_errstr(tree)));
824 io.lockx.level = RAW_LOCK_LOCKX;
825 io.lockx.in.file.fnum = fnum;
826 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
827 io.lockx.in.timeout = 0;
828 io.lockx.in.ulock_cnt = 0;
829 io.lockx.in.lock_cnt = 1;
830 lock[0].pid = session->pid;
831 lock[0].offset = 100;
832 lock[0].count = 10;
833 io.lockx.in.locks = &lock[0];
834 status = smb_raw_lock(tree, &io);
835 CHECK_STATUS(status, NT_STATUS_OK);
837 io.lockx.in.ulock_cnt = 0;
838 io.lockx.in.lock_cnt = 1;
839 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
840 io.lockx.in.timeout = 0;
841 status = smb_raw_lock(tree, &io);
842 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
844 io.lockx.in.timeout = 10000;
845 t = time(NULL);
846 req = smb_raw_lock_send(tree, &io);
847 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
848 "Failed to setup timed lock (%s)\n", __location__));
850 status = smb_raw_exit(session);
851 CHECK_STATUS(status, NT_STATUS_OK);
853 status = smbcli_request_simple_recv(req);
854 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
856 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
857 "lock cancel by exit was not immediate (%s)\n", __location__));
859 torture_comment(tctx, "testing cancel by ulogoff\n");
860 fname = BASEDIR "\\test_ulogoff.txt";
861 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
862 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
863 "Failed to reopen %s - %s\n",
864 fname, smbcli_errstr(tree)));
866 io.lockx.level = RAW_LOCK_LOCKX;
867 io.lockx.in.file.fnum = fnum;
868 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
869 io.lockx.in.timeout = 0;
870 io.lockx.in.ulock_cnt = 0;
871 io.lockx.in.lock_cnt = 1;
872 lock[0].pid = session->pid;
873 lock[0].offset = 100;
874 lock[0].count = 10;
875 io.lockx.in.locks = &lock[0];
876 status = smb_raw_lock(tree, &io);
877 CHECK_STATUS(status, NT_STATUS_OK);
879 io.lockx.in.ulock_cnt = 0;
880 io.lockx.in.lock_cnt = 1;
881 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
882 io.lockx.in.timeout = 0;
883 status = smb_raw_lock(tree, &io);
884 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
886 io.lockx.in.timeout = 10000;
887 t = time(NULL);
888 req = smb_raw_lock_send(tree, &io);
889 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
890 "Failed to setup timed lock (%s)\n", __location__));
892 status = smb_raw_ulogoff(session);
893 CHECK_STATUS(status, NT_STATUS_OK);
895 status = smbcli_request_simple_recv(req);
896 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
897 torture_result(tctx, TORTURE_FAIL,
898 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
899 nt_errstr(status));
900 smb_tree_disconnect(tree);
901 smb_raw_exit(session);
902 goto done;
904 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
906 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
907 "lock cancel by ulogoff was not immediate (%s)\n", __location__));
909 torture_comment(tctx, "testing cancel by tdis\n");
910 tree->session = cli->session;
912 fname = BASEDIR "\\test_tdis.txt";
913 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
914 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
915 "Failed to reopen %s - %s\n",
916 fname, smbcli_errstr(tree)));
918 io.lockx.level = RAW_LOCK_LOCKX;
919 io.lockx.in.file.fnum = fnum;
920 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
921 io.lockx.in.timeout = 0;
922 io.lockx.in.ulock_cnt = 0;
923 io.lockx.in.lock_cnt = 1;
924 lock[0].pid = cli->session->pid;
925 lock[0].offset = 100;
926 lock[0].count = 10;
927 io.lockx.in.locks = &lock[0];
928 status = smb_raw_lock(tree, &io);
929 CHECK_STATUS(status, NT_STATUS_OK);
931 status = smb_raw_lock(tree, &io);
932 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
934 io.lockx.in.timeout = 10000;
935 t = time(NULL);
936 req = smb_raw_lock_send(tree, &io);
937 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
938 "Failed to setup timed lock (%s)\n", __location__));
940 status = smb_tree_disconnect(tree);
941 CHECK_STATUS(status, NT_STATUS_OK);
943 status = smbcli_request_simple_recv(req);
944 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
946 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
947 "lock cancel by tdis was not immediate (%s)\n", __location__));
949 done:
950 smb_raw_exit(cli->session);
951 smbcli_deltree(cli->tree, BASEDIR);
952 return ret;
956 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
958 static bool test_errorcode(struct torture_context *tctx,
959 struct smbcli_state *cli)
961 union smb_lock io;
962 union smb_open op;
963 struct smb_lock_entry lock[2];
964 NTSTATUS status;
965 bool ret = true;
966 int fnum, fnum2;
967 const char *fname;
968 struct smbcli_request *req;
969 time_t start;
970 int t;
971 int delay;
972 uint16_t deny_mode = 0;
974 if (!torture_setup_dir(cli, BASEDIR)) {
975 return false;
978 torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
980 torture_comment(tctx, "testing with timeout = 0\n");
981 fname = BASEDIR "\\test0.txt";
982 t = 0;
985 * the first run is with t = 0,
986 * the second with t > 0 (=1)
988 next_run:
990 * use the DENY_DOS mode, that creates two fnum's of one low-level
991 * file handle, this demonstrates that the cache is per fnum, not
992 * per file handle
994 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
995 deny_mode = OPENX_MODE_DENY_DOS;
996 else
997 deny_mode = OPENX_MODE_DENY_NONE;
999 op.openx.level = RAW_OPEN_OPENX;
1000 op.openx.in.fname = fname;
1001 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1002 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
1003 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
1004 op.openx.in.search_attrs = 0;
1005 op.openx.in.file_attrs = 0;
1006 op.openx.in.write_time = 0;
1007 op.openx.in.size = 0;
1008 op.openx.in.timeout = 0;
1010 status = smb_raw_open(cli->tree, tctx, &op);
1011 CHECK_STATUS(status, NT_STATUS_OK);
1012 fnum = op.openx.out.file.fnum;
1014 status = smb_raw_open(cli->tree, tctx, &op);
1015 CHECK_STATUS(status, NT_STATUS_OK);
1016 fnum2 = op.openx.out.file.fnum;
1018 io.lockx.level = RAW_LOCK_LOCKX;
1019 io.lockx.in.file.fnum = fnum;
1020 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1021 io.lockx.in.timeout = t;
1022 io.lockx.in.ulock_cnt = 0;
1023 io.lockx.in.lock_cnt = 1;
1024 lock[0].pid = cli->session->pid;
1025 lock[0].offset = 100;
1026 lock[0].count = 10;
1027 io.lockx.in.locks = &lock[0];
1028 status = smb_raw_lock(cli->tree, &io);
1029 CHECK_STATUS(status, NT_STATUS_OK);
1032 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
1033 * this also demonstrates that the error code cache is per file handle
1034 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
1036 io.lockx.in.file.fnum = fnum2;
1037 status = smb_raw_lock(cli->tree, &io);
1038 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1040 io.lockx.in.file.fnum = fnum;
1041 status = smb_raw_lock(cli->tree, &io);
1042 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1044 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
1045 io.lockx.in.file.fnum = fnum;
1046 status = smb_raw_lock(cli->tree, &io);
1047 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1049 io.lockx.in.file.fnum = fnum2;
1050 status = smb_raw_lock(cli->tree, &io);
1051 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1053 io.lockx.in.file.fnum = fnum;
1054 status = smb_raw_lock(cli->tree, &io);
1055 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1057 io.lockx.in.file.fnum = fnum2;
1058 status = smb_raw_lock(cli->tree, &io);
1059 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1061 /* demonstrate that the smbpid doesn't matter */
1062 lock[0].pid++;
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);
1070 lock[0].pid--;
1073 * demonstrate the a successful lock with count = 0 and the same offset,
1074 * doesn't reset the error cache
1076 lock[0].offset = 100;
1077 lock[0].count = 0;
1078 io.lockx.in.file.fnum = fnum;
1079 status = smb_raw_lock(cli->tree, &io);
1080 CHECK_STATUS(status, NT_STATUS_OK);
1082 io.lockx.in.file.fnum = fnum2;
1083 status = smb_raw_lock(cli->tree, &io);
1084 CHECK_STATUS(status, NT_STATUS_OK);
1086 lock[0].offset = 100;
1087 lock[0].count = 10;
1088 io.lockx.in.file.fnum = fnum;
1089 status = smb_raw_lock(cli->tree, &io);
1090 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1092 io.lockx.in.file.fnum = fnum2;
1093 status = smb_raw_lock(cli->tree, &io);
1094 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1097 * demonstrate the a successful lock with count = 0 and outside the locked range,
1098 * doesn't reset the error cache
1100 lock[0].offset = 110;
1101 lock[0].count = 0;
1102 io.lockx.in.file.fnum = fnum;
1103 status = smb_raw_lock(cli->tree, &io);
1104 CHECK_STATUS(status, NT_STATUS_OK);
1106 io.lockx.in.file.fnum = fnum2;
1107 status = smb_raw_lock(cli->tree, &io);
1108 CHECK_STATUS(status, NT_STATUS_OK);
1110 lock[0].offset = 100;
1111 lock[0].count = 10;
1112 io.lockx.in.file.fnum = fnum;
1113 status = smb_raw_lock(cli->tree, &io);
1114 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1116 io.lockx.in.file.fnum = fnum2;
1117 status = smb_raw_lock(cli->tree, &io);
1118 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1120 lock[0].offset = 99;
1121 lock[0].count = 0;
1122 io.lockx.in.file.fnum = fnum;
1123 status = smb_raw_lock(cli->tree, &io);
1124 CHECK_STATUS(status, NT_STATUS_OK);
1126 io.lockx.in.file.fnum = fnum2;
1127 status = smb_raw_lock(cli->tree, &io);
1128 CHECK_STATUS(status, NT_STATUS_OK);
1130 lock[0].offset = 100;
1131 lock[0].count = 10;
1132 io.lockx.in.file.fnum = fnum;
1133 status = smb_raw_lock(cli->tree, &io);
1134 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1136 io.lockx.in.file.fnum = fnum2;
1137 status = smb_raw_lock(cli->tree, &io);
1138 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1140 /* demonstrate that a changing count doesn't reset the error cache */
1141 lock[0].offset = 100;
1142 lock[0].count = 5;
1143 io.lockx.in.file.fnum = fnum;
1144 status = smb_raw_lock(cli->tree, &io);
1145 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1147 io.lockx.in.file.fnum = fnum2;
1148 status = smb_raw_lock(cli->tree, &io);
1149 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1151 lock[0].offset = 100;
1152 lock[0].count = 15;
1153 io.lockx.in.file.fnum = fnum;
1154 status = smb_raw_lock(cli->tree, &io);
1155 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1157 io.lockx.in.file.fnum = fnum2;
1158 status = smb_raw_lock(cli->tree, &io);
1159 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1162 * demonstrate the a lock with count = 0 and inside the locked range,
1163 * fails and resets the error cache
1165 lock[0].offset = 101;
1166 lock[0].count = 0;
1167 io.lockx.in.file.fnum = fnum;
1168 status = smb_raw_lock(cli->tree, &io);
1169 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1170 status = smb_raw_lock(cli->tree, &io);
1171 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1173 io.lockx.in.file.fnum = fnum2;
1174 status = smb_raw_lock(cli->tree, &io);
1175 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1176 status = smb_raw_lock(cli->tree, &io);
1177 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1179 lock[0].offset = 100;
1180 lock[0].count = 10;
1181 io.lockx.in.file.fnum = fnum;
1182 status = smb_raw_lock(cli->tree, &io);
1183 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1184 status = smb_raw_lock(cli->tree, &io);
1185 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1187 io.lockx.in.file.fnum = fnum2;
1188 status = smb_raw_lock(cli->tree, &io);
1189 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1190 status = smb_raw_lock(cli->tree, &io);
1191 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1193 /* demonstrate the a changing offset, resets the error cache */
1194 lock[0].offset = 105;
1195 lock[0].count = 10;
1196 io.lockx.in.file.fnum = fnum;
1197 status = smb_raw_lock(cli->tree, &io);
1198 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1199 status = smb_raw_lock(cli->tree, &io);
1200 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1202 io.lockx.in.file.fnum = fnum2;
1203 status = smb_raw_lock(cli->tree, &io);
1204 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1205 status = smb_raw_lock(cli->tree, &io);
1206 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1208 lock[0].offset = 100;
1209 lock[0].count = 10;
1210 io.lockx.in.file.fnum = fnum;
1211 status = smb_raw_lock(cli->tree, &io);
1212 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1213 status = smb_raw_lock(cli->tree, &io);
1214 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1216 io.lockx.in.file.fnum = fnum2;
1217 status = smb_raw_lock(cli->tree, &io);
1218 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1219 status = smb_raw_lock(cli->tree, &io);
1220 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1222 lock[0].offset = 95;
1223 lock[0].count = 9;
1224 io.lockx.in.file.fnum = fnum;
1225 status = smb_raw_lock(cli->tree, &io);
1226 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1227 status = smb_raw_lock(cli->tree, &io);
1228 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1230 io.lockx.in.file.fnum = fnum2;
1231 status = smb_raw_lock(cli->tree, &io);
1232 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1233 status = smb_raw_lock(cli->tree, &io);
1234 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1236 lock[0].offset = 100;
1237 lock[0].count = 10;
1238 io.lockx.in.file.fnum = fnum;
1239 status = smb_raw_lock(cli->tree, &io);
1240 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1241 status = smb_raw_lock(cli->tree, &io);
1242 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1244 io.lockx.in.file.fnum = fnum2;
1245 status = smb_raw_lock(cli->tree, &io);
1246 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1247 status = smb_raw_lock(cli->tree, &io);
1248 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1251 * demonstrate the a successful lock in a different range,
1252 * doesn't reset the cache, the failing lock on the 2nd handle
1253 * resets the cache
1255 lock[0].offset = 120;
1256 lock[0].count = 15;
1257 io.lockx.in.file.fnum = fnum;
1258 status = smb_raw_lock(cli->tree, &io);
1259 CHECK_STATUS(status, NT_STATUS_OK);
1261 io.lockx.in.file.fnum = fnum2;
1262 status = smb_raw_lock(cli->tree, &io);
1263 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1265 lock[0].offset = 100;
1266 lock[0].count = 10;
1267 io.lockx.in.file.fnum = fnum;
1268 status = smb_raw_lock(cli->tree, &io);
1269 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1270 status = smb_raw_lock(cli->tree, &io);
1271 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1273 io.lockx.in.file.fnum = fnum2;
1274 status = smb_raw_lock(cli->tree, &io);
1275 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1276 status = smb_raw_lock(cli->tree, &io);
1277 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1279 /* end of the loop */
1280 if (t == 0) {
1281 smb_raw_exit(cli->session);
1282 t = 1;
1283 torture_comment(tctx, "testing with timeout > 0 (=%d)\n",
1285 fname = BASEDIR "\\test1.txt";
1286 goto next_run;
1289 t = 4000;
1290 torture_comment(tctx, "testing special cases with timeout > 0 (=%d)\n",
1294 * the following 3 test sections demonstrate that
1295 * the cache is only set when the error is reported
1296 * to the client (after the timeout went by)
1298 smb_raw_exit(cli->session);
1299 torture_comment(tctx, "testing a conflict while a lock is pending\n");
1300 fname = BASEDIR "\\test2.txt";
1301 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1302 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1303 "Failed to reopen %s - %s\n",
1304 fname, smbcli_errstr(cli->tree)));
1306 io.lockx.level = RAW_LOCK_LOCKX;
1307 io.lockx.in.file.fnum = fnum;
1308 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1309 io.lockx.in.timeout = 0;
1310 io.lockx.in.ulock_cnt = 0;
1311 io.lockx.in.lock_cnt = 1;
1312 lock[0].pid = cli->session->pid;
1313 lock[0].offset = 100;
1314 lock[0].count = 10;
1315 io.lockx.in.locks = &lock[0];
1316 status = smb_raw_lock(cli->tree, &io);
1317 CHECK_STATUS(status, NT_STATUS_OK);
1319 start = time(NULL);
1320 io.lockx.in.timeout = t;
1321 req = smb_raw_lock_send(cli->tree, &io);
1322 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1323 "Failed to setup timed lock (%s)\n", __location__));
1325 io.lockx.in.timeout = 0;
1326 lock[0].offset = 105;
1327 lock[0].count = 10;
1328 status = smb_raw_lock(cli->tree, &io);
1329 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1331 status = smbcli_request_simple_recv(req);
1332 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1334 delay = t / 1000;
1335 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1336 delay /= 2;
1339 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1340 "lock comes back to early timeout[%d] delay[%d]"
1341 "(%s)\n", t, delay, __location__));
1343 status = smb_raw_lock(cli->tree, &io);
1344 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1346 smbcli_close(cli->tree, fnum);
1347 fname = BASEDIR "\\test3.txt";
1348 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1349 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1350 "Failed to reopen %s - %s\n",
1351 fname, smbcli_errstr(cli->tree)));
1353 io.lockx.level = RAW_LOCK_LOCKX;
1354 io.lockx.in.file.fnum = fnum;
1355 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1356 io.lockx.in.timeout = 0;
1357 io.lockx.in.ulock_cnt = 0;
1358 io.lockx.in.lock_cnt = 1;
1359 lock[0].pid = cli->session->pid;
1360 lock[0].offset = 100;
1361 lock[0].count = 10;
1362 io.lockx.in.locks = &lock[0];
1363 status = smb_raw_lock(cli->tree, &io);
1364 CHECK_STATUS(status, NT_STATUS_OK);
1366 start = time(NULL);
1367 io.lockx.in.timeout = t;
1368 req = smb_raw_lock_send(cli->tree, &io);
1369 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1370 "Failed to setup timed lock (%s)\n", __location__));
1372 io.lockx.in.timeout = 0;
1373 lock[0].offset = 105;
1374 lock[0].count = 10;
1375 status = smb_raw_lock(cli->tree, &io);
1376 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1378 status = smbcli_request_simple_recv(req);
1379 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1381 delay = t / 1000;
1382 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1383 delay /= 2;
1386 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1387 "lock comes back to early timeout[%d] delay[%d]"
1388 "(%s)\n", t, delay, __location__));
1390 lock[0].offset = 100;
1391 lock[0].count = 10;
1392 status = smb_raw_lock(cli->tree, &io);
1393 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1395 smbcli_close(cli->tree, fnum);
1396 fname = BASEDIR "\\test4.txt";
1397 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1398 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1399 "Failed to reopen %s - %s\n",
1400 fname, smbcli_errstr(cli->tree)));
1402 io.lockx.level = RAW_LOCK_LOCKX;
1403 io.lockx.in.file.fnum = fnum;
1404 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1405 io.lockx.in.timeout = 0;
1406 io.lockx.in.ulock_cnt = 0;
1407 io.lockx.in.lock_cnt = 1;
1408 lock[0].pid = cli->session->pid;
1409 lock[0].offset = 100;
1410 lock[0].count = 10;
1411 io.lockx.in.locks = &lock[0];
1412 status = smb_raw_lock(cli->tree, &io);
1413 CHECK_STATUS(status, NT_STATUS_OK);
1415 start = time(NULL);
1416 io.lockx.in.timeout = t;
1417 req = smb_raw_lock_send(cli->tree, &io);
1418 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1419 "Failed to setup timed lock (%s)\n", __location__));
1421 io.lockx.in.timeout = 0;
1422 status = smb_raw_lock(cli->tree, &io);
1423 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1425 status = smbcli_request_simple_recv(req);
1426 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1428 delay = t / 1000;
1429 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1430 delay /= 2;
1433 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1434 "lock comes back to early timeout[%d] delay[%d]"
1435 "(%s)\n", t, delay, __location__));
1437 status = smb_raw_lock(cli->tree, &io);
1438 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1440 done:
1441 smb_raw_exit(cli->session);
1442 smbcli_deltree(cli->tree, BASEDIR);
1443 return ret;
1448 test LOCKING_ANDX_CHANGE_LOCKTYPE
1450 static bool test_changetype(struct torture_context *tctx,
1451 struct smbcli_state *cli)
1453 union smb_lock io;
1454 struct smb_lock_entry lock[2];
1455 NTSTATUS status;
1456 bool ret = true;
1457 int fnum;
1458 uint8_t c = 0;
1459 const char *fname = BASEDIR "\\test.txt";
1461 if (!torture_setup_dir(cli, BASEDIR)) {
1462 return false;
1465 torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1466 io.generic.level = RAW_LOCK_LOCKX;
1468 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1469 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1470 "Failed to create %s - %s\n",
1471 fname, smbcli_errstr(cli->tree)));
1473 io.lockx.level = RAW_LOCK_LOCKX;
1474 io.lockx.in.file.fnum = fnum;
1475 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1476 io.lockx.in.timeout = 0;
1477 io.lockx.in.ulock_cnt = 0;
1478 io.lockx.in.lock_cnt = 1;
1479 lock[0].pid = cli->session->pid;
1480 lock[0].offset = 100;
1481 lock[0].count = 10;
1482 io.lockx.in.locks = &lock[0];
1483 status = smb_raw_lock(cli->tree, &io);
1484 CHECK_STATUS(status, NT_STATUS_OK);
1486 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1487 torture_result(tctx, TORTURE_FAIL,
1488 "allowed write on read locked region (%s)\n", __location__);
1489 ret = false;
1490 goto done;
1493 /* windows server don't seem to support this */
1494 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1495 status = smb_raw_lock(cli->tree, &io);
1496 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1498 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1499 torture_result(tctx, TORTURE_FAIL,
1500 "allowed write after lock change (%s)\n", __location__);
1501 ret = false;
1502 goto done;
1505 done:
1506 smbcli_close(cli->tree, fnum);
1507 smb_raw_exit(cli->session);
1508 smbcli_deltree(cli->tree, BASEDIR);
1509 return ret;
1512 struct double_lock_test {
1513 struct smb_lock_entry lock1;
1514 struct smb_lock_entry lock2;
1515 NTSTATUS exp_status;
1519 * Tests zero byte locks.
1521 static struct double_lock_test zero_byte_tests[] = {
1522 /* {pid, offset, count}, {pid, offset, count}, status */
1524 /** First, takes a zero byte lock at offset 10. Then:
1525 * - Taking 0 byte lock at 10 should succeed.
1526 * - Taking 1 byte locks at 9,10,11 should succeed.
1527 * - Taking 2 byte lock at 9 should fail.
1528 * - Taking 2 byte lock at 10 should succeed.
1529 * - Taking 3 byte lock at 9 should fail.
1531 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1532 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
1533 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1534 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1535 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
1536 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1537 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
1539 /** Same, but opposite order. */
1540 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1541 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
1542 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1543 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1544 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1545 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1546 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1548 /** Zero zero case. */
1549 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
1552 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
1554 union smb_lock io;
1555 NTSTATUS status;
1556 bool ret = true;
1557 int fnum, i;
1558 const char *fname = BASEDIR "\\zero.txt";
1560 torture_comment(tctx, "Testing zero length byte range locks:\n");
1562 if (!torture_setup_dir(cli, BASEDIR)) {
1563 return false;
1566 io.generic.level = RAW_LOCK_LOCKX;
1568 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1569 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1570 "Failed to create %s - %s\n",
1571 fname, smbcli_errstr(cli->tree)));
1573 /* Setup initial parameters */
1574 io.lockx.level = RAW_LOCK_LOCKX;
1575 io.lockx.in.file.fnum = fnum;
1576 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1577 io.lockx.in.timeout = 0;
1579 /* Try every combination of locks in zero_byte_tests. The first lock is
1580 * assumed to succeed. The second lock may contend, depending on the
1581 * expected status. */
1582 for (i = 0;
1583 i < ARRAY_SIZE(zero_byte_tests);
1584 i++) {
1585 torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1586 zero_byte_tests[i].lock1.pid,
1587 zero_byte_tests[i].lock1.offset,
1588 zero_byte_tests[i].lock1.count,
1589 zero_byte_tests[i].lock2.pid,
1590 zero_byte_tests[i].lock2.offset,
1591 zero_byte_tests[i].lock2.count,
1592 nt_errstr(zero_byte_tests[i].exp_status));
1594 /* Lock both locks. */
1595 io.lockx.in.ulock_cnt = 0;
1596 io.lockx.in.lock_cnt = 1;
1598 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1599 &zero_byte_tests[i].lock1);
1600 status = smb_raw_lock(cli->tree, &io);
1601 CHECK_STATUS(status, NT_STATUS_OK);
1603 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1604 &zero_byte_tests[i].lock2);
1605 status = smb_raw_lock(cli->tree, &io);
1607 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1608 NT_STATUS_LOCK_NOT_GRANTED)) {
1609 /* Allow either of the failure messages and keep going
1610 * if we see the wrong status. */
1611 CHECK_STATUS_OR_CONT(status,
1612 NT_STATUS_LOCK_NOT_GRANTED,
1613 NT_STATUS_FILE_LOCK_CONFLICT);
1615 } else {
1616 CHECK_STATUS_CONT(status,
1617 zero_byte_tests[i].exp_status);
1620 /* Unlock both locks. */
1621 io.lockx.in.ulock_cnt = 1;
1622 io.lockx.in.lock_cnt = 0;
1624 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1625 status = smb_raw_lock(cli->tree, &io);
1626 CHECK_STATUS(status, NT_STATUS_OK);
1629 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1630 &zero_byte_tests[i].lock1);
1631 status = smb_raw_lock(cli->tree, &io);
1632 CHECK_STATUS(status, NT_STATUS_OK);
1635 done:
1636 smbcli_close(cli->tree, fnum);
1637 smb_raw_exit(cli->session);
1638 smbcli_deltree(cli->tree, BASEDIR);
1639 return ret;
1642 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1644 union smb_lock io;
1645 NTSTATUS status;
1646 bool ret = true;
1647 int fnum1, fnum2;
1648 const char *fname = BASEDIR "\\unlock.txt";
1649 struct smb_lock_entry lock1;
1650 struct smb_lock_entry lock2;
1652 torture_comment(tctx, "Testing LOCKX unlock:\n");
1654 if (!torture_setup_dir(cli, BASEDIR)) {
1655 return false;
1658 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1659 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1660 "Failed to create %s - %s\n",
1661 fname, smbcli_errstr(cli->tree)));
1663 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1664 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
1665 "Failed to create %s - %s\n",
1666 fname, smbcli_errstr(cli->tree)));
1668 /* Setup initial parameters */
1669 io.lockx.level = RAW_LOCK_LOCKX;
1670 io.lockx.in.timeout = 0;
1672 lock1.pid = cli->session->pid;
1673 lock1.offset = 0;
1674 lock1.count = 10;
1675 lock2.pid = cli->session->pid - 1;
1676 lock2.offset = 0;
1677 lock2.count = 10;
1680 * Take exclusive lock, then unlock it with a shared-unlock call.
1682 torture_comment(tctx, " taking exclusive lock.\n");
1683 io.lockx.in.ulock_cnt = 0;
1684 io.lockx.in.lock_cnt = 1;
1685 io.lockx.in.mode = 0;
1686 io.lockx.in.file.fnum = fnum1;
1687 io.lockx.in.locks = &lock1;
1688 status = smb_raw_lock(cli->tree, &io);
1689 CHECK_STATUS(status, NT_STATUS_OK);
1691 torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
1692 io.lockx.in.ulock_cnt = 1;
1693 io.lockx.in.lock_cnt = 0;
1694 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1695 io.lockx.in.file.fnum = fnum1;
1696 io.lockx.in.locks = &lock1;
1697 status = smb_raw_lock(cli->tree, &io);
1698 CHECK_STATUS(status, NT_STATUS_OK);
1700 torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
1701 io.lockx.in.ulock_cnt = 0;
1702 io.lockx.in.lock_cnt = 1;
1703 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1704 io.lockx.in.file.fnum = fnum2;
1705 io.lockx.in.locks = &lock2;
1706 status = smb_raw_lock(cli->tree, &io);
1707 CHECK_STATUS(status, NT_STATUS_OK);
1710 * Unlock a shared lock with an exclusive-unlock call.
1712 torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
1713 io.lockx.in.ulock_cnt = 1;
1714 io.lockx.in.lock_cnt = 0;
1715 io.lockx.in.mode = 0;
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);
1721 torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
1722 io.lockx.in.ulock_cnt = 0;
1723 io.lockx.in.lock_cnt = 1;
1724 io.lockx.in.mode = 0;
1725 io.lockx.in.file.fnum = fnum1;
1726 io.lockx.in.locks = &lock1;
1727 status = smb_raw_lock(cli->tree, &io);
1728 CHECK_STATUS(status, NT_STATUS_OK);
1730 /* cleanup */
1731 io.lockx.in.ulock_cnt = 1;
1732 io.lockx.in.lock_cnt = 0;
1733 status = smb_raw_lock(cli->tree, &io);
1734 CHECK_STATUS(status, NT_STATUS_OK);
1737 * Test unlocking of 0-byte locks.
1740 torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
1741 "always unlocks the exclusive first.\n");
1742 lock1.pid = cli->session->pid;
1743 lock1.offset = 10;
1744 lock1.count = 0;
1745 lock2.pid = cli->session->pid;
1746 lock2.offset = 5;
1747 lock2.count = 10;
1748 io.lockx.in.ulock_cnt = 0;
1749 io.lockx.in.lock_cnt = 1;
1750 io.lockx.in.file.fnum = fnum1;
1751 io.lockx.in.locks = &lock1;
1753 /* lock 0-byte shared
1754 * Note: Order of the shared/exclusive locks doesn't matter. */
1755 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1756 status = smb_raw_lock(cli->tree, &io);
1757 CHECK_STATUS(status, NT_STATUS_OK);
1759 /* lock 0-byte exclusive */
1760 io.lockx.in.mode = 0;
1761 status = smb_raw_lock(cli->tree, &io);
1762 CHECK_STATUS(status, NT_STATUS_OK);
1764 /* test contention */
1765 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1766 io.lockx.in.locks = &lock2;
1767 io.lockx.in.file.fnum = fnum2;
1768 status = smb_raw_lock(cli->tree, &io);
1769 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1770 NT_STATUS_FILE_LOCK_CONFLICT);
1772 /* unlock */
1773 io.lockx.in.ulock_cnt = 1;
1774 io.lockx.in.lock_cnt = 0;
1775 io.lockx.in.file.fnum = fnum1;
1776 io.lockx.in.locks = &lock1;
1777 status = smb_raw_lock(cli->tree, &io);
1778 CHECK_STATUS(status, NT_STATUS_OK);
1780 /* test - can we take a shared lock? */
1781 io.lockx.in.ulock_cnt = 0;
1782 io.lockx.in.lock_cnt = 1;
1783 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1784 io.lockx.in.file.fnum = fnum2;
1785 io.lockx.in.locks = &lock2;
1786 status = smb_raw_lock(cli->tree, &io);
1788 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1789 * new to Win7, it succeeds in WinXP too), until I can come to a
1790 * resolution as to whether Samba should support this or not. There is
1791 * code to preference unlocking exclusive locks before shared locks,
1792 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1793 if (TARGET_IS_SAMBA3(tctx)) {
1794 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1795 NT_STATUS_FILE_LOCK_CONFLICT);
1796 } else {
1797 CHECK_STATUS(status, NT_STATUS_OK);
1800 /* cleanup */
1801 io.lockx.in.ulock_cnt = 1;
1802 io.lockx.in.lock_cnt = 0;
1803 status = smb_raw_lock(cli->tree, &io);
1805 /* XXX Same as above. */
1806 if (TARGET_IS_SAMBA3(tctx)) {
1807 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1808 } else {
1809 CHECK_STATUS(status, NT_STATUS_OK);
1812 io.lockx.in.file.fnum = fnum1;
1813 io.lockx.in.locks = &lock1;
1814 status = smb_raw_lock(cli->tree, &io);
1815 CHECK_STATUS(status, NT_STATUS_OK);
1817 done:
1818 smbcli_close(cli->tree, fnum1);
1819 smbcli_close(cli->tree, fnum2);
1820 smb_raw_exit(cli->session);
1821 smbcli_deltree(cli->tree, BASEDIR);
1822 return ret;
1825 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1827 union smb_lock io;
1828 NTSTATUS status;
1829 bool ret = true;
1830 int fnum1;
1831 const char *fname = BASEDIR "\\unlock_multiple.txt";
1832 struct smb_lock_entry lock1;
1833 struct smb_lock_entry lock2;
1834 struct smb_lock_entry locks[2];
1836 torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
1838 if (!torture_setup_dir(cli, BASEDIR)) {
1839 return false;
1842 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1843 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1844 "Failed to create %s - %s\n",
1845 fname, smbcli_errstr(cli->tree)));
1847 /* Setup initial parameters */
1848 io.lockx.level = RAW_LOCK_LOCKX;
1849 io.lockx.in.timeout = 0;
1851 lock1.pid = cli->session->pid;
1852 lock1.offset = 0;
1853 lock1.count = 10;
1854 lock2.pid = cli->session->pid;
1855 lock2.offset = 10;
1856 lock2.count = 10;
1858 locks[0] = lock1;
1859 locks[1] = lock2;
1861 io.lockx.in.file.fnum = fnum1;
1862 io.lockx.in.mode = 0; /* exclusive */
1864 /** Test1: Take second lock, but not first. */
1865 torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
1866 "unlocked. \n");
1868 io.lockx.in.ulock_cnt = 0;
1869 io.lockx.in.lock_cnt = 1;
1870 io.lockx.in.locks = &lock2;
1871 status = smb_raw_lock(cli->tree, &io);
1872 CHECK_STATUS(status, NT_STATUS_OK);
1874 /* Try to unlock both locks. */
1875 io.lockx.in.ulock_cnt = 2;
1876 io.lockx.in.lock_cnt = 0;
1877 io.lockx.in.locks = locks;
1879 status = smb_raw_lock(cli->tree, &io);
1880 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1882 /* Second lock should not be unlocked. */
1883 io.lockx.in.ulock_cnt = 0;
1884 io.lockx.in.lock_cnt = 1;
1885 io.lockx.in.locks = &lock2;
1886 status = smb_raw_lock(cli->tree, &io);
1887 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1889 /* cleanup */
1890 io.lockx.in.ulock_cnt = 1;
1891 io.lockx.in.lock_cnt = 0;
1892 io.lockx.in.locks = &lock2;
1893 status = smb_raw_lock(cli->tree, &io);
1894 CHECK_STATUS(status, NT_STATUS_OK);
1896 /** Test2: Take first lock, but not second. */
1897 torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
1898 "unlocked.\n");
1900 io.lockx.in.ulock_cnt = 0;
1901 io.lockx.in.lock_cnt = 1;
1902 io.lockx.in.locks = &lock1;
1903 status = smb_raw_lock(cli->tree, &io);
1904 CHECK_STATUS(status, NT_STATUS_OK);
1906 /* Try to unlock both locks. */
1907 io.lockx.in.ulock_cnt = 2;
1908 io.lockx.in.lock_cnt = 0;
1909 io.lockx.in.locks = locks;
1911 status = smb_raw_lock(cli->tree, &io);
1912 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1914 /* First lock should be unlocked. */
1915 io.lockx.in.ulock_cnt = 0;
1916 io.lockx.in.lock_cnt = 1;
1917 io.lockx.in.locks = &lock1;
1918 status = smb_raw_lock(cli->tree, &io);
1919 CHECK_STATUS(status, NT_STATUS_OK);
1921 /* cleanup */
1922 io.lockx.in.ulock_cnt = 1;
1923 io.lockx.in.lock_cnt = 0;
1924 io.lockx.in.locks = &lock1;
1925 status = smb_raw_lock(cli->tree, &io);
1926 CHECK_STATUS(status, NT_STATUS_OK);
1928 /* Test3: Request 2 locks, second will contend. What happens to the
1929 * first? */
1930 torture_comment(tctx, " request 2 locks, second one will contend. "
1931 "Expect both to fail.\n");
1933 /* Lock the second range */
1934 io.lockx.in.ulock_cnt = 0;
1935 io.lockx.in.lock_cnt = 1;
1936 io.lockx.in.locks = &lock2;
1937 status = smb_raw_lock(cli->tree, &io);
1938 CHECK_STATUS(status, NT_STATUS_OK);
1940 /* Request both locks */
1941 io.lockx.in.ulock_cnt = 0;
1942 io.lockx.in.lock_cnt = 2;
1943 io.lockx.in.locks = locks;
1945 status = smb_raw_lock(cli->tree, &io);
1946 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1948 /* First lock should be unlocked. */
1949 io.lockx.in.ulock_cnt = 0;
1950 io.lockx.in.lock_cnt = 1;
1951 io.lockx.in.locks = &lock1;
1952 status = smb_raw_lock(cli->tree, &io);
1953 CHECK_STATUS(status, NT_STATUS_OK);
1955 /* cleanup */
1956 io.lockx.in.ulock_cnt = 2;
1957 io.lockx.in.lock_cnt = 0;
1958 io.lockx.in.locks = locks;
1959 status = smb_raw_lock(cli->tree, &io);
1960 CHECK_STATUS(status, NT_STATUS_OK);
1962 /* Test4: Request unlock and lock. The lock contends, is the unlock
1963 * then re-locked? */
1964 torture_comment(tctx, " request unlock and lock, second one will "
1965 "contend. Expect the unlock to succeed.\n");
1967 /* Lock both ranges */
1968 io.lockx.in.ulock_cnt = 0;
1969 io.lockx.in.lock_cnt = 2;
1970 io.lockx.in.locks = locks;
1971 status = smb_raw_lock(cli->tree, &io);
1972 CHECK_STATUS(status, NT_STATUS_OK);
1974 /* Attempt to unlock the first range and lock the second */
1975 io.lockx.in.ulock_cnt = 1;
1976 io.lockx.in.lock_cnt = 1;
1977 io.lockx.in.locks = locks;
1978 status = smb_raw_lock(cli->tree, &io);
1979 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1981 /* The first lock should've been unlocked */
1982 io.lockx.in.ulock_cnt = 0;
1983 io.lockx.in.lock_cnt = 1;
1984 io.lockx.in.locks = &lock1;
1985 status = smb_raw_lock(cli->tree, &io);
1986 CHECK_STATUS(status, NT_STATUS_OK);
1988 /* cleanup */
1989 io.lockx.in.ulock_cnt = 2;
1990 io.lockx.in.lock_cnt = 0;
1991 io.lockx.in.locks = locks;
1992 status = smb_raw_lock(cli->tree, &io);
1993 CHECK_STATUS(status, NT_STATUS_OK);
1995 done:
1996 smbcli_close(cli->tree, fnum1);
1997 smb_raw_exit(cli->session);
1998 smbcli_deltree(cli->tree, BASEDIR);
1999 return ret;
2003 * torture_locktest5 covers stacking pretty well, but its missing two tests:
2004 * - stacking an exclusive on top of shared fails
2005 * - stacking two exclusives fail
2007 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
2009 union smb_lock io;
2010 NTSTATUS status;
2011 bool ret = true;
2012 int fnum1;
2013 const char *fname = BASEDIR "\\stacking.txt";
2014 struct smb_lock_entry lock1;
2015 struct smb_lock_entry lock2;
2017 torture_comment(tctx, "Testing stacking:\n");
2019 if (!torture_setup_dir(cli, BASEDIR)) {
2020 return false;
2023 io.generic.level = RAW_LOCK_LOCKX;
2025 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2026 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
2027 "Failed to create %s - %s\n",
2028 fname, smbcli_errstr(cli->tree)));
2030 /* Setup initial parameters */
2031 io.lockx.level = RAW_LOCK_LOCKX;
2032 io.lockx.in.timeout = 0;
2034 lock1.pid = cli->session->pid;
2035 lock1.offset = 0;
2036 lock1.count = 10;
2037 lock2.pid = cli->session->pid - 1;
2038 lock2.offset = 0;
2039 lock2.count = 10;
2042 * Try to take a shared lock, then stack an exclusive.
2044 torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
2045 io.lockx.in.file.fnum = fnum1;
2046 io.lockx.in.locks = &lock1;
2048 io.lockx.in.ulock_cnt = 0;
2049 io.lockx.in.lock_cnt = 1;
2050 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
2051 status = smb_raw_lock(cli->tree, &io);
2052 CHECK_STATUS(status, NT_STATUS_OK);
2054 io.lockx.in.ulock_cnt = 0;
2055 io.lockx.in.lock_cnt = 1;
2056 io.lockx.in.mode = 0;
2057 status = smb_raw_lock(cli->tree, &io);
2058 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
2059 NT_STATUS_FILE_LOCK_CONFLICT);
2061 /* cleanup */
2062 io.lockx.in.ulock_cnt = 1;
2063 io.lockx.in.lock_cnt = 0;
2064 status = smb_raw_lock(cli->tree, &io);
2065 CHECK_STATUS(status, NT_STATUS_OK);
2068 * Prove that two exclusive locks do not stack.
2070 torture_comment(tctx, " two exclusive locks do not stack.\n");
2071 io.lockx.in.ulock_cnt = 0;
2072 io.lockx.in.lock_cnt = 1;
2073 io.lockx.in.mode = 0;
2074 status = smb_raw_lock(cli->tree, &io);
2075 CHECK_STATUS(status, NT_STATUS_OK);
2076 status = smb_raw_lock(cli->tree, &io);
2077 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
2078 NT_STATUS_FILE_LOCK_CONFLICT);
2080 /* cleanup */
2081 io.lockx.in.ulock_cnt = 1;
2082 io.lockx.in.lock_cnt = 0;
2083 status = smb_raw_lock(cli->tree, &io);
2084 CHECK_STATUS(status, NT_STATUS_OK);
2086 done:
2087 smbcli_close(cli->tree, fnum1);
2088 smb_raw_exit(cli->session);
2089 smbcli_deltree(cli->tree, BASEDIR);
2090 return ret;
2094 * Test how 0-byte read requests contend with byte range locks
2096 static bool test_zerobyteread(struct torture_context *tctx,
2097 struct smbcli_state *cli)
2099 union smb_lock io;
2100 union smb_read rd;
2101 NTSTATUS status;
2102 bool ret = true;
2103 int fnum1, fnum2;
2104 const char *fname = BASEDIR "\\zerobyteread.txt";
2105 struct smb_lock_entry lock1;
2106 uint8_t c = 1;
2108 if (!torture_setup_dir(cli, BASEDIR)) {
2109 return false;
2112 io.generic.level = RAW_LOCK_LOCKX;
2114 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2115 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
2116 "Failed to create %s - %s\n",
2117 fname, smbcli_errstr(cli->tree)));
2119 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2120 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
2121 "Failed to create %s - %s\n",
2122 fname, smbcli_errstr(cli->tree)));
2124 /* Setup initial parameters */
2125 io.lockx.level = RAW_LOCK_LOCKX;
2126 io.lockx.in.timeout = 0;
2128 lock1.pid = cli->session->pid;
2129 lock1.offset = 0;
2130 lock1.count = 10;
2132 ZERO_STRUCT(rd);
2133 rd.readx.level = RAW_READ_READX;
2135 torture_comment(tctx, "Testing zero byte read on lock range:\n");
2137 /* Take an exclusive lock */
2138 torture_comment(tctx, " taking exclusive lock.\n");
2139 io.lockx.in.ulock_cnt = 0;
2140 io.lockx.in.lock_cnt = 1;
2141 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2142 io.lockx.in.file.fnum = fnum1;
2143 io.lockx.in.locks = &lock1;
2144 status = smb_raw_lock(cli->tree, &io);
2145 CHECK_STATUS(status, NT_STATUS_OK);
2147 /* Try a zero byte read */
2148 torture_comment(tctx, " reading 0 bytes.\n");
2149 rd.readx.in.file.fnum = fnum2;
2150 rd.readx.in.offset = 5;
2151 rd.readx.in.mincnt = 0;
2152 rd.readx.in.maxcnt = 0;
2153 rd.readx.in.remaining = 0;
2154 rd.readx.in.read_for_execute = false;
2155 rd.readx.out.data = &c;
2156 status = smb_raw_read(cli->tree, &rd);
2157 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2158 "zero byte read did not return 0 bytes");
2159 CHECK_STATUS(status, NT_STATUS_OK);
2161 /* Unlock lock */
2162 io.lockx.in.ulock_cnt = 1;
2163 io.lockx.in.lock_cnt = 0;
2164 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2165 io.lockx.in.file.fnum = fnum1;
2166 io.lockx.in.locks = &lock1;
2167 status = smb_raw_lock(cli->tree, &io);
2168 CHECK_STATUS(status, NT_STATUS_OK);
2170 torture_comment(tctx, "Testing zero byte read on zero byte lock "
2171 "range:\n");
2173 /* Take an exclusive lock */
2174 torture_comment(tctx, " taking exclusive 0-byte lock.\n");
2175 io.lockx.in.ulock_cnt = 0;
2176 io.lockx.in.lock_cnt = 1;
2177 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2178 io.lockx.in.file.fnum = fnum1;
2179 io.lockx.in.locks = &lock1;
2180 lock1.offset = 5;
2181 lock1.count = 0;
2182 status = smb_raw_lock(cli->tree, &io);
2183 CHECK_STATUS(status, NT_STATUS_OK);
2185 /* Try a zero byte read before the lock */
2186 torture_comment(tctx, " reading 0 bytes before the lock.\n");
2187 rd.readx.in.file.fnum = fnum2;
2188 rd.readx.in.offset = 4;
2189 rd.readx.in.mincnt = 0;
2190 rd.readx.in.maxcnt = 0;
2191 rd.readx.in.remaining = 0;
2192 rd.readx.in.read_for_execute = false;
2193 rd.readx.out.data = &c;
2194 status = smb_raw_read(cli->tree, &rd);
2195 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2196 "zero byte read did not return 0 bytes");
2197 CHECK_STATUS(status, NT_STATUS_OK);
2199 /* Try a zero byte read on the lock */
2200 torture_comment(tctx, " reading 0 bytes on the lock.\n");
2201 rd.readx.in.file.fnum = fnum2;
2202 rd.readx.in.offset = 5;
2203 rd.readx.in.mincnt = 0;
2204 rd.readx.in.maxcnt = 0;
2205 rd.readx.in.remaining = 0;
2206 rd.readx.in.read_for_execute = false;
2207 rd.readx.out.data = &c;
2208 status = smb_raw_read(cli->tree, &rd);
2209 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2210 "zero byte read did not return 0 bytes");
2211 CHECK_STATUS(status, NT_STATUS_OK);
2213 /* Try a zero byte read after the lock */
2214 torture_comment(tctx, " reading 0 bytes after the lock.\n");
2215 rd.readx.in.file.fnum = fnum2;
2216 rd.readx.in.offset = 6;
2217 rd.readx.in.mincnt = 0;
2218 rd.readx.in.maxcnt = 0;
2219 rd.readx.in.remaining = 0;
2220 rd.readx.in.read_for_execute = false;
2221 rd.readx.out.data = &c;
2222 status = smb_raw_read(cli->tree, &rd);
2223 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2224 "zero byte read did not return 0 bytes");
2225 CHECK_STATUS(status, NT_STATUS_OK);
2227 /* Unlock lock */
2228 io.lockx.in.ulock_cnt = 1;
2229 io.lockx.in.lock_cnt = 0;
2230 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2231 io.lockx.in.file.fnum = fnum1;
2232 io.lockx.in.locks = &lock1;
2233 status = smb_raw_lock(cli->tree, &io);
2234 CHECK_STATUS(status, NT_STATUS_OK);
2236 done:
2237 smbcli_close(cli->tree, fnum1);
2238 smbcli_close(cli->tree, fnum2);
2239 smb_raw_exit(cli->session);
2240 smbcli_deltree(cli->tree, BASEDIR);
2241 return ret;
2245 basic testing of lock calls
2247 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
2249 struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
2251 torture_suite_add_1smb_test(suite, "lockx", test_lockx);
2252 torture_suite_add_1smb_test(suite, "lock", test_lock);
2253 torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
2254 torture_suite_add_1smb_test(suite, "async", test_async);
2255 torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
2256 torture_suite_add_1smb_test(suite, "changetype", test_changetype);
2258 torture_suite_add_1smb_test(suite, "stacking", test_stacking);
2259 torture_suite_add_1smb_test(suite, "unlock", test_unlock);
2260 torture_suite_add_1smb_test(suite, "multiple_unlock",
2261 test_multiple_unlock);
2262 torture_suite_add_1smb_test(suite, "zerobytelocks",
2263 test_zerobytelocks);
2264 torture_suite_add_1smb_test(suite, "zerobyteread",
2265 test_zerobyteread);
2267 return suite;