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