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) \
75 ((torture_setting_bool(_tctx, "w2k3", false)) || \
76 (torture_setting_bool(_tctx, "w2k8", false)) || \
77 (torture_setting_bool(_tctx, "win7", false)))
78 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
79 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
81 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
82 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
83 #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
84 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
85 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
86 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
88 test SMBlock and SMBunlock ops
90 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
96 const char *fname
= BASEDIR
"\\test.txt";
98 if (!TARGET_SUPPORTS_SMBLOCK(tctx
))
99 torture_skip(tctx
, "Target does not support the SMBlock PDU");
101 if (!torture_setup_dir(cli
, BASEDIR
)) {
105 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
106 io
.generic
.level
= RAW_LOCK_LOCK
;
108 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
109 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
110 "Failed to create %s - %s\n",
111 fname
, smbcli_errstr(cli
->tree
)));
113 torture_comment(tctx
, "Trying 0/0 lock\n");
114 io
.lock
.level
= RAW_LOCK_LOCK
;
115 io
.lock
.in
.file
.fnum
= fnum
;
116 io
.lock
.in
.count
= 0;
117 io
.lock
.in
.offset
= 0;
118 status
= smb_raw_lock(cli
->tree
, &io
);
119 CHECK_STATUS(status
, NT_STATUS_OK
);
121 status
= smb_raw_lock(cli
->tree
, &io
);
122 CHECK_STATUS(status
, NT_STATUS_OK
);
124 io
.lock
.level
= RAW_LOCK_UNLOCK
;
125 status
= smb_raw_lock(cli
->tree
, &io
);
126 CHECK_STATUS(status
, NT_STATUS_OK
);
128 torture_comment(tctx
, "Trying 0/1 lock\n");
129 io
.lock
.level
= RAW_LOCK_LOCK
;
130 io
.lock
.in
.file
.fnum
= fnum
;
131 io
.lock
.in
.count
= 1;
132 io
.lock
.in
.offset
= 0;
133 status
= smb_raw_lock(cli
->tree
, &io
);
134 CHECK_STATUS(status
, NT_STATUS_OK
);
136 status
= smb_raw_lock(cli
->tree
, &io
);
137 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
139 io
.lock
.level
= RAW_LOCK_UNLOCK
;
140 status
= smb_raw_lock(cli
->tree
, &io
);
141 CHECK_STATUS(status
, NT_STATUS_OK
);
142 io
.lock
.level
= RAW_LOCK_UNLOCK
;
143 status
= smb_raw_lock(cli
->tree
, &io
);
144 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
146 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
147 io
.lock
.level
= RAW_LOCK_LOCK
;
148 io
.lock
.in
.file
.fnum
= fnum
;
149 io
.lock
.in
.count
= 4000;
150 io
.lock
.in
.offset
= 0xEEFFFFFF;
151 status
= smb_raw_lock(cli
->tree
, &io
);
152 CHECK_STATUS(status
, NT_STATUS_OK
);
154 status
= smb_raw_lock(cli
->tree
, &io
);
155 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
157 io
.lock
.level
= RAW_LOCK_UNLOCK
;
158 status
= smb_raw_lock(cli
->tree
, &io
);
159 CHECK_STATUS(status
, NT_STATUS_OK
);
160 io
.lock
.level
= RAW_LOCK_UNLOCK
;
161 status
= smb_raw_lock(cli
->tree
, &io
);
162 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
164 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
165 io
.lock
.level
= RAW_LOCK_LOCK
;
166 io
.lock
.in
.file
.fnum
= fnum
;
167 io
.lock
.in
.count
= 4000;
168 io
.lock
.in
.offset
= 0xEEFFFFFF;
169 status
= smb_raw_lock(cli
->tree
, &io
);
170 CHECK_STATUS(status
, NT_STATUS_OK
);
172 status
= smb_raw_lock(cli
->tree
, &io
);
173 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
175 io
.lock
.level
= RAW_LOCK_UNLOCK
;
176 status
= smb_raw_lock(cli
->tree
, &io
);
177 CHECK_STATUS(status
, NT_STATUS_OK
);
178 io
.lock
.level
= RAW_LOCK_UNLOCK
;
179 status
= smb_raw_lock(cli
->tree
, &io
);
180 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
182 torture_comment(tctx
, "Trying max lock\n");
183 io
.lock
.level
= RAW_LOCK_LOCK
;
184 io
.lock
.in
.file
.fnum
= fnum
;
185 io
.lock
.in
.count
= 4000;
186 io
.lock
.in
.offset
= 0xEF000000;
187 status
= smb_raw_lock(cli
->tree
, &io
);
188 CHECK_STATUS(status
, NT_STATUS_OK
);
190 status
= smb_raw_lock(cli
->tree
, &io
);
191 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
193 io
.lock
.level
= RAW_LOCK_UNLOCK
;
194 status
= smb_raw_lock(cli
->tree
, &io
);
195 CHECK_STATUS(status
, NT_STATUS_OK
);
196 io
.lock
.level
= RAW_LOCK_UNLOCK
;
197 status
= smb_raw_lock(cli
->tree
, &io
);
198 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
200 torture_comment(tctx
, "Trying wrong pid unlock\n");
201 io
.lock
.level
= RAW_LOCK_LOCK
;
202 io
.lock
.in
.file
.fnum
= fnum
;
203 io
.lock
.in
.count
= 4002;
204 io
.lock
.in
.offset
= 10001;
205 status
= smb_raw_lock(cli
->tree
, &io
);
206 CHECK_STATUS(status
, NT_STATUS_OK
);
208 io
.lock
.level
= RAW_LOCK_UNLOCK
;
209 status
= smb_raw_lock(cli
->tree
, &io
);
210 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
212 status
= smb_raw_lock(cli
->tree
, &io
);
213 CHECK_STATUS(status
, NT_STATUS_OK
);
216 smbcli_close(cli
->tree
, fnum
);
217 smb_raw_exit(cli
->session
);
218 smbcli_deltree(cli
->tree
, BASEDIR
);
226 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
229 struct smb_lock_entry lock
[1];
233 const char *fname
= BASEDIR
"\\test.txt";
235 if (!torture_setup_dir(cli
, BASEDIR
)) {
239 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
240 io
.generic
.level
= RAW_LOCK_LOCKX
;
242 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
243 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
244 "Failed to create %s - %s\n",
245 fname
, smbcli_errstr(cli
->tree
)));
247 io
.lockx
.level
= RAW_LOCK_LOCKX
;
248 io
.lockx
.in
.file
.fnum
= fnum
;
249 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
250 io
.lockx
.in
.timeout
= 0;
251 io
.lockx
.in
.ulock_cnt
= 0;
252 io
.lockx
.in
.lock_cnt
= 1;
253 lock
[0].pid
= cli
->session
->pid
;
256 io
.lockx
.in
.locks
= &lock
[0];
257 status
= smb_raw_lock(cli
->tree
, &io
);
258 CHECK_STATUS(status
, NT_STATUS_OK
);
261 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
262 io
.lockx
.in
.ulock_cnt
= 0;
263 io
.lockx
.in
.lock_cnt
= 1;
264 lock
[0].count
= 4000;
265 lock
[0].offset
= 0xEEFFFFFF;
266 status
= smb_raw_lock(cli
->tree
, &io
);
267 CHECK_STATUS(status
, NT_STATUS_OK
);
269 status
= smb_raw_lock(cli
->tree
, &io
);
270 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
272 io
.lockx
.in
.ulock_cnt
= 1;
273 io
.lockx
.in
.lock_cnt
= 0;
274 status
= smb_raw_lock(cli
->tree
, &io
);
275 CHECK_STATUS(status
, NT_STATUS_OK
);
276 status
= smb_raw_lock(cli
->tree
, &io
);
277 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
279 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
280 io
.lockx
.in
.ulock_cnt
= 0;
281 io
.lockx
.in
.lock_cnt
= 1;
282 lock
[0].count
= 4000;
283 lock
[0].offset
= 0xEF000000;
284 status
= smb_raw_lock(cli
->tree
, &io
);
285 CHECK_STATUS(status
, NT_STATUS_OK
);
287 status
= smb_raw_lock(cli
->tree
, &io
);
288 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
290 io
.lockx
.in
.ulock_cnt
= 1;
291 io
.lockx
.in
.lock_cnt
= 0;
292 status
= smb_raw_lock(cli
->tree
, &io
);
293 CHECK_STATUS(status
, NT_STATUS_OK
);
294 status
= smb_raw_lock(cli
->tree
, &io
);
295 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
297 torture_comment(tctx
, "Trying zero lock\n");
298 io
.lockx
.in
.ulock_cnt
= 0;
299 io
.lockx
.in
.lock_cnt
= 1;
302 status
= smb_raw_lock(cli
->tree
, &io
);
303 CHECK_STATUS(status
, NT_STATUS_OK
);
305 status
= smb_raw_lock(cli
->tree
, &io
);
306 CHECK_STATUS(status
, NT_STATUS_OK
);
308 io
.lockx
.in
.ulock_cnt
= 1;
309 io
.lockx
.in
.lock_cnt
= 0;
310 status
= smb_raw_lock(cli
->tree
, &io
);
311 CHECK_STATUS(status
, NT_STATUS_OK
);
312 status
= smb_raw_lock(cli
->tree
, &io
);
313 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
315 torture_comment(tctx
, "Trying max lock\n");
316 io
.lockx
.in
.ulock_cnt
= 0;
317 io
.lockx
.in
.lock_cnt
= 1;
320 status
= smb_raw_lock(cli
->tree
, &io
);
321 CHECK_STATUS(status
, NT_STATUS_OK
);
323 status
= smb_raw_lock(cli
->tree
, &io
);
324 CHECK_STATUS(status
, NT_STATUS_OK
);
326 io
.lockx
.in
.ulock_cnt
= 1;
327 io
.lockx
.in
.lock_cnt
= 0;
328 status
= smb_raw_lock(cli
->tree
, &io
);
329 CHECK_STATUS(status
, NT_STATUS_OK
);
330 status
= smb_raw_lock(cli
->tree
, &io
);
331 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
333 torture_comment(tctx
, "Trying 2^63\n");
334 io
.lockx
.in
.ulock_cnt
= 0;
335 io
.lockx
.in
.lock_cnt
= 1;
338 lock
[0].offset
<<= 63;
339 status
= smb_raw_lock(cli
->tree
, &io
);
340 CHECK_STATUS(status
, NT_STATUS_OK
);
342 status
= smb_raw_lock(cli
->tree
, &io
);
343 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
345 io
.lockx
.in
.ulock_cnt
= 1;
346 io
.lockx
.in
.lock_cnt
= 0;
347 status
= smb_raw_lock(cli
->tree
, &io
);
348 CHECK_STATUS(status
, NT_STATUS_OK
);
349 status
= smb_raw_lock(cli
->tree
, &io
);
350 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
352 torture_comment(tctx
, "Trying 2^63 - 1\n");
353 io
.lockx
.in
.ulock_cnt
= 0;
354 io
.lockx
.in
.lock_cnt
= 1;
357 lock
[0].offset
<<= 63;
359 status
= smb_raw_lock(cli
->tree
, &io
);
360 CHECK_STATUS(status
, NT_STATUS_OK
);
362 status
= smb_raw_lock(cli
->tree
, &io
);
363 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
365 io
.lockx
.in
.ulock_cnt
= 1;
366 io
.lockx
.in
.lock_cnt
= 0;
367 status
= smb_raw_lock(cli
->tree
, &io
);
368 CHECK_STATUS(status
, NT_STATUS_OK
);
369 status
= smb_raw_lock(cli
->tree
, &io
);
370 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
372 torture_comment(tctx
, "Trying max lock 2\n");
373 io
.lockx
.in
.ulock_cnt
= 0;
374 io
.lockx
.in
.lock_cnt
= 1;
377 status
= smb_raw_lock(cli
->tree
, &io
);
378 CHECK_STATUS(status
, NT_STATUS_OK
);
381 status
= smb_raw_lock(cli
->tree
, &io
);
382 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx
))
383 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
385 CHECK_STATUS(status
, NT_STATUS_OK
);
387 io
.lockx
.in
.ulock_cnt
= 1;
388 io
.lockx
.in
.lock_cnt
= 0;
390 status
= smb_raw_lock(cli
->tree
, &io
);
392 CHECK_STATUS(status
, NT_STATUS_OK
);
393 status
= smb_raw_lock(cli
->tree
, &io
);
394 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
397 smbcli_close(cli
->tree
, fnum
);
398 smb_raw_exit(cli
->session
);
399 smbcli_deltree(cli
->tree
, BASEDIR
);
406 static bool test_pidhigh(struct torture_context
*tctx
,
407 struct smbcli_state
*cli
)
410 struct smb_lock_entry lock
[1];
414 const char *fname
= BASEDIR
"\\test.txt";
417 if (!torture_setup_dir(cli
, BASEDIR
)) {
421 torture_comment(tctx
, "Testing high pid\n");
422 io
.generic
.level
= RAW_LOCK_LOCKX
;
424 cli
->session
->pid
= 1;
426 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
427 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
428 "Failed to create %s - %s\n",
429 fname
, smbcli_errstr(cli
->tree
)));
431 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
432 torture_result(tctx
, TORTURE_FAIL
,
433 "Failed to write 1 byte - %s\n",
434 smbcli_errstr(cli
->tree
));
439 io
.lockx
.level
= RAW_LOCK_LOCKX
;
440 io
.lockx
.in
.file
.fnum
= fnum
;
441 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
442 io
.lockx
.in
.timeout
= 0;
443 io
.lockx
.in
.ulock_cnt
= 0;
444 io
.lockx
.in
.lock_cnt
= 1;
445 lock
[0].pid
= cli
->session
->pid
;
447 lock
[0].count
= 0xFFFFFFFF;
448 io
.lockx
.in
.locks
= &lock
[0];
449 status
= smb_raw_lock(cli
->tree
, &io
);
450 CHECK_STATUS(status
, NT_STATUS_OK
);
452 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
453 torture_result(tctx
, TORTURE_FAIL
,
454 "Failed to read 1 byte - %s\n",
455 smbcli_errstr(cli
->tree
));
460 cli
->session
->pid
= 2;
462 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
463 torture_result(tctx
, TORTURE_FAIL
,
464 "pid is incorrect handled for read with lock!\n");
469 cli
->session
->pid
= 0x10001;
471 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
472 torture_result(tctx
, TORTURE_FAIL
,
473 "High pid is used on this server!\n");
476 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
480 smbcli_close(cli
->tree
, fnum
);
481 smb_raw_exit(cli
->session
);
482 smbcli_deltree(cli
->tree
, BASEDIR
);
488 test locking&X async operation
490 static bool test_async(struct torture_context
*tctx
,
491 struct smbcli_state
*cli
)
493 struct smbcli_session
*session
;
494 struct smb_composite_sesssetup setup
;
495 struct smbcli_tree
*tree
;
497 const char *host
, *share
;
499 struct smb_lock_entry lock
[2];
503 const char *fname
= BASEDIR
"\\test.txt";
505 struct smbcli_request
*req
, *req2
;
506 struct smbcli_session_options options
;
508 if (!torture_setup_dir(cli
, BASEDIR
)) {
512 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
514 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
515 io
.generic
.level
= RAW_LOCK_LOCKX
;
517 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
518 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
519 "Failed to create %s - %s\n",
520 fname
, smbcli_errstr(cli
->tree
)));
522 io
.lockx
.level
= RAW_LOCK_LOCKX
;
523 io
.lockx
.in
.file
.fnum
= fnum
;
524 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
525 io
.lockx
.in
.timeout
= 0;
526 io
.lockx
.in
.ulock_cnt
= 0;
527 io
.lockx
.in
.lock_cnt
= 1;
528 lock
[0].pid
= cli
->session
->pid
;
529 lock
[0].offset
= 100;
531 lock
[1].pid
= cli
->session
->pid
;
532 lock
[1].offset
= 110;
534 io
.lockx
.in
.locks
= &lock
[0];
535 status
= smb_raw_lock(cli
->tree
, &io
);
536 CHECK_STATUS(status
, NT_STATUS_OK
);
540 torture_comment(tctx
, "testing cancel by CANCEL_LOCK\n");
542 /* setup a timed lock */
543 io
.lockx
.in
.timeout
= 10000;
544 req
= smb_raw_lock_send(cli
->tree
, &io
);
545 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
546 "Failed to setup timed lock (%s)\n", __location__
));
548 /* cancel the wrong range */
550 io
.lockx
.in
.timeout
= 0;
551 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
552 status
= smb_raw_lock(cli
->tree
, &io
);
553 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
555 /* cancel with the wrong bits set */
556 lock
[0].offset
= 100;
557 io
.lockx
.in
.timeout
= 0;
558 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
559 status
= smb_raw_lock(cli
->tree
, &io
);
560 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
562 /* cancel the right range */
563 lock
[0].offset
= 100;
564 io
.lockx
.in
.timeout
= 0;
565 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
566 status
= smb_raw_lock(cli
->tree
, &io
);
567 CHECK_STATUS(status
, NT_STATUS_OK
);
569 /* receive the failed lock request */
570 status
= smbcli_request_simple_recv(req
);
571 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
573 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
574 "lock cancel was not immediate (%s)\n", __location__
));
576 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
577 * if the lock vector contains one entry. When given mutliple cancel
578 * requests in a single PDU we expect the server to return an
579 * error. Samba4 handles this correctly. Windows servers seem to
580 * accept the request but only cancel the first lock. Samba3
581 * now does what Windows does (JRA).
583 torture_comment(tctx
, "testing multiple cancel\n");
585 /* acquire second lock */
586 io
.lockx
.in
.timeout
= 0;
587 io
.lockx
.in
.ulock_cnt
= 0;
588 io
.lockx
.in
.lock_cnt
= 1;
589 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
590 io
.lockx
.in
.locks
= &lock
[1];
591 status
= smb_raw_lock(cli
->tree
, &io
);
592 CHECK_STATUS(status
, NT_STATUS_OK
);
594 /* setup 2 timed locks */
596 io
.lockx
.in
.timeout
= 10000;
597 io
.lockx
.in
.lock_cnt
= 1;
598 io
.lockx
.in
.locks
= &lock
[0];
599 req
= smb_raw_lock_send(cli
->tree
, &io
);
600 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
601 "Failed to setup timed lock (%s)\n", __location__
));
602 io
.lockx
.in
.locks
= &lock
[1];
603 req2
= smb_raw_lock_send(cli
->tree
, &io
);
604 torture_assert(tctx
,(req2
!= NULL
), talloc_asprintf(tctx
,
605 "Failed to setup timed lock (%s)\n", __location__
));
607 /* try to cancel both locks in the same packet */
608 io
.lockx
.in
.timeout
= 0;
609 io
.lockx
.in
.lock_cnt
= 2;
610 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
611 io
.lockx
.in
.locks
= lock
;
612 status
= smb_raw_lock(cli
->tree
, &io
);
613 CHECK_STATUS(status
, NT_STATUS_OK
);
615 torture_warning(tctx
, "Target server accepted a lock cancel "
616 "request with multiple locks. This violates "
617 "MS-CIFS 2.2.4.32.1.\n");
619 /* receive the failed lock requests */
620 status
= smbcli_request_simple_recv(req
);
621 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
623 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
624 "first lock was not cancelled immediately (%s)\n",
627 /* send cancel to second lock */
628 io
.lockx
.in
.timeout
= 0;
629 io
.lockx
.in
.lock_cnt
= 1;
630 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
|
631 LOCKING_ANDX_LARGE_FILES
;
632 io
.lockx
.in
.locks
= &lock
[1];
633 status
= smb_raw_lock(cli
->tree
, &io
);
634 CHECK_STATUS(status
, NT_STATUS_OK
);
636 status
= smbcli_request_simple_recv(req2
);
637 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
639 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
640 "second lock was not cancelled immediately (%s)\n",
643 /* cleanup the second lock */
644 io
.lockx
.in
.ulock_cnt
= 1;
645 io
.lockx
.in
.lock_cnt
= 0;
646 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
647 io
.lockx
.in
.locks
= &lock
[1];
648 status
= smb_raw_lock(cli
->tree
, &io
);
649 CHECK_STATUS(status
, NT_STATUS_OK
);
651 /* If a lock request contained multiple ranges and we are cancelling
652 * one while it's still pending, what happens? */
653 torture_comment(tctx
, "testing cancel 1/2 lock request\n");
655 /* Send request with two ranges */
656 io
.lockx
.in
.timeout
= -1;
657 io
.lockx
.in
.ulock_cnt
= 0;
658 io
.lockx
.in
.lock_cnt
= 2;
659 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
660 io
.lockx
.in
.locks
= lock
;
661 req
= smb_raw_lock_send(cli
->tree
, &io
);
662 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
663 "Failed to setup pending lock (%s)\n", __location__
));
665 /* Try to cancel the first lock range */
666 io
.lockx
.in
.timeout
= 0;
667 io
.lockx
.in
.lock_cnt
= 1;
668 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
669 io
.lockx
.in
.locks
= &lock
[0];
670 status
= smb_raw_lock(cli
->tree
, &io
);
671 CHECK_STATUS(status
, NT_STATUS_OK
);
673 /* Locking request should've failed and second range should be
675 status
= smbcli_request_simple_recv(req
);
676 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
678 io
.lockx
.in
.timeout
= 0;
679 io
.lockx
.in
.ulock_cnt
= 0;
680 io
.lockx
.in
.lock_cnt
= 1;
681 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
682 io
.lockx
.in
.locks
= &lock
[1];
683 status
= smb_raw_lock(cli
->tree
, &io
);
684 CHECK_STATUS(status
, NT_STATUS_OK
);
686 /* Cleanup both locks */
687 io
.lockx
.in
.ulock_cnt
= 2;
688 io
.lockx
.in
.lock_cnt
= 0;
689 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
690 io
.lockx
.in
.locks
= lock
;
691 status
= smb_raw_lock(cli
->tree
, &io
);
692 CHECK_STATUS(status
, NT_STATUS_OK
);
694 torture_comment(tctx
, "testing cancel 2/2 lock request\n");
696 /* Lock second range so it contends */
697 io
.lockx
.in
.timeout
= 0;
698 io
.lockx
.in
.ulock_cnt
= 0;
699 io
.lockx
.in
.lock_cnt
= 1;
700 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
701 io
.lockx
.in
.locks
= &lock
[1];
702 status
= smb_raw_lock(cli
->tree
, &io
);
703 CHECK_STATUS(status
, NT_STATUS_OK
);
705 /* Send request with two ranges */
706 io
.lockx
.in
.timeout
= -1;
707 io
.lockx
.in
.ulock_cnt
= 0;
708 io
.lockx
.in
.lock_cnt
= 2;
709 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
710 io
.lockx
.in
.locks
= lock
;
711 req
= smb_raw_lock_send(cli
->tree
, &io
);
712 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
713 "Failed to setup pending lock (%s)\n", __location__
));
715 /* Try to cancel the second lock range */
716 io
.lockx
.in
.timeout
= 0;
717 io
.lockx
.in
.lock_cnt
= 1;
718 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
719 io
.lockx
.in
.locks
= &lock
[1];
720 status
= smb_raw_lock(cli
->tree
, &io
);
721 CHECK_STATUS(status
, NT_STATUS_OK
);
723 /* Locking request should've failed and first range should be
725 status
= smbcli_request_simple_recv(req
);
726 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
728 io
.lockx
.in
.timeout
= 0;
729 io
.lockx
.in
.ulock_cnt
= 0;
730 io
.lockx
.in
.lock_cnt
= 1;
731 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
732 io
.lockx
.in
.locks
= &lock
[0];
733 status
= smb_raw_lock(cli
->tree
, &io
);
734 CHECK_STATUS(status
, NT_STATUS_OK
);
736 /* Cleanup both locks */
737 io
.lockx
.in
.ulock_cnt
= 2;
738 io
.lockx
.in
.lock_cnt
= 0;
739 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
740 io
.lockx
.in
.locks
= lock
;
741 status
= smb_raw_lock(cli
->tree
, &io
);
742 CHECK_STATUS(status
, NT_STATUS_OK
);
744 torture_comment(tctx
, "testing cancel by unlock\n");
745 io
.lockx
.in
.ulock_cnt
= 0;
746 io
.lockx
.in
.lock_cnt
= 1;
747 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
748 io
.lockx
.in
.timeout
= 0;
749 io
.lockx
.in
.locks
= &lock
[0];
750 status
= smb_raw_lock(cli
->tree
, &io
);
751 CHECK_STATUS(status
, NT_STATUS_OK
);
753 io
.lockx
.in
.timeout
= 5000;
754 req
= smb_raw_lock_send(cli
->tree
, &io
);
755 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
756 "Failed to setup timed lock (%s)\n", __location__
));
758 io
.lockx
.in
.ulock_cnt
= 1;
759 io
.lockx
.in
.lock_cnt
= 0;
760 status
= smb_raw_lock(cli
->tree
, &io
);
761 CHECK_STATUS(status
, NT_STATUS_OK
);
764 status
= smbcli_request_simple_recv(req
);
765 CHECK_STATUS(status
, NT_STATUS_OK
);
767 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
768 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
769 __location__
, (int)(time(NULL
)-t
)));
771 torture_comment(tctx
, "testing cancel by close\n");
772 io
.lockx
.in
.ulock_cnt
= 0;
773 io
.lockx
.in
.lock_cnt
= 1;
774 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
775 io
.lockx
.in
.timeout
= 0;
776 status
= smb_raw_lock(cli
->tree
, &io
);
777 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
780 io
.lockx
.in
.timeout
= 10000;
781 req
= smb_raw_lock_send(cli
->tree
, &io
);
782 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
783 "Failed to setup timed lock (%s)\n", __location__
));
785 status
= smbcli_close(cli
->tree
, fnum
);
786 CHECK_STATUS(status
, NT_STATUS_OK
);
788 status
= smbcli_request_simple_recv(req
);
789 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
791 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
792 "lock cancel by close was not immediate (%s)\n", __location__
));
794 torture_comment(tctx
, "create a new sessions\n");
795 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
796 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
797 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
798 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
799 setup
.in
.credentials
= cmdline_credentials
;
800 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
801 status
= smb_composite_sesssetup(session
, &setup
);
802 CHECK_STATUS(status
, NT_STATUS_OK
);
803 session
->vuid
= setup
.out
.vuid
;
805 torture_comment(tctx
, "create new tree context\n");
806 share
= torture_setting_string(tctx
, "share", NULL
);
807 host
= torture_setting_string(tctx
, "host", NULL
);
808 tree
= smbcli_tree_init(session
, tctx
, false);
809 tcon
.generic
.level
= RAW_TCON_TCONX
;
810 tcon
.tconx
.in
.flags
= 0;
811 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
812 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
813 tcon
.tconx
.in
.device
= "A:";
814 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
815 CHECK_STATUS(status
, NT_STATUS_OK
);
816 tree
->tid
= tcon
.tconx
.out
.tid
;
818 torture_comment(tctx
, "testing cancel by exit\n");
819 fname
= BASEDIR
"\\test_exit.txt";
820 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
821 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
822 "Failed to reopen %s - %s\n",
823 fname
, smbcli_errstr(tree
)));
825 io
.lockx
.level
= RAW_LOCK_LOCKX
;
826 io
.lockx
.in
.file
.fnum
= fnum
;
827 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
828 io
.lockx
.in
.timeout
= 0;
829 io
.lockx
.in
.ulock_cnt
= 0;
830 io
.lockx
.in
.lock_cnt
= 1;
831 lock
[0].pid
= session
->pid
;
832 lock
[0].offset
= 100;
834 io
.lockx
.in
.locks
= &lock
[0];
835 status
= smb_raw_lock(tree
, &io
);
836 CHECK_STATUS(status
, NT_STATUS_OK
);
838 io
.lockx
.in
.ulock_cnt
= 0;
839 io
.lockx
.in
.lock_cnt
= 1;
840 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
841 io
.lockx
.in
.timeout
= 0;
842 status
= smb_raw_lock(tree
, &io
);
843 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
845 io
.lockx
.in
.timeout
= 10000;
847 req
= smb_raw_lock_send(tree
, &io
);
848 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
849 "Failed to setup timed lock (%s)\n", __location__
));
851 status
= smb_raw_exit(session
);
852 CHECK_STATUS(status
, NT_STATUS_OK
);
854 status
= smbcli_request_simple_recv(req
);
855 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
857 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
858 "lock cancel by exit was not immediate (%s)\n", __location__
));
860 torture_comment(tctx
, "testing cancel by ulogoff\n");
861 fname
= BASEDIR
"\\test_ulogoff.txt";
862 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
863 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
864 "Failed to reopen %s - %s\n",
865 fname
, smbcli_errstr(tree
)));
867 io
.lockx
.level
= RAW_LOCK_LOCKX
;
868 io
.lockx
.in
.file
.fnum
= fnum
;
869 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
870 io
.lockx
.in
.timeout
= 0;
871 io
.lockx
.in
.ulock_cnt
= 0;
872 io
.lockx
.in
.lock_cnt
= 1;
873 lock
[0].pid
= session
->pid
;
874 lock
[0].offset
= 100;
876 io
.lockx
.in
.locks
= &lock
[0];
877 status
= smb_raw_lock(tree
, &io
);
878 CHECK_STATUS(status
, NT_STATUS_OK
);
880 io
.lockx
.in
.ulock_cnt
= 0;
881 io
.lockx
.in
.lock_cnt
= 1;
882 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
883 io
.lockx
.in
.timeout
= 0;
884 status
= smb_raw_lock(tree
, &io
);
885 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
887 io
.lockx
.in
.timeout
= 10000;
889 req
= smb_raw_lock_send(tree
, &io
);
890 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
891 "Failed to setup timed lock (%s)\n", __location__
));
893 status
= smb_raw_ulogoff(session
);
894 CHECK_STATUS(status
, NT_STATUS_OK
);
896 status
= smbcli_request_simple_recv(req
);
897 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
898 torture_result(tctx
, TORTURE_FAIL
,
899 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
901 smb_tree_disconnect(tree
);
902 smb_raw_exit(session
);
905 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
907 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
908 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
910 torture_comment(tctx
, "testing cancel by tdis\n");
911 tree
->session
= cli
->session
;
913 fname
= BASEDIR
"\\test_tdis.txt";
914 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
915 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
916 "Failed to reopen %s - %s\n",
917 fname
, smbcli_errstr(tree
)));
919 io
.lockx
.level
= RAW_LOCK_LOCKX
;
920 io
.lockx
.in
.file
.fnum
= fnum
;
921 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
922 io
.lockx
.in
.timeout
= 0;
923 io
.lockx
.in
.ulock_cnt
= 0;
924 io
.lockx
.in
.lock_cnt
= 1;
925 lock
[0].pid
= cli
->session
->pid
;
926 lock
[0].offset
= 100;
928 io
.lockx
.in
.locks
= &lock
[0];
929 status
= smb_raw_lock(tree
, &io
);
930 CHECK_STATUS(status
, NT_STATUS_OK
);
932 status
= smb_raw_lock(tree
, &io
);
933 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
935 io
.lockx
.in
.timeout
= 10000;
937 req
= smb_raw_lock_send(tree
, &io
);
938 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
939 "Failed to setup timed lock (%s)\n", __location__
));
941 status
= smb_tree_disconnect(tree
);
942 CHECK_STATUS(status
, NT_STATUS_OK
);
944 status
= smbcli_request_simple_recv(req
);
945 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
947 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
948 "lock cancel by tdis was not immediate (%s)\n", __location__
));
951 smb_raw_exit(cli
->session
);
952 smbcli_deltree(cli
->tree
, BASEDIR
);
957 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
959 static bool test_errorcode(struct torture_context
*tctx
,
960 struct smbcli_state
*cli
)
964 struct smb_lock_entry lock
[2];
969 struct smbcli_request
*req
;
973 uint16_t deny_mode
= 0;
975 if (!torture_setup_dir(cli
, BASEDIR
)) {
979 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
981 torture_comment(tctx
, "testing with timeout = 0\n");
982 fname
= BASEDIR
"\\test0.txt";
986 * the first run is with t = 0,
987 * the second with t > 0 (=1)
991 * use the DENY_DOS mode, that creates two fnum's of one low-level
992 * file handle, this demonstrates that the cache is per fnum, not
995 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx
))
996 deny_mode
= OPENX_MODE_DENY_DOS
;
998 deny_mode
= OPENX_MODE_DENY_NONE
;
1000 op
.openx
.level
= RAW_OPEN_OPENX
;
1001 op
.openx
.in
.fname
= fname
;
1002 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1003 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| deny_mode
;
1004 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
1005 op
.openx
.in
.search_attrs
= 0;
1006 op
.openx
.in
.file_attrs
= 0;
1007 op
.openx
.in
.write_time
= 0;
1008 op
.openx
.in
.size
= 0;
1009 op
.openx
.in
.timeout
= 0;
1011 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1012 CHECK_STATUS(status
, NT_STATUS_OK
);
1013 fnum
= op
.openx
.out
.file
.fnum
;
1015 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1016 CHECK_STATUS(status
, NT_STATUS_OK
);
1017 fnum2
= op
.openx
.out
.file
.fnum
;
1019 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1020 io
.lockx
.in
.file
.fnum
= fnum
;
1021 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1022 io
.lockx
.in
.timeout
= t
;
1023 io
.lockx
.in
.ulock_cnt
= 0;
1024 io
.lockx
.in
.lock_cnt
= 1;
1025 lock
[0].pid
= cli
->session
->pid
;
1026 lock
[0].offset
= 100;
1028 io
.lockx
.in
.locks
= &lock
[0];
1029 status
= smb_raw_lock(cli
->tree
, &io
);
1030 CHECK_STATUS(status
, NT_STATUS_OK
);
1033 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
1034 * this also demonstrates that the error code cache is per file handle
1035 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
1037 io
.lockx
.in
.file
.fnum
= fnum2
;
1038 status
= smb_raw_lock(cli
->tree
, &io
);
1039 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1041 io
.lockx
.in
.file
.fnum
= fnum
;
1042 status
= smb_raw_lock(cli
->tree
, &io
);
1043 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1045 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
1046 io
.lockx
.in
.file
.fnum
= fnum
;
1047 status
= smb_raw_lock(cli
->tree
, &io
);
1048 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1050 io
.lockx
.in
.file
.fnum
= fnum2
;
1051 status
= smb_raw_lock(cli
->tree
, &io
);
1052 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1054 io
.lockx
.in
.file
.fnum
= fnum
;
1055 status
= smb_raw_lock(cli
->tree
, &io
);
1056 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1058 io
.lockx
.in
.file
.fnum
= fnum2
;
1059 status
= smb_raw_lock(cli
->tree
, &io
);
1060 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1062 /* demonstrate that the smbpid doesn't matter */
1064 io
.lockx
.in
.file
.fnum
= fnum
;
1065 status
= smb_raw_lock(cli
->tree
, &io
);
1066 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1068 io
.lockx
.in
.file
.fnum
= fnum2
;
1069 status
= smb_raw_lock(cli
->tree
, &io
);
1070 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1074 * demonstrate the a successful lock with count = 0 and the same offset,
1075 * doesn't reset the error cache
1077 lock
[0].offset
= 100;
1079 io
.lockx
.in
.file
.fnum
= fnum
;
1080 status
= smb_raw_lock(cli
->tree
, &io
);
1081 CHECK_STATUS(status
, NT_STATUS_OK
);
1083 io
.lockx
.in
.file
.fnum
= fnum2
;
1084 status
= smb_raw_lock(cli
->tree
, &io
);
1085 CHECK_STATUS(status
, NT_STATUS_OK
);
1087 lock
[0].offset
= 100;
1089 io
.lockx
.in
.file
.fnum
= fnum
;
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
, NT_STATUS_FILE_LOCK_CONFLICT
);
1098 * demonstrate the a successful lock with count = 0 and outside the locked range,
1099 * doesn't reset the error cache
1101 lock
[0].offset
= 110;
1103 io
.lockx
.in
.file
.fnum
= fnum
;
1104 status
= smb_raw_lock(cli
->tree
, &io
);
1105 CHECK_STATUS(status
, NT_STATUS_OK
);
1107 io
.lockx
.in
.file
.fnum
= fnum2
;
1108 status
= smb_raw_lock(cli
->tree
, &io
);
1109 CHECK_STATUS(status
, NT_STATUS_OK
);
1111 lock
[0].offset
= 100;
1113 io
.lockx
.in
.file
.fnum
= fnum
;
1114 status
= smb_raw_lock(cli
->tree
, &io
);
1115 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1117 io
.lockx
.in
.file
.fnum
= fnum2
;
1118 status
= smb_raw_lock(cli
->tree
, &io
);
1119 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1121 lock
[0].offset
= 99;
1123 io
.lockx
.in
.file
.fnum
= fnum
;
1124 status
= smb_raw_lock(cli
->tree
, &io
);
1125 CHECK_STATUS(status
, NT_STATUS_OK
);
1127 io
.lockx
.in
.file
.fnum
= fnum2
;
1128 status
= smb_raw_lock(cli
->tree
, &io
);
1129 CHECK_STATUS(status
, NT_STATUS_OK
);
1131 lock
[0].offset
= 100;
1133 io
.lockx
.in
.file
.fnum
= fnum
;
1134 status
= smb_raw_lock(cli
->tree
, &io
);
1135 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1137 io
.lockx
.in
.file
.fnum
= fnum2
;
1138 status
= smb_raw_lock(cli
->tree
, &io
);
1139 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1141 /* demonstrate that a changing count doesn't reset the error cache */
1142 lock
[0].offset
= 100;
1144 io
.lockx
.in
.file
.fnum
= fnum
;
1145 status
= smb_raw_lock(cli
->tree
, &io
);
1146 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1148 io
.lockx
.in
.file
.fnum
= fnum2
;
1149 status
= smb_raw_lock(cli
->tree
, &io
);
1150 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1152 lock
[0].offset
= 100;
1154 io
.lockx
.in
.file
.fnum
= fnum
;
1155 status
= smb_raw_lock(cli
->tree
, &io
);
1156 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1158 io
.lockx
.in
.file
.fnum
= fnum2
;
1159 status
= smb_raw_lock(cli
->tree
, &io
);
1160 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1163 * demonstrate the a lock with count = 0 and inside the locked range,
1164 * fails and resets the error cache
1166 lock
[0].offset
= 101;
1168 io
.lockx
.in
.file
.fnum
= fnum
;
1169 status
= smb_raw_lock(cli
->tree
, &io
);
1170 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1171 status
= smb_raw_lock(cli
->tree
, &io
);
1172 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1174 io
.lockx
.in
.file
.fnum
= fnum2
;
1175 status
= smb_raw_lock(cli
->tree
, &io
);
1176 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1177 status
= smb_raw_lock(cli
->tree
, &io
);
1178 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1180 lock
[0].offset
= 100;
1182 io
.lockx
.in
.file
.fnum
= fnum
;
1183 status
= smb_raw_lock(cli
->tree
, &io
);
1184 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1185 status
= smb_raw_lock(cli
->tree
, &io
);
1186 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1188 io
.lockx
.in
.file
.fnum
= fnum2
;
1189 status
= smb_raw_lock(cli
->tree
, &io
);
1190 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1191 status
= smb_raw_lock(cli
->tree
, &io
);
1192 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1194 /* demonstrate the a changing offset, resets the error cache */
1195 lock
[0].offset
= 105;
1197 io
.lockx
.in
.file
.fnum
= fnum
;
1198 status
= smb_raw_lock(cli
->tree
, &io
);
1199 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1200 status
= smb_raw_lock(cli
->tree
, &io
);
1201 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1203 io
.lockx
.in
.file
.fnum
= fnum2
;
1204 status
= smb_raw_lock(cli
->tree
, &io
);
1205 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1206 status
= smb_raw_lock(cli
->tree
, &io
);
1207 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1209 lock
[0].offset
= 100;
1211 io
.lockx
.in
.file
.fnum
= fnum
;
1212 status
= smb_raw_lock(cli
->tree
, &io
);
1213 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1214 status
= smb_raw_lock(cli
->tree
, &io
);
1215 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1217 io
.lockx
.in
.file
.fnum
= fnum2
;
1218 status
= smb_raw_lock(cli
->tree
, &io
);
1219 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1220 status
= smb_raw_lock(cli
->tree
, &io
);
1221 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1223 lock
[0].offset
= 95;
1225 io
.lockx
.in
.file
.fnum
= fnum
;
1226 status
= smb_raw_lock(cli
->tree
, &io
);
1227 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1228 status
= smb_raw_lock(cli
->tree
, &io
);
1229 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1231 io
.lockx
.in
.file
.fnum
= fnum2
;
1232 status
= smb_raw_lock(cli
->tree
, &io
);
1233 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1234 status
= smb_raw_lock(cli
->tree
, &io
);
1235 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1237 lock
[0].offset
= 100;
1239 io
.lockx
.in
.file
.fnum
= fnum
;
1240 status
= smb_raw_lock(cli
->tree
, &io
);
1241 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1242 status
= smb_raw_lock(cli
->tree
, &io
);
1243 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1245 io
.lockx
.in
.file
.fnum
= fnum2
;
1246 status
= smb_raw_lock(cli
->tree
, &io
);
1247 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1248 status
= smb_raw_lock(cli
->tree
, &io
);
1249 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1252 * demonstrate the a successful lock in a different range,
1253 * doesn't reset the cache, the failing lock on the 2nd handle
1256 lock
[0].offset
= 120;
1258 io
.lockx
.in
.file
.fnum
= fnum
;
1259 status
= smb_raw_lock(cli
->tree
, &io
);
1260 CHECK_STATUS(status
, NT_STATUS_OK
);
1262 io
.lockx
.in
.file
.fnum
= fnum2
;
1263 status
= smb_raw_lock(cli
->tree
, &io
);
1264 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1266 lock
[0].offset
= 100;
1268 io
.lockx
.in
.file
.fnum
= fnum
;
1269 status
= smb_raw_lock(cli
->tree
, &io
);
1270 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1271 status
= smb_raw_lock(cli
->tree
, &io
);
1272 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1274 io
.lockx
.in
.file
.fnum
= fnum2
;
1275 status
= smb_raw_lock(cli
->tree
, &io
);
1276 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1277 status
= smb_raw_lock(cli
->tree
, &io
);
1278 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1280 /* end of the loop */
1282 smb_raw_exit(cli
->session
);
1284 torture_comment(tctx
, "testing with timeout > 0 (=%d)\n",
1286 fname
= BASEDIR
"\\test1.txt";
1291 torture_comment(tctx
, "testing special cases with timeout > 0 (=%d)\n",
1295 * the following 3 test sections demonstrate that
1296 * the cache is only set when the error is reported
1297 * to the client (after the timeout went by)
1299 smb_raw_exit(cli
->session
);
1300 torture_comment(tctx
, "testing a conflict while a lock is pending\n");
1301 fname
= BASEDIR
"\\test2.txt";
1302 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1303 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1304 "Failed to reopen %s - %s\n",
1305 fname
, smbcli_errstr(cli
->tree
)));
1307 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1308 io
.lockx
.in
.file
.fnum
= fnum
;
1309 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1310 io
.lockx
.in
.timeout
= 0;
1311 io
.lockx
.in
.ulock_cnt
= 0;
1312 io
.lockx
.in
.lock_cnt
= 1;
1313 lock
[0].pid
= cli
->session
->pid
;
1314 lock
[0].offset
= 100;
1316 io
.lockx
.in
.locks
= &lock
[0];
1317 status
= smb_raw_lock(cli
->tree
, &io
);
1318 CHECK_STATUS(status
, NT_STATUS_OK
);
1321 io
.lockx
.in
.timeout
= t
;
1322 req
= smb_raw_lock_send(cli
->tree
, &io
);
1323 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1324 "Failed to setup timed lock (%s)\n", __location__
));
1326 io
.lockx
.in
.timeout
= 0;
1327 lock
[0].offset
= 105;
1329 status
= smb_raw_lock(cli
->tree
, &io
);
1330 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1332 status
= smbcli_request_simple_recv(req
);
1333 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1336 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1340 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1341 "lock comes back to early timeout[%d] delay[%d]"
1342 "(%s)\n", t
, delay
, __location__
));
1344 status
= smb_raw_lock(cli
->tree
, &io
);
1345 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1347 smbcli_close(cli
->tree
, fnum
);
1348 fname
= BASEDIR
"\\test3.txt";
1349 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1350 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1351 "Failed to reopen %s - %s\n",
1352 fname
, smbcli_errstr(cli
->tree
)));
1354 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1355 io
.lockx
.in
.file
.fnum
= fnum
;
1356 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1357 io
.lockx
.in
.timeout
= 0;
1358 io
.lockx
.in
.ulock_cnt
= 0;
1359 io
.lockx
.in
.lock_cnt
= 1;
1360 lock
[0].pid
= cli
->session
->pid
;
1361 lock
[0].offset
= 100;
1363 io
.lockx
.in
.locks
= &lock
[0];
1364 status
= smb_raw_lock(cli
->tree
, &io
);
1365 CHECK_STATUS(status
, NT_STATUS_OK
);
1368 io
.lockx
.in
.timeout
= t
;
1369 req
= smb_raw_lock_send(cli
->tree
, &io
);
1370 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1371 "Failed to setup timed lock (%s)\n", __location__
));
1373 io
.lockx
.in
.timeout
= 0;
1374 lock
[0].offset
= 105;
1376 status
= smb_raw_lock(cli
->tree
, &io
);
1377 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1379 status
= smbcli_request_simple_recv(req
);
1380 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1383 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1387 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1388 "lock comes back to early timeout[%d] delay[%d]"
1389 "(%s)\n", t
, delay
, __location__
));
1391 lock
[0].offset
= 100;
1393 status
= smb_raw_lock(cli
->tree
, &io
);
1394 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1396 smbcli_close(cli
->tree
, fnum
);
1397 fname
= BASEDIR
"\\test4.txt";
1398 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1399 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1400 "Failed to reopen %s - %s\n",
1401 fname
, smbcli_errstr(cli
->tree
)));
1403 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1404 io
.lockx
.in
.file
.fnum
= fnum
;
1405 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1406 io
.lockx
.in
.timeout
= 0;
1407 io
.lockx
.in
.ulock_cnt
= 0;
1408 io
.lockx
.in
.lock_cnt
= 1;
1409 lock
[0].pid
= cli
->session
->pid
;
1410 lock
[0].offset
= 100;
1412 io
.lockx
.in
.locks
= &lock
[0];
1413 status
= smb_raw_lock(cli
->tree
, &io
);
1414 CHECK_STATUS(status
, NT_STATUS_OK
);
1417 io
.lockx
.in
.timeout
= t
;
1418 req
= smb_raw_lock_send(cli
->tree
, &io
);
1419 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1420 "Failed to setup timed lock (%s)\n", __location__
));
1422 io
.lockx
.in
.timeout
= 0;
1423 status
= smb_raw_lock(cli
->tree
, &io
);
1424 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1426 status
= smbcli_request_simple_recv(req
);
1427 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1430 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1434 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1435 "lock comes back to early timeout[%d] delay[%d]"
1436 "(%s)\n", t
, delay
, __location__
));
1438 status
= smb_raw_lock(cli
->tree
, &io
);
1439 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1442 smb_raw_exit(cli
->session
);
1443 smbcli_deltree(cli
->tree
, BASEDIR
);
1449 test LOCKING_ANDX_CHANGE_LOCKTYPE
1451 static bool test_changetype(struct torture_context
*tctx
,
1452 struct smbcli_state
*cli
)
1455 struct smb_lock_entry lock
[2];
1460 const char *fname
= BASEDIR
"\\test.txt";
1462 if (!torture_setup_dir(cli
, BASEDIR
)) {
1466 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1467 io
.generic
.level
= RAW_LOCK_LOCKX
;
1469 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1470 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1471 "Failed to create %s - %s\n",
1472 fname
, smbcli_errstr(cli
->tree
)));
1474 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1475 io
.lockx
.in
.file
.fnum
= fnum
;
1476 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1477 io
.lockx
.in
.timeout
= 0;
1478 io
.lockx
.in
.ulock_cnt
= 0;
1479 io
.lockx
.in
.lock_cnt
= 1;
1480 lock
[0].pid
= cli
->session
->pid
;
1481 lock
[0].offset
= 100;
1483 io
.lockx
.in
.locks
= &lock
[0];
1484 status
= smb_raw_lock(cli
->tree
, &io
);
1485 CHECK_STATUS(status
, NT_STATUS_OK
);
1487 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1488 torture_result(tctx
, TORTURE_FAIL
,
1489 "allowed write on read locked region (%s)\n", __location__
);
1494 /* windows server don't seem to support this */
1495 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1496 status
= smb_raw_lock(cli
->tree
, &io
);
1497 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1499 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1500 torture_result(tctx
, TORTURE_FAIL
,
1501 "allowed write after lock change (%s)\n", __location__
);
1507 smbcli_close(cli
->tree
, fnum
);
1508 smb_raw_exit(cli
->session
);
1509 smbcli_deltree(cli
->tree
, BASEDIR
);
1513 struct double_lock_test
{
1514 struct smb_lock_entry lock1
;
1515 struct smb_lock_entry lock2
;
1516 NTSTATUS exp_status
;
1520 * Tests zero byte locks.
1522 static struct double_lock_test zero_byte_tests
[] = {
1523 /* {pid, offset, count}, {pid, offset, count}, status */
1525 /** First, takes a zero byte lock at offset 10. Then:
1526 * - Taking 0 byte lock at 10 should succeed.
1527 * - Taking 1 byte locks at 9,10,11 should succeed.
1528 * - Taking 2 byte lock at 9 should fail.
1529 * - Taking 2 byte lock at 10 should succeed.
1530 * - Taking 3 byte lock at 9 should fail.
1532 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1533 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1534 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1535 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1536 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1537 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1538 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1540 /** Same, but opposite order. */
1541 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1542 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1543 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1544 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1545 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1546 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1547 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1549 /** Zero zero case. */
1550 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1553 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1559 const char *fname
= BASEDIR
"\\zero.txt";
1561 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1563 if (!torture_setup_dir(cli
, BASEDIR
)) {
1567 io
.generic
.level
= RAW_LOCK_LOCKX
;
1569 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1570 torture_assert(tctx
,(fnum
!= -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
.file
.fnum
= fnum
;
1577 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1578 io
.lockx
.in
.timeout
= 0;
1580 /* Try every combination of locks in zero_byte_tests. The first lock is
1581 * assumed to succeed. The second lock may contend, depending on the
1582 * expected status. */
1584 i
< ARRAY_SIZE(zero_byte_tests
);
1586 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1587 zero_byte_tests
[i
].lock1
.pid
,
1588 zero_byte_tests
[i
].lock1
.offset
,
1589 zero_byte_tests
[i
].lock1
.count
,
1590 zero_byte_tests
[i
].lock2
.pid
,
1591 zero_byte_tests
[i
].lock2
.offset
,
1592 zero_byte_tests
[i
].lock2
.count
,
1593 nt_errstr(zero_byte_tests
[i
].exp_status
));
1595 /* Lock both locks. */
1596 io
.lockx
.in
.ulock_cnt
= 0;
1597 io
.lockx
.in
.lock_cnt
= 1;
1599 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1600 &zero_byte_tests
[i
].lock1
);
1601 status
= smb_raw_lock(cli
->tree
, &io
);
1602 CHECK_STATUS(status
, NT_STATUS_OK
);
1604 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1605 &zero_byte_tests
[i
].lock2
);
1606 status
= smb_raw_lock(cli
->tree
, &io
);
1608 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1609 NT_STATUS_LOCK_NOT_GRANTED
)) {
1610 /* Allow either of the failure messages and keep going
1611 * if we see the wrong status. */
1612 CHECK_STATUS_OR_CONT(status
,
1613 NT_STATUS_LOCK_NOT_GRANTED
,
1614 NT_STATUS_FILE_LOCK_CONFLICT
);
1617 CHECK_STATUS_CONT(status
,
1618 zero_byte_tests
[i
].exp_status
);
1621 /* Unlock both locks. */
1622 io
.lockx
.in
.ulock_cnt
= 1;
1623 io
.lockx
.in
.lock_cnt
= 0;
1625 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1626 status
= smb_raw_lock(cli
->tree
, &io
);
1627 CHECK_STATUS(status
, NT_STATUS_OK
);
1630 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1631 &zero_byte_tests
[i
].lock1
);
1632 status
= smb_raw_lock(cli
->tree
, &io
);
1633 CHECK_STATUS(status
, NT_STATUS_OK
);
1637 smbcli_close(cli
->tree
, fnum
);
1638 smb_raw_exit(cli
->session
);
1639 smbcli_deltree(cli
->tree
, BASEDIR
);
1643 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1649 const char *fname
= BASEDIR
"\\unlock.txt";
1650 struct smb_lock_entry lock1
;
1651 struct smb_lock_entry lock2
;
1653 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1655 if (!torture_setup_dir(cli
, BASEDIR
)) {
1659 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1660 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1661 "Failed to create %s - %s\n",
1662 fname
, smbcli_errstr(cli
->tree
)));
1664 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1665 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1666 "Failed to create %s - %s\n",
1667 fname
, smbcli_errstr(cli
->tree
)));
1669 /* Setup initial parameters */
1670 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1671 io
.lockx
.in
.timeout
= 0;
1673 lock1
.pid
= cli
->session
->pid
;
1676 lock2
.pid
= cli
->session
->pid
- 1;
1681 * Take exclusive lock, then unlock it with a shared-unlock call.
1683 torture_comment(tctx
, " taking exclusive lock.\n");
1684 io
.lockx
.in
.ulock_cnt
= 0;
1685 io
.lockx
.in
.lock_cnt
= 1;
1686 io
.lockx
.in
.mode
= 0;
1687 io
.lockx
.in
.file
.fnum
= fnum1
;
1688 io
.lockx
.in
.locks
= &lock1
;
1689 status
= smb_raw_lock(cli
->tree
, &io
);
1690 CHECK_STATUS(status
, NT_STATUS_OK
);
1692 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1693 io
.lockx
.in
.ulock_cnt
= 1;
1694 io
.lockx
.in
.lock_cnt
= 0;
1695 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1696 io
.lockx
.in
.file
.fnum
= fnum1
;
1697 io
.lockx
.in
.locks
= &lock1
;
1698 status
= smb_raw_lock(cli
->tree
, &io
);
1699 CHECK_STATUS(status
, NT_STATUS_OK
);
1701 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1702 io
.lockx
.in
.ulock_cnt
= 0;
1703 io
.lockx
.in
.lock_cnt
= 1;
1704 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1705 io
.lockx
.in
.file
.fnum
= fnum2
;
1706 io
.lockx
.in
.locks
= &lock2
;
1707 status
= smb_raw_lock(cli
->tree
, &io
);
1708 CHECK_STATUS(status
, NT_STATUS_OK
);
1711 * Unlock a shared lock with an exclusive-unlock call.
1713 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1714 io
.lockx
.in
.ulock_cnt
= 1;
1715 io
.lockx
.in
.lock_cnt
= 0;
1716 io
.lockx
.in
.mode
= 0;
1717 io
.lockx
.in
.file
.fnum
= fnum2
;
1718 io
.lockx
.in
.locks
= &lock2
;
1719 status
= smb_raw_lock(cli
->tree
, &io
);
1720 CHECK_STATUS(status
, NT_STATUS_OK
);
1722 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1723 io
.lockx
.in
.ulock_cnt
= 0;
1724 io
.lockx
.in
.lock_cnt
= 1;
1725 io
.lockx
.in
.mode
= 0;
1726 io
.lockx
.in
.file
.fnum
= fnum1
;
1727 io
.lockx
.in
.locks
= &lock1
;
1728 status
= smb_raw_lock(cli
->tree
, &io
);
1729 CHECK_STATUS(status
, NT_STATUS_OK
);
1732 io
.lockx
.in
.ulock_cnt
= 1;
1733 io
.lockx
.in
.lock_cnt
= 0;
1734 status
= smb_raw_lock(cli
->tree
, &io
);
1735 CHECK_STATUS(status
, NT_STATUS_OK
);
1738 * Test unlocking of 0-byte locks.
1741 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1742 "always unlocks the exclusive first.\n");
1743 lock1
.pid
= cli
->session
->pid
;
1746 lock2
.pid
= cli
->session
->pid
;
1749 io
.lockx
.in
.ulock_cnt
= 0;
1750 io
.lockx
.in
.lock_cnt
= 1;
1751 io
.lockx
.in
.file
.fnum
= fnum1
;
1752 io
.lockx
.in
.locks
= &lock1
;
1754 /* lock 0-byte shared
1755 * Note: Order of the shared/exclusive locks doesn't matter. */
1756 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1757 status
= smb_raw_lock(cli
->tree
, &io
);
1758 CHECK_STATUS(status
, NT_STATUS_OK
);
1760 /* lock 0-byte exclusive */
1761 io
.lockx
.in
.mode
= 0;
1762 status
= smb_raw_lock(cli
->tree
, &io
);
1763 CHECK_STATUS(status
, NT_STATUS_OK
);
1765 /* test contention */
1766 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1767 io
.lockx
.in
.locks
= &lock2
;
1768 io
.lockx
.in
.file
.fnum
= fnum2
;
1769 status
= smb_raw_lock(cli
->tree
, &io
);
1770 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1771 NT_STATUS_FILE_LOCK_CONFLICT
);
1774 io
.lockx
.in
.ulock_cnt
= 1;
1775 io
.lockx
.in
.lock_cnt
= 0;
1776 io
.lockx
.in
.file
.fnum
= fnum1
;
1777 io
.lockx
.in
.locks
= &lock1
;
1778 status
= smb_raw_lock(cli
->tree
, &io
);
1779 CHECK_STATUS(status
, NT_STATUS_OK
);
1781 /* test - can we take a shared lock? */
1782 io
.lockx
.in
.ulock_cnt
= 0;
1783 io
.lockx
.in
.lock_cnt
= 1;
1784 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1785 io
.lockx
.in
.file
.fnum
= fnum2
;
1786 io
.lockx
.in
.locks
= &lock2
;
1787 status
= smb_raw_lock(cli
->tree
, &io
);
1789 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1790 * new to Win7, it succeeds in WinXP too), until I can come to a
1791 * resolution as to whether Samba should support this or not. There is
1792 * code to preference unlocking exclusive locks before shared locks,
1793 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1794 if (TARGET_IS_SAMBA3(tctx
)) {
1795 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1796 NT_STATUS_FILE_LOCK_CONFLICT
);
1798 CHECK_STATUS(status
, NT_STATUS_OK
);
1802 io
.lockx
.in
.ulock_cnt
= 1;
1803 io
.lockx
.in
.lock_cnt
= 0;
1804 status
= smb_raw_lock(cli
->tree
, &io
);
1806 /* XXX Same as above. */
1807 if (TARGET_IS_SAMBA3(tctx
)) {
1808 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1810 CHECK_STATUS(status
, NT_STATUS_OK
);
1813 io
.lockx
.in
.file
.fnum
= fnum1
;
1814 io
.lockx
.in
.locks
= &lock1
;
1815 status
= smb_raw_lock(cli
->tree
, &io
);
1816 CHECK_STATUS(status
, NT_STATUS_OK
);
1819 smbcli_close(cli
->tree
, fnum1
);
1820 smbcli_close(cli
->tree
, fnum2
);
1821 smb_raw_exit(cli
->session
);
1822 smbcli_deltree(cli
->tree
, BASEDIR
);
1826 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1832 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1833 struct smb_lock_entry lock1
;
1834 struct smb_lock_entry lock2
;
1835 struct smb_lock_entry locks
[2];
1837 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1839 if (!torture_setup_dir(cli
, BASEDIR
)) {
1843 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1844 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1845 "Failed to create %s - %s\n",
1846 fname
, smbcli_errstr(cli
->tree
)));
1848 /* Setup initial parameters */
1849 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1850 io
.lockx
.in
.timeout
= 0;
1852 lock1
.pid
= cli
->session
->pid
;
1855 lock2
.pid
= cli
->session
->pid
;
1862 io
.lockx
.in
.file
.fnum
= fnum1
;
1863 io
.lockx
.in
.mode
= 0; /* exclusive */
1865 /** Test1: Take second lock, but not first. */
1866 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
1869 io
.lockx
.in
.ulock_cnt
= 0;
1870 io
.lockx
.in
.lock_cnt
= 1;
1871 io
.lockx
.in
.locks
= &lock2
;
1872 status
= smb_raw_lock(cli
->tree
, &io
);
1873 CHECK_STATUS(status
, NT_STATUS_OK
);
1875 /* Try to unlock both locks. */
1876 io
.lockx
.in
.ulock_cnt
= 2;
1877 io
.lockx
.in
.lock_cnt
= 0;
1878 io
.lockx
.in
.locks
= locks
;
1880 status
= smb_raw_lock(cli
->tree
, &io
);
1881 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1883 /* Second lock should not be unlocked. */
1884 io
.lockx
.in
.ulock_cnt
= 0;
1885 io
.lockx
.in
.lock_cnt
= 1;
1886 io
.lockx
.in
.locks
= &lock2
;
1887 status
= smb_raw_lock(cli
->tree
, &io
);
1888 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1891 io
.lockx
.in
.ulock_cnt
= 1;
1892 io
.lockx
.in
.lock_cnt
= 0;
1893 io
.lockx
.in
.locks
= &lock2
;
1894 status
= smb_raw_lock(cli
->tree
, &io
);
1895 CHECK_STATUS(status
, NT_STATUS_OK
);
1897 /** Test2: Take first lock, but not second. */
1898 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
1901 io
.lockx
.in
.ulock_cnt
= 0;
1902 io
.lockx
.in
.lock_cnt
= 1;
1903 io
.lockx
.in
.locks
= &lock1
;
1904 status
= smb_raw_lock(cli
->tree
, &io
);
1905 CHECK_STATUS(status
, NT_STATUS_OK
);
1907 /* Try to unlock both locks. */
1908 io
.lockx
.in
.ulock_cnt
= 2;
1909 io
.lockx
.in
.lock_cnt
= 0;
1910 io
.lockx
.in
.locks
= locks
;
1912 status
= smb_raw_lock(cli
->tree
, &io
);
1913 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1915 /* First lock should be unlocked. */
1916 io
.lockx
.in
.ulock_cnt
= 0;
1917 io
.lockx
.in
.lock_cnt
= 1;
1918 io
.lockx
.in
.locks
= &lock1
;
1919 status
= smb_raw_lock(cli
->tree
, &io
);
1920 CHECK_STATUS(status
, NT_STATUS_OK
);
1923 io
.lockx
.in
.ulock_cnt
= 1;
1924 io
.lockx
.in
.lock_cnt
= 0;
1925 io
.lockx
.in
.locks
= &lock1
;
1926 status
= smb_raw_lock(cli
->tree
, &io
);
1927 CHECK_STATUS(status
, NT_STATUS_OK
);
1929 /* Test3: Request 2 locks, second will contend. What happens to the
1931 torture_comment(tctx
, " request 2 locks, second one will contend. "
1932 "Expect both to fail.\n");
1934 /* Lock the second range */
1935 io
.lockx
.in
.ulock_cnt
= 0;
1936 io
.lockx
.in
.lock_cnt
= 1;
1937 io
.lockx
.in
.locks
= &lock2
;
1938 status
= smb_raw_lock(cli
->tree
, &io
);
1939 CHECK_STATUS(status
, NT_STATUS_OK
);
1941 /* Request both locks */
1942 io
.lockx
.in
.ulock_cnt
= 0;
1943 io
.lockx
.in
.lock_cnt
= 2;
1944 io
.lockx
.in
.locks
= locks
;
1946 status
= smb_raw_lock(cli
->tree
, &io
);
1947 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1949 /* First lock should be unlocked. */
1950 io
.lockx
.in
.ulock_cnt
= 0;
1951 io
.lockx
.in
.lock_cnt
= 1;
1952 io
.lockx
.in
.locks
= &lock1
;
1953 status
= smb_raw_lock(cli
->tree
, &io
);
1954 CHECK_STATUS(status
, NT_STATUS_OK
);
1957 io
.lockx
.in
.ulock_cnt
= 2;
1958 io
.lockx
.in
.lock_cnt
= 0;
1959 io
.lockx
.in
.locks
= locks
;
1960 status
= smb_raw_lock(cli
->tree
, &io
);
1961 CHECK_STATUS(status
, NT_STATUS_OK
);
1963 /* Test4: Request unlock and lock. The lock contends, is the unlock
1964 * then re-locked? */
1965 torture_comment(tctx
, " request unlock and lock, second one will "
1966 "contend. Expect the unlock to succeed.\n");
1968 /* Lock both ranges */
1969 io
.lockx
.in
.ulock_cnt
= 0;
1970 io
.lockx
.in
.lock_cnt
= 2;
1971 io
.lockx
.in
.locks
= locks
;
1972 status
= smb_raw_lock(cli
->tree
, &io
);
1973 CHECK_STATUS(status
, NT_STATUS_OK
);
1975 /* Attempt to unlock the first range and lock the second */
1976 io
.lockx
.in
.ulock_cnt
= 1;
1977 io
.lockx
.in
.lock_cnt
= 1;
1978 io
.lockx
.in
.locks
= locks
;
1979 status
= smb_raw_lock(cli
->tree
, &io
);
1980 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1982 /* The first lock should've been unlocked */
1983 io
.lockx
.in
.ulock_cnt
= 0;
1984 io
.lockx
.in
.lock_cnt
= 1;
1985 io
.lockx
.in
.locks
= &lock1
;
1986 status
= smb_raw_lock(cli
->tree
, &io
);
1987 CHECK_STATUS(status
, NT_STATUS_OK
);
1990 io
.lockx
.in
.ulock_cnt
= 2;
1991 io
.lockx
.in
.lock_cnt
= 0;
1992 io
.lockx
.in
.locks
= locks
;
1993 status
= smb_raw_lock(cli
->tree
, &io
);
1994 CHECK_STATUS(status
, NT_STATUS_OK
);
1997 smbcli_close(cli
->tree
, fnum1
);
1998 smb_raw_exit(cli
->session
);
1999 smbcli_deltree(cli
->tree
, BASEDIR
);
2004 * torture_locktest5 covers stacking pretty well, but its missing two tests:
2005 * - stacking an exclusive on top of shared fails
2006 * - stacking two exclusives fail
2008 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
2014 const char *fname
= BASEDIR
"\\stacking.txt";
2015 struct smb_lock_entry lock1
;
2016 struct smb_lock_entry lock2
;
2018 torture_comment(tctx
, "Testing stacking:\n");
2020 if (!torture_setup_dir(cli
, BASEDIR
)) {
2024 io
.generic
.level
= RAW_LOCK_LOCKX
;
2026 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2027 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2028 "Failed to create %s - %s\n",
2029 fname
, smbcli_errstr(cli
->tree
)));
2031 /* Setup initial parameters */
2032 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2033 io
.lockx
.in
.timeout
= 0;
2035 lock1
.pid
= cli
->session
->pid
;
2038 lock2
.pid
= cli
->session
->pid
- 1;
2043 * Try to take a shared lock, then stack an exclusive.
2045 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
2046 io
.lockx
.in
.file
.fnum
= fnum1
;
2047 io
.lockx
.in
.locks
= &lock1
;
2049 io
.lockx
.in
.ulock_cnt
= 0;
2050 io
.lockx
.in
.lock_cnt
= 1;
2051 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
2052 status
= smb_raw_lock(cli
->tree
, &io
);
2053 CHECK_STATUS(status
, NT_STATUS_OK
);
2055 io
.lockx
.in
.ulock_cnt
= 0;
2056 io
.lockx
.in
.lock_cnt
= 1;
2057 io
.lockx
.in
.mode
= 0;
2058 status
= smb_raw_lock(cli
->tree
, &io
);
2059 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2060 NT_STATUS_FILE_LOCK_CONFLICT
);
2063 io
.lockx
.in
.ulock_cnt
= 1;
2064 io
.lockx
.in
.lock_cnt
= 0;
2065 status
= smb_raw_lock(cli
->tree
, &io
);
2066 CHECK_STATUS(status
, NT_STATUS_OK
);
2069 * Prove that two exclusive locks do not stack.
2071 torture_comment(tctx
, " two exclusive locks do not stack.\n");
2072 io
.lockx
.in
.ulock_cnt
= 0;
2073 io
.lockx
.in
.lock_cnt
= 1;
2074 io
.lockx
.in
.mode
= 0;
2075 status
= smb_raw_lock(cli
->tree
, &io
);
2076 CHECK_STATUS(status
, NT_STATUS_OK
);
2077 status
= smb_raw_lock(cli
->tree
, &io
);
2078 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2079 NT_STATUS_FILE_LOCK_CONFLICT
);
2082 io
.lockx
.in
.ulock_cnt
= 1;
2083 io
.lockx
.in
.lock_cnt
= 0;
2084 status
= smb_raw_lock(cli
->tree
, &io
);
2085 CHECK_STATUS(status
, NT_STATUS_OK
);
2088 smbcli_close(cli
->tree
, fnum1
);
2089 smb_raw_exit(cli
->session
);
2090 smbcli_deltree(cli
->tree
, BASEDIR
);
2095 * Test how 0-byte read requests contend with byte range locks
2097 static bool test_zerobyteread(struct torture_context
*tctx
,
2098 struct smbcli_state
*cli
)
2105 const char *fname
= BASEDIR
"\\zerobyteread.txt";
2106 struct smb_lock_entry lock1
;
2109 if (!torture_setup_dir(cli
, BASEDIR
)) {
2113 io
.generic
.level
= RAW_LOCK_LOCKX
;
2115 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2116 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2117 "Failed to create %s - %s\n",
2118 fname
, smbcli_errstr(cli
->tree
)));
2120 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2121 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
2122 "Failed to create %s - %s\n",
2123 fname
, smbcli_errstr(cli
->tree
)));
2125 /* Setup initial parameters */
2126 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2127 io
.lockx
.in
.timeout
= 0;
2129 lock1
.pid
= cli
->session
->pid
;
2134 rd
.readx
.level
= RAW_READ_READX
;
2136 torture_comment(tctx
, "Testing zero byte read on lock range:\n");
2138 /* Take an exclusive lock */
2139 torture_comment(tctx
, " taking exclusive lock.\n");
2140 io
.lockx
.in
.ulock_cnt
= 0;
2141 io
.lockx
.in
.lock_cnt
= 1;
2142 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2143 io
.lockx
.in
.file
.fnum
= fnum1
;
2144 io
.lockx
.in
.locks
= &lock1
;
2145 status
= smb_raw_lock(cli
->tree
, &io
);
2146 CHECK_STATUS(status
, NT_STATUS_OK
);
2148 /* Try a zero byte read */
2149 torture_comment(tctx
, " reading 0 bytes.\n");
2150 rd
.readx
.in
.file
.fnum
= fnum2
;
2151 rd
.readx
.in
.offset
= 5;
2152 rd
.readx
.in
.mincnt
= 0;
2153 rd
.readx
.in
.maxcnt
= 0;
2154 rd
.readx
.in
.remaining
= 0;
2155 rd
.readx
.in
.read_for_execute
= false;
2156 rd
.readx
.out
.data
= &c
;
2157 status
= smb_raw_read(cli
->tree
, &rd
);
2158 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2159 "zero byte read did not return 0 bytes");
2160 CHECK_STATUS(status
, NT_STATUS_OK
);
2163 io
.lockx
.in
.ulock_cnt
= 1;
2164 io
.lockx
.in
.lock_cnt
= 0;
2165 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2166 io
.lockx
.in
.file
.fnum
= fnum1
;
2167 io
.lockx
.in
.locks
= &lock1
;
2168 status
= smb_raw_lock(cli
->tree
, &io
);
2169 CHECK_STATUS(status
, NT_STATUS_OK
);
2171 torture_comment(tctx
, "Testing zero byte read on zero byte lock "
2174 /* Take an exclusive lock */
2175 torture_comment(tctx
, " taking exclusive 0-byte lock.\n");
2176 io
.lockx
.in
.ulock_cnt
= 0;
2177 io
.lockx
.in
.lock_cnt
= 1;
2178 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2179 io
.lockx
.in
.file
.fnum
= fnum1
;
2180 io
.lockx
.in
.locks
= &lock1
;
2183 status
= smb_raw_lock(cli
->tree
, &io
);
2184 CHECK_STATUS(status
, NT_STATUS_OK
);
2186 /* Try a zero byte read before the lock */
2187 torture_comment(tctx
, " reading 0 bytes before the lock.\n");
2188 rd
.readx
.in
.file
.fnum
= fnum2
;
2189 rd
.readx
.in
.offset
= 4;
2190 rd
.readx
.in
.mincnt
= 0;
2191 rd
.readx
.in
.maxcnt
= 0;
2192 rd
.readx
.in
.remaining
= 0;
2193 rd
.readx
.in
.read_for_execute
= false;
2194 rd
.readx
.out
.data
= &c
;
2195 status
= smb_raw_read(cli
->tree
, &rd
);
2196 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2197 "zero byte read did not return 0 bytes");
2198 CHECK_STATUS(status
, NT_STATUS_OK
);
2200 /* Try a zero byte read on the lock */
2201 torture_comment(tctx
, " reading 0 bytes on the lock.\n");
2202 rd
.readx
.in
.file
.fnum
= fnum2
;
2203 rd
.readx
.in
.offset
= 5;
2204 rd
.readx
.in
.mincnt
= 0;
2205 rd
.readx
.in
.maxcnt
= 0;
2206 rd
.readx
.in
.remaining
= 0;
2207 rd
.readx
.in
.read_for_execute
= false;
2208 rd
.readx
.out
.data
= &c
;
2209 status
= smb_raw_read(cli
->tree
, &rd
);
2210 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2211 "zero byte read did not return 0 bytes");
2212 CHECK_STATUS(status
, NT_STATUS_OK
);
2214 /* Try a zero byte read after the lock */
2215 torture_comment(tctx
, " reading 0 bytes after the lock.\n");
2216 rd
.readx
.in
.file
.fnum
= fnum2
;
2217 rd
.readx
.in
.offset
= 6;
2218 rd
.readx
.in
.mincnt
= 0;
2219 rd
.readx
.in
.maxcnt
= 0;
2220 rd
.readx
.in
.remaining
= 0;
2221 rd
.readx
.in
.read_for_execute
= false;
2222 rd
.readx
.out
.data
= &c
;
2223 status
= smb_raw_read(cli
->tree
, &rd
);
2224 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2225 "zero byte read did not return 0 bytes");
2226 CHECK_STATUS(status
, NT_STATUS_OK
);
2229 io
.lockx
.in
.ulock_cnt
= 1;
2230 io
.lockx
.in
.lock_cnt
= 0;
2231 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2232 io
.lockx
.in
.file
.fnum
= fnum1
;
2233 io
.lockx
.in
.locks
= &lock1
;
2234 status
= smb_raw_lock(cli
->tree
, &io
);
2235 CHECK_STATUS(status
, NT_STATUS_OK
);
2238 smbcli_close(cli
->tree
, fnum1
);
2239 smbcli_close(cli
->tree
, fnum2
);
2240 smb_raw_exit(cli
->session
);
2241 smbcli_deltree(cli
->tree
, BASEDIR
);
2246 basic testing of lock calls
2248 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
2250 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "LOCK");
2252 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
2253 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
2254 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
2255 torture_suite_add_1smb_test(suite
, "async", test_async
);
2256 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
2257 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
2259 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
2260 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
2261 torture_suite_add_1smb_test(suite
, "multiple_unlock",
2262 test_multiple_unlock
);
2263 torture_suite_add_1smb_test(suite
, "zerobytelocks",
2264 test_zerobytelocks
);
2265 torture_suite_add_1smb_test(suite
, "zerobyteread",