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_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
73 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
76 test SMBlock and SMBunlock ops
78 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
84 const char *fname
= BASEDIR
"\\test.txt";
86 if (!torture_setup_dir(cli
, BASEDIR
)) {
90 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
91 io
.generic
.level
= RAW_LOCK_LOCK
;
93 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
94 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
95 "Failed to create %s - %s\n",
96 fname
, smbcli_errstr(cli
->tree
)));
98 torture_comment(tctx
, "Trying 0/0 lock\n");
99 io
.lock
.level
= RAW_LOCK_LOCK
;
100 io
.lock
.in
.file
.fnum
= fnum
;
101 io
.lock
.in
.count
= 0;
102 io
.lock
.in
.offset
= 0;
103 status
= smb_raw_lock(cli
->tree
, &io
);
104 CHECK_STATUS(status
, NT_STATUS_OK
);
106 status
= smb_raw_lock(cli
->tree
, &io
);
107 CHECK_STATUS(status
, NT_STATUS_OK
);
109 io
.lock
.level
= RAW_LOCK_UNLOCK
;
110 status
= smb_raw_lock(cli
->tree
, &io
);
111 CHECK_STATUS(status
, NT_STATUS_OK
);
113 torture_comment(tctx
, "Trying 0/1 lock\n");
114 io
.lock
.level
= RAW_LOCK_LOCK
;
115 io
.lock
.in
.file
.fnum
= fnum
;
116 io
.lock
.in
.count
= 1;
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_LOCK_NOT_GRANTED
);
124 io
.lock
.level
= RAW_LOCK_UNLOCK
;
125 status
= smb_raw_lock(cli
->tree
, &io
);
126 CHECK_STATUS(status
, NT_STATUS_OK
);
127 io
.lock
.level
= RAW_LOCK_UNLOCK
;
128 status
= smb_raw_lock(cli
->tree
, &io
);
129 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
131 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
132 io
.lock
.level
= RAW_LOCK_LOCK
;
133 io
.lock
.in
.file
.fnum
= fnum
;
134 io
.lock
.in
.count
= 4000;
135 io
.lock
.in
.offset
= 0xEEFFFFFF;
136 status
= smb_raw_lock(cli
->tree
, &io
);
137 CHECK_STATUS(status
, NT_STATUS_OK
);
139 status
= smb_raw_lock(cli
->tree
, &io
);
140 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
142 io
.lock
.level
= RAW_LOCK_UNLOCK
;
143 status
= smb_raw_lock(cli
->tree
, &io
);
144 CHECK_STATUS(status
, NT_STATUS_OK
);
145 io
.lock
.level
= RAW_LOCK_UNLOCK
;
146 status
= smb_raw_lock(cli
->tree
, &io
);
147 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
149 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
150 io
.lock
.level
= RAW_LOCK_LOCK
;
151 io
.lock
.in
.file
.fnum
= fnum
;
152 io
.lock
.in
.count
= 4000;
153 io
.lock
.in
.offset
= 0xEEFFFFFF;
154 status
= smb_raw_lock(cli
->tree
, &io
);
155 CHECK_STATUS(status
, NT_STATUS_OK
);
157 status
= smb_raw_lock(cli
->tree
, &io
);
158 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
160 io
.lock
.level
= RAW_LOCK_UNLOCK
;
161 status
= smb_raw_lock(cli
->tree
, &io
);
162 CHECK_STATUS(status
, NT_STATUS_OK
);
163 io
.lock
.level
= RAW_LOCK_UNLOCK
;
164 status
= smb_raw_lock(cli
->tree
, &io
);
165 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
167 torture_comment(tctx
, "Trying max lock\n");
168 io
.lock
.level
= RAW_LOCK_LOCK
;
169 io
.lock
.in
.file
.fnum
= fnum
;
170 io
.lock
.in
.count
= 4000;
171 io
.lock
.in
.offset
= 0xEF000000;
172 status
= smb_raw_lock(cli
->tree
, &io
);
173 CHECK_STATUS(status
, NT_STATUS_OK
);
175 status
= smb_raw_lock(cli
->tree
, &io
);
176 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
178 io
.lock
.level
= RAW_LOCK_UNLOCK
;
179 status
= smb_raw_lock(cli
->tree
, &io
);
180 CHECK_STATUS(status
, NT_STATUS_OK
);
181 io
.lock
.level
= RAW_LOCK_UNLOCK
;
182 status
= smb_raw_lock(cli
->tree
, &io
);
183 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
185 torture_comment(tctx
, "Trying wrong pid unlock\n");
186 io
.lock
.level
= RAW_LOCK_LOCK
;
187 io
.lock
.in
.file
.fnum
= fnum
;
188 io
.lock
.in
.count
= 4002;
189 io
.lock
.in
.offset
= 10001;
190 status
= smb_raw_lock(cli
->tree
, &io
);
191 CHECK_STATUS(status
, NT_STATUS_OK
);
193 io
.lock
.level
= RAW_LOCK_UNLOCK
;
194 status
= smb_raw_lock(cli
->tree
, &io
);
195 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
197 status
= smb_raw_lock(cli
->tree
, &io
);
198 CHECK_STATUS(status
, NT_STATUS_OK
);
201 smbcli_close(cli
->tree
, fnum
);
202 smb_raw_exit(cli
->session
);
203 smbcli_deltree(cli
->tree
, BASEDIR
);
211 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
214 struct smb_lock_entry lock
[1];
218 const char *fname
= BASEDIR
"\\test.txt";
220 if (!torture_setup_dir(cli
, BASEDIR
)) {
224 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
225 io
.generic
.level
= RAW_LOCK_LOCKX
;
227 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
228 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
229 "Failed to create %s - %s\n",
230 fname
, smbcli_errstr(cli
->tree
)));
232 io
.lockx
.level
= RAW_LOCK_LOCKX
;
233 io
.lockx
.in
.file
.fnum
= fnum
;
234 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
235 io
.lockx
.in
.timeout
= 0;
236 io
.lockx
.in
.ulock_cnt
= 0;
237 io
.lockx
.in
.lock_cnt
= 1;
238 lock
[0].pid
= cli
->session
->pid
;
241 io
.lockx
.in
.locks
= &lock
[0];
242 status
= smb_raw_lock(cli
->tree
, &io
);
243 CHECK_STATUS(status
, NT_STATUS_OK
);
246 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
247 io
.lockx
.in
.ulock_cnt
= 0;
248 io
.lockx
.in
.lock_cnt
= 1;
249 lock
[0].count
= 4000;
250 lock
[0].offset
= 0xEEFFFFFF;
251 status
= smb_raw_lock(cli
->tree
, &io
);
252 CHECK_STATUS(status
, NT_STATUS_OK
);
254 status
= smb_raw_lock(cli
->tree
, &io
);
255 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
257 io
.lockx
.in
.ulock_cnt
= 1;
258 io
.lockx
.in
.lock_cnt
= 0;
259 status
= smb_raw_lock(cli
->tree
, &io
);
260 CHECK_STATUS(status
, NT_STATUS_OK
);
261 status
= smb_raw_lock(cli
->tree
, &io
);
262 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
264 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
265 io
.lockx
.in
.ulock_cnt
= 0;
266 io
.lockx
.in
.lock_cnt
= 1;
267 lock
[0].count
= 4000;
268 lock
[0].offset
= 0xEF000000;
269 status
= smb_raw_lock(cli
->tree
, &io
);
270 CHECK_STATUS(status
, NT_STATUS_OK
);
272 status
= smb_raw_lock(cli
->tree
, &io
);
273 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
275 io
.lockx
.in
.ulock_cnt
= 1;
276 io
.lockx
.in
.lock_cnt
= 0;
277 status
= smb_raw_lock(cli
->tree
, &io
);
278 CHECK_STATUS(status
, NT_STATUS_OK
);
279 status
= smb_raw_lock(cli
->tree
, &io
);
280 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
282 torture_comment(tctx
, "Trying zero lock\n");
283 io
.lockx
.in
.ulock_cnt
= 0;
284 io
.lockx
.in
.lock_cnt
= 1;
287 status
= smb_raw_lock(cli
->tree
, &io
);
288 CHECK_STATUS(status
, NT_STATUS_OK
);
290 status
= smb_raw_lock(cli
->tree
, &io
);
291 CHECK_STATUS(status
, NT_STATUS_OK
);
293 io
.lockx
.in
.ulock_cnt
= 1;
294 io
.lockx
.in
.lock_cnt
= 0;
295 status
= smb_raw_lock(cli
->tree
, &io
);
296 CHECK_STATUS(status
, NT_STATUS_OK
);
297 status
= smb_raw_lock(cli
->tree
, &io
);
298 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
300 torture_comment(tctx
, "Trying max lock\n");
301 io
.lockx
.in
.ulock_cnt
= 0;
302 io
.lockx
.in
.lock_cnt
= 1;
305 status
= smb_raw_lock(cli
->tree
, &io
);
306 CHECK_STATUS(status
, NT_STATUS_OK
);
308 status
= smb_raw_lock(cli
->tree
, &io
);
309 CHECK_STATUS(status
, NT_STATUS_OK
);
311 io
.lockx
.in
.ulock_cnt
= 1;
312 io
.lockx
.in
.lock_cnt
= 0;
313 status
= smb_raw_lock(cli
->tree
, &io
);
314 CHECK_STATUS(status
, NT_STATUS_OK
);
315 status
= smb_raw_lock(cli
->tree
, &io
);
316 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
318 torture_comment(tctx
, "Trying 2^63\n");
319 io
.lockx
.in
.ulock_cnt
= 0;
320 io
.lockx
.in
.lock_cnt
= 1;
323 lock
[0].offset
<<= 63;
324 status
= smb_raw_lock(cli
->tree
, &io
);
325 CHECK_STATUS(status
, NT_STATUS_OK
);
327 status
= smb_raw_lock(cli
->tree
, &io
);
328 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
330 io
.lockx
.in
.ulock_cnt
= 1;
331 io
.lockx
.in
.lock_cnt
= 0;
332 status
= smb_raw_lock(cli
->tree
, &io
);
333 CHECK_STATUS(status
, NT_STATUS_OK
);
334 status
= smb_raw_lock(cli
->tree
, &io
);
335 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
337 torture_comment(tctx
, "Trying 2^63 - 1\n");
338 io
.lockx
.in
.ulock_cnt
= 0;
339 io
.lockx
.in
.lock_cnt
= 1;
342 lock
[0].offset
<<= 63;
344 status
= smb_raw_lock(cli
->tree
, &io
);
345 CHECK_STATUS(status
, NT_STATUS_OK
);
347 status
= smb_raw_lock(cli
->tree
, &io
);
348 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
350 io
.lockx
.in
.ulock_cnt
= 1;
351 io
.lockx
.in
.lock_cnt
= 0;
352 status
= smb_raw_lock(cli
->tree
, &io
);
353 CHECK_STATUS(status
, NT_STATUS_OK
);
354 status
= smb_raw_lock(cli
->tree
, &io
);
355 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
357 torture_comment(tctx
, "Trying max lock 2\n");
358 io
.lockx
.in
.ulock_cnt
= 0;
359 io
.lockx
.in
.lock_cnt
= 1;
362 status
= smb_raw_lock(cli
->tree
, &io
);
363 CHECK_STATUS(status
, NT_STATUS_OK
);
366 status
= smb_raw_lock(cli
->tree
, &io
);
367 if (TARGET_IS_WIN7(tctx
))
368 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
370 CHECK_STATUS(status
, NT_STATUS_OK
);
372 io
.lockx
.in
.ulock_cnt
= 1;
373 io
.lockx
.in
.lock_cnt
= 0;
375 status
= smb_raw_lock(cli
->tree
, &io
);
377 /* XXX This is very strange - Win7 gives us an invalid range when we
378 * unlock the range even though the range is locked! Win7 bug? */
379 if (TARGET_IS_WIN7(tctx
))
380 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
382 CHECK_STATUS(status
, NT_STATUS_OK
);
383 status
= smb_raw_lock(cli
->tree
, &io
);
384 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
388 smbcli_close(cli
->tree
, fnum
);
389 smb_raw_exit(cli
->session
);
390 smbcli_deltree(cli
->tree
, BASEDIR
);
397 static bool test_pidhigh(struct torture_context
*tctx
,
398 struct smbcli_state
*cli
)
401 struct smb_lock_entry lock
[1];
405 const char *fname
= BASEDIR
"\\test.txt";
408 if (!torture_setup_dir(cli
, BASEDIR
)) {
412 torture_comment(tctx
, "Testing high pid\n");
413 io
.generic
.level
= RAW_LOCK_LOCKX
;
415 cli
->session
->pid
= 1;
417 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
418 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
419 "Failed to create %s - %s\n",
420 fname
, smbcli_errstr(cli
->tree
)));
422 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
423 torture_result(tctx
, TORTURE_FAIL
,
424 "Failed to write 1 byte - %s\n",
425 smbcli_errstr(cli
->tree
));
430 io
.lockx
.level
= RAW_LOCK_LOCKX
;
431 io
.lockx
.in
.file
.fnum
= fnum
;
432 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
433 io
.lockx
.in
.timeout
= 0;
434 io
.lockx
.in
.ulock_cnt
= 0;
435 io
.lockx
.in
.lock_cnt
= 1;
436 lock
[0].pid
= cli
->session
->pid
;
438 lock
[0].count
= 0xFFFFFFFF;
439 io
.lockx
.in
.locks
= &lock
[0];
440 status
= smb_raw_lock(cli
->tree
, &io
);
441 CHECK_STATUS(status
, NT_STATUS_OK
);
443 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
444 torture_result(tctx
, TORTURE_FAIL
,
445 "Failed to read 1 byte - %s\n",
446 smbcli_errstr(cli
->tree
));
451 cli
->session
->pid
= 2;
453 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
454 torture_result(tctx
, TORTURE_FAIL
,
455 "pid is incorrect handled for read with lock!\n");
460 cli
->session
->pid
= 0x10001;
462 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
463 torture_result(tctx
, TORTURE_FAIL
,
464 "High pid is used on this server!\n");
467 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
471 smbcli_close(cli
->tree
, fnum
);
472 smb_raw_exit(cli
->session
);
473 smbcli_deltree(cli
->tree
, BASEDIR
);
479 test locking&X async operation
481 static bool test_async(struct torture_context
*tctx
,
482 struct smbcli_state
*cli
)
484 struct smbcli_session
*session
;
485 struct smb_composite_sesssetup setup
;
486 struct smbcli_tree
*tree
;
488 const char *host
, *share
;
490 struct smb_lock_entry lock
[2];
494 const char *fname
= BASEDIR
"\\test.txt";
496 struct smbcli_request
*req
;
497 struct smbcli_session_options options
;
499 if (!torture_setup_dir(cli
, BASEDIR
)) {
503 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
505 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
506 io
.generic
.level
= RAW_LOCK_LOCKX
;
508 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
509 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
510 "Failed to create %s - %s\n",
511 fname
, smbcli_errstr(cli
->tree
)));
513 io
.lockx
.level
= RAW_LOCK_LOCKX
;
514 io
.lockx
.in
.file
.fnum
= fnum
;
515 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
516 io
.lockx
.in
.timeout
= 0;
517 io
.lockx
.in
.ulock_cnt
= 0;
518 io
.lockx
.in
.lock_cnt
= 1;
519 lock
[0].pid
= cli
->session
->pid
;
520 lock
[0].offset
= 100;
522 io
.lockx
.in
.locks
= &lock
[0];
523 status
= smb_raw_lock(cli
->tree
, &io
);
524 CHECK_STATUS(status
, NT_STATUS_OK
);
528 torture_comment(tctx
, "testing cancel by CANCEL_LOCK\n");
530 /* setup a timed lock */
531 io
.lockx
.in
.timeout
= 10000;
532 req
= smb_raw_lock_send(cli
->tree
, &io
);
533 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
534 "Failed to setup timed lock (%s)\n", __location__
));
536 /* cancel the wrong range */
538 io
.lockx
.in
.timeout
= 0;
539 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
540 status
= smb_raw_lock(cli
->tree
, &io
);
541 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
543 /* cancel with the wrong bits set */
544 lock
[0].offset
= 100;
545 io
.lockx
.in
.timeout
= 0;
546 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
547 status
= smb_raw_lock(cli
->tree
, &io
);
548 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
550 /* cancel the right range */
551 lock
[0].offset
= 100;
552 io
.lockx
.in
.timeout
= 0;
553 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
554 status
= smb_raw_lock(cli
->tree
, &io
);
555 CHECK_STATUS(status
, NT_STATUS_OK
);
557 /* receive the failed lock request */
558 status
= smbcli_request_simple_recv(req
);
559 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
561 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
562 "lock cancel was not immediate (%s)\n", __location__
));
564 torture_comment(tctx
, "testing cancel by unlock\n");
565 io
.lockx
.in
.ulock_cnt
= 0;
566 io
.lockx
.in
.lock_cnt
= 1;
567 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
568 io
.lockx
.in
.timeout
= 0;
569 status
= smb_raw_lock(cli
->tree
, &io
);
570 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
572 io
.lockx
.in
.timeout
= 5000;
573 req
= smb_raw_lock_send(cli
->tree
, &io
);
574 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
575 "Failed to setup timed lock (%s)\n", __location__
));
577 io
.lockx
.in
.ulock_cnt
= 1;
578 io
.lockx
.in
.lock_cnt
= 0;
579 status
= smb_raw_lock(cli
->tree
, &io
);
580 CHECK_STATUS(status
, NT_STATUS_OK
);
583 status
= smbcli_request_simple_recv(req
);
584 CHECK_STATUS(status
, NT_STATUS_OK
);
586 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
587 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
588 __location__
, (int)(time(NULL
)-t
)));
590 torture_comment(tctx
, "testing cancel by close\n");
591 io
.lockx
.in
.ulock_cnt
= 0;
592 io
.lockx
.in
.lock_cnt
= 1;
593 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
594 io
.lockx
.in
.timeout
= 0;
595 status
= smb_raw_lock(cli
->tree
, &io
);
596 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
599 io
.lockx
.in
.timeout
= 10000;
600 req
= smb_raw_lock_send(cli
->tree
, &io
);
601 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
602 "Failed to setup timed lock (%s)\n", __location__
));
604 status
= smbcli_close(cli
->tree
, fnum
);
605 CHECK_STATUS(status
, NT_STATUS_OK
);
607 status
= smbcli_request_simple_recv(req
);
608 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
610 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
611 "lock cancel by close was not immediate (%s)\n", __location__
));
613 torture_comment(tctx
, "create a new sessions\n");
614 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
615 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
616 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
617 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
618 setup
.in
.credentials
= cmdline_credentials
;
619 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
620 status
= smb_composite_sesssetup(session
, &setup
);
621 CHECK_STATUS(status
, NT_STATUS_OK
);
622 session
->vuid
= setup
.out
.vuid
;
624 torture_comment(tctx
, "create new tree context\n");
625 share
= torture_setting_string(tctx
, "share", NULL
);
626 host
= torture_setting_string(tctx
, "host", NULL
);
627 tree
= smbcli_tree_init(session
, tctx
, false);
628 tcon
.generic
.level
= RAW_TCON_TCONX
;
629 tcon
.tconx
.in
.flags
= 0;
630 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
631 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
632 tcon
.tconx
.in
.device
= "A:";
633 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
634 CHECK_STATUS(status
, NT_STATUS_OK
);
635 tree
->tid
= tcon
.tconx
.out
.tid
;
637 torture_comment(tctx
, "testing cancel by exit\n");
638 fname
= BASEDIR
"\\test_exit.txt";
639 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
640 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
641 "Failed to reopen %s - %s\n",
642 fname
, smbcli_errstr(tree
)));
644 io
.lockx
.level
= RAW_LOCK_LOCKX
;
645 io
.lockx
.in
.file
.fnum
= fnum
;
646 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
647 io
.lockx
.in
.timeout
= 0;
648 io
.lockx
.in
.ulock_cnt
= 0;
649 io
.lockx
.in
.lock_cnt
= 1;
650 lock
[0].pid
= session
->pid
;
651 lock
[0].offset
= 100;
653 io
.lockx
.in
.locks
= &lock
[0];
654 status
= smb_raw_lock(tree
, &io
);
655 CHECK_STATUS(status
, NT_STATUS_OK
);
657 io
.lockx
.in
.ulock_cnt
= 0;
658 io
.lockx
.in
.lock_cnt
= 1;
659 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
660 io
.lockx
.in
.timeout
= 0;
661 status
= smb_raw_lock(tree
, &io
);
662 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
664 io
.lockx
.in
.timeout
= 10000;
666 req
= smb_raw_lock_send(tree
, &io
);
667 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
668 "Failed to setup timed lock (%s)\n", __location__
));
670 status
= smb_raw_exit(session
);
671 CHECK_STATUS(status
, NT_STATUS_OK
);
673 status
= smbcli_request_simple_recv(req
);
674 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
676 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
677 "lock cancel by exit was not immediate (%s)\n", __location__
));
679 torture_comment(tctx
, "testing cancel by ulogoff\n");
680 fname
= BASEDIR
"\\test_ulogoff.txt";
681 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
682 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
683 "Failed to reopen %s - %s\n",
684 fname
, smbcli_errstr(tree
)));
686 io
.lockx
.level
= RAW_LOCK_LOCKX
;
687 io
.lockx
.in
.file
.fnum
= fnum
;
688 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
689 io
.lockx
.in
.timeout
= 0;
690 io
.lockx
.in
.ulock_cnt
= 0;
691 io
.lockx
.in
.lock_cnt
= 1;
692 lock
[0].pid
= session
->pid
;
693 lock
[0].offset
= 100;
695 io
.lockx
.in
.locks
= &lock
[0];
696 status
= smb_raw_lock(tree
, &io
);
697 CHECK_STATUS(status
, NT_STATUS_OK
);
699 io
.lockx
.in
.ulock_cnt
= 0;
700 io
.lockx
.in
.lock_cnt
= 1;
701 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
702 io
.lockx
.in
.timeout
= 0;
703 status
= smb_raw_lock(tree
, &io
);
704 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
706 io
.lockx
.in
.timeout
= 10000;
708 req
= smb_raw_lock_send(tree
, &io
);
709 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
710 "Failed to setup timed lock (%s)\n", __location__
));
712 status
= smb_raw_ulogoff(session
);
713 CHECK_STATUS(status
, NT_STATUS_OK
);
715 status
= smbcli_request_simple_recv(req
);
716 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
717 torture_result(tctx
, TORTURE_FAIL
,
718 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
720 smb_tree_disconnect(tree
);
721 smb_raw_exit(session
);
724 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
726 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
727 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
729 torture_comment(tctx
, "testing cancel by tdis\n");
730 tree
->session
= cli
->session
;
732 fname
= BASEDIR
"\\test_tdis.txt";
733 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
734 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
735 "Failed to reopen %s - %s\n",
736 fname
, smbcli_errstr(tree
)));
738 io
.lockx
.level
= RAW_LOCK_LOCKX
;
739 io
.lockx
.in
.file
.fnum
= fnum
;
740 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
741 io
.lockx
.in
.timeout
= 0;
742 io
.lockx
.in
.ulock_cnt
= 0;
743 io
.lockx
.in
.lock_cnt
= 1;
744 lock
[0].pid
= cli
->session
->pid
;
745 lock
[0].offset
= 100;
747 io
.lockx
.in
.locks
= &lock
[0];
748 status
= smb_raw_lock(tree
, &io
);
749 CHECK_STATUS(status
, NT_STATUS_OK
);
751 status
= smb_raw_lock(tree
, &io
);
752 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
754 io
.lockx
.in
.timeout
= 10000;
756 req
= smb_raw_lock_send(tree
, &io
);
757 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
758 "Failed to setup timed lock (%s)\n", __location__
));
760 status
= smb_tree_disconnect(tree
);
761 CHECK_STATUS(status
, NT_STATUS_OK
);
763 status
= smbcli_request_simple_recv(req
);
764 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
766 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
767 "lock cancel by tdis was not immediate (%s)\n", __location__
));
770 smb_raw_exit(cli
->session
);
771 smbcli_deltree(cli
->tree
, BASEDIR
);
776 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
778 static bool test_errorcode(struct torture_context
*tctx
,
779 struct smbcli_state
*cli
)
783 struct smb_lock_entry lock
[2];
788 struct smbcli_request
*req
;
792 if (!torture_setup_dir(cli
, BASEDIR
)) {
796 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
798 torture_comment(tctx
, "testing with timeout = 0\n");
799 fname
= BASEDIR
"\\test0.txt";
803 * the first run is with t = 0,
804 * the second with t > 0 (=1)
808 * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
809 * this demonstrates that the cache is per fnum
811 op
.openx
.level
= RAW_OPEN_OPENX
;
812 op
.openx
.in
.fname
= fname
;
813 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
814 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| OPENX_MODE_DENY_DOS
;
815 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
816 op
.openx
.in
.search_attrs
= 0;
817 op
.openx
.in
.file_attrs
= 0;
818 op
.openx
.in
.write_time
= 0;
819 op
.openx
.in
.size
= 0;
820 op
.openx
.in
.timeout
= 0;
822 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
823 CHECK_STATUS(status
, NT_STATUS_OK
);
824 fnum
= op
.openx
.out
.file
.fnum
;
826 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
827 CHECK_STATUS(status
, NT_STATUS_OK
);
828 fnum2
= op
.openx
.out
.file
.fnum
;
830 io
.lockx
.level
= RAW_LOCK_LOCKX
;
831 io
.lockx
.in
.file
.fnum
= fnum
;
832 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
833 io
.lockx
.in
.timeout
= t
;
834 io
.lockx
.in
.ulock_cnt
= 0;
835 io
.lockx
.in
.lock_cnt
= 1;
836 lock
[0].pid
= cli
->session
->pid
;
837 lock
[0].offset
= 100;
839 io
.lockx
.in
.locks
= &lock
[0];
840 status
= smb_raw_lock(cli
->tree
, &io
);
841 CHECK_STATUS(status
, NT_STATUS_OK
);
844 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
845 * this also demonstrates that the error code cache is per file handle
846 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
848 io
.lockx
.in
.file
.fnum
= fnum2
;
849 status
= smb_raw_lock(cli
->tree
, &io
);
850 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
852 io
.lockx
.in
.file
.fnum
= fnum
;
853 status
= smb_raw_lock(cli
->tree
, &io
);
854 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
856 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
857 io
.lockx
.in
.file
.fnum
= fnum
;
858 status
= smb_raw_lock(cli
->tree
, &io
);
859 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
861 io
.lockx
.in
.file
.fnum
= fnum2
;
862 status
= smb_raw_lock(cli
->tree
, &io
);
863 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
865 io
.lockx
.in
.file
.fnum
= fnum
;
866 status
= smb_raw_lock(cli
->tree
, &io
);
867 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
869 io
.lockx
.in
.file
.fnum
= fnum2
;
870 status
= smb_raw_lock(cli
->tree
, &io
);
871 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
873 /* demonstrate that the smbpid doesn't matter */
875 io
.lockx
.in
.file
.fnum
= fnum
;
876 status
= smb_raw_lock(cli
->tree
, &io
);
877 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
879 io
.lockx
.in
.file
.fnum
= fnum2
;
880 status
= smb_raw_lock(cli
->tree
, &io
);
881 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
885 * demonstrate the a successful lock with count = 0 and the same offset,
886 * doesn't reset the error cache
888 lock
[0].offset
= 100;
890 io
.lockx
.in
.file
.fnum
= fnum
;
891 status
= smb_raw_lock(cli
->tree
, &io
);
892 CHECK_STATUS(status
, NT_STATUS_OK
);
894 io
.lockx
.in
.file
.fnum
= fnum2
;
895 status
= smb_raw_lock(cli
->tree
, &io
);
896 CHECK_STATUS(status
, NT_STATUS_OK
);
898 lock
[0].offset
= 100;
900 io
.lockx
.in
.file
.fnum
= fnum
;
901 status
= smb_raw_lock(cli
->tree
, &io
);
902 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
904 io
.lockx
.in
.file
.fnum
= fnum2
;
905 status
= smb_raw_lock(cli
->tree
, &io
);
906 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
909 * demonstrate the a successful lock with count = 0 and outside the locked range,
910 * doesn't reset the error cache
912 lock
[0].offset
= 110;
914 io
.lockx
.in
.file
.fnum
= fnum
;
915 status
= smb_raw_lock(cli
->tree
, &io
);
916 CHECK_STATUS(status
, NT_STATUS_OK
);
918 io
.lockx
.in
.file
.fnum
= fnum2
;
919 status
= smb_raw_lock(cli
->tree
, &io
);
920 CHECK_STATUS(status
, NT_STATUS_OK
);
922 lock
[0].offset
= 100;
924 io
.lockx
.in
.file
.fnum
= fnum
;
925 status
= smb_raw_lock(cli
->tree
, &io
);
926 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
928 io
.lockx
.in
.file
.fnum
= fnum2
;
929 status
= smb_raw_lock(cli
->tree
, &io
);
930 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
934 io
.lockx
.in
.file
.fnum
= fnum
;
935 status
= smb_raw_lock(cli
->tree
, &io
);
936 CHECK_STATUS(status
, NT_STATUS_OK
);
938 io
.lockx
.in
.file
.fnum
= fnum2
;
939 status
= smb_raw_lock(cli
->tree
, &io
);
940 CHECK_STATUS(status
, NT_STATUS_OK
);
942 lock
[0].offset
= 100;
944 io
.lockx
.in
.file
.fnum
= fnum
;
945 status
= smb_raw_lock(cli
->tree
, &io
);
946 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
948 io
.lockx
.in
.file
.fnum
= fnum2
;
949 status
= smb_raw_lock(cli
->tree
, &io
);
950 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
952 /* demonstrate that a changing count doesn't reset the error cache */
953 lock
[0].offset
= 100;
955 io
.lockx
.in
.file
.fnum
= fnum
;
956 status
= smb_raw_lock(cli
->tree
, &io
);
957 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
959 io
.lockx
.in
.file
.fnum
= fnum2
;
960 status
= smb_raw_lock(cli
->tree
, &io
);
961 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
963 lock
[0].offset
= 100;
965 io
.lockx
.in
.file
.fnum
= fnum
;
966 status
= smb_raw_lock(cli
->tree
, &io
);
967 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
969 io
.lockx
.in
.file
.fnum
= fnum2
;
970 status
= smb_raw_lock(cli
->tree
, &io
);
971 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
974 * demonstrate the a lock with count = 0 and inside the locked range,
975 * fails and resets the error cache
977 lock
[0].offset
= 101;
979 io
.lockx
.in
.file
.fnum
= fnum
;
980 status
= smb_raw_lock(cli
->tree
, &io
);
981 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
982 status
= smb_raw_lock(cli
->tree
, &io
);
983 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
985 io
.lockx
.in
.file
.fnum
= fnum2
;
986 status
= smb_raw_lock(cli
->tree
, &io
);
987 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
988 status
= smb_raw_lock(cli
->tree
, &io
);
989 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
991 lock
[0].offset
= 100;
993 io
.lockx
.in
.file
.fnum
= fnum
;
994 status
= smb_raw_lock(cli
->tree
, &io
);
995 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
996 status
= smb_raw_lock(cli
->tree
, &io
);
997 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
999 io
.lockx
.in
.file
.fnum
= fnum2
;
1000 status
= smb_raw_lock(cli
->tree
, &io
);
1001 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1002 status
= smb_raw_lock(cli
->tree
, &io
);
1003 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1005 /* demonstrate the a changing offset, resets the error cache */
1006 lock
[0].offset
= 105;
1008 io
.lockx
.in
.file
.fnum
= fnum
;
1009 status
= smb_raw_lock(cli
->tree
, &io
);
1010 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1011 status
= smb_raw_lock(cli
->tree
, &io
);
1012 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1014 io
.lockx
.in
.file
.fnum
= fnum2
;
1015 status
= smb_raw_lock(cli
->tree
, &io
);
1016 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1017 status
= smb_raw_lock(cli
->tree
, &io
);
1018 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1020 lock
[0].offset
= 100;
1022 io
.lockx
.in
.file
.fnum
= fnum
;
1023 status
= smb_raw_lock(cli
->tree
, &io
);
1024 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1025 status
= smb_raw_lock(cli
->tree
, &io
);
1026 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1028 io
.lockx
.in
.file
.fnum
= fnum2
;
1029 status
= smb_raw_lock(cli
->tree
, &io
);
1030 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1031 status
= smb_raw_lock(cli
->tree
, &io
);
1032 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1034 lock
[0].offset
= 95;
1036 io
.lockx
.in
.file
.fnum
= fnum
;
1037 status
= smb_raw_lock(cli
->tree
, &io
);
1038 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1039 status
= smb_raw_lock(cli
->tree
, &io
);
1040 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1042 io
.lockx
.in
.file
.fnum
= fnum2
;
1043 status
= smb_raw_lock(cli
->tree
, &io
);
1044 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1045 status
= smb_raw_lock(cli
->tree
, &io
);
1046 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1048 lock
[0].offset
= 100;
1050 io
.lockx
.in
.file
.fnum
= fnum
;
1051 status
= smb_raw_lock(cli
->tree
, &io
);
1052 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1053 status
= smb_raw_lock(cli
->tree
, &io
);
1054 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1056 io
.lockx
.in
.file
.fnum
= fnum2
;
1057 status
= smb_raw_lock(cli
->tree
, &io
);
1058 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1059 status
= smb_raw_lock(cli
->tree
, &io
);
1060 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1063 * demonstrate the a successful lock in a different range,
1064 * doesn't reset the cache, the failing lock on the 2nd handle
1065 * resets the resets the cache
1067 lock
[0].offset
= 120;
1069 io
.lockx
.in
.file
.fnum
= fnum
;
1070 status
= smb_raw_lock(cli
->tree
, &io
);
1071 CHECK_STATUS(status
, NT_STATUS_OK
);
1073 io
.lockx
.in
.file
.fnum
= fnum2
;
1074 status
= smb_raw_lock(cli
->tree
, &io
);
1075 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
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_FILE_LOCK_CONFLICT
);
1082 status
= smb_raw_lock(cli
->tree
, &io
);
1083 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1085 io
.lockx
.in
.file
.fnum
= fnum2
;
1086 status
= smb_raw_lock(cli
->tree
, &io
);
1087 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1088 status
= smb_raw_lock(cli
->tree
, &io
);
1089 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1091 /* end of the loop */
1093 smb_raw_exit(cli
->session
);
1094 torture_comment(tctx
, "testing with timeout > 0 (=1)\n");
1095 fname
= BASEDIR
"\\test1.txt";
1101 * the following 3 test sections demonstrate that
1102 * the cache is only set when the error is reported
1103 * to the client (after the timeout went by)
1105 smb_raw_exit(cli
->session
);
1106 torture_comment(tctx
, "testing a conflict while a lock is pending\n");
1107 fname
= BASEDIR
"\\test2.txt";
1108 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1109 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1110 "Failed to reopen %s - %s\n",
1111 fname
, smbcli_errstr(cli
->tree
)));
1113 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1114 io
.lockx
.in
.file
.fnum
= fnum
;
1115 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1116 io
.lockx
.in
.timeout
= 0;
1117 io
.lockx
.in
.ulock_cnt
= 0;
1118 io
.lockx
.in
.lock_cnt
= 1;
1119 lock
[0].pid
= cli
->session
->pid
;
1120 lock
[0].offset
= 100;
1122 io
.lockx
.in
.locks
= &lock
[0];
1123 status
= smb_raw_lock(cli
->tree
, &io
);
1124 CHECK_STATUS(status
, NT_STATUS_OK
);
1127 io
.lockx
.in
.timeout
= 1000;
1128 req
= smb_raw_lock_send(cli
->tree
, &io
);
1129 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1130 "Failed to setup timed lock (%s)\n", __location__
));
1132 io
.lockx
.in
.timeout
= 0;
1133 lock
[0].offset
= 105;
1135 status
= smb_raw_lock(cli
->tree
, &io
);
1136 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1138 status
= smbcli_request_simple_recv(req
);
1139 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1141 status
= smb_raw_lock(cli
->tree
, &io
);
1142 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1144 torture_assert(tctx
,!(time(NULL
) < start
+1), talloc_asprintf(tctx
,
1145 "lock comes back to early (%s)\n", __location__
));
1147 smbcli_close(cli
->tree
, fnum
);
1148 fname
= BASEDIR
"\\test3.txt";
1149 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1150 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1151 "Failed to reopen %s - %s\n",
1152 fname
, smbcli_errstr(cli
->tree
)));
1154 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1155 io
.lockx
.in
.file
.fnum
= fnum
;
1156 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1157 io
.lockx
.in
.timeout
= 0;
1158 io
.lockx
.in
.ulock_cnt
= 0;
1159 io
.lockx
.in
.lock_cnt
= 1;
1160 lock
[0].pid
= cli
->session
->pid
;
1161 lock
[0].offset
= 100;
1163 io
.lockx
.in
.locks
= &lock
[0];
1164 status
= smb_raw_lock(cli
->tree
, &io
);
1165 CHECK_STATUS(status
, NT_STATUS_OK
);
1168 io
.lockx
.in
.timeout
= 1000;
1169 req
= smb_raw_lock_send(cli
->tree
, &io
);
1170 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1171 "Failed to setup timed lock (%s)\n", __location__
));
1173 io
.lockx
.in
.timeout
= 0;
1174 lock
[0].offset
= 105;
1176 status
= smb_raw_lock(cli
->tree
, &io
);
1177 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1179 status
= smbcli_request_simple_recv(req
);
1180 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1182 lock
[0].offset
= 100;
1184 status
= smb_raw_lock(cli
->tree
, &io
);
1185 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1187 torture_assert(tctx
,!(time(NULL
) < start
+1), talloc_asprintf(tctx
,
1188 "lock comes back to early (%s)\n", __location__
));
1190 smbcli_close(cli
->tree
, fnum
);
1191 fname
= BASEDIR
"\\test4.txt";
1192 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1193 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1194 "Failed to reopen %s - %s\n",
1195 fname
, smbcli_errstr(cli
->tree
)));
1197 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1198 io
.lockx
.in
.file
.fnum
= fnum
;
1199 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1200 io
.lockx
.in
.timeout
= 0;
1201 io
.lockx
.in
.ulock_cnt
= 0;
1202 io
.lockx
.in
.lock_cnt
= 1;
1203 lock
[0].pid
= cli
->session
->pid
;
1204 lock
[0].offset
= 100;
1206 io
.lockx
.in
.locks
= &lock
[0];
1207 status
= smb_raw_lock(cli
->tree
, &io
);
1208 CHECK_STATUS(status
, NT_STATUS_OK
);
1211 io
.lockx
.in
.timeout
= 1000;
1212 req
= smb_raw_lock_send(cli
->tree
, &io
);
1213 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1214 "Failed to setup timed lock (%s)\n", __location__
));
1216 io
.lockx
.in
.timeout
= 0;
1217 status
= smb_raw_lock(cli
->tree
, &io
);
1218 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1220 status
= smbcli_request_simple_recv(req
);
1221 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1223 status
= smb_raw_lock(cli
->tree
, &io
);
1224 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1226 torture_assert(tctx
,!(time(NULL
) < start
+1), talloc_asprintf(tctx
,
1227 "lock comes back to early (%s)\n", __location__
));
1230 smb_raw_exit(cli
->session
);
1231 smbcli_deltree(cli
->tree
, BASEDIR
);
1237 test LOCKING_ANDX_CHANGE_LOCKTYPE
1239 static bool test_changetype(struct torture_context
*tctx
,
1240 struct smbcli_state
*cli
)
1243 struct smb_lock_entry lock
[2];
1248 const char *fname
= BASEDIR
"\\test.txt";
1250 if (!torture_setup_dir(cli
, BASEDIR
)) {
1254 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1255 io
.generic
.level
= RAW_LOCK_LOCKX
;
1257 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1258 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1259 "Failed to create %s - %s\n",
1260 fname
, smbcli_errstr(cli
->tree
)));
1262 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1263 io
.lockx
.in
.file
.fnum
= fnum
;
1264 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1265 io
.lockx
.in
.timeout
= 0;
1266 io
.lockx
.in
.ulock_cnt
= 0;
1267 io
.lockx
.in
.lock_cnt
= 1;
1268 lock
[0].pid
= cli
->session
->pid
;
1269 lock
[0].offset
= 100;
1271 io
.lockx
.in
.locks
= &lock
[0];
1272 status
= smb_raw_lock(cli
->tree
, &io
);
1273 CHECK_STATUS(status
, NT_STATUS_OK
);
1275 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1276 torture_result(tctx
, TORTURE_FAIL
,
1277 "allowed write on read locked region (%s)\n", __location__
);
1282 /* windows server don't seem to support this */
1283 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1284 status
= smb_raw_lock(cli
->tree
, &io
);
1285 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1287 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1288 torture_result(tctx
, TORTURE_FAIL
,
1289 "allowed write after lock change (%s)\n", __location__
);
1295 smbcli_close(cli
->tree
, fnum
);
1296 smb_raw_exit(cli
->session
);
1297 smbcli_deltree(cli
->tree
, BASEDIR
);
1301 struct double_lock_test
{
1302 struct smb_lock_entry lock1
;
1303 struct smb_lock_entry lock2
;
1304 NTSTATUS exp_status
;
1308 * Tests zero byte locks.
1310 struct double_lock_test zero_byte_tests
[] = {
1311 /* {pid, offset, count}, {pid, offset, count}, status */
1313 /** First, takes a zero byte lock at offset 10. Then:
1314 * - Taking 0 byte lock at 10 should succeed.
1315 * - Taking 1 byte locks at 9,10,11 should succeed.
1316 * - Taking 2 byte lock at 9 should fail.
1317 * - Taking 2 byte lock at 10 should succeed.
1318 * - Taking 3 byte lock at 9 should fail.
1320 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1321 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1322 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1323 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1324 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1325 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1326 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1328 /** Same, but opposite order. */
1329 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1330 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1331 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1332 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1333 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1334 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1335 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1337 /** Zero zero case. */
1338 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1341 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1344 struct smb_lock_entry zerozero
;
1348 const char *fname
= BASEDIR
"\\zero.txt";
1350 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1352 if (!torture_setup_dir(cli
, BASEDIR
)) {
1356 io
.generic
.level
= RAW_LOCK_LOCKX
;
1358 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1359 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1360 "Failed to create %s - %s\n",
1361 fname
, smbcli_errstr(cli
->tree
)));
1363 /* Setup initial parameters */
1364 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1365 io
.lockx
.in
.file
.fnum
= fnum
;
1366 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1367 io
.lockx
.in
.timeout
= 0;
1369 /* Try every combination of locks in zero_byte_tests. The first lock is
1370 * assumed to succeed. The second lock may contend, depending on the
1371 * expected status. */
1373 i
< sizeof(zero_byte_tests
) / sizeof(struct double_lock_test
);
1375 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1376 zero_byte_tests
[i
].lock1
.pid
,
1377 zero_byte_tests
[i
].lock1
.offset
,
1378 zero_byte_tests
[i
].lock1
.count
,
1379 zero_byte_tests
[i
].lock2
.pid
,
1380 zero_byte_tests
[i
].lock2
.offset
,
1381 zero_byte_tests
[i
].lock2
.count
,
1382 nt_errstr(zero_byte_tests
[i
].exp_status
));
1384 /* Lock both locks. */
1385 io
.lockx
.in
.ulock_cnt
= 0;
1386 io
.lockx
.in
.lock_cnt
= 1;
1388 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock1
;
1389 status
= smb_raw_lock(cli
->tree
, &io
);
1390 CHECK_STATUS(status
, NT_STATUS_OK
);
1392 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock2
;
1393 status
= smb_raw_lock(cli
->tree
, &io
);
1395 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1396 NT_STATUS_LOCK_NOT_GRANTED
)) {
1397 /* Allow either of the failure messages and keep going
1398 * if we see the wrong status. */
1399 CHECK_STATUS_OR_CONT(status
,
1400 NT_STATUS_LOCK_NOT_GRANTED
,
1401 NT_STATUS_FILE_LOCK_CONFLICT
);
1404 CHECK_STATUS_CONT(status
,
1405 zero_byte_tests
[i
].exp_status
);
1408 /* Unlock both locks. */
1409 io
.lockx
.in
.ulock_cnt
= 1;
1410 io
.lockx
.in
.lock_cnt
= 0;
1412 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1413 status
= smb_raw_lock(cli
->tree
, &io
);
1414 CHECK_STATUS(status
, NT_STATUS_OK
);
1417 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock1
;
1418 status
= smb_raw_lock(cli
->tree
, &io
);
1419 CHECK_STATUS(status
, NT_STATUS_OK
);
1423 smbcli_close(cli
->tree
, fnum
);
1424 smb_raw_exit(cli
->session
);
1425 smbcli_deltree(cli
->tree
, BASEDIR
);
1429 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1435 const char *fname
= BASEDIR
"\\unlock.txt";
1436 struct smb_lock_entry lock1
;
1437 struct smb_lock_entry lock2
;
1439 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1441 if (!torture_setup_dir(cli
, BASEDIR
)) {
1445 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1446 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1447 "Failed to create %s - %s\n",
1448 fname
, smbcli_errstr(cli
->tree
)));
1450 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1451 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1452 "Failed to create %s - %s\n",
1453 fname
, smbcli_errstr(cli
->tree
)));
1455 /* Setup initial parameters */
1456 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1457 io
.lockx
.in
.timeout
= 0;
1459 lock1
.pid
= cli
->session
->pid
;
1462 lock2
.pid
= cli
->session
->pid
- 1;
1467 * Take exclusive lock, then unlock it with a shared-unlock call.
1469 torture_comment(tctx
, " taking exclusive lock.\n");
1470 io
.lockx
.in
.ulock_cnt
= 0;
1471 io
.lockx
.in
.lock_cnt
= 1;
1472 io
.lockx
.in
.mode
= 0;
1473 io
.lockx
.in
.file
.fnum
= fnum1
;
1474 io
.lockx
.in
.locks
= &lock1
;
1475 status
= smb_raw_lock(cli
->tree
, &io
);
1476 CHECK_STATUS(status
, NT_STATUS_OK
);
1478 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1479 io
.lockx
.in
.ulock_cnt
= 1;
1480 io
.lockx
.in
.lock_cnt
= 0;
1481 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1482 io
.lockx
.in
.file
.fnum
= fnum1
;
1483 io
.lockx
.in
.locks
= &lock1
;
1484 status
= smb_raw_lock(cli
->tree
, &io
);
1485 CHECK_STATUS(status
, NT_STATUS_OK
);
1487 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1488 io
.lockx
.in
.ulock_cnt
= 0;
1489 io
.lockx
.in
.lock_cnt
= 1;
1490 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1491 io
.lockx
.in
.file
.fnum
= fnum2
;
1492 io
.lockx
.in
.locks
= &lock2
;
1493 status
= smb_raw_lock(cli
->tree
, &io
);
1494 CHECK_STATUS(status
, NT_STATUS_OK
);
1497 * Unlock a shared lock with an exclusive-unlock call.
1499 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1500 io
.lockx
.in
.ulock_cnt
= 1;
1501 io
.lockx
.in
.lock_cnt
= 0;
1502 io
.lockx
.in
.mode
= 0;
1503 io
.lockx
.in
.file
.fnum
= fnum2
;
1504 io
.lockx
.in
.locks
= &lock2
;
1505 status
= smb_raw_lock(cli
->tree
, &io
);
1506 CHECK_STATUS(status
, NT_STATUS_OK
);
1508 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1509 io
.lockx
.in
.ulock_cnt
= 0;
1510 io
.lockx
.in
.lock_cnt
= 1;
1511 io
.lockx
.in
.mode
= 0;
1512 io
.lockx
.in
.file
.fnum
= fnum1
;
1513 io
.lockx
.in
.locks
= &lock1
;
1514 status
= smb_raw_lock(cli
->tree
, &io
);
1515 CHECK_STATUS(status
, NT_STATUS_OK
);
1518 io
.lockx
.in
.ulock_cnt
= 1;
1519 io
.lockx
.in
.lock_cnt
= 0;
1520 status
= smb_raw_lock(cli
->tree
, &io
);
1521 CHECK_STATUS(status
, NT_STATUS_OK
);
1524 * Test unlocking of 0-byte locks.
1527 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1528 "always unlocks the exclusive first.\n");
1529 lock1
.pid
= cli
->session
->pid
;
1532 lock2
.pid
= cli
->session
->pid
;
1535 io
.lockx
.in
.ulock_cnt
= 0;
1536 io
.lockx
.in
.lock_cnt
= 1;
1537 io
.lockx
.in
.file
.fnum
= fnum1
;
1538 io
.lockx
.in
.locks
= &lock1
;
1540 /* lock 0-byte shared
1541 * Note: Order of the shared/exclusive locks doesn't matter. */
1542 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1543 status
= smb_raw_lock(cli
->tree
, &io
);
1544 CHECK_STATUS(status
, NT_STATUS_OK
);
1546 /* lock 0-byte exclusive */
1547 io
.lockx
.in
.mode
= 0;
1548 status
= smb_raw_lock(cli
->tree
, &io
);
1549 CHECK_STATUS(status
, NT_STATUS_OK
);
1551 /* test contention */
1552 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1553 io
.lockx
.in
.locks
= &lock2
;
1554 io
.lockx
.in
.file
.fnum
= fnum2
;
1555 status
= smb_raw_lock(cli
->tree
, &io
);
1556 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1557 NT_STATUS_FILE_LOCK_CONFLICT
);
1560 io
.lockx
.in
.ulock_cnt
= 1;
1561 io
.lockx
.in
.lock_cnt
= 0;
1562 io
.lockx
.in
.file
.fnum
= fnum1
;
1563 io
.lockx
.in
.locks
= &lock1
;
1564 status
= smb_raw_lock(cli
->tree
, &io
);
1565 CHECK_STATUS(status
, NT_STATUS_OK
);
1567 /* test - can we take a shared lock? */
1568 io
.lockx
.in
.ulock_cnt
= 0;
1569 io
.lockx
.in
.lock_cnt
= 1;
1570 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1571 io
.lockx
.in
.file
.fnum
= fnum2
;
1572 io
.lockx
.in
.locks
= &lock2
;
1573 status
= smb_raw_lock(cli
->tree
, &io
);
1575 /* XXX Samba will fail this test. This is temporary(because this isn't
1576 * new to Win7, it succeeds in WinXP too), until I can come to a
1577 * resolution as to whether Samba should support this or not. There is
1578 * code to preference unlocking exclusive locks before shared locks,
1579 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1580 if (TARGET_IS_WIN7(tctx
)) {
1581 CHECK_STATUS(status
, NT_STATUS_OK
);
1582 } else if (TARGET_IS_SAMBA4(tctx
)) {
1583 CHECK_STATUS(status
, NT_STATUS_OK
);
1585 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1586 NT_STATUS_FILE_LOCK_CONFLICT
);
1590 io
.lockx
.in
.ulock_cnt
= 1;
1591 io
.lockx
.in
.lock_cnt
= 0;
1592 status
= smb_raw_lock(cli
->tree
, &io
);
1594 /* XXX Same as above. */
1595 if (TARGET_IS_WIN7(tctx
)) {
1596 CHECK_STATUS(status
, NT_STATUS_OK
);
1597 } else if (TARGET_IS_SAMBA4(tctx
)) {
1598 CHECK_STATUS(status
, NT_STATUS_OK
);
1600 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1603 io
.lockx
.in
.file
.fnum
= fnum1
;
1604 io
.lockx
.in
.locks
= &lock1
;
1605 status
= smb_raw_lock(cli
->tree
, &io
);
1606 CHECK_STATUS(status
, NT_STATUS_OK
);
1609 smbcli_close(cli
->tree
, fnum1
);
1610 smbcli_close(cli
->tree
, fnum2
);
1611 smb_raw_exit(cli
->session
);
1612 smbcli_deltree(cli
->tree
, BASEDIR
);
1616 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1622 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1623 struct smb_lock_entry lock1
;
1624 struct smb_lock_entry lock2
;
1625 struct smb_lock_entry locks
[2];
1627 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1629 if (!torture_setup_dir(cli
, BASEDIR
)) {
1633 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1634 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1635 "Failed to create %s - %s\n",
1636 fname
, smbcli_errstr(cli
->tree
)));
1638 /* Setup initial parameters */
1639 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1640 io
.lockx
.in
.timeout
= 0;
1642 lock1
.pid
= cli
->session
->pid
;
1645 lock2
.pid
= cli
->session
->pid
;
1652 io
.lockx
.in
.file
.fnum
= fnum1
;
1653 io
.lockx
.in
.mode
= 0; /* exclusive */
1655 /** Test1: Take second lock, but not first. */
1656 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
1659 io
.lockx
.in
.ulock_cnt
= 0;
1660 io
.lockx
.in
.lock_cnt
= 1;
1661 io
.lockx
.in
.locks
= &lock2
;
1662 status
= smb_raw_lock(cli
->tree
, &io
);
1663 CHECK_STATUS(status
, NT_STATUS_OK
);
1665 /* Try to unlock both locks. */
1666 io
.lockx
.in
.ulock_cnt
= 2;
1667 io
.lockx
.in
.lock_cnt
= 0;
1668 io
.lockx
.in
.locks
= locks
;
1670 status
= smb_raw_lock(cli
->tree
, &io
);
1671 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1673 /* Second lock should not be unlocked. */
1674 io
.lockx
.in
.ulock_cnt
= 0;
1675 io
.lockx
.in
.lock_cnt
= 1;
1676 io
.lockx
.in
.locks
= &lock2
;
1677 status
= smb_raw_lock(cli
->tree
, &io
);
1678 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1681 io
.lockx
.in
.ulock_cnt
= 1;
1682 io
.lockx
.in
.lock_cnt
= 0;
1683 io
.lockx
.in
.locks
= &lock2
;
1684 status
= smb_raw_lock(cli
->tree
, &io
);
1685 CHECK_STATUS(status
, NT_STATUS_OK
);
1687 /** Test2: Take first lock, but not second. */
1688 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
1691 io
.lockx
.in
.ulock_cnt
= 0;
1692 io
.lockx
.in
.lock_cnt
= 1;
1693 io
.lockx
.in
.locks
= &lock1
;
1694 status
= smb_raw_lock(cli
->tree
, &io
);
1695 CHECK_STATUS(status
, NT_STATUS_OK
);
1697 /* Try to unlock both locks. */
1698 io
.lockx
.in
.ulock_cnt
= 2;
1699 io
.lockx
.in
.lock_cnt
= 0;
1700 io
.lockx
.in
.locks
= locks
;
1702 status
= smb_raw_lock(cli
->tree
, &io
);
1703 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1705 /* First lock should be unlocked. */
1706 io
.lockx
.in
.ulock_cnt
= 0;
1707 io
.lockx
.in
.lock_cnt
= 1;
1708 io
.lockx
.in
.locks
= &lock1
;
1709 status
= smb_raw_lock(cli
->tree
, &io
);
1710 CHECK_STATUS(status
, NT_STATUS_OK
);
1713 io
.lockx
.in
.ulock_cnt
= 1;
1714 io
.lockx
.in
.lock_cnt
= 0;
1715 io
.lockx
.in
.locks
= &lock1
;
1716 status
= smb_raw_lock(cli
->tree
, &io
);
1717 CHECK_STATUS(status
, NT_STATUS_OK
);
1720 smbcli_close(cli
->tree
, fnum1
);
1721 smb_raw_exit(cli
->session
);
1722 smbcli_deltree(cli
->tree
, BASEDIR
);
1727 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1728 * - stacking an exclusive on top of shared fails
1729 * - stacking two exclusives fail
1731 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1737 const char *fname
= BASEDIR
"\\stacking.txt";
1738 struct smb_lock_entry lock1
;
1739 struct smb_lock_entry lock2
;
1741 torture_comment(tctx
, "Testing stacking:\n");
1743 if (!torture_setup_dir(cli
, BASEDIR
)) {
1747 io
.generic
.level
= RAW_LOCK_LOCKX
;
1749 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1750 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1751 "Failed to create %s - %s\n",
1752 fname
, smbcli_errstr(cli
->tree
)));
1754 /* Setup initial parameters */
1755 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1756 io
.lockx
.in
.timeout
= 0;
1758 lock1
.pid
= cli
->session
->pid
;
1761 lock2
.pid
= cli
->session
->pid
- 1;
1766 * Try to take a shared lock, then stack an exclusive.
1768 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
1769 io
.lockx
.in
.file
.fnum
= fnum1
;
1770 io
.lockx
.in
.locks
= &lock1
;
1772 io
.lockx
.in
.ulock_cnt
= 0;
1773 io
.lockx
.in
.lock_cnt
= 1;
1774 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1775 status
= smb_raw_lock(cli
->tree
, &io
);
1776 CHECK_STATUS(status
, NT_STATUS_OK
);
1778 io
.lockx
.in
.ulock_cnt
= 0;
1779 io
.lockx
.in
.lock_cnt
= 1;
1780 io
.lockx
.in
.mode
= 0;
1781 status
= smb_raw_lock(cli
->tree
, &io
);
1782 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1783 NT_STATUS_FILE_LOCK_CONFLICT
);
1786 io
.lockx
.in
.ulock_cnt
= 1;
1787 io
.lockx
.in
.lock_cnt
= 0;
1788 status
= smb_raw_lock(cli
->tree
, &io
);
1789 CHECK_STATUS(status
, NT_STATUS_OK
);
1792 * Prove that two exclusive locks do not stack.
1794 torture_comment(tctx
, " two exclusive locks do not stack.\n");
1795 io
.lockx
.in
.ulock_cnt
= 0;
1796 io
.lockx
.in
.lock_cnt
= 1;
1797 io
.lockx
.in
.mode
= 0;
1798 status
= smb_raw_lock(cli
->tree
, &io
);
1799 CHECK_STATUS(status
, NT_STATUS_OK
);
1800 status
= smb_raw_lock(cli
->tree
, &io
);
1801 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1802 NT_STATUS_FILE_LOCK_CONFLICT
);
1805 io
.lockx
.in
.ulock_cnt
= 1;
1806 io
.lockx
.in
.lock_cnt
= 0;
1807 status
= smb_raw_lock(cli
->tree
, &io
);
1808 CHECK_STATUS(status
, NT_STATUS_OK
);
1811 smbcli_close(cli
->tree
, fnum1
);
1812 smb_raw_exit(cli
->session
);
1813 smbcli_deltree(cli
->tree
, BASEDIR
);
1818 basic testing of lock calls
1820 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
1822 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "LOCK");
1824 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
1825 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
1826 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
1827 torture_suite_add_1smb_test(suite
, "async", test_async
);
1828 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
1829 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
1831 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
1832 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
1833 torture_suite_add_1smb_test(suite
, "multiple_unlock",
1834 test_multiple_unlock
);
1835 torture_suite_add_1smb_test(suite
, "zerobytelocks",
1836 test_zerobytelocks
);