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/>.
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)); \
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)); \
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)); \
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)); \
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) ((torture_setting_bool(_tctx, "w2k8", false)) || \
75 (torture_setting_bool(_tctx, "win7", false)) || \
76 (torture_setting_bool(_tctx, "w2k3", false)))
77 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
78 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
80 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
81 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
82 #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
83 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
84 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
85 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
87 test SMBlock and SMBunlock ops
89 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
95 const char *fname
= BASEDIR
"\\test.txt";
97 if (!TARGET_SUPPORTS_SMBLOCK(tctx
))
98 torture_skip(tctx
, "Target does not support the SMBlock PDU");
100 if (!torture_setup_dir(cli
, BASEDIR
)) {
104 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
105 io
.generic
.level
= RAW_LOCK_LOCK
;
107 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
108 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
109 "Failed to create %s - %s\n",
110 fname
, smbcli_errstr(cli
->tree
)));
112 torture_comment(tctx
, "Trying 0/0 lock\n");
113 io
.lock
.level
= RAW_LOCK_LOCK
;
114 io
.lock
.in
.file
.fnum
= fnum
;
115 io
.lock
.in
.count
= 0;
116 io
.lock
.in
.offset
= 0;
117 status
= smb_raw_lock(cli
->tree
, &io
);
118 CHECK_STATUS(status
, NT_STATUS_OK
);
120 status
= smb_raw_lock(cli
->tree
, &io
);
121 CHECK_STATUS(status
, NT_STATUS_OK
);
123 io
.lock
.level
= RAW_LOCK_UNLOCK
;
124 status
= smb_raw_lock(cli
->tree
, &io
);
125 CHECK_STATUS(status
, NT_STATUS_OK
);
127 torture_comment(tctx
, "Trying 0/1 lock\n");
128 io
.lock
.level
= RAW_LOCK_LOCK
;
129 io
.lock
.in
.file
.fnum
= fnum
;
130 io
.lock
.in
.count
= 1;
131 io
.lock
.in
.offset
= 0;
132 status
= smb_raw_lock(cli
->tree
, &io
);
133 CHECK_STATUS(status
, NT_STATUS_OK
);
135 status
= smb_raw_lock(cli
->tree
, &io
);
136 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
138 io
.lock
.level
= RAW_LOCK_UNLOCK
;
139 status
= smb_raw_lock(cli
->tree
, &io
);
140 CHECK_STATUS(status
, NT_STATUS_OK
);
141 io
.lock
.level
= RAW_LOCK_UNLOCK
;
142 status
= smb_raw_lock(cli
->tree
, &io
);
143 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
145 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
146 io
.lock
.level
= RAW_LOCK_LOCK
;
147 io
.lock
.in
.file
.fnum
= fnum
;
148 io
.lock
.in
.count
= 4000;
149 io
.lock
.in
.offset
= 0xEEFFFFFF;
150 status
= smb_raw_lock(cli
->tree
, &io
);
151 CHECK_STATUS(status
, NT_STATUS_OK
);
153 status
= smb_raw_lock(cli
->tree
, &io
);
154 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
156 io
.lock
.level
= RAW_LOCK_UNLOCK
;
157 status
= smb_raw_lock(cli
->tree
, &io
);
158 CHECK_STATUS(status
, NT_STATUS_OK
);
159 io
.lock
.level
= RAW_LOCK_UNLOCK
;
160 status
= smb_raw_lock(cli
->tree
, &io
);
161 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
163 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
164 io
.lock
.level
= RAW_LOCK_LOCK
;
165 io
.lock
.in
.file
.fnum
= fnum
;
166 io
.lock
.in
.count
= 4000;
167 io
.lock
.in
.offset
= 0xEEFFFFFF;
168 status
= smb_raw_lock(cli
->tree
, &io
);
169 CHECK_STATUS(status
, NT_STATUS_OK
);
171 status
= smb_raw_lock(cli
->tree
, &io
);
172 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
174 io
.lock
.level
= RAW_LOCK_UNLOCK
;
175 status
= smb_raw_lock(cli
->tree
, &io
);
176 CHECK_STATUS(status
, NT_STATUS_OK
);
177 io
.lock
.level
= RAW_LOCK_UNLOCK
;
178 status
= smb_raw_lock(cli
->tree
, &io
);
179 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
181 torture_comment(tctx
, "Trying max lock\n");
182 io
.lock
.level
= RAW_LOCK_LOCK
;
183 io
.lock
.in
.file
.fnum
= fnum
;
184 io
.lock
.in
.count
= 4000;
185 io
.lock
.in
.offset
= 0xEF000000;
186 status
= smb_raw_lock(cli
->tree
, &io
);
187 CHECK_STATUS(status
, NT_STATUS_OK
);
189 status
= smb_raw_lock(cli
->tree
, &io
);
190 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
192 io
.lock
.level
= RAW_LOCK_UNLOCK
;
193 status
= smb_raw_lock(cli
->tree
, &io
);
194 CHECK_STATUS(status
, NT_STATUS_OK
);
195 io
.lock
.level
= RAW_LOCK_UNLOCK
;
196 status
= smb_raw_lock(cli
->tree
, &io
);
197 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
199 torture_comment(tctx
, "Trying wrong pid unlock\n");
200 io
.lock
.level
= RAW_LOCK_LOCK
;
201 io
.lock
.in
.file
.fnum
= fnum
;
202 io
.lock
.in
.count
= 4002;
203 io
.lock
.in
.offset
= 10001;
204 status
= smb_raw_lock(cli
->tree
, &io
);
205 CHECK_STATUS(status
, NT_STATUS_OK
);
207 io
.lock
.level
= RAW_LOCK_UNLOCK
;
208 status
= smb_raw_lock(cli
->tree
, &io
);
209 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
211 status
= smb_raw_lock(cli
->tree
, &io
);
212 CHECK_STATUS(status
, NT_STATUS_OK
);
215 smbcli_close(cli
->tree
, fnum
);
216 smb_raw_exit(cli
->session
);
217 smbcli_deltree(cli
->tree
, BASEDIR
);
225 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
228 struct smb_lock_entry lock
[1];
232 const char *fname
= BASEDIR
"\\test.txt";
234 if (!torture_setup_dir(cli
, BASEDIR
)) {
238 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
239 io
.generic
.level
= RAW_LOCK_LOCKX
;
241 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
242 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
243 "Failed to create %s - %s\n",
244 fname
, smbcli_errstr(cli
->tree
)));
246 io
.lockx
.level
= RAW_LOCK_LOCKX
;
247 io
.lockx
.in
.file
.fnum
= fnum
;
248 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
249 io
.lockx
.in
.timeout
= 0;
250 io
.lockx
.in
.ulock_cnt
= 0;
251 io
.lockx
.in
.lock_cnt
= 1;
252 lock
[0].pid
= cli
->session
->pid
;
255 io
.lockx
.in
.locks
= &lock
[0];
256 status
= smb_raw_lock(cli
->tree
, &io
);
257 CHECK_STATUS(status
, NT_STATUS_OK
);
260 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
261 io
.lockx
.in
.ulock_cnt
= 0;
262 io
.lockx
.in
.lock_cnt
= 1;
263 lock
[0].count
= 4000;
264 lock
[0].offset
= 0xEEFFFFFF;
265 status
= smb_raw_lock(cli
->tree
, &io
);
266 CHECK_STATUS(status
, NT_STATUS_OK
);
268 status
= smb_raw_lock(cli
->tree
, &io
);
269 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
271 io
.lockx
.in
.ulock_cnt
= 1;
272 io
.lockx
.in
.lock_cnt
= 0;
273 status
= smb_raw_lock(cli
->tree
, &io
);
274 CHECK_STATUS(status
, NT_STATUS_OK
);
275 status
= smb_raw_lock(cli
->tree
, &io
);
276 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
278 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
279 io
.lockx
.in
.ulock_cnt
= 0;
280 io
.lockx
.in
.lock_cnt
= 1;
281 lock
[0].count
= 4000;
282 lock
[0].offset
= 0xEF000000;
283 status
= smb_raw_lock(cli
->tree
, &io
);
284 CHECK_STATUS(status
, NT_STATUS_OK
);
286 status
= smb_raw_lock(cli
->tree
, &io
);
287 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
289 io
.lockx
.in
.ulock_cnt
= 1;
290 io
.lockx
.in
.lock_cnt
= 0;
291 status
= smb_raw_lock(cli
->tree
, &io
);
292 CHECK_STATUS(status
, NT_STATUS_OK
);
293 status
= smb_raw_lock(cli
->tree
, &io
);
294 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
296 torture_comment(tctx
, "Trying zero lock\n");
297 io
.lockx
.in
.ulock_cnt
= 0;
298 io
.lockx
.in
.lock_cnt
= 1;
301 status
= smb_raw_lock(cli
->tree
, &io
);
302 CHECK_STATUS(status
, NT_STATUS_OK
);
304 status
= smb_raw_lock(cli
->tree
, &io
);
305 CHECK_STATUS(status
, NT_STATUS_OK
);
307 io
.lockx
.in
.ulock_cnt
= 1;
308 io
.lockx
.in
.lock_cnt
= 0;
309 status
= smb_raw_lock(cli
->tree
, &io
);
310 CHECK_STATUS(status
, NT_STATUS_OK
);
311 status
= smb_raw_lock(cli
->tree
, &io
);
312 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
314 torture_comment(tctx
, "Trying max lock\n");
315 io
.lockx
.in
.ulock_cnt
= 0;
316 io
.lockx
.in
.lock_cnt
= 1;
319 status
= smb_raw_lock(cli
->tree
, &io
);
320 CHECK_STATUS(status
, NT_STATUS_OK
);
322 status
= smb_raw_lock(cli
->tree
, &io
);
323 CHECK_STATUS(status
, NT_STATUS_OK
);
325 io
.lockx
.in
.ulock_cnt
= 1;
326 io
.lockx
.in
.lock_cnt
= 0;
327 status
= smb_raw_lock(cli
->tree
, &io
);
328 CHECK_STATUS(status
, NT_STATUS_OK
);
329 status
= smb_raw_lock(cli
->tree
, &io
);
330 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
332 torture_comment(tctx
, "Trying 2^63\n");
333 io
.lockx
.in
.ulock_cnt
= 0;
334 io
.lockx
.in
.lock_cnt
= 1;
337 lock
[0].offset
<<= 63;
338 status
= smb_raw_lock(cli
->tree
, &io
);
339 CHECK_STATUS(status
, NT_STATUS_OK
);
341 status
= smb_raw_lock(cli
->tree
, &io
);
342 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
344 io
.lockx
.in
.ulock_cnt
= 1;
345 io
.lockx
.in
.lock_cnt
= 0;
346 status
= smb_raw_lock(cli
->tree
, &io
);
347 CHECK_STATUS(status
, NT_STATUS_OK
);
348 status
= smb_raw_lock(cli
->tree
, &io
);
349 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
351 torture_comment(tctx
, "Trying 2^63 - 1\n");
352 io
.lockx
.in
.ulock_cnt
= 0;
353 io
.lockx
.in
.lock_cnt
= 1;
356 lock
[0].offset
<<= 63;
358 status
= smb_raw_lock(cli
->tree
, &io
);
359 CHECK_STATUS(status
, NT_STATUS_OK
);
361 status
= smb_raw_lock(cli
->tree
, &io
);
362 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
364 io
.lockx
.in
.ulock_cnt
= 1;
365 io
.lockx
.in
.lock_cnt
= 0;
366 status
= smb_raw_lock(cli
->tree
, &io
);
367 CHECK_STATUS(status
, NT_STATUS_OK
);
368 status
= smb_raw_lock(cli
->tree
, &io
);
369 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
371 torture_comment(tctx
, "Trying max lock 2\n");
372 io
.lockx
.in
.ulock_cnt
= 0;
373 io
.lockx
.in
.lock_cnt
= 1;
376 status
= smb_raw_lock(cli
->tree
, &io
);
377 CHECK_STATUS(status
, NT_STATUS_OK
);
380 status
= smb_raw_lock(cli
->tree
, &io
);
381 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx
))
382 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
384 CHECK_STATUS(status
, NT_STATUS_OK
);
386 io
.lockx
.in
.ulock_cnt
= 1;
387 io
.lockx
.in
.lock_cnt
= 0;
389 status
= smb_raw_lock(cli
->tree
, &io
);
391 CHECK_STATUS(status
, NT_STATUS_OK
);
392 status
= smb_raw_lock(cli
->tree
, &io
);
393 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
396 smbcli_close(cli
->tree
, fnum
);
397 smb_raw_exit(cli
->session
);
398 smbcli_deltree(cli
->tree
, BASEDIR
);
405 static bool test_pidhigh(struct torture_context
*tctx
,
406 struct smbcli_state
*cli
)
409 struct smb_lock_entry lock
[1];
413 const char *fname
= BASEDIR
"\\test.txt";
416 if (!torture_setup_dir(cli
, BASEDIR
)) {
420 torture_comment(tctx
, "Testing high pid\n");
421 io
.generic
.level
= RAW_LOCK_LOCKX
;
423 cli
->session
->pid
= 1;
425 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
426 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
427 "Failed to create %s - %s\n",
428 fname
, smbcli_errstr(cli
->tree
)));
430 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
431 torture_result(tctx
, TORTURE_FAIL
,
432 "Failed to write 1 byte - %s\n",
433 smbcli_errstr(cli
->tree
));
438 io
.lockx
.level
= RAW_LOCK_LOCKX
;
439 io
.lockx
.in
.file
.fnum
= fnum
;
440 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
441 io
.lockx
.in
.timeout
= 0;
442 io
.lockx
.in
.ulock_cnt
= 0;
443 io
.lockx
.in
.lock_cnt
= 1;
444 lock
[0].pid
= cli
->session
->pid
;
446 lock
[0].count
= 0xFFFFFFFF;
447 io
.lockx
.in
.locks
= &lock
[0];
448 status
= smb_raw_lock(cli
->tree
, &io
);
449 CHECK_STATUS(status
, NT_STATUS_OK
);
451 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
452 torture_result(tctx
, TORTURE_FAIL
,
453 "Failed to read 1 byte - %s\n",
454 smbcli_errstr(cli
->tree
));
459 cli
->session
->pid
= 2;
461 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
462 torture_result(tctx
, TORTURE_FAIL
,
463 "pid is incorrect handled for read with lock!\n");
468 cli
->session
->pid
= 0x10001;
470 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
471 torture_result(tctx
, TORTURE_FAIL
,
472 "High pid is used on this server!\n");
475 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
479 smbcli_close(cli
->tree
, fnum
);
480 smb_raw_exit(cli
->session
);
481 smbcli_deltree(cli
->tree
, BASEDIR
);
487 test locking&X async operation
489 static bool test_async(struct torture_context
*tctx
,
490 struct smbcli_state
*cli
)
492 struct smbcli_session
*session
;
493 struct smb_composite_sesssetup setup
;
494 struct smbcli_tree
*tree
;
496 const char *host
, *share
;
498 struct smb_lock_entry lock
[2];
502 const char *fname
= BASEDIR
"\\test.txt";
504 struct smbcli_request
*req
, *req2
;
505 struct smbcli_session_options options
;
507 if (!torture_setup_dir(cli
, BASEDIR
)) {
511 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
513 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
514 io
.generic
.level
= RAW_LOCK_LOCKX
;
516 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
517 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
518 "Failed to create %s - %s\n",
519 fname
, smbcli_errstr(cli
->tree
)));
521 io
.lockx
.level
= RAW_LOCK_LOCKX
;
522 io
.lockx
.in
.file
.fnum
= fnum
;
523 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
524 io
.lockx
.in
.timeout
= 0;
525 io
.lockx
.in
.ulock_cnt
= 0;
526 io
.lockx
.in
.lock_cnt
= 1;
527 lock
[0].pid
= cli
->session
->pid
;
528 lock
[0].offset
= 100;
530 lock
[1].pid
= cli
->session
->pid
;
531 lock
[1].offset
= 110;
533 io
.lockx
.in
.locks
= &lock
[0];
534 status
= smb_raw_lock(cli
->tree
, &io
);
535 CHECK_STATUS(status
, NT_STATUS_OK
);
539 torture_comment(tctx
, "testing cancel by CANCEL_LOCK\n");
541 /* setup a timed lock */
542 io
.lockx
.in
.timeout
= 10000;
543 req
= smb_raw_lock_send(cli
->tree
, &io
);
544 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
545 "Failed to setup timed lock (%s)\n", __location__
));
547 /* cancel the wrong range */
549 io
.lockx
.in
.timeout
= 0;
550 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
551 status
= smb_raw_lock(cli
->tree
, &io
);
552 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
554 /* cancel with the wrong bits set */
555 lock
[0].offset
= 100;
556 io
.lockx
.in
.timeout
= 0;
557 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
558 status
= smb_raw_lock(cli
->tree
, &io
);
559 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
561 /* cancel the right range */
562 lock
[0].offset
= 100;
563 io
.lockx
.in
.timeout
= 0;
564 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
565 status
= smb_raw_lock(cli
->tree
, &io
);
566 CHECK_STATUS(status
, NT_STATUS_OK
);
568 /* receive the failed lock request */
569 status
= smbcli_request_simple_recv(req
);
570 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
572 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
573 "lock cancel was not immediate (%s)\n", __location__
));
575 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
576 * if the lock vector contains one entry. When given mutliple cancel
577 * requests in a single PDU we expect the server to return an
578 * error. Samba4 handles this correctly. Windows servers seem to
579 * accept the request but only cancel the first lock. Samba3
580 * now does what Windows does (JRA).
582 torture_comment(tctx
, "testing multiple cancel\n");
584 /* acquire second lock */
585 io
.lockx
.in
.timeout
= 0;
586 io
.lockx
.in
.ulock_cnt
= 0;
587 io
.lockx
.in
.lock_cnt
= 1;
588 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
589 io
.lockx
.in
.locks
= &lock
[1];
590 status
= smb_raw_lock(cli
->tree
, &io
);
591 CHECK_STATUS(status
, NT_STATUS_OK
);
593 /* setup 2 timed locks */
595 io
.lockx
.in
.timeout
= 10000;
596 io
.lockx
.in
.lock_cnt
= 1;
597 io
.lockx
.in
.locks
= &lock
[0];
598 req
= smb_raw_lock_send(cli
->tree
, &io
);
599 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
600 "Failed to setup timed lock (%s)\n", __location__
));
601 io
.lockx
.in
.locks
= &lock
[1];
602 req2
= smb_raw_lock_send(cli
->tree
, &io
);
603 torture_assert(tctx
,(req2
!= NULL
), talloc_asprintf(tctx
,
604 "Failed to setup timed lock (%s)\n", __location__
));
606 /* try to cancel both locks in the same packet */
607 io
.lockx
.in
.timeout
= 0;
608 io
.lockx
.in
.lock_cnt
= 2;
609 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
610 io
.lockx
.in
.locks
= lock
;
611 status
= smb_raw_lock(cli
->tree
, &io
);
612 CHECK_STATUS(status
, NT_STATUS_OK
);
614 torture_warning(tctx
, "Target server accepted a lock cancel "
615 "request with multiple locks. This violates "
616 "MS-CIFS 2.2.4.32.1.\n");
618 /* receive the failed lock requests */
619 status
= smbcli_request_simple_recv(req
);
620 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
622 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
623 "first lock was not cancelled immediately (%s)\n",
626 /* send cancel to second lock */
627 io
.lockx
.in
.timeout
= 0;
628 io
.lockx
.in
.lock_cnt
= 1;
629 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
|
630 LOCKING_ANDX_LARGE_FILES
;
631 io
.lockx
.in
.locks
= &lock
[1];
632 status
= smb_raw_lock(cli
->tree
, &io
);
633 CHECK_STATUS(status
, NT_STATUS_OK
);
635 status
= smbcli_request_simple_recv(req2
);
636 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
638 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
639 "second lock was not cancelled immediately (%s)\n",
642 /* cleanup the second lock */
643 io
.lockx
.in
.ulock_cnt
= 1;
644 io
.lockx
.in
.lock_cnt
= 0;
645 io
.lockx
.in
.locks
= &lock
[1];
646 status
= smb_raw_lock(cli
->tree
, &io
);
647 CHECK_STATUS(status
, NT_STATUS_OK
);
649 torture_comment(tctx
, "testing cancel by unlock\n");
650 io
.lockx
.in
.ulock_cnt
= 0;
651 io
.lockx
.in
.lock_cnt
= 1;
652 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
653 io
.lockx
.in
.timeout
= 0;
654 io
.lockx
.in
.locks
= &lock
[0];
655 status
= smb_raw_lock(cli
->tree
, &io
);
656 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
658 io
.lockx
.in
.timeout
= 5000;
659 req
= smb_raw_lock_send(cli
->tree
, &io
);
660 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
661 "Failed to setup timed lock (%s)\n", __location__
));
663 io
.lockx
.in
.ulock_cnt
= 1;
664 io
.lockx
.in
.lock_cnt
= 0;
665 status
= smb_raw_lock(cli
->tree
, &io
);
666 CHECK_STATUS(status
, NT_STATUS_OK
);
669 status
= smbcli_request_simple_recv(req
);
670 CHECK_STATUS(status
, NT_STATUS_OK
);
672 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
673 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
674 __location__
, (int)(time(NULL
)-t
)));
676 torture_comment(tctx
, "testing cancel by close\n");
677 io
.lockx
.in
.ulock_cnt
= 0;
678 io
.lockx
.in
.lock_cnt
= 1;
679 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
680 io
.lockx
.in
.timeout
= 0;
681 status
= smb_raw_lock(cli
->tree
, &io
);
682 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
685 io
.lockx
.in
.timeout
= 10000;
686 req
= smb_raw_lock_send(cli
->tree
, &io
);
687 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
688 "Failed to setup timed lock (%s)\n", __location__
));
690 status
= smbcli_close(cli
->tree
, fnum
);
691 CHECK_STATUS(status
, NT_STATUS_OK
);
693 status
= smbcli_request_simple_recv(req
);
694 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
696 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
697 "lock cancel by close was not immediate (%s)\n", __location__
));
699 torture_comment(tctx
, "create a new sessions\n");
700 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
701 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
702 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
703 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
704 setup
.in
.credentials
= cmdline_credentials
;
705 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
706 status
= smb_composite_sesssetup(session
, &setup
);
707 CHECK_STATUS(status
, NT_STATUS_OK
);
708 session
->vuid
= setup
.out
.vuid
;
710 torture_comment(tctx
, "create new tree context\n");
711 share
= torture_setting_string(tctx
, "share", NULL
);
712 host
= torture_setting_string(tctx
, "host", NULL
);
713 tree
= smbcli_tree_init(session
, tctx
, false);
714 tcon
.generic
.level
= RAW_TCON_TCONX
;
715 tcon
.tconx
.in
.flags
= 0;
716 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
717 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
718 tcon
.tconx
.in
.device
= "A:";
719 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
720 CHECK_STATUS(status
, NT_STATUS_OK
);
721 tree
->tid
= tcon
.tconx
.out
.tid
;
723 torture_comment(tctx
, "testing cancel by exit\n");
724 fname
= BASEDIR
"\\test_exit.txt";
725 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
726 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
727 "Failed to reopen %s - %s\n",
728 fname
, smbcli_errstr(tree
)));
730 io
.lockx
.level
= RAW_LOCK_LOCKX
;
731 io
.lockx
.in
.file
.fnum
= fnum
;
732 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
733 io
.lockx
.in
.timeout
= 0;
734 io
.lockx
.in
.ulock_cnt
= 0;
735 io
.lockx
.in
.lock_cnt
= 1;
736 lock
[0].pid
= session
->pid
;
737 lock
[0].offset
= 100;
739 io
.lockx
.in
.locks
= &lock
[0];
740 status
= smb_raw_lock(tree
, &io
);
741 CHECK_STATUS(status
, NT_STATUS_OK
);
743 io
.lockx
.in
.ulock_cnt
= 0;
744 io
.lockx
.in
.lock_cnt
= 1;
745 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
746 io
.lockx
.in
.timeout
= 0;
747 status
= smb_raw_lock(tree
, &io
);
748 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
750 io
.lockx
.in
.timeout
= 10000;
752 req
= smb_raw_lock_send(tree
, &io
);
753 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
754 "Failed to setup timed lock (%s)\n", __location__
));
756 status
= smb_raw_exit(session
);
757 CHECK_STATUS(status
, NT_STATUS_OK
);
759 status
= smbcli_request_simple_recv(req
);
760 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
762 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
763 "lock cancel by exit was not immediate (%s)\n", __location__
));
765 torture_comment(tctx
, "testing cancel by ulogoff\n");
766 fname
= BASEDIR
"\\test_ulogoff.txt";
767 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
768 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
769 "Failed to reopen %s - %s\n",
770 fname
, smbcli_errstr(tree
)));
772 io
.lockx
.level
= RAW_LOCK_LOCKX
;
773 io
.lockx
.in
.file
.fnum
= fnum
;
774 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
775 io
.lockx
.in
.timeout
= 0;
776 io
.lockx
.in
.ulock_cnt
= 0;
777 io
.lockx
.in
.lock_cnt
= 1;
778 lock
[0].pid
= session
->pid
;
779 lock
[0].offset
= 100;
781 io
.lockx
.in
.locks
= &lock
[0];
782 status
= smb_raw_lock(tree
, &io
);
783 CHECK_STATUS(status
, NT_STATUS_OK
);
785 io
.lockx
.in
.ulock_cnt
= 0;
786 io
.lockx
.in
.lock_cnt
= 1;
787 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
788 io
.lockx
.in
.timeout
= 0;
789 status
= smb_raw_lock(tree
, &io
);
790 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
792 io
.lockx
.in
.timeout
= 10000;
794 req
= smb_raw_lock_send(tree
, &io
);
795 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
796 "Failed to setup timed lock (%s)\n", __location__
));
798 status
= smb_raw_ulogoff(session
);
799 CHECK_STATUS(status
, NT_STATUS_OK
);
801 status
= smbcli_request_simple_recv(req
);
802 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
803 torture_result(tctx
, TORTURE_FAIL
,
804 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
806 smb_tree_disconnect(tree
);
807 smb_raw_exit(session
);
810 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
812 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
813 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
815 torture_comment(tctx
, "testing cancel by tdis\n");
816 tree
->session
= cli
->session
;
818 fname
= BASEDIR
"\\test_tdis.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
= cli
->session
->pid
;
831 lock
[0].offset
= 100;
833 io
.lockx
.in
.locks
= &lock
[0];
834 status
= smb_raw_lock(tree
, &io
);
835 CHECK_STATUS(status
, NT_STATUS_OK
);
837 status
= smb_raw_lock(tree
, &io
);
838 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
840 io
.lockx
.in
.timeout
= 10000;
842 req
= smb_raw_lock_send(tree
, &io
);
843 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
844 "Failed to setup timed lock (%s)\n", __location__
));
846 status
= smb_tree_disconnect(tree
);
847 CHECK_STATUS(status
, NT_STATUS_OK
);
849 status
= smbcli_request_simple_recv(req
);
850 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
852 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
853 "lock cancel by tdis was not immediate (%s)\n", __location__
));
856 smb_raw_exit(cli
->session
);
857 smbcli_deltree(cli
->tree
, BASEDIR
);
862 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
864 static bool test_errorcode(struct torture_context
*tctx
,
865 struct smbcli_state
*cli
)
869 struct smb_lock_entry lock
[2];
874 struct smbcli_request
*req
;
878 uint16_t deny_mode
= 0;
880 if (!torture_setup_dir(cli
, BASEDIR
)) {
884 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
886 torture_comment(tctx
, "testing with timeout = 0\n");
887 fname
= BASEDIR
"\\test0.txt";
891 * the first run is with t = 0,
892 * the second with t > 0 (=1)
896 * use the DENY_DOS mode, that creates two fnum's of one low-level
897 * file handle, this demonstrates that the cache is per fnum, not
900 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx
))
901 deny_mode
= OPENX_MODE_DENY_DOS
;
903 deny_mode
= OPENX_MODE_DENY_NONE
;
905 op
.openx
.level
= RAW_OPEN_OPENX
;
906 op
.openx
.in
.fname
= fname
;
907 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
908 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| deny_mode
;
909 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
910 op
.openx
.in
.search_attrs
= 0;
911 op
.openx
.in
.file_attrs
= 0;
912 op
.openx
.in
.write_time
= 0;
913 op
.openx
.in
.size
= 0;
914 op
.openx
.in
.timeout
= 0;
916 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
917 CHECK_STATUS(status
, NT_STATUS_OK
);
918 fnum
= op
.openx
.out
.file
.fnum
;
920 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
921 CHECK_STATUS(status
, NT_STATUS_OK
);
922 fnum2
= op
.openx
.out
.file
.fnum
;
924 io
.lockx
.level
= RAW_LOCK_LOCKX
;
925 io
.lockx
.in
.file
.fnum
= fnum
;
926 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
927 io
.lockx
.in
.timeout
= t
;
928 io
.lockx
.in
.ulock_cnt
= 0;
929 io
.lockx
.in
.lock_cnt
= 1;
930 lock
[0].pid
= cli
->session
->pid
;
931 lock
[0].offset
= 100;
933 io
.lockx
.in
.locks
= &lock
[0];
934 status
= smb_raw_lock(cli
->tree
, &io
);
935 CHECK_STATUS(status
, NT_STATUS_OK
);
938 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
939 * this also demonstrates that the error code cache is per file handle
940 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
942 io
.lockx
.in
.file
.fnum
= fnum2
;
943 status
= smb_raw_lock(cli
->tree
, &io
);
944 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
946 io
.lockx
.in
.file
.fnum
= fnum
;
947 status
= smb_raw_lock(cli
->tree
, &io
);
948 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
950 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
951 io
.lockx
.in
.file
.fnum
= fnum
;
952 status
= smb_raw_lock(cli
->tree
, &io
);
953 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
955 io
.lockx
.in
.file
.fnum
= fnum2
;
956 status
= smb_raw_lock(cli
->tree
, &io
);
957 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
959 io
.lockx
.in
.file
.fnum
= fnum
;
960 status
= smb_raw_lock(cli
->tree
, &io
);
961 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
963 io
.lockx
.in
.file
.fnum
= fnum2
;
964 status
= smb_raw_lock(cli
->tree
, &io
);
965 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
967 /* demonstrate that the smbpid doesn't matter */
969 io
.lockx
.in
.file
.fnum
= fnum
;
970 status
= smb_raw_lock(cli
->tree
, &io
);
971 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
973 io
.lockx
.in
.file
.fnum
= fnum2
;
974 status
= smb_raw_lock(cli
->tree
, &io
);
975 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
979 * demonstrate the a successful lock with count = 0 and the same offset,
980 * doesn't reset the error cache
982 lock
[0].offset
= 100;
984 io
.lockx
.in
.file
.fnum
= fnum
;
985 status
= smb_raw_lock(cli
->tree
, &io
);
986 CHECK_STATUS(status
, NT_STATUS_OK
);
988 io
.lockx
.in
.file
.fnum
= fnum2
;
989 status
= smb_raw_lock(cli
->tree
, &io
);
990 CHECK_STATUS(status
, NT_STATUS_OK
);
992 lock
[0].offset
= 100;
994 io
.lockx
.in
.file
.fnum
= fnum
;
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
, NT_STATUS_FILE_LOCK_CONFLICT
);
1003 * demonstrate the a successful lock with count = 0 and outside the locked range,
1004 * doesn't reset the error cache
1006 lock
[0].offset
= 110;
1008 io
.lockx
.in
.file
.fnum
= fnum
;
1009 status
= smb_raw_lock(cli
->tree
, &io
);
1010 CHECK_STATUS(status
, NT_STATUS_OK
);
1012 io
.lockx
.in
.file
.fnum
= fnum2
;
1013 status
= smb_raw_lock(cli
->tree
, &io
);
1014 CHECK_STATUS(status
, NT_STATUS_OK
);
1016 lock
[0].offset
= 100;
1018 io
.lockx
.in
.file
.fnum
= fnum
;
1019 status
= smb_raw_lock(cli
->tree
, &io
);
1020 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1022 io
.lockx
.in
.file
.fnum
= fnum2
;
1023 status
= smb_raw_lock(cli
->tree
, &io
);
1024 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1026 lock
[0].offset
= 99;
1028 io
.lockx
.in
.file
.fnum
= fnum
;
1029 status
= smb_raw_lock(cli
->tree
, &io
);
1030 CHECK_STATUS(status
, NT_STATUS_OK
);
1032 io
.lockx
.in
.file
.fnum
= fnum2
;
1033 status
= smb_raw_lock(cli
->tree
, &io
);
1034 CHECK_STATUS(status
, NT_STATUS_OK
);
1036 lock
[0].offset
= 100;
1038 io
.lockx
.in
.file
.fnum
= fnum
;
1039 status
= smb_raw_lock(cli
->tree
, &io
);
1040 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1042 io
.lockx
.in
.file
.fnum
= fnum2
;
1043 status
= smb_raw_lock(cli
->tree
, &io
);
1044 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1046 /* demonstrate that a changing count doesn't reset the error cache */
1047 lock
[0].offset
= 100;
1049 io
.lockx
.in
.file
.fnum
= fnum
;
1050 status
= smb_raw_lock(cli
->tree
, &io
);
1051 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1053 io
.lockx
.in
.file
.fnum
= fnum2
;
1054 status
= smb_raw_lock(cli
->tree
, &io
);
1055 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1057 lock
[0].offset
= 100;
1059 io
.lockx
.in
.file
.fnum
= fnum
;
1060 status
= smb_raw_lock(cli
->tree
, &io
);
1061 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1063 io
.lockx
.in
.file
.fnum
= fnum2
;
1064 status
= smb_raw_lock(cli
->tree
, &io
);
1065 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1068 * demonstrate the a lock with count = 0 and inside the locked range,
1069 * fails and resets the error cache
1071 lock
[0].offset
= 101;
1073 io
.lockx
.in
.file
.fnum
= fnum
;
1074 status
= smb_raw_lock(cli
->tree
, &io
);
1075 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1076 status
= smb_raw_lock(cli
->tree
, &io
);
1077 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1079 io
.lockx
.in
.file
.fnum
= fnum2
;
1080 status
= smb_raw_lock(cli
->tree
, &io
);
1081 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1082 status
= smb_raw_lock(cli
->tree
, &io
);
1083 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1085 lock
[0].offset
= 100;
1087 io
.lockx
.in
.file
.fnum
= fnum
;
1088 status
= smb_raw_lock(cli
->tree
, &io
);
1089 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1090 status
= smb_raw_lock(cli
->tree
, &io
);
1091 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1093 io
.lockx
.in
.file
.fnum
= fnum2
;
1094 status
= smb_raw_lock(cli
->tree
, &io
);
1095 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1096 status
= smb_raw_lock(cli
->tree
, &io
);
1097 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1099 /* demonstrate the a changing offset, resets the error cache */
1100 lock
[0].offset
= 105;
1102 io
.lockx
.in
.file
.fnum
= fnum
;
1103 status
= smb_raw_lock(cli
->tree
, &io
);
1104 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1105 status
= smb_raw_lock(cli
->tree
, &io
);
1106 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1108 io
.lockx
.in
.file
.fnum
= fnum2
;
1109 status
= smb_raw_lock(cli
->tree
, &io
);
1110 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1111 status
= smb_raw_lock(cli
->tree
, &io
);
1112 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1114 lock
[0].offset
= 100;
1116 io
.lockx
.in
.file
.fnum
= fnum
;
1117 status
= smb_raw_lock(cli
->tree
, &io
);
1118 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1119 status
= smb_raw_lock(cli
->tree
, &io
);
1120 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1122 io
.lockx
.in
.file
.fnum
= fnum2
;
1123 status
= smb_raw_lock(cli
->tree
, &io
);
1124 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1125 status
= smb_raw_lock(cli
->tree
, &io
);
1126 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1128 lock
[0].offset
= 95;
1130 io
.lockx
.in
.file
.fnum
= fnum
;
1131 status
= smb_raw_lock(cli
->tree
, &io
);
1132 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
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
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1139 status
= smb_raw_lock(cli
->tree
, &io
);
1140 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1142 lock
[0].offset
= 100;
1144 io
.lockx
.in
.file
.fnum
= fnum
;
1145 status
= smb_raw_lock(cli
->tree
, &io
);
1146 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1147 status
= smb_raw_lock(cli
->tree
, &io
);
1148 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1150 io
.lockx
.in
.file
.fnum
= fnum2
;
1151 status
= smb_raw_lock(cli
->tree
, &io
);
1152 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1153 status
= smb_raw_lock(cli
->tree
, &io
);
1154 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1157 * demonstrate the a successful lock in a different range,
1158 * doesn't reset the cache, the failing lock on the 2nd handle
1161 lock
[0].offset
= 120;
1163 io
.lockx
.in
.file
.fnum
= fnum
;
1164 status
= smb_raw_lock(cli
->tree
, &io
);
1165 CHECK_STATUS(status
, NT_STATUS_OK
);
1167 io
.lockx
.in
.file
.fnum
= fnum2
;
1168 status
= smb_raw_lock(cli
->tree
, &io
);
1169 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1171 lock
[0].offset
= 100;
1173 io
.lockx
.in
.file
.fnum
= fnum
;
1174 status
= smb_raw_lock(cli
->tree
, &io
);
1175 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1176 status
= smb_raw_lock(cli
->tree
, &io
);
1177 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1179 io
.lockx
.in
.file
.fnum
= fnum2
;
1180 status
= smb_raw_lock(cli
->tree
, &io
);
1181 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1182 status
= smb_raw_lock(cli
->tree
, &io
);
1183 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1185 /* end of the loop */
1187 smb_raw_exit(cli
->session
);
1189 torture_comment(tctx
, "testing with timeout > 0 (=%d)\n",
1191 fname
= BASEDIR
"\\test1.txt";
1196 torture_comment(tctx
, "testing special cases with timeout > 0 (=%d)\n",
1200 * the following 3 test sections demonstrate that
1201 * the cache is only set when the error is reported
1202 * to the client (after the timeout went by)
1204 smb_raw_exit(cli
->session
);
1205 torture_comment(tctx
, "testing a conflict while a lock is pending\n");
1206 fname
= BASEDIR
"\\test2.txt";
1207 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1208 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1209 "Failed to reopen %s - %s\n",
1210 fname
, smbcli_errstr(cli
->tree
)));
1212 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1213 io
.lockx
.in
.file
.fnum
= fnum
;
1214 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1215 io
.lockx
.in
.timeout
= 0;
1216 io
.lockx
.in
.ulock_cnt
= 0;
1217 io
.lockx
.in
.lock_cnt
= 1;
1218 lock
[0].pid
= cli
->session
->pid
;
1219 lock
[0].offset
= 100;
1221 io
.lockx
.in
.locks
= &lock
[0];
1222 status
= smb_raw_lock(cli
->tree
, &io
);
1223 CHECK_STATUS(status
, NT_STATUS_OK
);
1226 io
.lockx
.in
.timeout
= t
;
1227 req
= smb_raw_lock_send(cli
->tree
, &io
);
1228 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1229 "Failed to setup timed lock (%s)\n", __location__
));
1231 io
.lockx
.in
.timeout
= 0;
1232 lock
[0].offset
= 105;
1234 status
= smb_raw_lock(cli
->tree
, &io
);
1235 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1237 status
= smbcli_request_simple_recv(req
);
1238 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1241 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1245 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1246 "lock comes back to early timeout[%d] delay[%d]"
1247 "(%s)\n", t
, delay
, __location__
));
1249 status
= smb_raw_lock(cli
->tree
, &io
);
1250 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1252 smbcli_close(cli
->tree
, fnum
);
1253 fname
= BASEDIR
"\\test3.txt";
1254 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1255 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1256 "Failed to reopen %s - %s\n",
1257 fname
, smbcli_errstr(cli
->tree
)));
1259 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1260 io
.lockx
.in
.file
.fnum
= fnum
;
1261 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1262 io
.lockx
.in
.timeout
= 0;
1263 io
.lockx
.in
.ulock_cnt
= 0;
1264 io
.lockx
.in
.lock_cnt
= 1;
1265 lock
[0].pid
= cli
->session
->pid
;
1266 lock
[0].offset
= 100;
1268 io
.lockx
.in
.locks
= &lock
[0];
1269 status
= smb_raw_lock(cli
->tree
, &io
);
1270 CHECK_STATUS(status
, NT_STATUS_OK
);
1273 io
.lockx
.in
.timeout
= t
;
1274 req
= smb_raw_lock_send(cli
->tree
, &io
);
1275 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1276 "Failed to setup timed lock (%s)\n", __location__
));
1278 io
.lockx
.in
.timeout
= 0;
1279 lock
[0].offset
= 105;
1281 status
= smb_raw_lock(cli
->tree
, &io
);
1282 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1284 status
= smbcli_request_simple_recv(req
);
1285 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1288 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1292 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1293 "lock comes back to early timeout[%d] delay[%d]"
1294 "(%s)\n", t
, delay
, __location__
));
1296 lock
[0].offset
= 100;
1298 status
= smb_raw_lock(cli
->tree
, &io
);
1299 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1301 smbcli_close(cli
->tree
, fnum
);
1302 fname
= BASEDIR
"\\test4.txt";
1303 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1304 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1305 "Failed to reopen %s - %s\n",
1306 fname
, smbcli_errstr(cli
->tree
)));
1308 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1309 io
.lockx
.in
.file
.fnum
= fnum
;
1310 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1311 io
.lockx
.in
.timeout
= 0;
1312 io
.lockx
.in
.ulock_cnt
= 0;
1313 io
.lockx
.in
.lock_cnt
= 1;
1314 lock
[0].pid
= cli
->session
->pid
;
1315 lock
[0].offset
= 100;
1317 io
.lockx
.in
.locks
= &lock
[0];
1318 status
= smb_raw_lock(cli
->tree
, &io
);
1319 CHECK_STATUS(status
, NT_STATUS_OK
);
1322 io
.lockx
.in
.timeout
= t
;
1323 req
= smb_raw_lock_send(cli
->tree
, &io
);
1324 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1325 "Failed to setup timed lock (%s)\n", __location__
));
1327 io
.lockx
.in
.timeout
= 0;
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
);
1335 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
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_FILE_LOCK_CONFLICT
);
1347 smb_raw_exit(cli
->session
);
1348 smbcli_deltree(cli
->tree
, BASEDIR
);
1354 test LOCKING_ANDX_CHANGE_LOCKTYPE
1356 static bool test_changetype(struct torture_context
*tctx
,
1357 struct smbcli_state
*cli
)
1360 struct smb_lock_entry lock
[2];
1365 const char *fname
= BASEDIR
"\\test.txt";
1367 if (!torture_setup_dir(cli
, BASEDIR
)) {
1371 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1372 io
.generic
.level
= RAW_LOCK_LOCKX
;
1374 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1375 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1376 "Failed to create %s - %s\n",
1377 fname
, smbcli_errstr(cli
->tree
)));
1379 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1380 io
.lockx
.in
.file
.fnum
= fnum
;
1381 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1382 io
.lockx
.in
.timeout
= 0;
1383 io
.lockx
.in
.ulock_cnt
= 0;
1384 io
.lockx
.in
.lock_cnt
= 1;
1385 lock
[0].pid
= cli
->session
->pid
;
1386 lock
[0].offset
= 100;
1388 io
.lockx
.in
.locks
= &lock
[0];
1389 status
= smb_raw_lock(cli
->tree
, &io
);
1390 CHECK_STATUS(status
, NT_STATUS_OK
);
1392 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1393 torture_result(tctx
, TORTURE_FAIL
,
1394 "allowed write on read locked region (%s)\n", __location__
);
1399 /* windows server don't seem to support this */
1400 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1401 status
= smb_raw_lock(cli
->tree
, &io
);
1402 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1404 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1405 torture_result(tctx
, TORTURE_FAIL
,
1406 "allowed write after lock change (%s)\n", __location__
);
1412 smbcli_close(cli
->tree
, fnum
);
1413 smb_raw_exit(cli
->session
);
1414 smbcli_deltree(cli
->tree
, BASEDIR
);
1418 struct double_lock_test
{
1419 struct smb_lock_entry lock1
;
1420 struct smb_lock_entry lock2
;
1421 NTSTATUS exp_status
;
1425 * Tests zero byte locks.
1427 static struct double_lock_test zero_byte_tests
[] = {
1428 /* {pid, offset, count}, {pid, offset, count}, status */
1430 /** First, takes a zero byte lock at offset 10. Then:
1431 * - Taking 0 byte lock at 10 should succeed.
1432 * - Taking 1 byte locks at 9,10,11 should succeed.
1433 * - Taking 2 byte lock at 9 should fail.
1434 * - Taking 2 byte lock at 10 should succeed.
1435 * - Taking 3 byte lock at 9 should fail.
1437 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1438 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1439 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1440 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1441 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1442 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1443 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1445 /** Same, but opposite order. */
1446 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1447 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1448 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1449 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1450 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1451 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1452 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1454 /** Zero zero case. */
1455 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1458 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1464 const char *fname
= BASEDIR
"\\zero.txt";
1466 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1468 if (!torture_setup_dir(cli
, BASEDIR
)) {
1472 io
.generic
.level
= RAW_LOCK_LOCKX
;
1474 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1475 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1476 "Failed to create %s - %s\n",
1477 fname
, smbcli_errstr(cli
->tree
)));
1479 /* Setup initial parameters */
1480 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1481 io
.lockx
.in
.file
.fnum
= fnum
;
1482 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1483 io
.lockx
.in
.timeout
= 0;
1485 /* Try every combination of locks in zero_byte_tests. The first lock is
1486 * assumed to succeed. The second lock may contend, depending on the
1487 * expected status. */
1489 i
< ARRAY_SIZE(zero_byte_tests
);
1491 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1492 zero_byte_tests
[i
].lock1
.pid
,
1493 zero_byte_tests
[i
].lock1
.offset
,
1494 zero_byte_tests
[i
].lock1
.count
,
1495 zero_byte_tests
[i
].lock2
.pid
,
1496 zero_byte_tests
[i
].lock2
.offset
,
1497 zero_byte_tests
[i
].lock2
.count
,
1498 nt_errstr(zero_byte_tests
[i
].exp_status
));
1500 /* Lock both locks. */
1501 io
.lockx
.in
.ulock_cnt
= 0;
1502 io
.lockx
.in
.lock_cnt
= 1;
1504 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1505 &zero_byte_tests
[i
].lock1
);
1506 status
= smb_raw_lock(cli
->tree
, &io
);
1507 CHECK_STATUS(status
, NT_STATUS_OK
);
1509 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1510 &zero_byte_tests
[i
].lock2
);
1511 status
= smb_raw_lock(cli
->tree
, &io
);
1513 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1514 NT_STATUS_LOCK_NOT_GRANTED
)) {
1515 /* Allow either of the failure messages and keep going
1516 * if we see the wrong status. */
1517 CHECK_STATUS_OR_CONT(status
,
1518 NT_STATUS_LOCK_NOT_GRANTED
,
1519 NT_STATUS_FILE_LOCK_CONFLICT
);
1522 CHECK_STATUS_CONT(status
,
1523 zero_byte_tests
[i
].exp_status
);
1526 /* Unlock both locks. */
1527 io
.lockx
.in
.ulock_cnt
= 1;
1528 io
.lockx
.in
.lock_cnt
= 0;
1530 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1531 status
= smb_raw_lock(cli
->tree
, &io
);
1532 CHECK_STATUS(status
, NT_STATUS_OK
);
1535 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1536 &zero_byte_tests
[i
].lock1
);
1537 status
= smb_raw_lock(cli
->tree
, &io
);
1538 CHECK_STATUS(status
, NT_STATUS_OK
);
1542 smbcli_close(cli
->tree
, fnum
);
1543 smb_raw_exit(cli
->session
);
1544 smbcli_deltree(cli
->tree
, BASEDIR
);
1548 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1554 const char *fname
= BASEDIR
"\\unlock.txt";
1555 struct smb_lock_entry lock1
;
1556 struct smb_lock_entry lock2
;
1558 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1560 if (!torture_setup_dir(cli
, BASEDIR
)) {
1564 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1565 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1566 "Failed to create %s - %s\n",
1567 fname
, smbcli_errstr(cli
->tree
)));
1569 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1570 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1571 "Failed to create %s - %s\n",
1572 fname
, smbcli_errstr(cli
->tree
)));
1574 /* Setup initial parameters */
1575 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1576 io
.lockx
.in
.timeout
= 0;
1578 lock1
.pid
= cli
->session
->pid
;
1581 lock2
.pid
= cli
->session
->pid
- 1;
1586 * Take exclusive lock, then unlock it with a shared-unlock call.
1588 torture_comment(tctx
, " taking exclusive lock.\n");
1589 io
.lockx
.in
.ulock_cnt
= 0;
1590 io
.lockx
.in
.lock_cnt
= 1;
1591 io
.lockx
.in
.mode
= 0;
1592 io
.lockx
.in
.file
.fnum
= fnum1
;
1593 io
.lockx
.in
.locks
= &lock1
;
1594 status
= smb_raw_lock(cli
->tree
, &io
);
1595 CHECK_STATUS(status
, NT_STATUS_OK
);
1597 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1598 io
.lockx
.in
.ulock_cnt
= 1;
1599 io
.lockx
.in
.lock_cnt
= 0;
1600 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1601 io
.lockx
.in
.file
.fnum
= fnum1
;
1602 io
.lockx
.in
.locks
= &lock1
;
1603 status
= smb_raw_lock(cli
->tree
, &io
);
1604 CHECK_STATUS(status
, NT_STATUS_OK
);
1606 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1607 io
.lockx
.in
.ulock_cnt
= 0;
1608 io
.lockx
.in
.lock_cnt
= 1;
1609 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1610 io
.lockx
.in
.file
.fnum
= fnum2
;
1611 io
.lockx
.in
.locks
= &lock2
;
1612 status
= smb_raw_lock(cli
->tree
, &io
);
1613 CHECK_STATUS(status
, NT_STATUS_OK
);
1616 * Unlock a shared lock with an exclusive-unlock call.
1618 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1619 io
.lockx
.in
.ulock_cnt
= 1;
1620 io
.lockx
.in
.lock_cnt
= 0;
1621 io
.lockx
.in
.mode
= 0;
1622 io
.lockx
.in
.file
.fnum
= fnum2
;
1623 io
.lockx
.in
.locks
= &lock2
;
1624 status
= smb_raw_lock(cli
->tree
, &io
);
1625 CHECK_STATUS(status
, NT_STATUS_OK
);
1627 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1628 io
.lockx
.in
.ulock_cnt
= 0;
1629 io
.lockx
.in
.lock_cnt
= 1;
1630 io
.lockx
.in
.mode
= 0;
1631 io
.lockx
.in
.file
.fnum
= fnum1
;
1632 io
.lockx
.in
.locks
= &lock1
;
1633 status
= smb_raw_lock(cli
->tree
, &io
);
1634 CHECK_STATUS(status
, NT_STATUS_OK
);
1637 io
.lockx
.in
.ulock_cnt
= 1;
1638 io
.lockx
.in
.lock_cnt
= 0;
1639 status
= smb_raw_lock(cli
->tree
, &io
);
1640 CHECK_STATUS(status
, NT_STATUS_OK
);
1643 * Test unlocking of 0-byte locks.
1646 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1647 "always unlocks the exclusive first.\n");
1648 lock1
.pid
= cli
->session
->pid
;
1651 lock2
.pid
= cli
->session
->pid
;
1654 io
.lockx
.in
.ulock_cnt
= 0;
1655 io
.lockx
.in
.lock_cnt
= 1;
1656 io
.lockx
.in
.file
.fnum
= fnum1
;
1657 io
.lockx
.in
.locks
= &lock1
;
1659 /* lock 0-byte shared
1660 * Note: Order of the shared/exclusive locks doesn't matter. */
1661 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1662 status
= smb_raw_lock(cli
->tree
, &io
);
1663 CHECK_STATUS(status
, NT_STATUS_OK
);
1665 /* lock 0-byte exclusive */
1666 io
.lockx
.in
.mode
= 0;
1667 status
= smb_raw_lock(cli
->tree
, &io
);
1668 CHECK_STATUS(status
, NT_STATUS_OK
);
1670 /* test contention */
1671 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1672 io
.lockx
.in
.locks
= &lock2
;
1673 io
.lockx
.in
.file
.fnum
= fnum2
;
1674 status
= smb_raw_lock(cli
->tree
, &io
);
1675 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1676 NT_STATUS_FILE_LOCK_CONFLICT
);
1679 io
.lockx
.in
.ulock_cnt
= 1;
1680 io
.lockx
.in
.lock_cnt
= 0;
1681 io
.lockx
.in
.file
.fnum
= fnum1
;
1682 io
.lockx
.in
.locks
= &lock1
;
1683 status
= smb_raw_lock(cli
->tree
, &io
);
1684 CHECK_STATUS(status
, NT_STATUS_OK
);
1686 /* test - can we take a shared lock? */
1687 io
.lockx
.in
.ulock_cnt
= 0;
1688 io
.lockx
.in
.lock_cnt
= 1;
1689 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1690 io
.lockx
.in
.file
.fnum
= fnum2
;
1691 io
.lockx
.in
.locks
= &lock2
;
1692 status
= smb_raw_lock(cli
->tree
, &io
);
1694 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1695 * new to Win7, it succeeds in WinXP too), until I can come to a
1696 * resolution as to whether Samba should support this or not. There is
1697 * code to preference unlocking exclusive locks before shared locks,
1698 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1699 if (TARGET_IS_SAMBA3(tctx
)) {
1700 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1701 NT_STATUS_FILE_LOCK_CONFLICT
);
1703 CHECK_STATUS(status
, NT_STATUS_OK
);
1707 io
.lockx
.in
.ulock_cnt
= 1;
1708 io
.lockx
.in
.lock_cnt
= 0;
1709 status
= smb_raw_lock(cli
->tree
, &io
);
1711 /* XXX Same as above. */
1712 if (TARGET_IS_SAMBA3(tctx
)) {
1713 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1715 CHECK_STATUS(status
, NT_STATUS_OK
);
1718 io
.lockx
.in
.file
.fnum
= fnum1
;
1719 io
.lockx
.in
.locks
= &lock1
;
1720 status
= smb_raw_lock(cli
->tree
, &io
);
1721 CHECK_STATUS(status
, NT_STATUS_OK
);
1724 smbcli_close(cli
->tree
, fnum1
);
1725 smbcli_close(cli
->tree
, fnum2
);
1726 smb_raw_exit(cli
->session
);
1727 smbcli_deltree(cli
->tree
, BASEDIR
);
1731 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1737 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1738 struct smb_lock_entry lock1
;
1739 struct smb_lock_entry lock2
;
1740 struct smb_lock_entry locks
[2];
1742 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1744 if (!torture_setup_dir(cli
, BASEDIR
)) {
1748 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1749 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1750 "Failed to create %s - %s\n",
1751 fname
, smbcli_errstr(cli
->tree
)));
1753 /* Setup initial parameters */
1754 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1755 io
.lockx
.in
.timeout
= 0;
1757 lock1
.pid
= cli
->session
->pid
;
1760 lock2
.pid
= cli
->session
->pid
;
1767 io
.lockx
.in
.file
.fnum
= fnum1
;
1768 io
.lockx
.in
.mode
= 0; /* exclusive */
1770 /** Test1: Take second lock, but not first. */
1771 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
1774 io
.lockx
.in
.ulock_cnt
= 0;
1775 io
.lockx
.in
.lock_cnt
= 1;
1776 io
.lockx
.in
.locks
= &lock2
;
1777 status
= smb_raw_lock(cli
->tree
, &io
);
1778 CHECK_STATUS(status
, NT_STATUS_OK
);
1780 /* Try to unlock both locks. */
1781 io
.lockx
.in
.ulock_cnt
= 2;
1782 io
.lockx
.in
.lock_cnt
= 0;
1783 io
.lockx
.in
.locks
= locks
;
1785 status
= smb_raw_lock(cli
->tree
, &io
);
1786 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1788 /* Second lock should not be unlocked. */
1789 io
.lockx
.in
.ulock_cnt
= 0;
1790 io
.lockx
.in
.lock_cnt
= 1;
1791 io
.lockx
.in
.locks
= &lock2
;
1792 status
= smb_raw_lock(cli
->tree
, &io
);
1793 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1796 io
.lockx
.in
.ulock_cnt
= 1;
1797 io
.lockx
.in
.lock_cnt
= 0;
1798 io
.lockx
.in
.locks
= &lock2
;
1799 status
= smb_raw_lock(cli
->tree
, &io
);
1800 CHECK_STATUS(status
, NT_STATUS_OK
);
1802 /** Test2: Take first lock, but not second. */
1803 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
1806 io
.lockx
.in
.ulock_cnt
= 0;
1807 io
.lockx
.in
.lock_cnt
= 1;
1808 io
.lockx
.in
.locks
= &lock1
;
1809 status
= smb_raw_lock(cli
->tree
, &io
);
1810 CHECK_STATUS(status
, NT_STATUS_OK
);
1812 /* Try to unlock both locks. */
1813 io
.lockx
.in
.ulock_cnt
= 2;
1814 io
.lockx
.in
.lock_cnt
= 0;
1815 io
.lockx
.in
.locks
= locks
;
1817 status
= smb_raw_lock(cli
->tree
, &io
);
1818 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1820 /* First lock should be unlocked. */
1821 io
.lockx
.in
.ulock_cnt
= 0;
1822 io
.lockx
.in
.lock_cnt
= 1;
1823 io
.lockx
.in
.locks
= &lock1
;
1824 status
= smb_raw_lock(cli
->tree
, &io
);
1825 CHECK_STATUS(status
, NT_STATUS_OK
);
1828 io
.lockx
.in
.ulock_cnt
= 1;
1829 io
.lockx
.in
.lock_cnt
= 0;
1830 io
.lockx
.in
.locks
= &lock1
;
1831 status
= smb_raw_lock(cli
->tree
, &io
);
1832 CHECK_STATUS(status
, NT_STATUS_OK
);
1834 /* Test3: Request 2 locks, second will contend. What happens to the
1836 torture_comment(tctx
, " request 2 locks, second one will contend. "
1837 "Expect both to fail.\n");
1839 /* Lock the second range */
1840 io
.lockx
.in
.ulock_cnt
= 0;
1841 io
.lockx
.in
.lock_cnt
= 1;
1842 io
.lockx
.in
.locks
= &lock2
;
1843 status
= smb_raw_lock(cli
->tree
, &io
);
1844 CHECK_STATUS(status
, NT_STATUS_OK
);
1846 /* Request both locks */
1847 io
.lockx
.in
.ulock_cnt
= 0;
1848 io
.lockx
.in
.lock_cnt
= 2;
1849 io
.lockx
.in
.locks
= locks
;
1851 status
= smb_raw_lock(cli
->tree
, &io
);
1852 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1854 /* First lock should be unlocked. */
1855 io
.lockx
.in
.ulock_cnt
= 0;
1856 io
.lockx
.in
.lock_cnt
= 1;
1857 io
.lockx
.in
.locks
= &lock1
;
1858 status
= smb_raw_lock(cli
->tree
, &io
);
1859 CHECK_STATUS(status
, NT_STATUS_OK
);
1862 io
.lockx
.in
.ulock_cnt
= 2;
1863 io
.lockx
.in
.lock_cnt
= 0;
1864 io
.lockx
.in
.locks
= locks
;
1865 status
= smb_raw_lock(cli
->tree
, &io
);
1866 CHECK_STATUS(status
, NT_STATUS_OK
);
1868 /* Test4: Request unlock and lock. The lock contends, is the unlock
1869 * then re-locked? */
1870 torture_comment(tctx
, " request unlock and lock, second one will "
1871 "contend. Expect the unlock to succeed.\n");
1873 /* Lock both ranges */
1874 io
.lockx
.in
.ulock_cnt
= 0;
1875 io
.lockx
.in
.lock_cnt
= 2;
1876 io
.lockx
.in
.locks
= locks
;
1877 status
= smb_raw_lock(cli
->tree
, &io
);
1878 CHECK_STATUS(status
, NT_STATUS_OK
);
1880 /* Attempt to unlock the first range and lock the second */
1881 io
.lockx
.in
.ulock_cnt
= 1;
1882 io
.lockx
.in
.lock_cnt
= 1;
1883 io
.lockx
.in
.locks
= locks
;
1884 status
= smb_raw_lock(cli
->tree
, &io
);
1885 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1887 /* The first lock should've been unlocked */
1888 io
.lockx
.in
.ulock_cnt
= 0;
1889 io
.lockx
.in
.lock_cnt
= 1;
1890 io
.lockx
.in
.locks
= &lock1
;
1891 status
= smb_raw_lock(cli
->tree
, &io
);
1892 CHECK_STATUS(status
, NT_STATUS_OK
);
1895 io
.lockx
.in
.ulock_cnt
= 2;
1896 io
.lockx
.in
.lock_cnt
= 0;
1897 io
.lockx
.in
.locks
= locks
;
1898 status
= smb_raw_lock(cli
->tree
, &io
);
1899 CHECK_STATUS(status
, NT_STATUS_OK
);
1902 smbcli_close(cli
->tree
, fnum1
);
1903 smb_raw_exit(cli
->session
);
1904 smbcli_deltree(cli
->tree
, BASEDIR
);
1909 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1910 * - stacking an exclusive on top of shared fails
1911 * - stacking two exclusives fail
1913 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1919 const char *fname
= BASEDIR
"\\stacking.txt";
1920 struct smb_lock_entry lock1
;
1921 struct smb_lock_entry lock2
;
1923 torture_comment(tctx
, "Testing stacking:\n");
1925 if (!torture_setup_dir(cli
, BASEDIR
)) {
1929 io
.generic
.level
= RAW_LOCK_LOCKX
;
1931 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1932 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1933 "Failed to create %s - %s\n",
1934 fname
, smbcli_errstr(cli
->tree
)));
1936 /* Setup initial parameters */
1937 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1938 io
.lockx
.in
.timeout
= 0;
1940 lock1
.pid
= cli
->session
->pid
;
1943 lock2
.pid
= cli
->session
->pid
- 1;
1948 * Try to take a shared lock, then stack an exclusive.
1950 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
1951 io
.lockx
.in
.file
.fnum
= fnum1
;
1952 io
.lockx
.in
.locks
= &lock1
;
1954 io
.lockx
.in
.ulock_cnt
= 0;
1955 io
.lockx
.in
.lock_cnt
= 1;
1956 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1957 status
= smb_raw_lock(cli
->tree
, &io
);
1958 CHECK_STATUS(status
, NT_STATUS_OK
);
1960 io
.lockx
.in
.ulock_cnt
= 0;
1961 io
.lockx
.in
.lock_cnt
= 1;
1962 io
.lockx
.in
.mode
= 0;
1963 status
= smb_raw_lock(cli
->tree
, &io
);
1964 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1965 NT_STATUS_FILE_LOCK_CONFLICT
);
1968 io
.lockx
.in
.ulock_cnt
= 1;
1969 io
.lockx
.in
.lock_cnt
= 0;
1970 status
= smb_raw_lock(cli
->tree
, &io
);
1971 CHECK_STATUS(status
, NT_STATUS_OK
);
1974 * Prove that two exclusive locks do not stack.
1976 torture_comment(tctx
, " two exclusive locks do not stack.\n");
1977 io
.lockx
.in
.ulock_cnt
= 0;
1978 io
.lockx
.in
.lock_cnt
= 1;
1979 io
.lockx
.in
.mode
= 0;
1980 status
= smb_raw_lock(cli
->tree
, &io
);
1981 CHECK_STATUS(status
, NT_STATUS_OK
);
1982 status
= smb_raw_lock(cli
->tree
, &io
);
1983 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1984 NT_STATUS_FILE_LOCK_CONFLICT
);
1987 io
.lockx
.in
.ulock_cnt
= 1;
1988 io
.lockx
.in
.lock_cnt
= 0;
1989 status
= smb_raw_lock(cli
->tree
, &io
);
1990 CHECK_STATUS(status
, NT_STATUS_OK
);
1993 smbcli_close(cli
->tree
, fnum1
);
1994 smb_raw_exit(cli
->session
);
1995 smbcli_deltree(cli
->tree
, BASEDIR
);
2000 basic testing of lock calls
2002 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
2004 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "LOCK");
2006 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
2007 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
2008 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
2009 torture_suite_add_1smb_test(suite
, "async", test_async
);
2010 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
2011 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
2013 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
2014 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
2015 torture_suite_add_1smb_test(suite
, "multiple_unlock",
2016 test_multiple_unlock
);
2017 torture_suite_add_1smb_test(suite
, "zerobytelocks",
2018 test_zerobytelocks
);