2 Unix SMB/CIFS implementation.
3 test suite for various lock operations
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/raw/raw_proto.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
28 #include "libcli/composite/composite.h"
29 #include "libcli/smb_composite/smb_composite.h"
30 #include "lib/cmdline/popt_common.h"
31 #include "param/param.h"
33 #define CHECK_STATUS(status, correct) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 torture_result(tctx, TORTURE_FAIL, \
36 "(%s) Incorrect status %s - should be %s\n", \
37 __location__, nt_errstr(status), nt_errstr(correct)); \
42 #define CHECK_STATUS_CONT(status, correct) do { \
43 if (!NT_STATUS_EQUAL(status, correct)) { \
44 torture_result(tctx, TORTURE_FAIL, \
45 "(%s) Incorrect status %s - should be %s\n", \
46 __location__, nt_errstr(status), nt_errstr(correct)); \
50 #define CHECK_STATUS_OR(status, correct1, correct2) do { \
51 if ((!NT_STATUS_EQUAL(status, correct1)) && \
52 (!NT_STATUS_EQUAL(status, correct2))) { \
53 torture_result(tctx, TORTURE_FAIL, \
54 "(%s) Incorrect status %s - should be %s or %s\n", \
55 __location__, nt_errstr(status), nt_errstr(correct1), \
56 nt_errstr(correct2)); \
61 #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
62 if ((!NT_STATUS_EQUAL(status, correct1)) && \
63 (!NT_STATUS_EQUAL(status, correct2))) { \
64 torture_result(tctx, TORTURE_FAIL, \
65 "(%s) Incorrect status %s - should be %s or %s\n", \
66 __location__, nt_errstr(status), nt_errstr(correct1), \
67 nt_errstr(correct2)); \
70 #define BASEDIR "\\testlock"
72 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
73 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
74 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
77 test SMBlock and SMBunlock ops
79 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
85 const char *fname
= BASEDIR
"\\test.txt";
87 if (!torture_setup_dir(cli
, BASEDIR
)) {
91 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
92 io
.generic
.level
= RAW_LOCK_LOCK
;
94 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
95 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
96 "Failed to create %s - %s\n",
97 fname
, smbcli_errstr(cli
->tree
)));
99 torture_comment(tctx
, "Trying 0/0 lock\n");
100 io
.lock
.level
= RAW_LOCK_LOCK
;
101 io
.lock
.in
.file
.fnum
= fnum
;
102 io
.lock
.in
.count
= 0;
103 io
.lock
.in
.offset
= 0;
104 status
= smb_raw_lock(cli
->tree
, &io
);
105 CHECK_STATUS(status
, NT_STATUS_OK
);
107 status
= smb_raw_lock(cli
->tree
, &io
);
108 CHECK_STATUS(status
, NT_STATUS_OK
);
110 io
.lock
.level
= RAW_LOCK_UNLOCK
;
111 status
= smb_raw_lock(cli
->tree
, &io
);
112 CHECK_STATUS(status
, NT_STATUS_OK
);
114 torture_comment(tctx
, "Trying 0/1 lock\n");
115 io
.lock
.level
= RAW_LOCK_LOCK
;
116 io
.lock
.in
.file
.fnum
= fnum
;
117 io
.lock
.in
.count
= 1;
118 io
.lock
.in
.offset
= 0;
119 status
= smb_raw_lock(cli
->tree
, &io
);
120 CHECK_STATUS(status
, NT_STATUS_OK
);
122 status
= smb_raw_lock(cli
->tree
, &io
);
123 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
125 io
.lock
.level
= RAW_LOCK_UNLOCK
;
126 status
= smb_raw_lock(cli
->tree
, &io
);
127 CHECK_STATUS(status
, NT_STATUS_OK
);
128 io
.lock
.level
= RAW_LOCK_UNLOCK
;
129 status
= smb_raw_lock(cli
->tree
, &io
);
130 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
132 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
133 io
.lock
.level
= RAW_LOCK_LOCK
;
134 io
.lock
.in
.file
.fnum
= fnum
;
135 io
.lock
.in
.count
= 4000;
136 io
.lock
.in
.offset
= 0xEEFFFFFF;
137 status
= smb_raw_lock(cli
->tree
, &io
);
138 CHECK_STATUS(status
, NT_STATUS_OK
);
140 status
= smb_raw_lock(cli
->tree
, &io
);
141 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
143 io
.lock
.level
= RAW_LOCK_UNLOCK
;
144 status
= smb_raw_lock(cli
->tree
, &io
);
145 CHECK_STATUS(status
, NT_STATUS_OK
);
146 io
.lock
.level
= RAW_LOCK_UNLOCK
;
147 status
= smb_raw_lock(cli
->tree
, &io
);
148 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
150 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
151 io
.lock
.level
= RAW_LOCK_LOCK
;
152 io
.lock
.in
.file
.fnum
= fnum
;
153 io
.lock
.in
.count
= 4000;
154 io
.lock
.in
.offset
= 0xEEFFFFFF;
155 status
= smb_raw_lock(cli
->tree
, &io
);
156 CHECK_STATUS(status
, NT_STATUS_OK
);
158 status
= smb_raw_lock(cli
->tree
, &io
);
159 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
161 io
.lock
.level
= RAW_LOCK_UNLOCK
;
162 status
= smb_raw_lock(cli
->tree
, &io
);
163 CHECK_STATUS(status
, NT_STATUS_OK
);
164 io
.lock
.level
= RAW_LOCK_UNLOCK
;
165 status
= smb_raw_lock(cli
->tree
, &io
);
166 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
168 torture_comment(tctx
, "Trying max lock\n");
169 io
.lock
.level
= RAW_LOCK_LOCK
;
170 io
.lock
.in
.file
.fnum
= fnum
;
171 io
.lock
.in
.count
= 4000;
172 io
.lock
.in
.offset
= 0xEF000000;
173 status
= smb_raw_lock(cli
->tree
, &io
);
174 CHECK_STATUS(status
, NT_STATUS_OK
);
176 status
= smb_raw_lock(cli
->tree
, &io
);
177 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
179 io
.lock
.level
= RAW_LOCK_UNLOCK
;
180 status
= smb_raw_lock(cli
->tree
, &io
);
181 CHECK_STATUS(status
, NT_STATUS_OK
);
182 io
.lock
.level
= RAW_LOCK_UNLOCK
;
183 status
= smb_raw_lock(cli
->tree
, &io
);
184 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
186 torture_comment(tctx
, "Trying wrong pid unlock\n");
187 io
.lock
.level
= RAW_LOCK_LOCK
;
188 io
.lock
.in
.file
.fnum
= fnum
;
189 io
.lock
.in
.count
= 4002;
190 io
.lock
.in
.offset
= 10001;
191 status
= smb_raw_lock(cli
->tree
, &io
);
192 CHECK_STATUS(status
, NT_STATUS_OK
);
194 io
.lock
.level
= RAW_LOCK_UNLOCK
;
195 status
= smb_raw_lock(cli
->tree
, &io
);
196 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
198 status
= smb_raw_lock(cli
->tree
, &io
);
199 CHECK_STATUS(status
, NT_STATUS_OK
);
202 smbcli_close(cli
->tree
, fnum
);
203 smb_raw_exit(cli
->session
);
204 smbcli_deltree(cli
->tree
, BASEDIR
);
212 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
215 struct smb_lock_entry lock
[1];
219 const char *fname
= BASEDIR
"\\test.txt";
221 if (!torture_setup_dir(cli
, BASEDIR
)) {
225 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
226 io
.generic
.level
= RAW_LOCK_LOCKX
;
228 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
229 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
230 "Failed to create %s - %s\n",
231 fname
, smbcli_errstr(cli
->tree
)));
233 io
.lockx
.level
= RAW_LOCK_LOCKX
;
234 io
.lockx
.in
.file
.fnum
= fnum
;
235 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
236 io
.lockx
.in
.timeout
= 0;
237 io
.lockx
.in
.ulock_cnt
= 0;
238 io
.lockx
.in
.lock_cnt
= 1;
239 lock
[0].pid
= cli
->session
->pid
;
242 io
.lockx
.in
.locks
= &lock
[0];
243 status
= smb_raw_lock(cli
->tree
, &io
);
244 CHECK_STATUS(status
, NT_STATUS_OK
);
247 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
248 io
.lockx
.in
.ulock_cnt
= 0;
249 io
.lockx
.in
.lock_cnt
= 1;
250 lock
[0].count
= 4000;
251 lock
[0].offset
= 0xEEFFFFFF;
252 status
= smb_raw_lock(cli
->tree
, &io
);
253 CHECK_STATUS(status
, NT_STATUS_OK
);
255 status
= smb_raw_lock(cli
->tree
, &io
);
256 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
258 io
.lockx
.in
.ulock_cnt
= 1;
259 io
.lockx
.in
.lock_cnt
= 0;
260 status
= smb_raw_lock(cli
->tree
, &io
);
261 CHECK_STATUS(status
, NT_STATUS_OK
);
262 status
= smb_raw_lock(cli
->tree
, &io
);
263 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
265 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
266 io
.lockx
.in
.ulock_cnt
= 0;
267 io
.lockx
.in
.lock_cnt
= 1;
268 lock
[0].count
= 4000;
269 lock
[0].offset
= 0xEF000000;
270 status
= smb_raw_lock(cli
->tree
, &io
);
271 CHECK_STATUS(status
, NT_STATUS_OK
);
273 status
= smb_raw_lock(cli
->tree
, &io
);
274 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
276 io
.lockx
.in
.ulock_cnt
= 1;
277 io
.lockx
.in
.lock_cnt
= 0;
278 status
= smb_raw_lock(cli
->tree
, &io
);
279 CHECK_STATUS(status
, NT_STATUS_OK
);
280 status
= smb_raw_lock(cli
->tree
, &io
);
281 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
283 torture_comment(tctx
, "Trying zero lock\n");
284 io
.lockx
.in
.ulock_cnt
= 0;
285 io
.lockx
.in
.lock_cnt
= 1;
288 status
= smb_raw_lock(cli
->tree
, &io
);
289 CHECK_STATUS(status
, NT_STATUS_OK
);
291 status
= smb_raw_lock(cli
->tree
, &io
);
292 CHECK_STATUS(status
, NT_STATUS_OK
);
294 io
.lockx
.in
.ulock_cnt
= 1;
295 io
.lockx
.in
.lock_cnt
= 0;
296 status
= smb_raw_lock(cli
->tree
, &io
);
297 CHECK_STATUS(status
, NT_STATUS_OK
);
298 status
= smb_raw_lock(cli
->tree
, &io
);
299 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
301 torture_comment(tctx
, "Trying max lock\n");
302 io
.lockx
.in
.ulock_cnt
= 0;
303 io
.lockx
.in
.lock_cnt
= 1;
306 status
= smb_raw_lock(cli
->tree
, &io
);
307 CHECK_STATUS(status
, NT_STATUS_OK
);
309 status
= smb_raw_lock(cli
->tree
, &io
);
310 CHECK_STATUS(status
, NT_STATUS_OK
);
312 io
.lockx
.in
.ulock_cnt
= 1;
313 io
.lockx
.in
.lock_cnt
= 0;
314 status
= smb_raw_lock(cli
->tree
, &io
);
315 CHECK_STATUS(status
, NT_STATUS_OK
);
316 status
= smb_raw_lock(cli
->tree
, &io
);
317 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
319 torture_comment(tctx
, "Trying 2^63\n");
320 io
.lockx
.in
.ulock_cnt
= 0;
321 io
.lockx
.in
.lock_cnt
= 1;
324 lock
[0].offset
<<= 63;
325 status
= smb_raw_lock(cli
->tree
, &io
);
326 CHECK_STATUS(status
, NT_STATUS_OK
);
328 status
= smb_raw_lock(cli
->tree
, &io
);
329 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
331 io
.lockx
.in
.ulock_cnt
= 1;
332 io
.lockx
.in
.lock_cnt
= 0;
333 status
= smb_raw_lock(cli
->tree
, &io
);
334 CHECK_STATUS(status
, NT_STATUS_OK
);
335 status
= smb_raw_lock(cli
->tree
, &io
);
336 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
338 torture_comment(tctx
, "Trying 2^63 - 1\n");
339 io
.lockx
.in
.ulock_cnt
= 0;
340 io
.lockx
.in
.lock_cnt
= 1;
343 lock
[0].offset
<<= 63;
345 status
= smb_raw_lock(cli
->tree
, &io
);
346 CHECK_STATUS(status
, NT_STATUS_OK
);
348 status
= smb_raw_lock(cli
->tree
, &io
);
349 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
351 io
.lockx
.in
.ulock_cnt
= 1;
352 io
.lockx
.in
.lock_cnt
= 0;
353 status
= smb_raw_lock(cli
->tree
, &io
);
354 CHECK_STATUS(status
, NT_STATUS_OK
);
355 status
= smb_raw_lock(cli
->tree
, &io
);
356 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
358 torture_comment(tctx
, "Trying max lock 2\n");
359 io
.lockx
.in
.ulock_cnt
= 0;
360 io
.lockx
.in
.lock_cnt
= 1;
363 status
= smb_raw_lock(cli
->tree
, &io
);
364 CHECK_STATUS(status
, NT_STATUS_OK
);
367 status
= smb_raw_lock(cli
->tree
, &io
);
368 if (TARGET_IS_WIN7(tctx
))
369 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
371 CHECK_STATUS(status
, NT_STATUS_OK
);
373 io
.lockx
.in
.ulock_cnt
= 1;
374 io
.lockx
.in
.lock_cnt
= 0;
376 status
= smb_raw_lock(cli
->tree
, &io
);
378 CHECK_STATUS(status
, NT_STATUS_OK
);
379 status
= smb_raw_lock(cli
->tree
, &io
);
380 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
383 smbcli_close(cli
->tree
, fnum
);
384 smb_raw_exit(cli
->session
);
385 smbcli_deltree(cli
->tree
, BASEDIR
);
392 static bool test_pidhigh(struct torture_context
*tctx
,
393 struct smbcli_state
*cli
)
396 struct smb_lock_entry lock
[1];
400 const char *fname
= BASEDIR
"\\test.txt";
403 if (!torture_setup_dir(cli
, BASEDIR
)) {
407 torture_comment(tctx
, "Testing high pid\n");
408 io
.generic
.level
= RAW_LOCK_LOCKX
;
410 cli
->session
->pid
= 1;
412 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
413 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
414 "Failed to create %s - %s\n",
415 fname
, smbcli_errstr(cli
->tree
)));
417 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
418 torture_result(tctx
, TORTURE_FAIL
,
419 "Failed to write 1 byte - %s\n",
420 smbcli_errstr(cli
->tree
));
425 io
.lockx
.level
= RAW_LOCK_LOCKX
;
426 io
.lockx
.in
.file
.fnum
= fnum
;
427 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
428 io
.lockx
.in
.timeout
= 0;
429 io
.lockx
.in
.ulock_cnt
= 0;
430 io
.lockx
.in
.lock_cnt
= 1;
431 lock
[0].pid
= cli
->session
->pid
;
433 lock
[0].count
= 0xFFFFFFFF;
434 io
.lockx
.in
.locks
= &lock
[0];
435 status
= smb_raw_lock(cli
->tree
, &io
);
436 CHECK_STATUS(status
, NT_STATUS_OK
);
438 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
439 torture_result(tctx
, TORTURE_FAIL
,
440 "Failed to read 1 byte - %s\n",
441 smbcli_errstr(cli
->tree
));
446 cli
->session
->pid
= 2;
448 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
449 torture_result(tctx
, TORTURE_FAIL
,
450 "pid is incorrect handled for read with lock!\n");
455 cli
->session
->pid
= 0x10001;
457 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
458 torture_result(tctx
, TORTURE_FAIL
,
459 "High pid is used on this server!\n");
462 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
466 smbcli_close(cli
->tree
, fnum
);
467 smb_raw_exit(cli
->session
);
468 smbcli_deltree(cli
->tree
, BASEDIR
);
474 test locking&X async operation
476 static bool test_async(struct torture_context
*tctx
,
477 struct smbcli_state
*cli
)
479 struct smbcli_session
*session
;
480 struct smb_composite_sesssetup setup
;
481 struct smbcli_tree
*tree
;
483 const char *host
, *share
;
485 struct smb_lock_entry lock
[2];
489 const char *fname
= BASEDIR
"\\test.txt";
491 struct smbcli_request
*req
;
492 struct smbcli_session_options options
;
494 if (!torture_setup_dir(cli
, BASEDIR
)) {
498 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
500 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
501 io
.generic
.level
= RAW_LOCK_LOCKX
;
503 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
504 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
505 "Failed to create %s - %s\n",
506 fname
, smbcli_errstr(cli
->tree
)));
508 io
.lockx
.level
= RAW_LOCK_LOCKX
;
509 io
.lockx
.in
.file
.fnum
= fnum
;
510 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
511 io
.lockx
.in
.timeout
= 0;
512 io
.lockx
.in
.ulock_cnt
= 0;
513 io
.lockx
.in
.lock_cnt
= 1;
514 lock
[0].pid
= cli
->session
->pid
;
515 lock
[0].offset
= 100;
517 io
.lockx
.in
.locks
= &lock
[0];
518 status
= smb_raw_lock(cli
->tree
, &io
);
519 CHECK_STATUS(status
, NT_STATUS_OK
);
523 torture_comment(tctx
, "testing cancel by CANCEL_LOCK\n");
525 /* setup a timed lock */
526 io
.lockx
.in
.timeout
= 10000;
527 req
= smb_raw_lock_send(cli
->tree
, &io
);
528 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
529 "Failed to setup timed lock (%s)\n", __location__
));
531 /* cancel the wrong range */
533 io
.lockx
.in
.timeout
= 0;
534 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
535 status
= smb_raw_lock(cli
->tree
, &io
);
536 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
538 /* cancel with the wrong bits set */
539 lock
[0].offset
= 100;
540 io
.lockx
.in
.timeout
= 0;
541 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
542 status
= smb_raw_lock(cli
->tree
, &io
);
543 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
545 /* cancel the right range */
546 lock
[0].offset
= 100;
547 io
.lockx
.in
.timeout
= 0;
548 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
549 status
= smb_raw_lock(cli
->tree
, &io
);
550 CHECK_STATUS(status
, NT_STATUS_OK
);
552 /* receive the failed lock request */
553 status
= smbcli_request_simple_recv(req
);
554 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
556 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
557 "lock cancel was not immediate (%s)\n", __location__
));
559 torture_comment(tctx
, "testing cancel by unlock\n");
560 io
.lockx
.in
.ulock_cnt
= 0;
561 io
.lockx
.in
.lock_cnt
= 1;
562 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
563 io
.lockx
.in
.timeout
= 0;
564 status
= smb_raw_lock(cli
->tree
, &io
);
565 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
567 io
.lockx
.in
.timeout
= 5000;
568 req
= smb_raw_lock_send(cli
->tree
, &io
);
569 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
570 "Failed to setup timed lock (%s)\n", __location__
));
572 io
.lockx
.in
.ulock_cnt
= 1;
573 io
.lockx
.in
.lock_cnt
= 0;
574 status
= smb_raw_lock(cli
->tree
, &io
);
575 CHECK_STATUS(status
, NT_STATUS_OK
);
578 status
= smbcli_request_simple_recv(req
);
579 CHECK_STATUS(status
, NT_STATUS_OK
);
581 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
582 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
583 __location__
, (int)(time(NULL
)-t
)));
585 torture_comment(tctx
, "testing cancel by close\n");
586 io
.lockx
.in
.ulock_cnt
= 0;
587 io
.lockx
.in
.lock_cnt
= 1;
588 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
589 io
.lockx
.in
.timeout
= 0;
590 status
= smb_raw_lock(cli
->tree
, &io
);
591 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
594 io
.lockx
.in
.timeout
= 10000;
595 req
= smb_raw_lock_send(cli
->tree
, &io
);
596 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
597 "Failed to setup timed lock (%s)\n", __location__
));
599 status
= smbcli_close(cli
->tree
, fnum
);
600 CHECK_STATUS(status
, NT_STATUS_OK
);
602 status
= smbcli_request_simple_recv(req
);
603 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
605 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
606 "lock cancel by close was not immediate (%s)\n", __location__
));
608 torture_comment(tctx
, "create a new sessions\n");
609 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
610 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
611 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
612 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
613 setup
.in
.credentials
= cmdline_credentials
;
614 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
615 status
= smb_composite_sesssetup(session
, &setup
);
616 CHECK_STATUS(status
, NT_STATUS_OK
);
617 session
->vuid
= setup
.out
.vuid
;
619 torture_comment(tctx
, "create new tree context\n");
620 share
= torture_setting_string(tctx
, "share", NULL
);
621 host
= torture_setting_string(tctx
, "host", NULL
);
622 tree
= smbcli_tree_init(session
, tctx
, false);
623 tcon
.generic
.level
= RAW_TCON_TCONX
;
624 tcon
.tconx
.in
.flags
= 0;
625 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
626 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
627 tcon
.tconx
.in
.device
= "A:";
628 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
629 CHECK_STATUS(status
, NT_STATUS_OK
);
630 tree
->tid
= tcon
.tconx
.out
.tid
;
632 torture_comment(tctx
, "testing cancel by exit\n");
633 fname
= BASEDIR
"\\test_exit.txt";
634 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
635 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
636 "Failed to reopen %s - %s\n",
637 fname
, smbcli_errstr(tree
)));
639 io
.lockx
.level
= RAW_LOCK_LOCKX
;
640 io
.lockx
.in
.file
.fnum
= fnum
;
641 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
642 io
.lockx
.in
.timeout
= 0;
643 io
.lockx
.in
.ulock_cnt
= 0;
644 io
.lockx
.in
.lock_cnt
= 1;
645 lock
[0].pid
= session
->pid
;
646 lock
[0].offset
= 100;
648 io
.lockx
.in
.locks
= &lock
[0];
649 status
= smb_raw_lock(tree
, &io
);
650 CHECK_STATUS(status
, NT_STATUS_OK
);
652 io
.lockx
.in
.ulock_cnt
= 0;
653 io
.lockx
.in
.lock_cnt
= 1;
654 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
655 io
.lockx
.in
.timeout
= 0;
656 status
= smb_raw_lock(tree
, &io
);
657 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
659 io
.lockx
.in
.timeout
= 10000;
661 req
= smb_raw_lock_send(tree
, &io
);
662 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
663 "Failed to setup timed lock (%s)\n", __location__
));
665 status
= smb_raw_exit(session
);
666 CHECK_STATUS(status
, NT_STATUS_OK
);
668 status
= smbcli_request_simple_recv(req
);
669 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
671 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
672 "lock cancel by exit was not immediate (%s)\n", __location__
));
674 torture_comment(tctx
, "testing cancel by ulogoff\n");
675 fname
= BASEDIR
"\\test_ulogoff.txt";
676 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
677 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
678 "Failed to reopen %s - %s\n",
679 fname
, smbcli_errstr(tree
)));
681 io
.lockx
.level
= RAW_LOCK_LOCKX
;
682 io
.lockx
.in
.file
.fnum
= fnum
;
683 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
684 io
.lockx
.in
.timeout
= 0;
685 io
.lockx
.in
.ulock_cnt
= 0;
686 io
.lockx
.in
.lock_cnt
= 1;
687 lock
[0].pid
= session
->pid
;
688 lock
[0].offset
= 100;
690 io
.lockx
.in
.locks
= &lock
[0];
691 status
= smb_raw_lock(tree
, &io
);
692 CHECK_STATUS(status
, NT_STATUS_OK
);
694 io
.lockx
.in
.ulock_cnt
= 0;
695 io
.lockx
.in
.lock_cnt
= 1;
696 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
697 io
.lockx
.in
.timeout
= 0;
698 status
= smb_raw_lock(tree
, &io
);
699 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
701 io
.lockx
.in
.timeout
= 10000;
703 req
= smb_raw_lock_send(tree
, &io
);
704 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
705 "Failed to setup timed lock (%s)\n", __location__
));
707 status
= smb_raw_ulogoff(session
);
708 CHECK_STATUS(status
, NT_STATUS_OK
);
710 status
= smbcli_request_simple_recv(req
);
711 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
712 torture_result(tctx
, TORTURE_FAIL
,
713 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
715 smb_tree_disconnect(tree
);
716 smb_raw_exit(session
);
719 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
721 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
722 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
724 torture_comment(tctx
, "testing cancel by tdis\n");
725 tree
->session
= cli
->session
;
727 fname
= BASEDIR
"\\test_tdis.txt";
728 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
729 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
730 "Failed to reopen %s - %s\n",
731 fname
, smbcli_errstr(tree
)));
733 io
.lockx
.level
= RAW_LOCK_LOCKX
;
734 io
.lockx
.in
.file
.fnum
= fnum
;
735 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
736 io
.lockx
.in
.timeout
= 0;
737 io
.lockx
.in
.ulock_cnt
= 0;
738 io
.lockx
.in
.lock_cnt
= 1;
739 lock
[0].pid
= cli
->session
->pid
;
740 lock
[0].offset
= 100;
742 io
.lockx
.in
.locks
= &lock
[0];
743 status
= smb_raw_lock(tree
, &io
);
744 CHECK_STATUS(status
, NT_STATUS_OK
);
746 status
= smb_raw_lock(tree
, &io
);
747 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
749 io
.lockx
.in
.timeout
= 10000;
751 req
= smb_raw_lock_send(tree
, &io
);
752 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
753 "Failed to setup timed lock (%s)\n", __location__
));
755 status
= smb_tree_disconnect(tree
);
756 CHECK_STATUS(status
, NT_STATUS_OK
);
758 status
= smbcli_request_simple_recv(req
);
759 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
761 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
762 "lock cancel by tdis was not immediate (%s)\n", __location__
));
765 smb_raw_exit(cli
->session
);
766 smbcli_deltree(cli
->tree
, BASEDIR
);
771 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
773 static bool test_errorcode(struct torture_context
*tctx
,
774 struct smbcli_state
*cli
)
778 struct smb_lock_entry lock
[2];
783 struct smbcli_request
*req
;
788 if (!torture_setup_dir(cli
, BASEDIR
)) {
792 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
794 torture_comment(tctx
, "testing with timeout = 0\n");
795 fname
= BASEDIR
"\\test0.txt";
799 * the first run is with t = 0,
800 * the second with t > 0 (=1)
804 * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
805 * this demonstrates that the cache is per fnum
807 op
.openx
.level
= RAW_OPEN_OPENX
;
808 op
.openx
.in
.fname
= fname
;
809 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
810 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| OPENX_MODE_DENY_DOS
;
811 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
812 op
.openx
.in
.search_attrs
= 0;
813 op
.openx
.in
.file_attrs
= 0;
814 op
.openx
.in
.write_time
= 0;
815 op
.openx
.in
.size
= 0;
816 op
.openx
.in
.timeout
= 0;
818 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
819 CHECK_STATUS(status
, NT_STATUS_OK
);
820 fnum
= op
.openx
.out
.file
.fnum
;
822 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
823 CHECK_STATUS(status
, NT_STATUS_OK
);
824 fnum2
= op
.openx
.out
.file
.fnum
;
826 io
.lockx
.level
= RAW_LOCK_LOCKX
;
827 io
.lockx
.in
.file
.fnum
= fnum
;
828 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
829 io
.lockx
.in
.timeout
= t
;
830 io
.lockx
.in
.ulock_cnt
= 0;
831 io
.lockx
.in
.lock_cnt
= 1;
832 lock
[0].pid
= cli
->session
->pid
;
833 lock
[0].offset
= 100;
835 io
.lockx
.in
.locks
= &lock
[0];
836 status
= smb_raw_lock(cli
->tree
, &io
);
837 CHECK_STATUS(status
, NT_STATUS_OK
);
840 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
841 * this also demonstrates that the error code cache is per file handle
842 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
844 io
.lockx
.in
.file
.fnum
= fnum2
;
845 status
= smb_raw_lock(cli
->tree
, &io
);
846 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
848 io
.lockx
.in
.file
.fnum
= fnum
;
849 status
= smb_raw_lock(cli
->tree
, &io
);
850 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
852 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
853 io
.lockx
.in
.file
.fnum
= fnum
;
854 status
= smb_raw_lock(cli
->tree
, &io
);
855 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
857 io
.lockx
.in
.file
.fnum
= fnum2
;
858 status
= smb_raw_lock(cli
->tree
, &io
);
859 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
861 io
.lockx
.in
.file
.fnum
= fnum
;
862 status
= smb_raw_lock(cli
->tree
, &io
);
863 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
865 io
.lockx
.in
.file
.fnum
= fnum2
;
866 status
= smb_raw_lock(cli
->tree
, &io
);
867 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
869 /* demonstrate that the smbpid doesn't matter */
871 io
.lockx
.in
.file
.fnum
= fnum
;
872 status
= smb_raw_lock(cli
->tree
, &io
);
873 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
875 io
.lockx
.in
.file
.fnum
= fnum2
;
876 status
= smb_raw_lock(cli
->tree
, &io
);
877 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
881 * demonstrate the a successful lock with count = 0 and the same offset,
882 * doesn't reset the error cache
884 lock
[0].offset
= 100;
886 io
.lockx
.in
.file
.fnum
= fnum
;
887 status
= smb_raw_lock(cli
->tree
, &io
);
888 CHECK_STATUS(status
, NT_STATUS_OK
);
890 io
.lockx
.in
.file
.fnum
= fnum2
;
891 status
= smb_raw_lock(cli
->tree
, &io
);
892 CHECK_STATUS(status
, NT_STATUS_OK
);
894 lock
[0].offset
= 100;
896 io
.lockx
.in
.file
.fnum
= fnum
;
897 status
= smb_raw_lock(cli
->tree
, &io
);
898 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
900 io
.lockx
.in
.file
.fnum
= fnum2
;
901 status
= smb_raw_lock(cli
->tree
, &io
);
902 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
905 * demonstrate the a successful lock with count = 0 and outside the locked range,
906 * doesn't reset the error cache
908 lock
[0].offset
= 110;
910 io
.lockx
.in
.file
.fnum
= fnum
;
911 status
= smb_raw_lock(cli
->tree
, &io
);
912 CHECK_STATUS(status
, NT_STATUS_OK
);
914 io
.lockx
.in
.file
.fnum
= fnum2
;
915 status
= smb_raw_lock(cli
->tree
, &io
);
916 CHECK_STATUS(status
, NT_STATUS_OK
);
918 lock
[0].offset
= 100;
920 io
.lockx
.in
.file
.fnum
= fnum
;
921 status
= smb_raw_lock(cli
->tree
, &io
);
922 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
924 io
.lockx
.in
.file
.fnum
= fnum2
;
925 status
= smb_raw_lock(cli
->tree
, &io
);
926 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
930 io
.lockx
.in
.file
.fnum
= fnum
;
931 status
= smb_raw_lock(cli
->tree
, &io
);
932 CHECK_STATUS(status
, NT_STATUS_OK
);
934 io
.lockx
.in
.file
.fnum
= fnum2
;
935 status
= smb_raw_lock(cli
->tree
, &io
);
936 CHECK_STATUS(status
, NT_STATUS_OK
);
938 lock
[0].offset
= 100;
940 io
.lockx
.in
.file
.fnum
= fnum
;
941 status
= smb_raw_lock(cli
->tree
, &io
);
942 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
944 io
.lockx
.in
.file
.fnum
= fnum2
;
945 status
= smb_raw_lock(cli
->tree
, &io
);
946 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
948 /* demonstrate that a changing count doesn't reset the error cache */
949 lock
[0].offset
= 100;
951 io
.lockx
.in
.file
.fnum
= fnum
;
952 status
= smb_raw_lock(cli
->tree
, &io
);
953 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
955 io
.lockx
.in
.file
.fnum
= fnum2
;
956 status
= smb_raw_lock(cli
->tree
, &io
);
957 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
959 lock
[0].offset
= 100;
961 io
.lockx
.in
.file
.fnum
= fnum
;
962 status
= smb_raw_lock(cli
->tree
, &io
);
963 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
965 io
.lockx
.in
.file
.fnum
= fnum2
;
966 status
= smb_raw_lock(cli
->tree
, &io
);
967 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
970 * demonstrate the a lock with count = 0 and inside the locked range,
971 * fails and resets the error cache
973 lock
[0].offset
= 101;
975 io
.lockx
.in
.file
.fnum
= fnum
;
976 status
= smb_raw_lock(cli
->tree
, &io
);
977 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
978 status
= smb_raw_lock(cli
->tree
, &io
);
979 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
981 io
.lockx
.in
.file
.fnum
= fnum2
;
982 status
= smb_raw_lock(cli
->tree
, &io
);
983 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
984 status
= smb_raw_lock(cli
->tree
, &io
);
985 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
987 lock
[0].offset
= 100;
989 io
.lockx
.in
.file
.fnum
= fnum
;
990 status
= smb_raw_lock(cli
->tree
, &io
);
991 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
992 status
= smb_raw_lock(cli
->tree
, &io
);
993 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
995 io
.lockx
.in
.file
.fnum
= fnum2
;
996 status
= smb_raw_lock(cli
->tree
, &io
);
997 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
998 status
= smb_raw_lock(cli
->tree
, &io
);
999 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1001 /* demonstrate the a changing offset, resets the error cache */
1002 lock
[0].offset
= 105;
1004 io
.lockx
.in
.file
.fnum
= fnum
;
1005 status
= smb_raw_lock(cli
->tree
, &io
);
1006 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1007 status
= smb_raw_lock(cli
->tree
, &io
);
1008 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1010 io
.lockx
.in
.file
.fnum
= fnum2
;
1011 status
= smb_raw_lock(cli
->tree
, &io
);
1012 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1013 status
= smb_raw_lock(cli
->tree
, &io
);
1014 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1016 lock
[0].offset
= 100;
1018 io
.lockx
.in
.file
.fnum
= fnum
;
1019 status
= smb_raw_lock(cli
->tree
, &io
);
1020 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1021 status
= smb_raw_lock(cli
->tree
, &io
);
1022 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1024 io
.lockx
.in
.file
.fnum
= fnum2
;
1025 status
= smb_raw_lock(cli
->tree
, &io
);
1026 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1027 status
= smb_raw_lock(cli
->tree
, &io
);
1028 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1030 lock
[0].offset
= 95;
1032 io
.lockx
.in
.file
.fnum
= fnum
;
1033 status
= smb_raw_lock(cli
->tree
, &io
);
1034 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1035 status
= smb_raw_lock(cli
->tree
, &io
);
1036 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1038 io
.lockx
.in
.file
.fnum
= fnum2
;
1039 status
= smb_raw_lock(cli
->tree
, &io
);
1040 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1041 status
= smb_raw_lock(cli
->tree
, &io
);
1042 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1044 lock
[0].offset
= 100;
1046 io
.lockx
.in
.file
.fnum
= fnum
;
1047 status
= smb_raw_lock(cli
->tree
, &io
);
1048 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1049 status
= smb_raw_lock(cli
->tree
, &io
);
1050 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1052 io
.lockx
.in
.file
.fnum
= fnum2
;
1053 status
= smb_raw_lock(cli
->tree
, &io
);
1054 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1055 status
= smb_raw_lock(cli
->tree
, &io
);
1056 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1059 * demonstrate the a successful lock in a different range,
1060 * doesn't reset the cache, the failing lock on the 2nd handle
1061 * resets the resets the cache
1063 lock
[0].offset
= 120;
1065 io
.lockx
.in
.file
.fnum
= fnum
;
1066 status
= smb_raw_lock(cli
->tree
, &io
);
1067 CHECK_STATUS(status
, NT_STATUS_OK
);
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
));
1073 lock
[0].offset
= 100;
1075 io
.lockx
.in
.file
.fnum
= fnum
;
1076 status
= smb_raw_lock(cli
->tree
, &io
);
1077 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1078 status
= smb_raw_lock(cli
->tree
, &io
);
1079 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1081 io
.lockx
.in
.file
.fnum
= fnum2
;
1082 status
= smb_raw_lock(cli
->tree
, &io
);
1083 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1084 status
= smb_raw_lock(cli
->tree
, &io
);
1085 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1087 /* end of the loop */
1089 smb_raw_exit(cli
->session
);
1091 torture_comment(tctx
, "testing with timeout > 0 (=%d)\n",
1093 fname
= BASEDIR
"\\test1.txt";
1098 torture_comment(tctx
, "testing special cases with timeout > 0 (=%d)\n",
1102 * the following 3 test sections demonstrate that
1103 * the cache is only set when the error is reported
1104 * to the client (after the timeout went by)
1106 smb_raw_exit(cli
->session
);
1107 torture_comment(tctx
, "testing a conflict while a lock is pending\n");
1108 fname
= BASEDIR
"\\test2.txt";
1109 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1110 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1111 "Failed to reopen %s - %s\n",
1112 fname
, smbcli_errstr(cli
->tree
)));
1114 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1115 io
.lockx
.in
.file
.fnum
= fnum
;
1116 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1117 io
.lockx
.in
.timeout
= 0;
1118 io
.lockx
.in
.ulock_cnt
= 0;
1119 io
.lockx
.in
.lock_cnt
= 1;
1120 lock
[0].pid
= cli
->session
->pid
;
1121 lock
[0].offset
= 100;
1123 io
.lockx
.in
.locks
= &lock
[0];
1124 status
= smb_raw_lock(cli
->tree
, &io
);
1125 CHECK_STATUS(status
, NT_STATUS_OK
);
1128 io
.lockx
.in
.timeout
= t
;
1129 req
= smb_raw_lock_send(cli
->tree
, &io
);
1130 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1131 "Failed to setup timed lock (%s)\n", __location__
));
1133 io
.lockx
.in
.timeout
= 0;
1134 lock
[0].offset
= 105;
1136 status
= smb_raw_lock(cli
->tree
, &io
);
1137 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1139 status
= smbcli_request_simple_recv(req
);
1140 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1143 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1147 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1148 "lock comes back to early timeout[%d] delay[%d]"
1149 "(%s)\n", t
, delay
, __location__
));
1151 status
= smb_raw_lock(cli
->tree
, &io
);
1152 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1154 smbcli_close(cli
->tree
, fnum
);
1155 fname
= BASEDIR
"\\test3.txt";
1156 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1157 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1158 "Failed to reopen %s - %s\n",
1159 fname
, smbcli_errstr(cli
->tree
)));
1161 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1162 io
.lockx
.in
.file
.fnum
= fnum
;
1163 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1164 io
.lockx
.in
.timeout
= 0;
1165 io
.lockx
.in
.ulock_cnt
= 0;
1166 io
.lockx
.in
.lock_cnt
= 1;
1167 lock
[0].pid
= cli
->session
->pid
;
1168 lock
[0].offset
= 100;
1170 io
.lockx
.in
.locks
= &lock
[0];
1171 status
= smb_raw_lock(cli
->tree
, &io
);
1172 CHECK_STATUS(status
, NT_STATUS_OK
);
1175 io
.lockx
.in
.timeout
= t
;
1176 req
= smb_raw_lock_send(cli
->tree
, &io
);
1177 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1178 "Failed to setup timed lock (%s)\n", __location__
));
1180 io
.lockx
.in
.timeout
= 0;
1181 lock
[0].offset
= 105;
1183 status
= smb_raw_lock(cli
->tree
, &io
);
1184 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1186 status
= smbcli_request_simple_recv(req
);
1187 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1190 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1194 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1195 "lock comes back to early timeout[%d] delay[%d]"
1196 "(%s)\n", t
, delay
, __location__
));
1198 lock
[0].offset
= 100;
1200 status
= smb_raw_lock(cli
->tree
, &io
);
1201 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1203 smbcli_close(cli
->tree
, fnum
);
1204 fname
= BASEDIR
"\\test4.txt";
1205 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1206 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1207 "Failed to reopen %s - %s\n",
1208 fname
, smbcli_errstr(cli
->tree
)));
1210 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1211 io
.lockx
.in
.file
.fnum
= fnum
;
1212 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1213 io
.lockx
.in
.timeout
= 0;
1214 io
.lockx
.in
.ulock_cnt
= 0;
1215 io
.lockx
.in
.lock_cnt
= 1;
1216 lock
[0].pid
= cli
->session
->pid
;
1217 lock
[0].offset
= 100;
1219 io
.lockx
.in
.locks
= &lock
[0];
1220 status
= smb_raw_lock(cli
->tree
, &io
);
1221 CHECK_STATUS(status
, NT_STATUS_OK
);
1224 io
.lockx
.in
.timeout
= t
;
1225 req
= smb_raw_lock_send(cli
->tree
, &io
);
1226 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1227 "Failed to setup timed lock (%s)\n", __location__
));
1229 io
.lockx
.in
.timeout
= 0;
1230 status
= smb_raw_lock(cli
->tree
, &io
);
1231 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1233 status
= smbcli_request_simple_recv(req
);
1234 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1237 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1241 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1242 "lock comes back to early timeout[%d] delay[%d]"
1243 "(%s)\n", t
, delay
, __location__
));
1245 status
= smb_raw_lock(cli
->tree
, &io
);
1246 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1249 smb_raw_exit(cli
->session
);
1250 smbcli_deltree(cli
->tree
, BASEDIR
);
1256 test LOCKING_ANDX_CHANGE_LOCKTYPE
1258 static bool test_changetype(struct torture_context
*tctx
,
1259 struct smbcli_state
*cli
)
1262 struct smb_lock_entry lock
[2];
1267 const char *fname
= BASEDIR
"\\test.txt";
1269 if (!torture_setup_dir(cli
, BASEDIR
)) {
1273 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1274 io
.generic
.level
= RAW_LOCK_LOCKX
;
1276 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1277 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1278 "Failed to create %s - %s\n",
1279 fname
, smbcli_errstr(cli
->tree
)));
1281 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1282 io
.lockx
.in
.file
.fnum
= fnum
;
1283 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1284 io
.lockx
.in
.timeout
= 0;
1285 io
.lockx
.in
.ulock_cnt
= 0;
1286 io
.lockx
.in
.lock_cnt
= 1;
1287 lock
[0].pid
= cli
->session
->pid
;
1288 lock
[0].offset
= 100;
1290 io
.lockx
.in
.locks
= &lock
[0];
1291 status
= smb_raw_lock(cli
->tree
, &io
);
1292 CHECK_STATUS(status
, NT_STATUS_OK
);
1294 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1295 torture_result(tctx
, TORTURE_FAIL
,
1296 "allowed write on read locked region (%s)\n", __location__
);
1301 /* windows server don't seem to support this */
1302 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1303 status
= smb_raw_lock(cli
->tree
, &io
);
1304 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1306 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1307 torture_result(tctx
, TORTURE_FAIL
,
1308 "allowed write after lock change (%s)\n", __location__
);
1314 smbcli_close(cli
->tree
, fnum
);
1315 smb_raw_exit(cli
->session
);
1316 smbcli_deltree(cli
->tree
, BASEDIR
);
1320 struct double_lock_test
{
1321 struct smb_lock_entry lock1
;
1322 struct smb_lock_entry lock2
;
1323 NTSTATUS exp_status
;
1327 * Tests zero byte locks.
1329 static const struct double_lock_test zero_byte_tests
[] = {
1330 /* {pid, offset, count}, {pid, offset, count}, status */
1332 /** First, takes a zero byte lock at offset 10. Then:
1333 * - Taking 0 byte lock at 10 should succeed.
1334 * - Taking 1 byte locks at 9,10,11 should succeed.
1335 * - Taking 2 byte lock at 9 should fail.
1336 * - Taking 2 byte lock at 10 should succeed.
1337 * - Taking 3 byte lock at 9 should fail.
1339 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1340 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1341 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1342 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1343 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1344 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1345 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1347 /** Same, but opposite order. */
1348 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1349 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1350 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1351 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1352 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1353 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1354 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1356 /** Zero zero case. */
1357 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1360 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1366 const char *fname
= BASEDIR
"\\zero.txt";
1368 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1370 if (!torture_setup_dir(cli
, BASEDIR
)) {
1374 io
.generic
.level
= RAW_LOCK_LOCKX
;
1376 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1377 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1378 "Failed to create %s - %s\n",
1379 fname
, smbcli_errstr(cli
->tree
)));
1381 /* Setup initial parameters */
1382 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1383 io
.lockx
.in
.file
.fnum
= fnum
;
1384 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1385 io
.lockx
.in
.timeout
= 0;
1387 /* Try every combination of locks in zero_byte_tests. The first lock is
1388 * assumed to succeed. The second lock may contend, depending on the
1389 * expected status. */
1391 i
< ARRAY_SIZE(zero_byte_tests
);
1393 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1394 zero_byte_tests
[i
].lock1
.pid
,
1395 zero_byte_tests
[i
].lock1
.offset
,
1396 zero_byte_tests
[i
].lock1
.count
,
1397 zero_byte_tests
[i
].lock2
.pid
,
1398 zero_byte_tests
[i
].lock2
.offset
,
1399 zero_byte_tests
[i
].lock2
.count
,
1400 nt_errstr(zero_byte_tests
[i
].exp_status
));
1402 /* Lock both locks. */
1403 io
.lockx
.in
.ulock_cnt
= 0;
1404 io
.lockx
.in
.lock_cnt
= 1;
1406 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock1
;
1407 status
= smb_raw_lock(cli
->tree
, &io
);
1408 CHECK_STATUS(status
, NT_STATUS_OK
);
1410 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock2
;
1411 status
= smb_raw_lock(cli
->tree
, &io
);
1413 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1414 NT_STATUS_LOCK_NOT_GRANTED
)) {
1415 /* Allow either of the failure messages and keep going
1416 * if we see the wrong status. */
1417 CHECK_STATUS_OR_CONT(status
,
1418 NT_STATUS_LOCK_NOT_GRANTED
,
1419 NT_STATUS_FILE_LOCK_CONFLICT
);
1422 CHECK_STATUS_CONT(status
,
1423 zero_byte_tests
[i
].exp_status
);
1426 /* Unlock both locks. */
1427 io
.lockx
.in
.ulock_cnt
= 1;
1428 io
.lockx
.in
.lock_cnt
= 0;
1430 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1431 status
= smb_raw_lock(cli
->tree
, &io
);
1432 CHECK_STATUS(status
, NT_STATUS_OK
);
1435 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock1
;
1436 status
= smb_raw_lock(cli
->tree
, &io
);
1437 CHECK_STATUS(status
, NT_STATUS_OK
);
1441 smbcli_close(cli
->tree
, fnum
);
1442 smb_raw_exit(cli
->session
);
1443 smbcli_deltree(cli
->tree
, BASEDIR
);
1447 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1453 const char *fname
= BASEDIR
"\\unlock.txt";
1454 struct smb_lock_entry lock1
;
1455 struct smb_lock_entry lock2
;
1457 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1459 if (!torture_setup_dir(cli
, BASEDIR
)) {
1463 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1464 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1465 "Failed to create %s - %s\n",
1466 fname
, smbcli_errstr(cli
->tree
)));
1468 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1469 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1470 "Failed to create %s - %s\n",
1471 fname
, smbcli_errstr(cli
->tree
)));
1473 /* Setup initial parameters */
1474 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1475 io
.lockx
.in
.timeout
= 0;
1477 lock1
.pid
= cli
->session
->pid
;
1480 lock2
.pid
= cli
->session
->pid
- 1;
1485 * Take exclusive lock, then unlock it with a shared-unlock call.
1487 torture_comment(tctx
, " taking exclusive lock.\n");
1488 io
.lockx
.in
.ulock_cnt
= 0;
1489 io
.lockx
.in
.lock_cnt
= 1;
1490 io
.lockx
.in
.mode
= 0;
1491 io
.lockx
.in
.file
.fnum
= fnum1
;
1492 io
.lockx
.in
.locks
= &lock1
;
1493 status
= smb_raw_lock(cli
->tree
, &io
);
1494 CHECK_STATUS(status
, NT_STATUS_OK
);
1496 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1497 io
.lockx
.in
.ulock_cnt
= 1;
1498 io
.lockx
.in
.lock_cnt
= 0;
1499 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1500 io
.lockx
.in
.file
.fnum
= fnum1
;
1501 io
.lockx
.in
.locks
= &lock1
;
1502 status
= smb_raw_lock(cli
->tree
, &io
);
1503 CHECK_STATUS(status
, NT_STATUS_OK
);
1505 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1506 io
.lockx
.in
.ulock_cnt
= 0;
1507 io
.lockx
.in
.lock_cnt
= 1;
1508 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1509 io
.lockx
.in
.file
.fnum
= fnum2
;
1510 io
.lockx
.in
.locks
= &lock2
;
1511 status
= smb_raw_lock(cli
->tree
, &io
);
1512 CHECK_STATUS(status
, NT_STATUS_OK
);
1515 * Unlock a shared lock with an exclusive-unlock call.
1517 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1518 io
.lockx
.in
.ulock_cnt
= 1;
1519 io
.lockx
.in
.lock_cnt
= 0;
1520 io
.lockx
.in
.mode
= 0;
1521 io
.lockx
.in
.file
.fnum
= fnum2
;
1522 io
.lockx
.in
.locks
= &lock2
;
1523 status
= smb_raw_lock(cli
->tree
, &io
);
1524 CHECK_STATUS(status
, NT_STATUS_OK
);
1526 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1527 io
.lockx
.in
.ulock_cnt
= 0;
1528 io
.lockx
.in
.lock_cnt
= 1;
1529 io
.lockx
.in
.mode
= 0;
1530 io
.lockx
.in
.file
.fnum
= fnum1
;
1531 io
.lockx
.in
.locks
= &lock1
;
1532 status
= smb_raw_lock(cli
->tree
, &io
);
1533 CHECK_STATUS(status
, NT_STATUS_OK
);
1536 io
.lockx
.in
.ulock_cnt
= 1;
1537 io
.lockx
.in
.lock_cnt
= 0;
1538 status
= smb_raw_lock(cli
->tree
, &io
);
1539 CHECK_STATUS(status
, NT_STATUS_OK
);
1542 * Test unlocking of 0-byte locks.
1545 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1546 "always unlocks the exclusive first.\n");
1547 lock1
.pid
= cli
->session
->pid
;
1550 lock2
.pid
= cli
->session
->pid
;
1553 io
.lockx
.in
.ulock_cnt
= 0;
1554 io
.lockx
.in
.lock_cnt
= 1;
1555 io
.lockx
.in
.file
.fnum
= fnum1
;
1556 io
.lockx
.in
.locks
= &lock1
;
1558 /* lock 0-byte shared
1559 * Note: Order of the shared/exclusive locks doesn't matter. */
1560 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1561 status
= smb_raw_lock(cli
->tree
, &io
);
1562 CHECK_STATUS(status
, NT_STATUS_OK
);
1564 /* lock 0-byte exclusive */
1565 io
.lockx
.in
.mode
= 0;
1566 status
= smb_raw_lock(cli
->tree
, &io
);
1567 CHECK_STATUS(status
, NT_STATUS_OK
);
1569 /* test contention */
1570 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1571 io
.lockx
.in
.locks
= &lock2
;
1572 io
.lockx
.in
.file
.fnum
= fnum2
;
1573 status
= smb_raw_lock(cli
->tree
, &io
);
1574 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1575 NT_STATUS_FILE_LOCK_CONFLICT
);
1578 io
.lockx
.in
.ulock_cnt
= 1;
1579 io
.lockx
.in
.lock_cnt
= 0;
1580 io
.lockx
.in
.file
.fnum
= fnum1
;
1581 io
.lockx
.in
.locks
= &lock1
;
1582 status
= smb_raw_lock(cli
->tree
, &io
);
1583 CHECK_STATUS(status
, NT_STATUS_OK
);
1585 /* test - can we take a shared lock? */
1586 io
.lockx
.in
.ulock_cnt
= 0;
1587 io
.lockx
.in
.lock_cnt
= 1;
1588 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1589 io
.lockx
.in
.file
.fnum
= fnum2
;
1590 io
.lockx
.in
.locks
= &lock2
;
1591 status
= smb_raw_lock(cli
->tree
, &io
);
1593 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1594 * new to Win7, it succeeds in WinXP too), until I can come to a
1595 * resolution as to whether Samba should support this or not. There is
1596 * code to preference unlocking exclusive locks before shared locks,
1597 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1598 if (TARGET_IS_SAMBA3(tctx
)) {
1599 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1600 NT_STATUS_FILE_LOCK_CONFLICT
);
1602 CHECK_STATUS(status
, NT_STATUS_OK
);
1606 io
.lockx
.in
.ulock_cnt
= 1;
1607 io
.lockx
.in
.lock_cnt
= 0;
1608 status
= smb_raw_lock(cli
->tree
, &io
);
1610 /* XXX Same as above. */
1611 if (TARGET_IS_SAMBA3(tctx
)) {
1612 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1614 CHECK_STATUS(status
, NT_STATUS_OK
);
1617 io
.lockx
.in
.file
.fnum
= fnum1
;
1618 io
.lockx
.in
.locks
= &lock1
;
1619 status
= smb_raw_lock(cli
->tree
, &io
);
1620 CHECK_STATUS(status
, NT_STATUS_OK
);
1623 smbcli_close(cli
->tree
, fnum1
);
1624 smbcli_close(cli
->tree
, fnum2
);
1625 smb_raw_exit(cli
->session
);
1626 smbcli_deltree(cli
->tree
, BASEDIR
);
1630 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1636 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1637 struct smb_lock_entry lock1
;
1638 struct smb_lock_entry lock2
;
1639 struct smb_lock_entry locks
[2];
1641 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1643 if (!torture_setup_dir(cli
, BASEDIR
)) {
1647 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1648 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1649 "Failed to create %s - %s\n",
1650 fname
, smbcli_errstr(cli
->tree
)));
1652 /* Setup initial parameters */
1653 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1654 io
.lockx
.in
.timeout
= 0;
1656 lock1
.pid
= cli
->session
->pid
;
1659 lock2
.pid
= cli
->session
->pid
;
1666 io
.lockx
.in
.file
.fnum
= fnum1
;
1667 io
.lockx
.in
.mode
= 0; /* exclusive */
1669 /** Test1: Take second lock, but not first. */
1670 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
1673 io
.lockx
.in
.ulock_cnt
= 0;
1674 io
.lockx
.in
.lock_cnt
= 1;
1675 io
.lockx
.in
.locks
= &lock2
;
1676 status
= smb_raw_lock(cli
->tree
, &io
);
1677 CHECK_STATUS(status
, NT_STATUS_OK
);
1679 /* Try to unlock both locks. */
1680 io
.lockx
.in
.ulock_cnt
= 2;
1681 io
.lockx
.in
.lock_cnt
= 0;
1682 io
.lockx
.in
.locks
= locks
;
1684 status
= smb_raw_lock(cli
->tree
, &io
);
1685 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1687 /* Second lock should not be unlocked. */
1688 io
.lockx
.in
.ulock_cnt
= 0;
1689 io
.lockx
.in
.lock_cnt
= 1;
1690 io
.lockx
.in
.locks
= &lock2
;
1691 status
= smb_raw_lock(cli
->tree
, &io
);
1692 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1695 io
.lockx
.in
.ulock_cnt
= 1;
1696 io
.lockx
.in
.lock_cnt
= 0;
1697 io
.lockx
.in
.locks
= &lock2
;
1698 status
= smb_raw_lock(cli
->tree
, &io
);
1699 CHECK_STATUS(status
, NT_STATUS_OK
);
1701 /** Test2: Take first lock, but not second. */
1702 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
1705 io
.lockx
.in
.ulock_cnt
= 0;
1706 io
.lockx
.in
.lock_cnt
= 1;
1707 io
.lockx
.in
.locks
= &lock1
;
1708 status
= smb_raw_lock(cli
->tree
, &io
);
1709 CHECK_STATUS(status
, NT_STATUS_OK
);
1711 /* Try to unlock both locks. */
1712 io
.lockx
.in
.ulock_cnt
= 2;
1713 io
.lockx
.in
.lock_cnt
= 0;
1714 io
.lockx
.in
.locks
= locks
;
1716 status
= smb_raw_lock(cli
->tree
, &io
);
1717 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1719 /* First lock should be unlocked. */
1720 io
.lockx
.in
.ulock_cnt
= 0;
1721 io
.lockx
.in
.lock_cnt
= 1;
1722 io
.lockx
.in
.locks
= &lock1
;
1723 status
= smb_raw_lock(cli
->tree
, &io
);
1724 CHECK_STATUS(status
, NT_STATUS_OK
);
1727 io
.lockx
.in
.ulock_cnt
= 1;
1728 io
.lockx
.in
.lock_cnt
= 0;
1729 io
.lockx
.in
.locks
= &lock1
;
1730 status
= smb_raw_lock(cli
->tree
, &io
);
1731 CHECK_STATUS(status
, NT_STATUS_OK
);
1734 smbcli_close(cli
->tree
, fnum1
);
1735 smb_raw_exit(cli
->session
);
1736 smbcli_deltree(cli
->tree
, BASEDIR
);
1741 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1742 * - stacking an exclusive on top of shared fails
1743 * - stacking two exclusives fail
1745 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1751 const char *fname
= BASEDIR
"\\stacking.txt";
1752 struct smb_lock_entry lock1
;
1753 struct smb_lock_entry lock2
;
1755 torture_comment(tctx
, "Testing stacking:\n");
1757 if (!torture_setup_dir(cli
, BASEDIR
)) {
1761 io
.generic
.level
= RAW_LOCK_LOCKX
;
1763 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1764 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1765 "Failed to create %s - %s\n",
1766 fname
, smbcli_errstr(cli
->tree
)));
1768 /* Setup initial parameters */
1769 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1770 io
.lockx
.in
.timeout
= 0;
1772 lock1
.pid
= cli
->session
->pid
;
1775 lock2
.pid
= cli
->session
->pid
- 1;
1780 * Try to take a shared lock, then stack an exclusive.
1782 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
1783 io
.lockx
.in
.file
.fnum
= fnum1
;
1784 io
.lockx
.in
.locks
= &lock1
;
1786 io
.lockx
.in
.ulock_cnt
= 0;
1787 io
.lockx
.in
.lock_cnt
= 1;
1788 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1789 status
= smb_raw_lock(cli
->tree
, &io
);
1790 CHECK_STATUS(status
, NT_STATUS_OK
);
1792 io
.lockx
.in
.ulock_cnt
= 0;
1793 io
.lockx
.in
.lock_cnt
= 1;
1794 io
.lockx
.in
.mode
= 0;
1795 status
= smb_raw_lock(cli
->tree
, &io
);
1796 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1797 NT_STATUS_FILE_LOCK_CONFLICT
);
1800 io
.lockx
.in
.ulock_cnt
= 1;
1801 io
.lockx
.in
.lock_cnt
= 0;
1802 status
= smb_raw_lock(cli
->tree
, &io
);
1803 CHECK_STATUS(status
, NT_STATUS_OK
);
1806 * Prove that two exclusive locks do not stack.
1808 torture_comment(tctx
, " two exclusive locks do not stack.\n");
1809 io
.lockx
.in
.ulock_cnt
= 0;
1810 io
.lockx
.in
.lock_cnt
= 1;
1811 io
.lockx
.in
.mode
= 0;
1812 status
= smb_raw_lock(cli
->tree
, &io
);
1813 CHECK_STATUS(status
, NT_STATUS_OK
);
1814 status
= smb_raw_lock(cli
->tree
, &io
);
1815 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1816 NT_STATUS_FILE_LOCK_CONFLICT
);
1819 io
.lockx
.in
.ulock_cnt
= 1;
1820 io
.lockx
.in
.lock_cnt
= 0;
1821 status
= smb_raw_lock(cli
->tree
, &io
);
1822 CHECK_STATUS(status
, NT_STATUS_OK
);
1825 smbcli_close(cli
->tree
, fnum1
);
1826 smb_raw_exit(cli
->session
);
1827 smbcli_deltree(cli
->tree
, BASEDIR
);
1832 basic testing of lock calls
1834 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
1836 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "LOCK");
1838 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
1839 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
1840 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
1841 torture_suite_add_1smb_test(suite
, "async", test_async
);
1842 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
1843 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
1845 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
1846 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
1847 torture_suite_add_1smb_test(suite
, "multiple_unlock",
1848 test_multiple_unlock
);
1849 torture_suite_add_1smb_test(suite
, "zerobytelocks",
1850 test_zerobytelocks
);