s4/torture: fix build warnings by removing unecessary const
[Samba/ekacnet.git] / source4 / torture / raw / lock.c
blob77de1d8abe945b3435f4a014a8e0d4c95f889400
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_SUPPORTS_SMBLOCK(_tctx) \
73 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
74 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
75 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
76 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
77 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
78 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
79 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
80 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
81 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
84 test SMBlock and SMBunlock ops
86 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
88 union smb_lock io;
89 NTSTATUS status;
90 bool ret = true;
91 int fnum;
92 const char *fname = BASEDIR "\\test.txt";
94 if (!TARGET_SUPPORTS_SMBLOCK(tctx))
95 torture_skip(tctx, "Target does not support the SMBlock PDU");
97 if (!torture_setup_dir(cli, BASEDIR)) {
98 return false;
101 torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
102 io.generic.level = RAW_LOCK_LOCK;
104 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
105 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
106 "Failed to create %s - %s\n",
107 fname, smbcli_errstr(cli->tree)));
109 torture_comment(tctx, "Trying 0/0 lock\n");
110 io.lock.level = RAW_LOCK_LOCK;
111 io.lock.in.file.fnum = fnum;
112 io.lock.in.count = 0;
113 io.lock.in.offset = 0;
114 status = smb_raw_lock(cli->tree, &io);
115 CHECK_STATUS(status, NT_STATUS_OK);
116 cli->session->pid++;
117 status = smb_raw_lock(cli->tree, &io);
118 CHECK_STATUS(status, NT_STATUS_OK);
119 cli->session->pid--;
120 io.lock.level = RAW_LOCK_UNLOCK;
121 status = smb_raw_lock(cli->tree, &io);
122 CHECK_STATUS(status, NT_STATUS_OK);
124 torture_comment(tctx, "Trying 0/1 lock\n");
125 io.lock.level = RAW_LOCK_LOCK;
126 io.lock.in.file.fnum = fnum;
127 io.lock.in.count = 1;
128 io.lock.in.offset = 0;
129 status = smb_raw_lock(cli->tree, &io);
130 CHECK_STATUS(status, NT_STATUS_OK);
131 cli->session->pid++;
132 status = smb_raw_lock(cli->tree, &io);
133 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
134 cli->session->pid--;
135 io.lock.level = RAW_LOCK_UNLOCK;
136 status = smb_raw_lock(cli->tree, &io);
137 CHECK_STATUS(status, NT_STATUS_OK);
138 io.lock.level = RAW_LOCK_UNLOCK;
139 status = smb_raw_lock(cli->tree, &io);
140 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
142 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
143 io.lock.level = RAW_LOCK_LOCK;
144 io.lock.in.file.fnum = fnum;
145 io.lock.in.count = 4000;
146 io.lock.in.offset = 0xEEFFFFFF;
147 status = smb_raw_lock(cli->tree, &io);
148 CHECK_STATUS(status, NT_STATUS_OK);
149 cli->session->pid++;
150 status = smb_raw_lock(cli->tree, &io);
151 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
152 cli->session->pid--;
153 io.lock.level = RAW_LOCK_UNLOCK;
154 status = smb_raw_lock(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_OK);
156 io.lock.level = RAW_LOCK_UNLOCK;
157 status = smb_raw_lock(cli->tree, &io);
158 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
160 torture_comment(tctx, "Trying 0xEF000000 lock\n");
161 io.lock.level = RAW_LOCK_LOCK;
162 io.lock.in.file.fnum = fnum;
163 io.lock.in.count = 4000;
164 io.lock.in.offset = 0xEEFFFFFF;
165 status = smb_raw_lock(cli->tree, &io);
166 CHECK_STATUS(status, NT_STATUS_OK);
167 cli->session->pid++;
168 status = smb_raw_lock(cli->tree, &io);
169 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
170 cli->session->pid--;
171 io.lock.level = RAW_LOCK_UNLOCK;
172 status = smb_raw_lock(cli->tree, &io);
173 CHECK_STATUS(status, NT_STATUS_OK);
174 io.lock.level = RAW_LOCK_UNLOCK;
175 status = smb_raw_lock(cli->tree, &io);
176 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
178 torture_comment(tctx, "Trying max lock\n");
179 io.lock.level = RAW_LOCK_LOCK;
180 io.lock.in.file.fnum = fnum;
181 io.lock.in.count = 4000;
182 io.lock.in.offset = 0xEF000000;
183 status = smb_raw_lock(cli->tree, &io);
184 CHECK_STATUS(status, NT_STATUS_OK);
185 cli->session->pid++;
186 status = smb_raw_lock(cli->tree, &io);
187 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
188 cli->session->pid--;
189 io.lock.level = RAW_LOCK_UNLOCK;
190 status = smb_raw_lock(cli->tree, &io);
191 CHECK_STATUS(status, NT_STATUS_OK);
192 io.lock.level = RAW_LOCK_UNLOCK;
193 status = smb_raw_lock(cli->tree, &io);
194 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
196 torture_comment(tctx, "Trying wrong pid unlock\n");
197 io.lock.level = RAW_LOCK_LOCK;
198 io.lock.in.file.fnum = fnum;
199 io.lock.in.count = 4002;
200 io.lock.in.offset = 10001;
201 status = smb_raw_lock(cli->tree, &io);
202 CHECK_STATUS(status, NT_STATUS_OK);
203 cli->session->pid++;
204 io.lock.level = RAW_LOCK_UNLOCK;
205 status = smb_raw_lock(cli->tree, &io);
206 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
207 cli->session->pid--;
208 status = smb_raw_lock(cli->tree, &io);
209 CHECK_STATUS(status, NT_STATUS_OK);
211 done:
212 smbcli_close(cli->tree, fnum);
213 smb_raw_exit(cli->session);
214 smbcli_deltree(cli->tree, BASEDIR);
215 return ret;
220 test locking&X ops
222 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
224 union smb_lock io;
225 struct smb_lock_entry lock[1];
226 NTSTATUS status;
227 bool ret = true;
228 int fnum;
229 const char *fname = BASEDIR "\\test.txt";
231 if (!torture_setup_dir(cli, BASEDIR)) {
232 return false;
235 torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
236 io.generic.level = RAW_LOCK_LOCKX;
238 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
239 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
240 "Failed to create %s - %s\n",
241 fname, smbcli_errstr(cli->tree)));
243 io.lockx.level = RAW_LOCK_LOCKX;
244 io.lockx.in.file.fnum = fnum;
245 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
246 io.lockx.in.timeout = 0;
247 io.lockx.in.ulock_cnt = 0;
248 io.lockx.in.lock_cnt = 1;
249 lock[0].pid = cli->session->pid;
250 lock[0].offset = 10;
251 lock[0].count = 1;
252 io.lockx.in.locks = &lock[0];
253 status = smb_raw_lock(cli->tree, &io);
254 CHECK_STATUS(status, NT_STATUS_OK);
257 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
258 io.lockx.in.ulock_cnt = 0;
259 io.lockx.in.lock_cnt = 1;
260 lock[0].count = 4000;
261 lock[0].offset = 0xEEFFFFFF;
262 status = smb_raw_lock(cli->tree, &io);
263 CHECK_STATUS(status, NT_STATUS_OK);
264 lock[0].pid++;
265 status = smb_raw_lock(cli->tree, &io);
266 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
267 lock[0].pid--;
268 io.lockx.in.ulock_cnt = 1;
269 io.lockx.in.lock_cnt = 0;
270 status = smb_raw_lock(cli->tree, &io);
271 CHECK_STATUS(status, NT_STATUS_OK);
272 status = smb_raw_lock(cli->tree, &io);
273 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
275 torture_comment(tctx, "Trying 0xEF000000 lock\n");
276 io.lockx.in.ulock_cnt = 0;
277 io.lockx.in.lock_cnt = 1;
278 lock[0].count = 4000;
279 lock[0].offset = 0xEF000000;
280 status = smb_raw_lock(cli->tree, &io);
281 CHECK_STATUS(status, NT_STATUS_OK);
282 lock[0].pid++;
283 status = smb_raw_lock(cli->tree, &io);
284 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
285 lock[0].pid--;
286 io.lockx.in.ulock_cnt = 1;
287 io.lockx.in.lock_cnt = 0;
288 status = smb_raw_lock(cli->tree, &io);
289 CHECK_STATUS(status, NT_STATUS_OK);
290 status = smb_raw_lock(cli->tree, &io);
291 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
293 torture_comment(tctx, "Trying zero lock\n");
294 io.lockx.in.ulock_cnt = 0;
295 io.lockx.in.lock_cnt = 1;
296 lock[0].count = 0;
297 lock[0].offset = ~0;
298 status = smb_raw_lock(cli->tree, &io);
299 CHECK_STATUS(status, NT_STATUS_OK);
300 lock[0].pid++;
301 status = smb_raw_lock(cli->tree, &io);
302 CHECK_STATUS(status, NT_STATUS_OK);
303 lock[0].pid--;
304 io.lockx.in.ulock_cnt = 1;
305 io.lockx.in.lock_cnt = 0;
306 status = smb_raw_lock(cli->tree, &io);
307 CHECK_STATUS(status, NT_STATUS_OK);
308 status = smb_raw_lock(cli->tree, &io);
309 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
311 torture_comment(tctx, "Trying max lock\n");
312 io.lockx.in.ulock_cnt = 0;
313 io.lockx.in.lock_cnt = 1;
314 lock[0].count = 0;
315 lock[0].offset = ~0;
316 status = smb_raw_lock(cli->tree, &io);
317 CHECK_STATUS(status, NT_STATUS_OK);
318 lock[0].pid++;
319 status = smb_raw_lock(cli->tree, &io);
320 CHECK_STATUS(status, NT_STATUS_OK);
321 lock[0].pid--;
322 io.lockx.in.ulock_cnt = 1;
323 io.lockx.in.lock_cnt = 0;
324 status = smb_raw_lock(cli->tree, &io);
325 CHECK_STATUS(status, NT_STATUS_OK);
326 status = smb_raw_lock(cli->tree, &io);
327 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
329 torture_comment(tctx, "Trying 2^63\n");
330 io.lockx.in.ulock_cnt = 0;
331 io.lockx.in.lock_cnt = 1;
332 lock[0].count = 1;
333 lock[0].offset = 1;
334 lock[0].offset <<= 63;
335 status = smb_raw_lock(cli->tree, &io);
336 CHECK_STATUS(status, NT_STATUS_OK);
337 lock[0].pid++;
338 status = smb_raw_lock(cli->tree, &io);
339 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
340 lock[0].pid--;
341 io.lockx.in.ulock_cnt = 1;
342 io.lockx.in.lock_cnt = 0;
343 status = smb_raw_lock(cli->tree, &io);
344 CHECK_STATUS(status, NT_STATUS_OK);
345 status = smb_raw_lock(cli->tree, &io);
346 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
348 torture_comment(tctx, "Trying 2^63 - 1\n");
349 io.lockx.in.ulock_cnt = 0;
350 io.lockx.in.lock_cnt = 1;
351 lock[0].count = 1;
352 lock[0].offset = 1;
353 lock[0].offset <<= 63;
354 lock[0].offset--;
355 status = smb_raw_lock(cli->tree, &io);
356 CHECK_STATUS(status, NT_STATUS_OK);
357 lock[0].pid++;
358 status = smb_raw_lock(cli->tree, &io);
359 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
360 lock[0].pid--;
361 io.lockx.in.ulock_cnt = 1;
362 io.lockx.in.lock_cnt = 0;
363 status = smb_raw_lock(cli->tree, &io);
364 CHECK_STATUS(status, NT_STATUS_OK);
365 status = smb_raw_lock(cli->tree, &io);
366 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
368 torture_comment(tctx, "Trying max lock 2\n");
369 io.lockx.in.ulock_cnt = 0;
370 io.lockx.in.lock_cnt = 1;
371 lock[0].count = 1;
372 lock[0].offset = ~0;
373 status = smb_raw_lock(cli->tree, &io);
374 CHECK_STATUS(status, NT_STATUS_OK);
375 lock[0].pid++;
376 lock[0].count = 2;
377 status = smb_raw_lock(cli->tree, &io);
378 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
379 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
380 else
381 CHECK_STATUS(status, NT_STATUS_OK);
382 lock[0].pid--;
383 io.lockx.in.ulock_cnt = 1;
384 io.lockx.in.lock_cnt = 0;
385 lock[0].count = 1;
386 status = smb_raw_lock(cli->tree, &io);
388 CHECK_STATUS(status, NT_STATUS_OK);
389 status = smb_raw_lock(cli->tree, &io);
390 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
392 done:
393 smbcli_close(cli->tree, fnum);
394 smb_raw_exit(cli->session);
395 smbcli_deltree(cli->tree, BASEDIR);
396 return ret;
400 test high pid
402 static bool test_pidhigh(struct torture_context *tctx,
403 struct smbcli_state *cli)
405 union smb_lock io;
406 struct smb_lock_entry lock[1];
407 NTSTATUS status;
408 bool ret = true;
409 int fnum;
410 const char *fname = BASEDIR "\\test.txt";
411 uint8_t c = 1;
413 if (!torture_setup_dir(cli, BASEDIR)) {
414 return false;
417 torture_comment(tctx, "Testing high pid\n");
418 io.generic.level = RAW_LOCK_LOCKX;
420 cli->session->pid = 1;
422 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
423 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
424 "Failed to create %s - %s\n",
425 fname, smbcli_errstr(cli->tree)));
427 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
428 torture_result(tctx, TORTURE_FAIL,
429 "Failed to write 1 byte - %s\n",
430 smbcli_errstr(cli->tree));
431 ret = false;
432 goto done;
435 io.lockx.level = RAW_LOCK_LOCKX;
436 io.lockx.in.file.fnum = fnum;
437 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
438 io.lockx.in.timeout = 0;
439 io.lockx.in.ulock_cnt = 0;
440 io.lockx.in.lock_cnt = 1;
441 lock[0].pid = cli->session->pid;
442 lock[0].offset = 0;
443 lock[0].count = 0xFFFFFFFF;
444 io.lockx.in.locks = &lock[0];
445 status = smb_raw_lock(cli->tree, &io);
446 CHECK_STATUS(status, NT_STATUS_OK);
448 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
449 torture_result(tctx, TORTURE_FAIL,
450 "Failed to read 1 byte - %s\n",
451 smbcli_errstr(cli->tree));
452 ret = false;
453 goto done;
456 cli->session->pid = 2;
458 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
459 torture_result(tctx, TORTURE_FAIL,
460 "pid is incorrect handled for read with lock!\n");
461 ret = false;
462 goto done;
465 cli->session->pid = 0x10001;
467 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
468 torture_result(tctx, TORTURE_FAIL,
469 "High pid is used on this server!\n");
470 ret = false;
471 } else {
472 torture_warning(tctx, "High pid is not used on this server (correct)\n");
475 done:
476 smbcli_close(cli->tree, fnum);
477 smb_raw_exit(cli->session);
478 smbcli_deltree(cli->tree, BASEDIR);
479 return ret;
484 test locking&X async operation
486 static bool test_async(struct torture_context *tctx,
487 struct smbcli_state *cli)
489 struct smbcli_session *session;
490 struct smb_composite_sesssetup setup;
491 struct smbcli_tree *tree;
492 union smb_tcon tcon;
493 const char *host, *share;
494 union smb_lock io;
495 struct smb_lock_entry lock[2];
496 NTSTATUS status;
497 bool ret = true;
498 int fnum;
499 const char *fname = BASEDIR "\\test.txt";
500 time_t t;
501 struct smbcli_request *req;
502 struct smbcli_session_options options;
504 if (!torture_setup_dir(cli, BASEDIR)) {
505 return false;
508 lp_smbcli_session_options(tctx->lp_ctx, &options);
510 torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
511 io.generic.level = RAW_LOCK_LOCKX;
513 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
514 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
515 "Failed to create %s - %s\n",
516 fname, smbcli_errstr(cli->tree)));
518 io.lockx.level = RAW_LOCK_LOCKX;
519 io.lockx.in.file.fnum = fnum;
520 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
521 io.lockx.in.timeout = 0;
522 io.lockx.in.ulock_cnt = 0;
523 io.lockx.in.lock_cnt = 1;
524 lock[0].pid = cli->session->pid;
525 lock[0].offset = 100;
526 lock[0].count = 10;
527 io.lockx.in.locks = &lock[0];
528 status = smb_raw_lock(cli->tree, &io);
529 CHECK_STATUS(status, NT_STATUS_OK);
531 t = time(NULL);
533 torture_comment(tctx, "testing cancel by CANCEL_LOCK\n");
535 /* setup a timed lock */
536 io.lockx.in.timeout = 10000;
537 req = smb_raw_lock_send(cli->tree, &io);
538 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
539 "Failed to setup timed lock (%s)\n", __location__));
541 /* cancel the wrong range */
542 lock[0].offset = 0;
543 io.lockx.in.timeout = 0;
544 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
545 status = smb_raw_lock(cli->tree, &io);
546 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
548 /* cancel with the wrong bits set */
549 lock[0].offset = 100;
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 the right range */
556 lock[0].offset = 100;
557 io.lockx.in.timeout = 0;
558 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
559 status = smb_raw_lock(cli->tree, &io);
560 CHECK_STATUS(status, NT_STATUS_OK);
562 /* receive the failed lock request */
563 status = smbcli_request_simple_recv(req);
564 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
566 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
567 "lock cancel was not immediate (%s)\n", __location__));
569 torture_comment(tctx, "testing cancel by unlock\n");
570 io.lockx.in.ulock_cnt = 0;
571 io.lockx.in.lock_cnt = 1;
572 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
573 io.lockx.in.timeout = 0;
574 status = smb_raw_lock(cli->tree, &io);
575 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
577 io.lockx.in.timeout = 5000;
578 req = smb_raw_lock_send(cli->tree, &io);
579 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
580 "Failed to setup timed lock (%s)\n", __location__));
582 io.lockx.in.ulock_cnt = 1;
583 io.lockx.in.lock_cnt = 0;
584 status = smb_raw_lock(cli->tree, &io);
585 CHECK_STATUS(status, NT_STATUS_OK);
587 t = time(NULL);
588 status = smbcli_request_simple_recv(req);
589 CHECK_STATUS(status, NT_STATUS_OK);
591 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
592 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
593 __location__, (int)(time(NULL)-t)));
595 torture_comment(tctx, "testing cancel by close\n");
596 io.lockx.in.ulock_cnt = 0;
597 io.lockx.in.lock_cnt = 1;
598 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
599 io.lockx.in.timeout = 0;
600 status = smb_raw_lock(cli->tree, &io);
601 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
603 t = time(NULL);
604 io.lockx.in.timeout = 10000;
605 req = smb_raw_lock_send(cli->tree, &io);
606 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
607 "Failed to setup timed lock (%s)\n", __location__));
609 status = smbcli_close(cli->tree, fnum);
610 CHECK_STATUS(status, NT_STATUS_OK);
612 status = smbcli_request_simple_recv(req);
613 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
615 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
616 "lock cancel by close was not immediate (%s)\n", __location__));
618 torture_comment(tctx, "create a new sessions\n");
619 session = smbcli_session_init(cli->transport, tctx, false, options);
620 setup.in.sesskey = cli->transport->negotiate.sesskey;
621 setup.in.capabilities = cli->transport->negotiate.capabilities;
622 setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
623 setup.in.credentials = cmdline_credentials;
624 setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
625 status = smb_composite_sesssetup(session, &setup);
626 CHECK_STATUS(status, NT_STATUS_OK);
627 session->vuid = setup.out.vuid;
629 torture_comment(tctx, "create new tree context\n");
630 share = torture_setting_string(tctx, "share", NULL);
631 host = torture_setting_string(tctx, "host", NULL);
632 tree = smbcli_tree_init(session, tctx, false);
633 tcon.generic.level = RAW_TCON_TCONX;
634 tcon.tconx.in.flags = 0;
635 tcon.tconx.in.password = data_blob(NULL, 0);
636 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
637 tcon.tconx.in.device = "A:";
638 status = smb_raw_tcon(tree, tctx, &tcon);
639 CHECK_STATUS(status, NT_STATUS_OK);
640 tree->tid = tcon.tconx.out.tid;
642 torture_comment(tctx, "testing cancel by exit\n");
643 fname = BASEDIR "\\test_exit.txt";
644 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
645 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
646 "Failed to reopen %s - %s\n",
647 fname, smbcli_errstr(tree)));
649 io.lockx.level = RAW_LOCK_LOCKX;
650 io.lockx.in.file.fnum = fnum;
651 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
652 io.lockx.in.timeout = 0;
653 io.lockx.in.ulock_cnt = 0;
654 io.lockx.in.lock_cnt = 1;
655 lock[0].pid = session->pid;
656 lock[0].offset = 100;
657 lock[0].count = 10;
658 io.lockx.in.locks = &lock[0];
659 status = smb_raw_lock(tree, &io);
660 CHECK_STATUS(status, NT_STATUS_OK);
662 io.lockx.in.ulock_cnt = 0;
663 io.lockx.in.lock_cnt = 1;
664 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
665 io.lockx.in.timeout = 0;
666 status = smb_raw_lock(tree, &io);
667 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
669 io.lockx.in.timeout = 10000;
670 t = time(NULL);
671 req = smb_raw_lock_send(tree, &io);
672 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
673 "Failed to setup timed lock (%s)\n", __location__));
675 status = smb_raw_exit(session);
676 CHECK_STATUS(status, NT_STATUS_OK);
678 status = smbcli_request_simple_recv(req);
679 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
681 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
682 "lock cancel by exit was not immediate (%s)\n", __location__));
684 torture_comment(tctx, "testing cancel by ulogoff\n");
685 fname = BASEDIR "\\test_ulogoff.txt";
686 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
687 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
688 "Failed to reopen %s - %s\n",
689 fname, smbcli_errstr(tree)));
691 io.lockx.level = RAW_LOCK_LOCKX;
692 io.lockx.in.file.fnum = fnum;
693 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
694 io.lockx.in.timeout = 0;
695 io.lockx.in.ulock_cnt = 0;
696 io.lockx.in.lock_cnt = 1;
697 lock[0].pid = session->pid;
698 lock[0].offset = 100;
699 lock[0].count = 10;
700 io.lockx.in.locks = &lock[0];
701 status = smb_raw_lock(tree, &io);
702 CHECK_STATUS(status, NT_STATUS_OK);
704 io.lockx.in.ulock_cnt = 0;
705 io.lockx.in.lock_cnt = 1;
706 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
707 io.lockx.in.timeout = 0;
708 status = smb_raw_lock(tree, &io);
709 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
711 io.lockx.in.timeout = 10000;
712 t = time(NULL);
713 req = smb_raw_lock_send(tree, &io);
714 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
715 "Failed to setup timed lock (%s)\n", __location__));
717 status = smb_raw_ulogoff(session);
718 CHECK_STATUS(status, NT_STATUS_OK);
720 status = smbcli_request_simple_recv(req);
721 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
722 torture_result(tctx, TORTURE_FAIL,
723 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
724 nt_errstr(status));
725 smb_tree_disconnect(tree);
726 smb_raw_exit(session);
727 goto done;
729 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
731 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
732 "lock cancel by ulogoff was not immediate (%s)\n", __location__));
734 torture_comment(tctx, "testing cancel by tdis\n");
735 tree->session = cli->session;
737 fname = BASEDIR "\\test_tdis.txt";
738 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
739 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
740 "Failed to reopen %s - %s\n",
741 fname, smbcli_errstr(tree)));
743 io.lockx.level = RAW_LOCK_LOCKX;
744 io.lockx.in.file.fnum = fnum;
745 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
746 io.lockx.in.timeout = 0;
747 io.lockx.in.ulock_cnt = 0;
748 io.lockx.in.lock_cnt = 1;
749 lock[0].pid = cli->session->pid;
750 lock[0].offset = 100;
751 lock[0].count = 10;
752 io.lockx.in.locks = &lock[0];
753 status = smb_raw_lock(tree, &io);
754 CHECK_STATUS(status, NT_STATUS_OK);
756 status = smb_raw_lock(tree, &io);
757 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
759 io.lockx.in.timeout = 10000;
760 t = time(NULL);
761 req = smb_raw_lock_send(tree, &io);
762 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
763 "Failed to setup timed lock (%s)\n", __location__));
765 status = smb_tree_disconnect(tree);
766 CHECK_STATUS(status, NT_STATUS_OK);
768 status = smbcli_request_simple_recv(req);
769 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
771 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
772 "lock cancel by tdis was not immediate (%s)\n", __location__));
774 done:
775 smb_raw_exit(cli->session);
776 smbcli_deltree(cli->tree, BASEDIR);
777 return ret;
781 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
783 static bool test_errorcode(struct torture_context *tctx,
784 struct smbcli_state *cli)
786 union smb_lock io;
787 union smb_open op;
788 struct smb_lock_entry lock[2];
789 NTSTATUS status;
790 bool ret = true;
791 int fnum, fnum2;
792 const char *fname;
793 struct smbcli_request *req;
794 time_t start;
795 int t;
796 int delay;
797 uint16_t deny_mode = 0;
799 if (!torture_setup_dir(cli, BASEDIR)) {
800 return false;
803 torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
805 torture_comment(tctx, "testing with timeout = 0\n");
806 fname = BASEDIR "\\test0.txt";
807 t = 0;
810 * the first run is with t = 0,
811 * the second with t > 0 (=1)
813 next_run:
815 * use the DENY_DOS mode, that creates two fnum's of one low-level
816 * file handle, this demonstrates that the cache is per fnum, not
817 * per file handle
819 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
820 deny_mode = OPENX_MODE_DENY_DOS;
821 else
822 deny_mode = OPENX_MODE_DENY_NONE;
824 op.openx.level = RAW_OPEN_OPENX;
825 op.openx.in.fname = fname;
826 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
827 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
828 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
829 op.openx.in.search_attrs = 0;
830 op.openx.in.file_attrs = 0;
831 op.openx.in.write_time = 0;
832 op.openx.in.size = 0;
833 op.openx.in.timeout = 0;
835 status = smb_raw_open(cli->tree, tctx, &op);
836 CHECK_STATUS(status, NT_STATUS_OK);
837 fnum = op.openx.out.file.fnum;
839 status = smb_raw_open(cli->tree, tctx, &op);
840 CHECK_STATUS(status, NT_STATUS_OK);
841 fnum2 = op.openx.out.file.fnum;
843 io.lockx.level = RAW_LOCK_LOCKX;
844 io.lockx.in.file.fnum = fnum;
845 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
846 io.lockx.in.timeout = t;
847 io.lockx.in.ulock_cnt = 0;
848 io.lockx.in.lock_cnt = 1;
849 lock[0].pid = cli->session->pid;
850 lock[0].offset = 100;
851 lock[0].count = 10;
852 io.lockx.in.locks = &lock[0];
853 status = smb_raw_lock(cli->tree, &io);
854 CHECK_STATUS(status, NT_STATUS_OK);
857 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
858 * this also demonstrates that the error code cache is per file handle
859 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
861 io.lockx.in.file.fnum = fnum2;
862 status = smb_raw_lock(cli->tree, &io);
863 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
865 io.lockx.in.file.fnum = fnum;
866 status = smb_raw_lock(cli->tree, &io);
867 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
869 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
870 io.lockx.in.file.fnum = fnum;
871 status = smb_raw_lock(cli->tree, &io);
872 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
874 io.lockx.in.file.fnum = fnum2;
875 status = smb_raw_lock(cli->tree, &io);
876 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
878 io.lockx.in.file.fnum = fnum;
879 status = smb_raw_lock(cli->tree, &io);
880 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
882 io.lockx.in.file.fnum = fnum2;
883 status = smb_raw_lock(cli->tree, &io);
884 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
886 /* demonstrate that the smbpid doesn't matter */
887 lock[0].pid++;
888 io.lockx.in.file.fnum = fnum;
889 status = smb_raw_lock(cli->tree, &io);
890 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
892 io.lockx.in.file.fnum = fnum2;
893 status = smb_raw_lock(cli->tree, &io);
894 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
895 lock[0].pid--;
898 * demonstrate the a successful lock with count = 0 and the same offset,
899 * doesn't reset the error cache
901 lock[0].offset = 100;
902 lock[0].count = 0;
903 io.lockx.in.file.fnum = fnum;
904 status = smb_raw_lock(cli->tree, &io);
905 CHECK_STATUS(status, NT_STATUS_OK);
907 io.lockx.in.file.fnum = fnum2;
908 status = smb_raw_lock(cli->tree, &io);
909 CHECK_STATUS(status, NT_STATUS_OK);
911 lock[0].offset = 100;
912 lock[0].count = 10;
913 io.lockx.in.file.fnum = fnum;
914 status = smb_raw_lock(cli->tree, &io);
915 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
917 io.lockx.in.file.fnum = fnum2;
918 status = smb_raw_lock(cli->tree, &io);
919 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
922 * demonstrate the a successful lock with count = 0 and outside the locked range,
923 * doesn't reset the error cache
925 lock[0].offset = 110;
926 lock[0].count = 0;
927 io.lockx.in.file.fnum = fnum;
928 status = smb_raw_lock(cli->tree, &io);
929 CHECK_STATUS(status, NT_STATUS_OK);
931 io.lockx.in.file.fnum = fnum2;
932 status = smb_raw_lock(cli->tree, &io);
933 CHECK_STATUS(status, NT_STATUS_OK);
935 lock[0].offset = 100;
936 lock[0].count = 10;
937 io.lockx.in.file.fnum = fnum;
938 status = smb_raw_lock(cli->tree, &io);
939 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
941 io.lockx.in.file.fnum = fnum2;
942 status = smb_raw_lock(cli->tree, &io);
943 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
945 lock[0].offset = 99;
946 lock[0].count = 0;
947 io.lockx.in.file.fnum = fnum;
948 status = smb_raw_lock(cli->tree, &io);
949 CHECK_STATUS(status, NT_STATUS_OK);
951 io.lockx.in.file.fnum = fnum2;
952 status = smb_raw_lock(cli->tree, &io);
953 CHECK_STATUS(status, NT_STATUS_OK);
955 lock[0].offset = 100;
956 lock[0].count = 10;
957 io.lockx.in.file.fnum = fnum;
958 status = smb_raw_lock(cli->tree, &io);
959 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
961 io.lockx.in.file.fnum = fnum2;
962 status = smb_raw_lock(cli->tree, &io);
963 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
965 /* demonstrate that a changing count doesn't reset the error cache */
966 lock[0].offset = 100;
967 lock[0].count = 5;
968 io.lockx.in.file.fnum = fnum;
969 status = smb_raw_lock(cli->tree, &io);
970 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
972 io.lockx.in.file.fnum = fnum2;
973 status = smb_raw_lock(cli->tree, &io);
974 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
976 lock[0].offset = 100;
977 lock[0].count = 15;
978 io.lockx.in.file.fnum = fnum;
979 status = smb_raw_lock(cli->tree, &io);
980 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
982 io.lockx.in.file.fnum = fnum2;
983 status = smb_raw_lock(cli->tree, &io);
984 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
987 * demonstrate the a lock with count = 0 and inside the locked range,
988 * fails and resets the error cache
990 lock[0].offset = 101;
991 lock[0].count = 0;
992 io.lockx.in.file.fnum = fnum;
993 status = smb_raw_lock(cli->tree, &io);
994 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
995 status = smb_raw_lock(cli->tree, &io);
996 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
998 io.lockx.in.file.fnum = fnum2;
999 status = smb_raw_lock(cli->tree, &io);
1000 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1001 status = smb_raw_lock(cli->tree, &io);
1002 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1004 lock[0].offset = 100;
1005 lock[0].count = 10;
1006 io.lockx.in.file.fnum = fnum;
1007 status = smb_raw_lock(cli->tree, &io);
1008 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1009 status = smb_raw_lock(cli->tree, &io);
1010 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1012 io.lockx.in.file.fnum = fnum2;
1013 status = smb_raw_lock(cli->tree, &io);
1014 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1015 status = smb_raw_lock(cli->tree, &io);
1016 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1018 /* demonstrate the a changing offset, resets the error cache */
1019 lock[0].offset = 105;
1020 lock[0].count = 10;
1021 io.lockx.in.file.fnum = fnum;
1022 status = smb_raw_lock(cli->tree, &io);
1023 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1024 status = smb_raw_lock(cli->tree, &io);
1025 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1027 io.lockx.in.file.fnum = fnum2;
1028 status = smb_raw_lock(cli->tree, &io);
1029 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1030 status = smb_raw_lock(cli->tree, &io);
1031 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1033 lock[0].offset = 100;
1034 lock[0].count = 10;
1035 io.lockx.in.file.fnum = fnum;
1036 status = smb_raw_lock(cli->tree, &io);
1037 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1038 status = smb_raw_lock(cli->tree, &io);
1039 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1041 io.lockx.in.file.fnum = fnum2;
1042 status = smb_raw_lock(cli->tree, &io);
1043 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1044 status = smb_raw_lock(cli->tree, &io);
1045 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1047 lock[0].offset = 95;
1048 lock[0].count = 9;
1049 io.lockx.in.file.fnum = fnum;
1050 status = smb_raw_lock(cli->tree, &io);
1051 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1052 status = smb_raw_lock(cli->tree, &io);
1053 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1055 io.lockx.in.file.fnum = fnum2;
1056 status = smb_raw_lock(cli->tree, &io);
1057 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1058 status = smb_raw_lock(cli->tree, &io);
1059 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1061 lock[0].offset = 100;
1062 lock[0].count = 10;
1063 io.lockx.in.file.fnum = fnum;
1064 status = smb_raw_lock(cli->tree, &io);
1065 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1066 status = smb_raw_lock(cli->tree, &io);
1067 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1069 io.lockx.in.file.fnum = fnum2;
1070 status = smb_raw_lock(cli->tree, &io);
1071 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1072 status = smb_raw_lock(cli->tree, &io);
1073 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1076 * demonstrate the a successful lock in a different range,
1077 * doesn't reset the cache, the failing lock on the 2nd handle
1078 * resets the cache
1080 lock[0].offset = 120;
1081 lock[0].count = 15;
1082 io.lockx.in.file.fnum = fnum;
1083 status = smb_raw_lock(cli->tree, &io);
1084 CHECK_STATUS(status, NT_STATUS_OK);
1086 io.lockx.in.file.fnum = fnum2;
1087 status = smb_raw_lock(cli->tree, &io);
1088 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1090 lock[0].offset = 100;
1091 lock[0].count = 10;
1092 io.lockx.in.file.fnum = fnum;
1093 status = smb_raw_lock(cli->tree, &io);
1094 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1095 status = smb_raw_lock(cli->tree, &io);
1096 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1098 io.lockx.in.file.fnum = fnum2;
1099 status = smb_raw_lock(cli->tree, &io);
1100 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1101 status = smb_raw_lock(cli->tree, &io);
1102 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1104 /* end of the loop */
1105 if (t == 0) {
1106 smb_raw_exit(cli->session);
1107 t = 1;
1108 torture_comment(tctx, "testing with timeout > 0 (=%d)\n",
1110 fname = BASEDIR "\\test1.txt";
1111 goto next_run;
1114 t = 4000;
1115 torture_comment(tctx, "testing special cases with timeout > 0 (=%d)\n",
1119 * the following 3 test sections demonstrate that
1120 * the cache is only set when the error is reported
1121 * to the client (after the timeout went by)
1123 smb_raw_exit(cli->session);
1124 torture_comment(tctx, "testing a conflict while a lock is pending\n");
1125 fname = BASEDIR "\\test2.txt";
1126 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1127 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1128 "Failed to reopen %s - %s\n",
1129 fname, smbcli_errstr(cli->tree)));
1131 io.lockx.level = RAW_LOCK_LOCKX;
1132 io.lockx.in.file.fnum = fnum;
1133 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1134 io.lockx.in.timeout = 0;
1135 io.lockx.in.ulock_cnt = 0;
1136 io.lockx.in.lock_cnt = 1;
1137 lock[0].pid = cli->session->pid;
1138 lock[0].offset = 100;
1139 lock[0].count = 10;
1140 io.lockx.in.locks = &lock[0];
1141 status = smb_raw_lock(cli->tree, &io);
1142 CHECK_STATUS(status, NT_STATUS_OK);
1144 start = time(NULL);
1145 io.lockx.in.timeout = t;
1146 req = smb_raw_lock_send(cli->tree, &io);
1147 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1148 "Failed to setup timed lock (%s)\n", __location__));
1150 io.lockx.in.timeout = 0;
1151 lock[0].offset = 105;
1152 lock[0].count = 10;
1153 status = smb_raw_lock(cli->tree, &io);
1154 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1156 status = smbcli_request_simple_recv(req);
1157 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1159 delay = t / 1000;
1160 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1161 delay /= 2;
1164 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1165 "lock comes back to early timeout[%d] delay[%d]"
1166 "(%s)\n", t, delay, __location__));
1168 status = smb_raw_lock(cli->tree, &io);
1169 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1171 smbcli_close(cli->tree, fnum);
1172 fname = BASEDIR "\\test3.txt";
1173 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1174 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1175 "Failed to reopen %s - %s\n",
1176 fname, smbcli_errstr(cli->tree)));
1178 io.lockx.level = RAW_LOCK_LOCKX;
1179 io.lockx.in.file.fnum = fnum;
1180 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1181 io.lockx.in.timeout = 0;
1182 io.lockx.in.ulock_cnt = 0;
1183 io.lockx.in.lock_cnt = 1;
1184 lock[0].pid = cli->session->pid;
1185 lock[0].offset = 100;
1186 lock[0].count = 10;
1187 io.lockx.in.locks = &lock[0];
1188 status = smb_raw_lock(cli->tree, &io);
1189 CHECK_STATUS(status, NT_STATUS_OK);
1191 start = time(NULL);
1192 io.lockx.in.timeout = t;
1193 req = smb_raw_lock_send(cli->tree, &io);
1194 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1195 "Failed to setup timed lock (%s)\n", __location__));
1197 io.lockx.in.timeout = 0;
1198 lock[0].offset = 105;
1199 lock[0].count = 10;
1200 status = smb_raw_lock(cli->tree, &io);
1201 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1203 status = smbcli_request_simple_recv(req);
1204 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1206 delay = t / 1000;
1207 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1208 delay /= 2;
1211 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1212 "lock comes back to early timeout[%d] delay[%d]"
1213 "(%s)\n", t, delay, __location__));
1215 lock[0].offset = 100;
1216 lock[0].count = 10;
1217 status = smb_raw_lock(cli->tree, &io);
1218 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1220 smbcli_close(cli->tree, fnum);
1221 fname = BASEDIR "\\test4.txt";
1222 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1223 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1224 "Failed to reopen %s - %s\n",
1225 fname, smbcli_errstr(cli->tree)));
1227 io.lockx.level = RAW_LOCK_LOCKX;
1228 io.lockx.in.file.fnum = fnum;
1229 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1230 io.lockx.in.timeout = 0;
1231 io.lockx.in.ulock_cnt = 0;
1232 io.lockx.in.lock_cnt = 1;
1233 lock[0].pid = cli->session->pid;
1234 lock[0].offset = 100;
1235 lock[0].count = 10;
1236 io.lockx.in.locks = &lock[0];
1237 status = smb_raw_lock(cli->tree, &io);
1238 CHECK_STATUS(status, NT_STATUS_OK);
1240 start = time(NULL);
1241 io.lockx.in.timeout = t;
1242 req = smb_raw_lock_send(cli->tree, &io);
1243 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1244 "Failed to setup timed lock (%s)\n", __location__));
1246 io.lockx.in.timeout = 0;
1247 status = smb_raw_lock(cli->tree, &io);
1248 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1250 status = smbcli_request_simple_recv(req);
1251 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1253 delay = t / 1000;
1254 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1255 delay /= 2;
1258 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1259 "lock comes back to early timeout[%d] delay[%d]"
1260 "(%s)\n", t, delay, __location__));
1262 status = smb_raw_lock(cli->tree, &io);
1263 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1265 done:
1266 smb_raw_exit(cli->session);
1267 smbcli_deltree(cli->tree, BASEDIR);
1268 return ret;
1273 test LOCKING_ANDX_CHANGE_LOCKTYPE
1275 static bool test_changetype(struct torture_context *tctx,
1276 struct smbcli_state *cli)
1278 union smb_lock io;
1279 struct smb_lock_entry lock[2];
1280 NTSTATUS status;
1281 bool ret = true;
1282 int fnum;
1283 uint8_t c = 0;
1284 const char *fname = BASEDIR "\\test.txt";
1286 if (!torture_setup_dir(cli, BASEDIR)) {
1287 return false;
1290 torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1291 io.generic.level = RAW_LOCK_LOCKX;
1293 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1294 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1295 "Failed to create %s - %s\n",
1296 fname, smbcli_errstr(cli->tree)));
1298 io.lockx.level = RAW_LOCK_LOCKX;
1299 io.lockx.in.file.fnum = fnum;
1300 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1301 io.lockx.in.timeout = 0;
1302 io.lockx.in.ulock_cnt = 0;
1303 io.lockx.in.lock_cnt = 1;
1304 lock[0].pid = cli->session->pid;
1305 lock[0].offset = 100;
1306 lock[0].count = 10;
1307 io.lockx.in.locks = &lock[0];
1308 status = smb_raw_lock(cli->tree, &io);
1309 CHECK_STATUS(status, NT_STATUS_OK);
1311 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1312 torture_result(tctx, TORTURE_FAIL,
1313 "allowed write on read locked region (%s)\n", __location__);
1314 ret = false;
1315 goto done;
1318 /* windows server don't seem to support this */
1319 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1320 status = smb_raw_lock(cli->tree, &io);
1321 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1323 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1324 torture_result(tctx, TORTURE_FAIL,
1325 "allowed write after lock change (%s)\n", __location__);
1326 ret = false;
1327 goto done;
1330 done:
1331 smbcli_close(cli->tree, fnum);
1332 smb_raw_exit(cli->session);
1333 smbcli_deltree(cli->tree, BASEDIR);
1334 return ret;
1337 struct double_lock_test {
1338 struct smb_lock_entry lock1;
1339 struct smb_lock_entry lock2;
1340 NTSTATUS exp_status;
1344 * Tests zero byte locks.
1346 static struct double_lock_test zero_byte_tests[] = {
1347 /* {pid, offset, count}, {pid, offset, count}, status */
1349 /** First, takes a zero byte lock at offset 10. Then:
1350 * - Taking 0 byte lock at 10 should succeed.
1351 * - Taking 1 byte locks at 9,10,11 should succeed.
1352 * - Taking 2 byte lock at 9 should fail.
1353 * - Taking 2 byte lock at 10 should succeed.
1354 * - Taking 3 byte lock at 9 should fail.
1356 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1357 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
1358 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1359 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1360 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
1361 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1362 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
1364 /** Same, but opposite order. */
1365 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1366 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
1367 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1368 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1369 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1370 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1371 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1373 /** Zero zero case. */
1374 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
1377 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
1379 union smb_lock io;
1380 NTSTATUS status;
1381 bool ret = true;
1382 int fnum, i;
1383 const char *fname = BASEDIR "\\zero.txt";
1385 torture_comment(tctx, "Testing zero length byte range locks:\n");
1387 if (!torture_setup_dir(cli, BASEDIR)) {
1388 return false;
1391 io.generic.level = RAW_LOCK_LOCKX;
1393 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1394 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1395 "Failed to create %s - %s\n",
1396 fname, smbcli_errstr(cli->tree)));
1398 /* Setup initial parameters */
1399 io.lockx.level = RAW_LOCK_LOCKX;
1400 io.lockx.in.file.fnum = fnum;
1401 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1402 io.lockx.in.timeout = 0;
1404 /* Try every combination of locks in zero_byte_tests. The first lock is
1405 * assumed to succeed. The second lock may contend, depending on the
1406 * expected status. */
1407 for (i = 0;
1408 i < ARRAY_SIZE(zero_byte_tests);
1409 i++) {
1410 torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1411 zero_byte_tests[i].lock1.pid,
1412 zero_byte_tests[i].lock1.offset,
1413 zero_byte_tests[i].lock1.count,
1414 zero_byte_tests[i].lock2.pid,
1415 zero_byte_tests[i].lock2.offset,
1416 zero_byte_tests[i].lock2.count,
1417 nt_errstr(zero_byte_tests[i].exp_status));
1419 /* Lock both locks. */
1420 io.lockx.in.ulock_cnt = 0;
1421 io.lockx.in.lock_cnt = 1;
1423 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1424 &zero_byte_tests[i].lock1);
1425 status = smb_raw_lock(cli->tree, &io);
1426 CHECK_STATUS(status, NT_STATUS_OK);
1428 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1429 &zero_byte_tests[i].lock2);
1430 status = smb_raw_lock(cli->tree, &io);
1432 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1433 NT_STATUS_LOCK_NOT_GRANTED)) {
1434 /* Allow either of the failure messages and keep going
1435 * if we see the wrong status. */
1436 CHECK_STATUS_OR_CONT(status,
1437 NT_STATUS_LOCK_NOT_GRANTED,
1438 NT_STATUS_FILE_LOCK_CONFLICT);
1440 } else {
1441 CHECK_STATUS_CONT(status,
1442 zero_byte_tests[i].exp_status);
1445 /* Unlock both locks. */
1446 io.lockx.in.ulock_cnt = 1;
1447 io.lockx.in.lock_cnt = 0;
1449 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1450 status = smb_raw_lock(cli->tree, &io);
1451 CHECK_STATUS(status, NT_STATUS_OK);
1454 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1455 &zero_byte_tests[i].lock1);
1456 status = smb_raw_lock(cli->tree, &io);
1457 CHECK_STATUS(status, NT_STATUS_OK);
1460 done:
1461 smbcli_close(cli->tree, fnum);
1462 smb_raw_exit(cli->session);
1463 smbcli_deltree(cli->tree, BASEDIR);
1464 return ret;
1467 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1469 union smb_lock io;
1470 NTSTATUS status;
1471 bool ret = true;
1472 int fnum1, fnum2;
1473 const char *fname = BASEDIR "\\unlock.txt";
1474 struct smb_lock_entry lock1;
1475 struct smb_lock_entry lock2;
1477 torture_comment(tctx, "Testing LOCKX unlock:\n");
1479 if (!torture_setup_dir(cli, BASEDIR)) {
1480 return false;
1483 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1484 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1485 "Failed to create %s - %s\n",
1486 fname, smbcli_errstr(cli->tree)));
1488 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1489 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
1490 "Failed to create %s - %s\n",
1491 fname, smbcli_errstr(cli->tree)));
1493 /* Setup initial parameters */
1494 io.lockx.level = RAW_LOCK_LOCKX;
1495 io.lockx.in.timeout = 0;
1497 lock1.pid = cli->session->pid;
1498 lock1.offset = 0;
1499 lock1.count = 10;
1500 lock2.pid = cli->session->pid - 1;
1501 lock2.offset = 0;
1502 lock2.count = 10;
1505 * Take exclusive lock, then unlock it with a shared-unlock call.
1507 torture_comment(tctx, " taking exclusive lock.\n");
1508 io.lockx.in.ulock_cnt = 0;
1509 io.lockx.in.lock_cnt = 1;
1510 io.lockx.in.mode = 0;
1511 io.lockx.in.file.fnum = fnum1;
1512 io.lockx.in.locks = &lock1;
1513 status = smb_raw_lock(cli->tree, &io);
1514 CHECK_STATUS(status, NT_STATUS_OK);
1516 torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
1517 io.lockx.in.ulock_cnt = 1;
1518 io.lockx.in.lock_cnt = 0;
1519 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1520 io.lockx.in.file.fnum = fnum1;
1521 io.lockx.in.locks = &lock1;
1522 status = smb_raw_lock(cli->tree, &io);
1523 CHECK_STATUS(status, NT_STATUS_OK);
1525 torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
1526 io.lockx.in.ulock_cnt = 0;
1527 io.lockx.in.lock_cnt = 1;
1528 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1529 io.lockx.in.file.fnum = fnum2;
1530 io.lockx.in.locks = &lock2;
1531 status = smb_raw_lock(cli->tree, &io);
1532 CHECK_STATUS(status, NT_STATUS_OK);
1535 * Unlock a shared lock with an exclusive-unlock call.
1537 torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
1538 io.lockx.in.ulock_cnt = 1;
1539 io.lockx.in.lock_cnt = 0;
1540 io.lockx.in.mode = 0;
1541 io.lockx.in.file.fnum = fnum2;
1542 io.lockx.in.locks = &lock2;
1543 status = smb_raw_lock(cli->tree, &io);
1544 CHECK_STATUS(status, NT_STATUS_OK);
1546 torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
1547 io.lockx.in.ulock_cnt = 0;
1548 io.lockx.in.lock_cnt = 1;
1549 io.lockx.in.mode = 0;
1550 io.lockx.in.file.fnum = fnum1;
1551 io.lockx.in.locks = &lock1;
1552 status = smb_raw_lock(cli->tree, &io);
1553 CHECK_STATUS(status, NT_STATUS_OK);
1555 /* cleanup */
1556 io.lockx.in.ulock_cnt = 1;
1557 io.lockx.in.lock_cnt = 0;
1558 status = smb_raw_lock(cli->tree, &io);
1559 CHECK_STATUS(status, NT_STATUS_OK);
1562 * Test unlocking of 0-byte locks.
1565 torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
1566 "always unlocks the exclusive first.\n");
1567 lock1.pid = cli->session->pid;
1568 lock1.offset = 10;
1569 lock1.count = 0;
1570 lock2.pid = cli->session->pid;
1571 lock2.offset = 5;
1572 lock2.count = 10;
1573 io.lockx.in.ulock_cnt = 0;
1574 io.lockx.in.lock_cnt = 1;
1575 io.lockx.in.file.fnum = fnum1;
1576 io.lockx.in.locks = &lock1;
1578 /* lock 0-byte shared
1579 * Note: Order of the shared/exclusive locks doesn't matter. */
1580 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1581 status = smb_raw_lock(cli->tree, &io);
1582 CHECK_STATUS(status, NT_STATUS_OK);
1584 /* lock 0-byte exclusive */
1585 io.lockx.in.mode = 0;
1586 status = smb_raw_lock(cli->tree, &io);
1587 CHECK_STATUS(status, NT_STATUS_OK);
1589 /* test contention */
1590 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1591 io.lockx.in.locks = &lock2;
1592 io.lockx.in.file.fnum = fnum2;
1593 status = smb_raw_lock(cli->tree, &io);
1594 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1595 NT_STATUS_FILE_LOCK_CONFLICT);
1597 /* unlock */
1598 io.lockx.in.ulock_cnt = 1;
1599 io.lockx.in.lock_cnt = 0;
1600 io.lockx.in.file.fnum = fnum1;
1601 io.lockx.in.locks = &lock1;
1602 status = smb_raw_lock(cli->tree, &io);
1603 CHECK_STATUS(status, NT_STATUS_OK);
1605 /* test - can we take a shared lock? */
1606 io.lockx.in.ulock_cnt = 0;
1607 io.lockx.in.lock_cnt = 1;
1608 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1609 io.lockx.in.file.fnum = fnum2;
1610 io.lockx.in.locks = &lock2;
1611 status = smb_raw_lock(cli->tree, &io);
1613 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1614 * new to Win7, it succeeds in WinXP too), until I can come to a
1615 * resolution as to whether Samba should support this or not. There is
1616 * code to preference unlocking exclusive locks before shared locks,
1617 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1618 if (TARGET_IS_SAMBA3(tctx)) {
1619 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1620 NT_STATUS_FILE_LOCK_CONFLICT);
1621 } else {
1622 CHECK_STATUS(status, NT_STATUS_OK);
1625 /* cleanup */
1626 io.lockx.in.ulock_cnt = 1;
1627 io.lockx.in.lock_cnt = 0;
1628 status = smb_raw_lock(cli->tree, &io);
1630 /* XXX Same as above. */
1631 if (TARGET_IS_SAMBA3(tctx)) {
1632 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1633 } else {
1634 CHECK_STATUS(status, NT_STATUS_OK);
1637 io.lockx.in.file.fnum = fnum1;
1638 io.lockx.in.locks = &lock1;
1639 status = smb_raw_lock(cli->tree, &io);
1640 CHECK_STATUS(status, NT_STATUS_OK);
1642 done:
1643 smbcli_close(cli->tree, fnum1);
1644 smbcli_close(cli->tree, fnum2);
1645 smb_raw_exit(cli->session);
1646 smbcli_deltree(cli->tree, BASEDIR);
1647 return ret;
1650 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1652 union smb_lock io;
1653 NTSTATUS status;
1654 bool ret = true;
1655 int fnum1;
1656 const char *fname = BASEDIR "\\unlock_multiple.txt";
1657 struct smb_lock_entry lock1;
1658 struct smb_lock_entry lock2;
1659 struct smb_lock_entry locks[2];
1661 torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
1663 if (!torture_setup_dir(cli, BASEDIR)) {
1664 return false;
1667 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1668 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1669 "Failed to create %s - %s\n",
1670 fname, smbcli_errstr(cli->tree)));
1672 /* Setup initial parameters */
1673 io.lockx.level = RAW_LOCK_LOCKX;
1674 io.lockx.in.timeout = 0;
1676 lock1.pid = cli->session->pid;
1677 lock1.offset = 0;
1678 lock1.count = 10;
1679 lock2.pid = cli->session->pid;
1680 lock2.offset = 10;
1681 lock2.count = 10;
1683 locks[0] = lock1;
1684 locks[1] = lock2;
1686 io.lockx.in.file.fnum = fnum1;
1687 io.lockx.in.mode = 0; /* exclusive */
1689 /** Test1: Take second lock, but not first. */
1690 torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
1691 "unlocked. \n");
1693 io.lockx.in.ulock_cnt = 0;
1694 io.lockx.in.lock_cnt = 1;
1695 io.lockx.in.locks = &lock2;
1696 status = smb_raw_lock(cli->tree, &io);
1697 CHECK_STATUS(status, NT_STATUS_OK);
1699 /* Try to unlock both locks. */
1700 io.lockx.in.ulock_cnt = 2;
1701 io.lockx.in.lock_cnt = 0;
1702 io.lockx.in.locks = locks;
1704 status = smb_raw_lock(cli->tree, &io);
1705 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1707 /* Second lock should not be unlocked. */
1708 io.lockx.in.ulock_cnt = 0;
1709 io.lockx.in.lock_cnt = 1;
1710 io.lockx.in.locks = &lock2;
1711 status = smb_raw_lock(cli->tree, &io);
1712 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1714 /* cleanup */
1715 io.lockx.in.ulock_cnt = 1;
1716 io.lockx.in.lock_cnt = 0;
1717 io.lockx.in.locks = &lock2;
1718 status = smb_raw_lock(cli->tree, &io);
1719 CHECK_STATUS(status, NT_STATUS_OK);
1721 /** Test2: Take first lock, but not second. */
1722 torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
1723 "unlocked.\n");
1725 io.lockx.in.ulock_cnt = 0;
1726 io.lockx.in.lock_cnt = 1;
1727 io.lockx.in.locks = &lock1;
1728 status = smb_raw_lock(cli->tree, &io);
1729 CHECK_STATUS(status, NT_STATUS_OK);
1731 /* Try to unlock both locks. */
1732 io.lockx.in.ulock_cnt = 2;
1733 io.lockx.in.lock_cnt = 0;
1734 io.lockx.in.locks = locks;
1736 status = smb_raw_lock(cli->tree, &io);
1737 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1739 /* First lock should be unlocked. */
1740 io.lockx.in.ulock_cnt = 0;
1741 io.lockx.in.lock_cnt = 1;
1742 io.lockx.in.locks = &lock1;
1743 status = smb_raw_lock(cli->tree, &io);
1744 CHECK_STATUS(status, NT_STATUS_OK);
1746 /* cleanup */
1747 io.lockx.in.ulock_cnt = 1;
1748 io.lockx.in.lock_cnt = 0;
1749 io.lockx.in.locks = &lock1;
1750 status = smb_raw_lock(cli->tree, &io);
1751 CHECK_STATUS(status, NT_STATUS_OK);
1753 done:
1754 smbcli_close(cli->tree, fnum1);
1755 smb_raw_exit(cli->session);
1756 smbcli_deltree(cli->tree, BASEDIR);
1757 return ret;
1761 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1762 * - stacking an exclusive on top of shared fails
1763 * - stacking two exclusives fail
1765 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
1767 union smb_lock io;
1768 NTSTATUS status;
1769 bool ret = true;
1770 int fnum1;
1771 const char *fname = BASEDIR "\\stacking.txt";
1772 struct smb_lock_entry lock1;
1773 struct smb_lock_entry lock2;
1775 torture_comment(tctx, "Testing stacking:\n");
1777 if (!torture_setup_dir(cli, BASEDIR)) {
1778 return false;
1781 io.generic.level = RAW_LOCK_LOCKX;
1783 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1784 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1785 "Failed to create %s - %s\n",
1786 fname, smbcli_errstr(cli->tree)));
1788 /* Setup initial parameters */
1789 io.lockx.level = RAW_LOCK_LOCKX;
1790 io.lockx.in.timeout = 0;
1792 lock1.pid = cli->session->pid;
1793 lock1.offset = 0;
1794 lock1.count = 10;
1795 lock2.pid = cli->session->pid - 1;
1796 lock2.offset = 0;
1797 lock2.count = 10;
1800 * Try to take a shared lock, then stack an exclusive.
1802 torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
1803 io.lockx.in.file.fnum = fnum1;
1804 io.lockx.in.locks = &lock1;
1806 io.lockx.in.ulock_cnt = 0;
1807 io.lockx.in.lock_cnt = 1;
1808 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1809 status = smb_raw_lock(cli->tree, &io);
1810 CHECK_STATUS(status, NT_STATUS_OK);
1812 io.lockx.in.ulock_cnt = 0;
1813 io.lockx.in.lock_cnt = 1;
1814 io.lockx.in.mode = 0;
1815 status = smb_raw_lock(cli->tree, &io);
1816 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1817 NT_STATUS_FILE_LOCK_CONFLICT);
1819 /* cleanup */
1820 io.lockx.in.ulock_cnt = 1;
1821 io.lockx.in.lock_cnt = 0;
1822 status = smb_raw_lock(cli->tree, &io);
1823 CHECK_STATUS(status, NT_STATUS_OK);
1826 * Prove that two exclusive locks do not stack.
1828 torture_comment(tctx, " two exclusive locks do not stack.\n");
1829 io.lockx.in.ulock_cnt = 0;
1830 io.lockx.in.lock_cnt = 1;
1831 io.lockx.in.mode = 0;
1832 status = smb_raw_lock(cli->tree, &io);
1833 CHECK_STATUS(status, NT_STATUS_OK);
1834 status = smb_raw_lock(cli->tree, &io);
1835 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1836 NT_STATUS_FILE_LOCK_CONFLICT);
1838 /* cleanup */
1839 io.lockx.in.ulock_cnt = 1;
1840 io.lockx.in.lock_cnt = 0;
1841 status = smb_raw_lock(cli->tree, &io);
1842 CHECK_STATUS(status, NT_STATUS_OK);
1844 done:
1845 smbcli_close(cli->tree, fnum1);
1846 smb_raw_exit(cli->session);
1847 smbcli_deltree(cli->tree, BASEDIR);
1848 return ret;
1852 basic testing of lock calls
1854 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
1856 struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
1858 torture_suite_add_1smb_test(suite, "lockx", test_lockx);
1859 torture_suite_add_1smb_test(suite, "lock", test_lock);
1860 torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
1861 torture_suite_add_1smb_test(suite, "async", test_async);
1862 torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
1863 torture_suite_add_1smb_test(suite, "changetype", test_changetype);
1865 torture_suite_add_1smb_test(suite, "stacking", test_stacking);
1866 torture_suite_add_1smb_test(suite, "unlock", test_unlock);
1867 torture_suite_add_1smb_test(suite, "multiple_unlock",
1868 test_multiple_unlock);
1869 torture_suite_add_1smb_test(suite, "zerobytelocks",
1870 test_zerobytelocks);
1872 return suite;