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))
75 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
78 test SMBlock and SMBunlock ops
80 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
86 const char *fname
= BASEDIR
"\\test.txt";
88 if (!torture_setup_dir(cli
, BASEDIR
)) {
92 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
93 io
.generic
.level
= RAW_LOCK_LOCK
;
95 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
96 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
97 "Failed to create %s - %s\n",
98 fname
, smbcli_errstr(cli
->tree
)));
100 torture_comment(tctx
, "Trying 0/0 lock\n");
101 io
.lock
.level
= RAW_LOCK_LOCK
;
102 io
.lock
.in
.file
.fnum
= fnum
;
103 io
.lock
.in
.count
= 0;
104 io
.lock
.in
.offset
= 0;
105 status
= smb_raw_lock(cli
->tree
, &io
);
106 CHECK_STATUS(status
, NT_STATUS_OK
);
108 status
= smb_raw_lock(cli
->tree
, &io
);
109 CHECK_STATUS(status
, NT_STATUS_OK
);
111 io
.lock
.level
= RAW_LOCK_UNLOCK
;
112 status
= smb_raw_lock(cli
->tree
, &io
);
113 CHECK_STATUS(status
, NT_STATUS_OK
);
115 torture_comment(tctx
, "Trying 0/1 lock\n");
116 io
.lock
.level
= RAW_LOCK_LOCK
;
117 io
.lock
.in
.file
.fnum
= fnum
;
118 io
.lock
.in
.count
= 1;
119 io
.lock
.in
.offset
= 0;
120 status
= smb_raw_lock(cli
->tree
, &io
);
121 CHECK_STATUS(status
, NT_STATUS_OK
);
123 status
= smb_raw_lock(cli
->tree
, &io
);
124 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
126 io
.lock
.level
= RAW_LOCK_UNLOCK
;
127 status
= smb_raw_lock(cli
->tree
, &io
);
128 CHECK_STATUS(status
, NT_STATUS_OK
);
129 io
.lock
.level
= RAW_LOCK_UNLOCK
;
130 status
= smb_raw_lock(cli
->tree
, &io
);
131 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
133 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
134 io
.lock
.level
= RAW_LOCK_LOCK
;
135 io
.lock
.in
.file
.fnum
= fnum
;
136 io
.lock
.in
.count
= 4000;
137 io
.lock
.in
.offset
= 0xEEFFFFFF;
138 status
= smb_raw_lock(cli
->tree
, &io
);
139 CHECK_STATUS(status
, NT_STATUS_OK
);
141 status
= smb_raw_lock(cli
->tree
, &io
);
142 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
144 io
.lock
.level
= RAW_LOCK_UNLOCK
;
145 status
= smb_raw_lock(cli
->tree
, &io
);
146 CHECK_STATUS(status
, NT_STATUS_OK
);
147 io
.lock
.level
= RAW_LOCK_UNLOCK
;
148 status
= smb_raw_lock(cli
->tree
, &io
);
149 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
151 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
152 io
.lock
.level
= RAW_LOCK_LOCK
;
153 io
.lock
.in
.file
.fnum
= fnum
;
154 io
.lock
.in
.count
= 4000;
155 io
.lock
.in
.offset
= 0xEEFFFFFF;
156 status
= smb_raw_lock(cli
->tree
, &io
);
157 CHECK_STATUS(status
, NT_STATUS_OK
);
159 status
= smb_raw_lock(cli
->tree
, &io
);
160 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
162 io
.lock
.level
= RAW_LOCK_UNLOCK
;
163 status
= smb_raw_lock(cli
->tree
, &io
);
164 CHECK_STATUS(status
, NT_STATUS_OK
);
165 io
.lock
.level
= RAW_LOCK_UNLOCK
;
166 status
= smb_raw_lock(cli
->tree
, &io
);
167 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
169 torture_comment(tctx
, "Trying max lock\n");
170 io
.lock
.level
= RAW_LOCK_LOCK
;
171 io
.lock
.in
.file
.fnum
= fnum
;
172 io
.lock
.in
.count
= 4000;
173 io
.lock
.in
.offset
= 0xEF000000;
174 status
= smb_raw_lock(cli
->tree
, &io
);
175 CHECK_STATUS(status
, NT_STATUS_OK
);
177 status
= smb_raw_lock(cli
->tree
, &io
);
178 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
180 io
.lock
.level
= RAW_LOCK_UNLOCK
;
181 status
= smb_raw_lock(cli
->tree
, &io
);
182 CHECK_STATUS(status
, NT_STATUS_OK
);
183 io
.lock
.level
= RAW_LOCK_UNLOCK
;
184 status
= smb_raw_lock(cli
->tree
, &io
);
185 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
187 torture_comment(tctx
, "Trying wrong pid unlock\n");
188 io
.lock
.level
= RAW_LOCK_LOCK
;
189 io
.lock
.in
.file
.fnum
= fnum
;
190 io
.lock
.in
.count
= 4002;
191 io
.lock
.in
.offset
= 10001;
192 status
= smb_raw_lock(cli
->tree
, &io
);
193 CHECK_STATUS(status
, NT_STATUS_OK
);
195 io
.lock
.level
= RAW_LOCK_UNLOCK
;
196 status
= smb_raw_lock(cli
->tree
, &io
);
197 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
199 status
= smb_raw_lock(cli
->tree
, &io
);
200 CHECK_STATUS(status
, NT_STATUS_OK
);
203 smbcli_close(cli
->tree
, fnum
);
204 smb_raw_exit(cli
->session
);
205 smbcli_deltree(cli
->tree
, BASEDIR
);
213 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
216 struct smb_lock_entry lock
[1];
220 const char *fname
= BASEDIR
"\\test.txt";
222 if (!torture_setup_dir(cli
, BASEDIR
)) {
226 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
227 io
.generic
.level
= RAW_LOCK_LOCKX
;
229 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
230 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
231 "Failed to create %s - %s\n",
232 fname
, smbcli_errstr(cli
->tree
)));
234 io
.lockx
.level
= RAW_LOCK_LOCKX
;
235 io
.lockx
.in
.file
.fnum
= fnum
;
236 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
237 io
.lockx
.in
.timeout
= 0;
238 io
.lockx
.in
.ulock_cnt
= 0;
239 io
.lockx
.in
.lock_cnt
= 1;
240 lock
[0].pid
= cli
->session
->pid
;
243 io
.lockx
.in
.locks
= &lock
[0];
244 status
= smb_raw_lock(cli
->tree
, &io
);
245 CHECK_STATUS(status
, NT_STATUS_OK
);
248 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
249 io
.lockx
.in
.ulock_cnt
= 0;
250 io
.lockx
.in
.lock_cnt
= 1;
251 lock
[0].count
= 4000;
252 lock
[0].offset
= 0xEEFFFFFF;
253 status
= smb_raw_lock(cli
->tree
, &io
);
254 CHECK_STATUS(status
, NT_STATUS_OK
);
256 status
= smb_raw_lock(cli
->tree
, &io
);
257 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
259 io
.lockx
.in
.ulock_cnt
= 1;
260 io
.lockx
.in
.lock_cnt
= 0;
261 status
= smb_raw_lock(cli
->tree
, &io
);
262 CHECK_STATUS(status
, NT_STATUS_OK
);
263 status
= smb_raw_lock(cli
->tree
, &io
);
264 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
266 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
267 io
.lockx
.in
.ulock_cnt
= 0;
268 io
.lockx
.in
.lock_cnt
= 1;
269 lock
[0].count
= 4000;
270 lock
[0].offset
= 0xEF000000;
271 status
= smb_raw_lock(cli
->tree
, &io
);
272 CHECK_STATUS(status
, NT_STATUS_OK
);
274 status
= smb_raw_lock(cli
->tree
, &io
);
275 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
277 io
.lockx
.in
.ulock_cnt
= 1;
278 io
.lockx
.in
.lock_cnt
= 0;
279 status
= smb_raw_lock(cli
->tree
, &io
);
280 CHECK_STATUS(status
, NT_STATUS_OK
);
281 status
= smb_raw_lock(cli
->tree
, &io
);
282 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
284 torture_comment(tctx
, "Trying zero lock\n");
285 io
.lockx
.in
.ulock_cnt
= 0;
286 io
.lockx
.in
.lock_cnt
= 1;
289 status
= smb_raw_lock(cli
->tree
, &io
);
290 CHECK_STATUS(status
, NT_STATUS_OK
);
292 status
= smb_raw_lock(cli
->tree
, &io
);
293 CHECK_STATUS(status
, NT_STATUS_OK
);
295 io
.lockx
.in
.ulock_cnt
= 1;
296 io
.lockx
.in
.lock_cnt
= 0;
297 status
= smb_raw_lock(cli
->tree
, &io
);
298 CHECK_STATUS(status
, NT_STATUS_OK
);
299 status
= smb_raw_lock(cli
->tree
, &io
);
300 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
302 torture_comment(tctx
, "Trying max lock\n");
303 io
.lockx
.in
.ulock_cnt
= 0;
304 io
.lockx
.in
.lock_cnt
= 1;
307 status
= smb_raw_lock(cli
->tree
, &io
);
308 CHECK_STATUS(status
, NT_STATUS_OK
);
310 status
= smb_raw_lock(cli
->tree
, &io
);
311 CHECK_STATUS(status
, NT_STATUS_OK
);
313 io
.lockx
.in
.ulock_cnt
= 1;
314 io
.lockx
.in
.lock_cnt
= 0;
315 status
= smb_raw_lock(cli
->tree
, &io
);
316 CHECK_STATUS(status
, NT_STATUS_OK
);
317 status
= smb_raw_lock(cli
->tree
, &io
);
318 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
320 torture_comment(tctx
, "Trying 2^63\n");
321 io
.lockx
.in
.ulock_cnt
= 0;
322 io
.lockx
.in
.lock_cnt
= 1;
325 lock
[0].offset
<<= 63;
326 status
= smb_raw_lock(cli
->tree
, &io
);
327 CHECK_STATUS(status
, NT_STATUS_OK
);
329 status
= smb_raw_lock(cli
->tree
, &io
);
330 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
332 io
.lockx
.in
.ulock_cnt
= 1;
333 io
.lockx
.in
.lock_cnt
= 0;
334 status
= smb_raw_lock(cli
->tree
, &io
);
335 CHECK_STATUS(status
, NT_STATUS_OK
);
336 status
= smb_raw_lock(cli
->tree
, &io
);
337 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
339 torture_comment(tctx
, "Trying 2^63 - 1\n");
340 io
.lockx
.in
.ulock_cnt
= 0;
341 io
.lockx
.in
.lock_cnt
= 1;
344 lock
[0].offset
<<= 63;
346 status
= smb_raw_lock(cli
->tree
, &io
);
347 CHECK_STATUS(status
, NT_STATUS_OK
);
349 status
= smb_raw_lock(cli
->tree
, &io
);
350 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
352 io
.lockx
.in
.ulock_cnt
= 1;
353 io
.lockx
.in
.lock_cnt
= 0;
354 status
= smb_raw_lock(cli
->tree
, &io
);
355 CHECK_STATUS(status
, NT_STATUS_OK
);
356 status
= smb_raw_lock(cli
->tree
, &io
);
357 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
359 torture_comment(tctx
, "Trying max lock 2\n");
360 io
.lockx
.in
.ulock_cnt
= 0;
361 io
.lockx
.in
.lock_cnt
= 1;
364 status
= smb_raw_lock(cli
->tree
, &io
);
365 CHECK_STATUS(status
, NT_STATUS_OK
);
368 status
= smb_raw_lock(cli
->tree
, &io
);
369 if (TARGET_IS_WIN7(tctx
) || TARGET_IS_SAMBA4(tctx
))
370 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
372 CHECK_STATUS(status
, NT_STATUS_OK
);
374 io
.lockx
.in
.ulock_cnt
= 1;
375 io
.lockx
.in
.lock_cnt
= 0;
377 status
= smb_raw_lock(cli
->tree
, &io
);
379 CHECK_STATUS(status
, NT_STATUS_OK
);
380 status
= smb_raw_lock(cli
->tree
, &io
);
381 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
384 smbcli_close(cli
->tree
, fnum
);
385 smb_raw_exit(cli
->session
);
386 smbcli_deltree(cli
->tree
, BASEDIR
);
393 static bool test_pidhigh(struct torture_context
*tctx
,
394 struct smbcli_state
*cli
)
397 struct smb_lock_entry lock
[1];
401 const char *fname
= BASEDIR
"\\test.txt";
404 if (!torture_setup_dir(cli
, BASEDIR
)) {
408 torture_comment(tctx
, "Testing high pid\n");
409 io
.generic
.level
= RAW_LOCK_LOCKX
;
411 cli
->session
->pid
= 1;
413 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
414 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
415 "Failed to create %s - %s\n",
416 fname
, smbcli_errstr(cli
->tree
)));
418 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
419 torture_result(tctx
, TORTURE_FAIL
,
420 "Failed to write 1 byte - %s\n",
421 smbcli_errstr(cli
->tree
));
426 io
.lockx
.level
= RAW_LOCK_LOCKX
;
427 io
.lockx
.in
.file
.fnum
= fnum
;
428 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
429 io
.lockx
.in
.timeout
= 0;
430 io
.lockx
.in
.ulock_cnt
= 0;
431 io
.lockx
.in
.lock_cnt
= 1;
432 lock
[0].pid
= cli
->session
->pid
;
434 lock
[0].count
= 0xFFFFFFFF;
435 io
.lockx
.in
.locks
= &lock
[0];
436 status
= smb_raw_lock(cli
->tree
, &io
);
437 CHECK_STATUS(status
, NT_STATUS_OK
);
439 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
440 torture_result(tctx
, TORTURE_FAIL
,
441 "Failed to read 1 byte - %s\n",
442 smbcli_errstr(cli
->tree
));
447 cli
->session
->pid
= 2;
449 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
450 torture_result(tctx
, TORTURE_FAIL
,
451 "pid is incorrect handled for read with lock!\n");
456 cli
->session
->pid
= 0x10001;
458 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
459 torture_result(tctx
, TORTURE_FAIL
,
460 "High pid is used on this server!\n");
463 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
467 smbcli_close(cli
->tree
, fnum
);
468 smb_raw_exit(cli
->session
);
469 smbcli_deltree(cli
->tree
, BASEDIR
);
475 test locking&X async operation
477 static bool test_async(struct torture_context
*tctx
,
478 struct smbcli_state
*cli
)
480 struct smbcli_session
*session
;
481 struct smb_composite_sesssetup setup
;
482 struct smbcli_tree
*tree
;
484 const char *host
, *share
;
486 struct smb_lock_entry lock
[2];
490 const char *fname
= BASEDIR
"\\test.txt";
492 struct smbcli_request
*req
;
493 struct smbcli_session_options options
;
495 if (!torture_setup_dir(cli
, BASEDIR
)) {
499 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
501 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
502 io
.generic
.level
= RAW_LOCK_LOCKX
;
504 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
505 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
506 "Failed to create %s - %s\n",
507 fname
, smbcli_errstr(cli
->tree
)));
509 io
.lockx
.level
= RAW_LOCK_LOCKX
;
510 io
.lockx
.in
.file
.fnum
= fnum
;
511 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
512 io
.lockx
.in
.timeout
= 0;
513 io
.lockx
.in
.ulock_cnt
= 0;
514 io
.lockx
.in
.lock_cnt
= 1;
515 lock
[0].pid
= cli
->session
->pid
;
516 lock
[0].offset
= 100;
518 io
.lockx
.in
.locks
= &lock
[0];
519 status
= smb_raw_lock(cli
->tree
, &io
);
520 CHECK_STATUS(status
, NT_STATUS_OK
);
524 torture_comment(tctx
, "testing cancel by CANCEL_LOCK\n");
526 /* setup a timed lock */
527 io
.lockx
.in
.timeout
= 10000;
528 req
= smb_raw_lock_send(cli
->tree
, &io
);
529 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
530 "Failed to setup timed lock (%s)\n", __location__
));
532 /* cancel the wrong range */
534 io
.lockx
.in
.timeout
= 0;
535 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
536 status
= smb_raw_lock(cli
->tree
, &io
);
537 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
539 /* cancel with the wrong bits set */
540 lock
[0].offset
= 100;
541 io
.lockx
.in
.timeout
= 0;
542 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
543 status
= smb_raw_lock(cli
->tree
, &io
);
544 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
546 /* cancel the right range */
547 lock
[0].offset
= 100;
548 io
.lockx
.in
.timeout
= 0;
549 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
550 status
= smb_raw_lock(cli
->tree
, &io
);
551 CHECK_STATUS(status
, NT_STATUS_OK
);
553 /* receive the failed lock request */
554 status
= smbcli_request_simple_recv(req
);
555 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
557 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
558 "lock cancel was not immediate (%s)\n", __location__
));
560 torture_comment(tctx
, "testing cancel by unlock\n");
561 io
.lockx
.in
.ulock_cnt
= 0;
562 io
.lockx
.in
.lock_cnt
= 1;
563 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
564 io
.lockx
.in
.timeout
= 0;
565 status
= smb_raw_lock(cli
->tree
, &io
);
566 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
568 io
.lockx
.in
.timeout
= 5000;
569 req
= smb_raw_lock_send(cli
->tree
, &io
);
570 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
571 "Failed to setup timed lock (%s)\n", __location__
));
573 io
.lockx
.in
.ulock_cnt
= 1;
574 io
.lockx
.in
.lock_cnt
= 0;
575 status
= smb_raw_lock(cli
->tree
, &io
);
576 CHECK_STATUS(status
, NT_STATUS_OK
);
579 status
= smbcli_request_simple_recv(req
);
580 CHECK_STATUS(status
, NT_STATUS_OK
);
582 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
583 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
584 __location__
, (int)(time(NULL
)-t
)));
586 torture_comment(tctx
, "testing cancel by close\n");
587 io
.lockx
.in
.ulock_cnt
= 0;
588 io
.lockx
.in
.lock_cnt
= 1;
589 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
590 io
.lockx
.in
.timeout
= 0;
591 status
= smb_raw_lock(cli
->tree
, &io
);
592 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
595 io
.lockx
.in
.timeout
= 10000;
596 req
= smb_raw_lock_send(cli
->tree
, &io
);
597 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
598 "Failed to setup timed lock (%s)\n", __location__
));
600 status
= smbcli_close(cli
->tree
, fnum
);
601 CHECK_STATUS(status
, NT_STATUS_OK
);
603 status
= smbcli_request_simple_recv(req
);
604 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
606 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
607 "lock cancel by close was not immediate (%s)\n", __location__
));
609 torture_comment(tctx
, "create a new sessions\n");
610 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
611 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
612 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
613 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
614 setup
.in
.credentials
= cmdline_credentials
;
615 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
616 status
= smb_composite_sesssetup(session
, &setup
);
617 CHECK_STATUS(status
, NT_STATUS_OK
);
618 session
->vuid
= setup
.out
.vuid
;
620 torture_comment(tctx
, "create new tree context\n");
621 share
= torture_setting_string(tctx
, "share", NULL
);
622 host
= torture_setting_string(tctx
, "host", NULL
);
623 tree
= smbcli_tree_init(session
, tctx
, false);
624 tcon
.generic
.level
= RAW_TCON_TCONX
;
625 tcon
.tconx
.in
.flags
= 0;
626 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
627 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
628 tcon
.tconx
.in
.device
= "A:";
629 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
630 CHECK_STATUS(status
, NT_STATUS_OK
);
631 tree
->tid
= tcon
.tconx
.out
.tid
;
633 torture_comment(tctx
, "testing cancel by exit\n");
634 fname
= BASEDIR
"\\test_exit.txt";
635 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
636 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
637 "Failed to reopen %s - %s\n",
638 fname
, smbcli_errstr(tree
)));
640 io
.lockx
.level
= RAW_LOCK_LOCKX
;
641 io
.lockx
.in
.file
.fnum
= fnum
;
642 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
643 io
.lockx
.in
.timeout
= 0;
644 io
.lockx
.in
.ulock_cnt
= 0;
645 io
.lockx
.in
.lock_cnt
= 1;
646 lock
[0].pid
= session
->pid
;
647 lock
[0].offset
= 100;
649 io
.lockx
.in
.locks
= &lock
[0];
650 status
= smb_raw_lock(tree
, &io
);
651 CHECK_STATUS(status
, NT_STATUS_OK
);
653 io
.lockx
.in
.ulock_cnt
= 0;
654 io
.lockx
.in
.lock_cnt
= 1;
655 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
656 io
.lockx
.in
.timeout
= 0;
657 status
= smb_raw_lock(tree
, &io
);
658 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
660 io
.lockx
.in
.timeout
= 10000;
662 req
= smb_raw_lock_send(tree
, &io
);
663 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
664 "Failed to setup timed lock (%s)\n", __location__
));
666 status
= smb_raw_exit(session
);
667 CHECK_STATUS(status
, NT_STATUS_OK
);
669 status
= smbcli_request_simple_recv(req
);
670 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
672 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
673 "lock cancel by exit was not immediate (%s)\n", __location__
));
675 torture_comment(tctx
, "testing cancel by ulogoff\n");
676 fname
= BASEDIR
"\\test_ulogoff.txt";
677 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
678 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
679 "Failed to reopen %s - %s\n",
680 fname
, smbcli_errstr(tree
)));
682 io
.lockx
.level
= RAW_LOCK_LOCKX
;
683 io
.lockx
.in
.file
.fnum
= fnum
;
684 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
685 io
.lockx
.in
.timeout
= 0;
686 io
.lockx
.in
.ulock_cnt
= 0;
687 io
.lockx
.in
.lock_cnt
= 1;
688 lock
[0].pid
= session
->pid
;
689 lock
[0].offset
= 100;
691 io
.lockx
.in
.locks
= &lock
[0];
692 status
= smb_raw_lock(tree
, &io
);
693 CHECK_STATUS(status
, NT_STATUS_OK
);
695 io
.lockx
.in
.ulock_cnt
= 0;
696 io
.lockx
.in
.lock_cnt
= 1;
697 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
698 io
.lockx
.in
.timeout
= 0;
699 status
= smb_raw_lock(tree
, &io
);
700 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
702 io
.lockx
.in
.timeout
= 10000;
704 req
= smb_raw_lock_send(tree
, &io
);
705 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
706 "Failed to setup timed lock (%s)\n", __location__
));
708 status
= smb_raw_ulogoff(session
);
709 CHECK_STATUS(status
, NT_STATUS_OK
);
711 status
= smbcli_request_simple_recv(req
);
712 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
713 torture_result(tctx
, TORTURE_FAIL
,
714 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
716 smb_tree_disconnect(tree
);
717 smb_raw_exit(session
);
720 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
722 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
723 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
725 torture_comment(tctx
, "testing cancel by tdis\n");
726 tree
->session
= cli
->session
;
728 fname
= BASEDIR
"\\test_tdis.txt";
729 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
730 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
731 "Failed to reopen %s - %s\n",
732 fname
, smbcli_errstr(tree
)));
734 io
.lockx
.level
= RAW_LOCK_LOCKX
;
735 io
.lockx
.in
.file
.fnum
= fnum
;
736 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
737 io
.lockx
.in
.timeout
= 0;
738 io
.lockx
.in
.ulock_cnt
= 0;
739 io
.lockx
.in
.lock_cnt
= 1;
740 lock
[0].pid
= cli
->session
->pid
;
741 lock
[0].offset
= 100;
743 io
.lockx
.in
.locks
= &lock
[0];
744 status
= smb_raw_lock(tree
, &io
);
745 CHECK_STATUS(status
, NT_STATUS_OK
);
747 status
= smb_raw_lock(tree
, &io
);
748 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
750 io
.lockx
.in
.timeout
= 10000;
752 req
= smb_raw_lock_send(tree
, &io
);
753 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
754 "Failed to setup timed lock (%s)\n", __location__
));
756 status
= smb_tree_disconnect(tree
);
757 CHECK_STATUS(status
, NT_STATUS_OK
);
759 status
= smbcli_request_simple_recv(req
);
760 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
762 torture_assert(tctx
,!(time(NULL
) > t
+2), talloc_asprintf(tctx
,
763 "lock cancel by tdis was not immediate (%s)\n", __location__
));
766 smb_raw_exit(cli
->session
);
767 smbcli_deltree(cli
->tree
, BASEDIR
);
772 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
774 static bool test_errorcode(struct torture_context
*tctx
,
775 struct smbcli_state
*cli
)
779 struct smb_lock_entry lock
[2];
784 struct smbcli_request
*req
;
789 if (!torture_setup_dir(cli
, BASEDIR
)) {
793 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
795 torture_comment(tctx
, "testing with timeout = 0\n");
796 fname
= BASEDIR
"\\test0.txt";
800 * the first run is with t = 0,
801 * the second with t > 0 (=1)
805 * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
806 * this demonstrates that the cache is per fnum
808 op
.openx
.level
= RAW_OPEN_OPENX
;
809 op
.openx
.in
.fname
= fname
;
810 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
811 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| OPENX_MODE_DENY_DOS
;
812 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
813 op
.openx
.in
.search_attrs
= 0;
814 op
.openx
.in
.file_attrs
= 0;
815 op
.openx
.in
.write_time
= 0;
816 op
.openx
.in
.size
= 0;
817 op
.openx
.in
.timeout
= 0;
819 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
820 CHECK_STATUS(status
, NT_STATUS_OK
);
821 fnum
= op
.openx
.out
.file
.fnum
;
823 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
824 CHECK_STATUS(status
, NT_STATUS_OK
);
825 fnum2
= op
.openx
.out
.file
.fnum
;
827 io
.lockx
.level
= RAW_LOCK_LOCKX
;
828 io
.lockx
.in
.file
.fnum
= fnum
;
829 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
830 io
.lockx
.in
.timeout
= t
;
831 io
.lockx
.in
.ulock_cnt
= 0;
832 io
.lockx
.in
.lock_cnt
= 1;
833 lock
[0].pid
= cli
->session
->pid
;
834 lock
[0].offset
= 100;
836 io
.lockx
.in
.locks
= &lock
[0];
837 status
= smb_raw_lock(cli
->tree
, &io
);
838 CHECK_STATUS(status
, NT_STATUS_OK
);
841 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
842 * this also demonstrates that the error code cache is per file handle
843 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
845 io
.lockx
.in
.file
.fnum
= fnum2
;
846 status
= smb_raw_lock(cli
->tree
, &io
);
847 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
849 io
.lockx
.in
.file
.fnum
= fnum
;
850 status
= smb_raw_lock(cli
->tree
, &io
);
851 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
853 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
854 io
.lockx
.in
.file
.fnum
= fnum
;
855 status
= smb_raw_lock(cli
->tree
, &io
);
856 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
858 io
.lockx
.in
.file
.fnum
= fnum2
;
859 status
= smb_raw_lock(cli
->tree
, &io
);
860 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
862 io
.lockx
.in
.file
.fnum
= fnum
;
863 status
= smb_raw_lock(cli
->tree
, &io
);
864 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
866 io
.lockx
.in
.file
.fnum
= fnum2
;
867 status
= smb_raw_lock(cli
->tree
, &io
);
868 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
870 /* demonstrate that the smbpid doesn't matter */
872 io
.lockx
.in
.file
.fnum
= fnum
;
873 status
= smb_raw_lock(cli
->tree
, &io
);
874 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
876 io
.lockx
.in
.file
.fnum
= fnum2
;
877 status
= smb_raw_lock(cli
->tree
, &io
);
878 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
882 * demonstrate the a successful lock with count = 0 and the same offset,
883 * doesn't reset the error cache
885 lock
[0].offset
= 100;
887 io
.lockx
.in
.file
.fnum
= fnum
;
888 status
= smb_raw_lock(cli
->tree
, &io
);
889 CHECK_STATUS(status
, NT_STATUS_OK
);
891 io
.lockx
.in
.file
.fnum
= fnum2
;
892 status
= smb_raw_lock(cli
->tree
, &io
);
893 CHECK_STATUS(status
, NT_STATUS_OK
);
895 lock
[0].offset
= 100;
897 io
.lockx
.in
.file
.fnum
= fnum
;
898 status
= smb_raw_lock(cli
->tree
, &io
);
899 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
901 io
.lockx
.in
.file
.fnum
= fnum2
;
902 status
= smb_raw_lock(cli
->tree
, &io
);
903 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
906 * demonstrate the a successful lock with count = 0 and outside the locked range,
907 * doesn't reset the error cache
909 lock
[0].offset
= 110;
911 io
.lockx
.in
.file
.fnum
= fnum
;
912 status
= smb_raw_lock(cli
->tree
, &io
);
913 CHECK_STATUS(status
, NT_STATUS_OK
);
915 io
.lockx
.in
.file
.fnum
= fnum2
;
916 status
= smb_raw_lock(cli
->tree
, &io
);
917 CHECK_STATUS(status
, NT_STATUS_OK
);
919 lock
[0].offset
= 100;
921 io
.lockx
.in
.file
.fnum
= fnum
;
922 status
= smb_raw_lock(cli
->tree
, &io
);
923 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
925 io
.lockx
.in
.file
.fnum
= fnum2
;
926 status
= smb_raw_lock(cli
->tree
, &io
);
927 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
931 io
.lockx
.in
.file
.fnum
= fnum
;
932 status
= smb_raw_lock(cli
->tree
, &io
);
933 CHECK_STATUS(status
, NT_STATUS_OK
);
935 io
.lockx
.in
.file
.fnum
= fnum2
;
936 status
= smb_raw_lock(cli
->tree
, &io
);
937 CHECK_STATUS(status
, NT_STATUS_OK
);
939 lock
[0].offset
= 100;
941 io
.lockx
.in
.file
.fnum
= fnum
;
942 status
= smb_raw_lock(cli
->tree
, &io
);
943 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
945 io
.lockx
.in
.file
.fnum
= fnum2
;
946 status
= smb_raw_lock(cli
->tree
, &io
);
947 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
949 /* demonstrate that a changing count doesn't reset the error cache */
950 lock
[0].offset
= 100;
952 io
.lockx
.in
.file
.fnum
= fnum
;
953 status
= smb_raw_lock(cli
->tree
, &io
);
954 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
956 io
.lockx
.in
.file
.fnum
= fnum2
;
957 status
= smb_raw_lock(cli
->tree
, &io
);
958 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
960 lock
[0].offset
= 100;
962 io
.lockx
.in
.file
.fnum
= fnum
;
963 status
= smb_raw_lock(cli
->tree
, &io
);
964 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
966 io
.lockx
.in
.file
.fnum
= fnum2
;
967 status
= smb_raw_lock(cli
->tree
, &io
);
968 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
971 * demonstrate the a lock with count = 0 and inside the locked range,
972 * fails and resets the error cache
974 lock
[0].offset
= 101;
976 io
.lockx
.in
.file
.fnum
= fnum
;
977 status
= smb_raw_lock(cli
->tree
, &io
);
978 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
979 status
= smb_raw_lock(cli
->tree
, &io
);
980 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
982 io
.lockx
.in
.file
.fnum
= fnum2
;
983 status
= smb_raw_lock(cli
->tree
, &io
);
984 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
985 status
= smb_raw_lock(cli
->tree
, &io
);
986 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
988 lock
[0].offset
= 100;
990 io
.lockx
.in
.file
.fnum
= fnum
;
991 status
= smb_raw_lock(cli
->tree
, &io
);
992 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
993 status
= smb_raw_lock(cli
->tree
, &io
);
994 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
996 io
.lockx
.in
.file
.fnum
= fnum2
;
997 status
= smb_raw_lock(cli
->tree
, &io
);
998 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
999 status
= smb_raw_lock(cli
->tree
, &io
);
1000 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1002 /* demonstrate the a changing offset, resets the error cache */
1003 lock
[0].offset
= 105;
1005 io
.lockx
.in
.file
.fnum
= fnum
;
1006 status
= smb_raw_lock(cli
->tree
, &io
);
1007 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1008 status
= smb_raw_lock(cli
->tree
, &io
);
1009 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1011 io
.lockx
.in
.file
.fnum
= fnum2
;
1012 status
= smb_raw_lock(cli
->tree
, &io
);
1013 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1014 status
= smb_raw_lock(cli
->tree
, &io
);
1015 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1017 lock
[0].offset
= 100;
1019 io
.lockx
.in
.file
.fnum
= fnum
;
1020 status
= smb_raw_lock(cli
->tree
, &io
);
1021 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1022 status
= smb_raw_lock(cli
->tree
, &io
);
1023 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1025 io
.lockx
.in
.file
.fnum
= fnum2
;
1026 status
= smb_raw_lock(cli
->tree
, &io
);
1027 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1028 status
= smb_raw_lock(cli
->tree
, &io
);
1029 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1031 lock
[0].offset
= 95;
1033 io
.lockx
.in
.file
.fnum
= fnum
;
1034 status
= smb_raw_lock(cli
->tree
, &io
);
1035 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1036 status
= smb_raw_lock(cli
->tree
, &io
);
1037 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1039 io
.lockx
.in
.file
.fnum
= fnum2
;
1040 status
= smb_raw_lock(cli
->tree
, &io
);
1041 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1042 status
= smb_raw_lock(cli
->tree
, &io
);
1043 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1045 lock
[0].offset
= 100;
1047 io
.lockx
.in
.file
.fnum
= fnum
;
1048 status
= smb_raw_lock(cli
->tree
, &io
);
1049 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1050 status
= smb_raw_lock(cli
->tree
, &io
);
1051 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1053 io
.lockx
.in
.file
.fnum
= fnum2
;
1054 status
= smb_raw_lock(cli
->tree
, &io
);
1055 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1056 status
= smb_raw_lock(cli
->tree
, &io
);
1057 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1060 * demonstrate the a successful lock in a different range,
1061 * doesn't reset the cache, the failing lock on the 2nd handle
1062 * resets the resets the cache
1064 lock
[0].offset
= 120;
1066 io
.lockx
.in
.file
.fnum
= fnum
;
1067 status
= smb_raw_lock(cli
->tree
, &io
);
1068 CHECK_STATUS(status
, NT_STATUS_OK
);
1070 io
.lockx
.in
.file
.fnum
= fnum2
;
1071 status
= smb_raw_lock(cli
->tree
, &io
);
1072 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1074 lock
[0].offset
= 100;
1076 io
.lockx
.in
.file
.fnum
= fnum
;
1077 status
= smb_raw_lock(cli
->tree
, &io
);
1078 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1079 status
= smb_raw_lock(cli
->tree
, &io
);
1080 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1082 io
.lockx
.in
.file
.fnum
= fnum2
;
1083 status
= smb_raw_lock(cli
->tree
, &io
);
1084 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1085 status
= smb_raw_lock(cli
->tree
, &io
);
1086 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1088 /* end of the loop */
1090 smb_raw_exit(cli
->session
);
1092 torture_comment(tctx
, "testing with timeout > 0 (=%d)\n",
1094 fname
= BASEDIR
"\\test1.txt";
1099 torture_comment(tctx
, "testing special cases with timeout > 0 (=%d)\n",
1103 * the following 3 test sections demonstrate that
1104 * the cache is only set when the error is reported
1105 * to the client (after the timeout went by)
1107 smb_raw_exit(cli
->session
);
1108 torture_comment(tctx
, "testing a conflict while a lock is pending\n");
1109 fname
= BASEDIR
"\\test2.txt";
1110 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1111 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1112 "Failed to reopen %s - %s\n",
1113 fname
, smbcli_errstr(cli
->tree
)));
1115 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1116 io
.lockx
.in
.file
.fnum
= fnum
;
1117 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1118 io
.lockx
.in
.timeout
= 0;
1119 io
.lockx
.in
.ulock_cnt
= 0;
1120 io
.lockx
.in
.lock_cnt
= 1;
1121 lock
[0].pid
= cli
->session
->pid
;
1122 lock
[0].offset
= 100;
1124 io
.lockx
.in
.locks
= &lock
[0];
1125 status
= smb_raw_lock(cli
->tree
, &io
);
1126 CHECK_STATUS(status
, NT_STATUS_OK
);
1129 io
.lockx
.in
.timeout
= t
;
1130 req
= smb_raw_lock_send(cli
->tree
, &io
);
1131 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1132 "Failed to setup timed lock (%s)\n", __location__
));
1134 io
.lockx
.in
.timeout
= 0;
1135 lock
[0].offset
= 105;
1137 status
= smb_raw_lock(cli
->tree
, &io
);
1138 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1140 status
= smbcli_request_simple_recv(req
);
1141 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1144 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1148 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1149 "lock comes back to early timeout[%d] delay[%d]"
1150 "(%s)\n", t
, delay
, __location__
));
1152 status
= smb_raw_lock(cli
->tree
, &io
);
1153 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1155 smbcli_close(cli
->tree
, fnum
);
1156 fname
= BASEDIR
"\\test3.txt";
1157 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1158 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1159 "Failed to reopen %s - %s\n",
1160 fname
, smbcli_errstr(cli
->tree
)));
1162 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1163 io
.lockx
.in
.file
.fnum
= fnum
;
1164 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1165 io
.lockx
.in
.timeout
= 0;
1166 io
.lockx
.in
.ulock_cnt
= 0;
1167 io
.lockx
.in
.lock_cnt
= 1;
1168 lock
[0].pid
= cli
->session
->pid
;
1169 lock
[0].offset
= 100;
1171 io
.lockx
.in
.locks
= &lock
[0];
1172 status
= smb_raw_lock(cli
->tree
, &io
);
1173 CHECK_STATUS(status
, NT_STATUS_OK
);
1176 io
.lockx
.in
.timeout
= t
;
1177 req
= smb_raw_lock_send(cli
->tree
, &io
);
1178 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1179 "Failed to setup timed lock (%s)\n", __location__
));
1181 io
.lockx
.in
.timeout
= 0;
1182 lock
[0].offset
= 105;
1184 status
= smb_raw_lock(cli
->tree
, &io
);
1185 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1187 status
= smbcli_request_simple_recv(req
);
1188 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1191 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1195 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1196 "lock comes back to early timeout[%d] delay[%d]"
1197 "(%s)\n", t
, delay
, __location__
));
1199 lock
[0].offset
= 100;
1201 status
= smb_raw_lock(cli
->tree
, &io
);
1202 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1204 smbcli_close(cli
->tree
, fnum
);
1205 fname
= BASEDIR
"\\test4.txt";
1206 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1207 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1208 "Failed to reopen %s - %s\n",
1209 fname
, smbcli_errstr(cli
->tree
)));
1211 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1212 io
.lockx
.in
.file
.fnum
= fnum
;
1213 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1214 io
.lockx
.in
.timeout
= 0;
1215 io
.lockx
.in
.ulock_cnt
= 0;
1216 io
.lockx
.in
.lock_cnt
= 1;
1217 lock
[0].pid
= cli
->session
->pid
;
1218 lock
[0].offset
= 100;
1220 io
.lockx
.in
.locks
= &lock
[0];
1221 status
= smb_raw_lock(cli
->tree
, &io
);
1222 CHECK_STATUS(status
, NT_STATUS_OK
);
1225 io
.lockx
.in
.timeout
= t
;
1226 req
= smb_raw_lock_send(cli
->tree
, &io
);
1227 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1228 "Failed to setup timed lock (%s)\n", __location__
));
1230 io
.lockx
.in
.timeout
= 0;
1231 status
= smb_raw_lock(cli
->tree
, &io
);
1232 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1234 status
= smbcli_request_simple_recv(req
);
1235 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1238 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1242 torture_assert(tctx
,!(time(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1243 "lock comes back to early timeout[%d] delay[%d]"
1244 "(%s)\n", t
, delay
, __location__
));
1246 status
= smb_raw_lock(cli
->tree
, &io
);
1247 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1250 smb_raw_exit(cli
->session
);
1251 smbcli_deltree(cli
->tree
, BASEDIR
);
1257 test LOCKING_ANDX_CHANGE_LOCKTYPE
1259 static bool test_changetype(struct torture_context
*tctx
,
1260 struct smbcli_state
*cli
)
1263 struct smb_lock_entry lock
[2];
1268 const char *fname
= BASEDIR
"\\test.txt";
1270 if (!torture_setup_dir(cli
, BASEDIR
)) {
1274 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1275 io
.generic
.level
= RAW_LOCK_LOCKX
;
1277 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1278 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1279 "Failed to create %s - %s\n",
1280 fname
, smbcli_errstr(cli
->tree
)));
1282 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1283 io
.lockx
.in
.file
.fnum
= fnum
;
1284 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1285 io
.lockx
.in
.timeout
= 0;
1286 io
.lockx
.in
.ulock_cnt
= 0;
1287 io
.lockx
.in
.lock_cnt
= 1;
1288 lock
[0].pid
= cli
->session
->pid
;
1289 lock
[0].offset
= 100;
1291 io
.lockx
.in
.locks
= &lock
[0];
1292 status
= smb_raw_lock(cli
->tree
, &io
);
1293 CHECK_STATUS(status
, NT_STATUS_OK
);
1295 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1296 torture_result(tctx
, TORTURE_FAIL
,
1297 "allowed write on read locked region (%s)\n", __location__
);
1302 /* windows server don't seem to support this */
1303 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1304 status
= smb_raw_lock(cli
->tree
, &io
);
1305 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1307 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1308 torture_result(tctx
, TORTURE_FAIL
,
1309 "allowed write after lock change (%s)\n", __location__
);
1315 smbcli_close(cli
->tree
, fnum
);
1316 smb_raw_exit(cli
->session
);
1317 smbcli_deltree(cli
->tree
, BASEDIR
);
1321 struct double_lock_test
{
1322 struct smb_lock_entry lock1
;
1323 struct smb_lock_entry lock2
;
1324 NTSTATUS exp_status
;
1328 * Tests zero byte locks.
1330 static const struct double_lock_test zero_byte_tests
[] = {
1331 /* {pid, offset, count}, {pid, offset, count}, status */
1333 /** First, takes a zero byte lock at offset 10. Then:
1334 * - Taking 0 byte lock at 10 should succeed.
1335 * - Taking 1 byte locks at 9,10,11 should succeed.
1336 * - Taking 2 byte lock at 9 should fail.
1337 * - Taking 2 byte lock at 10 should succeed.
1338 * - Taking 3 byte lock at 9 should fail.
1340 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1341 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1342 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1343 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1344 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1345 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1346 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1348 /** Same, but opposite order. */
1349 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1350 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1351 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1352 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1353 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1354 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1355 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1357 /** Zero zero case. */
1358 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1361 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1367 const char *fname
= BASEDIR
"\\zero.txt";
1369 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1371 if (!torture_setup_dir(cli
, BASEDIR
)) {
1375 io
.generic
.level
= RAW_LOCK_LOCKX
;
1377 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1378 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1379 "Failed to create %s - %s\n",
1380 fname
, smbcli_errstr(cli
->tree
)));
1382 /* Setup initial parameters */
1383 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1384 io
.lockx
.in
.file
.fnum
= fnum
;
1385 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1386 io
.lockx
.in
.timeout
= 0;
1388 /* Try every combination of locks in zero_byte_tests. The first lock is
1389 * assumed to succeed. The second lock may contend, depending on the
1390 * expected status. */
1392 i
< ARRAY_SIZE(zero_byte_tests
);
1394 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1395 zero_byte_tests
[i
].lock1
.pid
,
1396 zero_byte_tests
[i
].lock1
.offset
,
1397 zero_byte_tests
[i
].lock1
.count
,
1398 zero_byte_tests
[i
].lock2
.pid
,
1399 zero_byte_tests
[i
].lock2
.offset
,
1400 zero_byte_tests
[i
].lock2
.count
,
1401 nt_errstr(zero_byte_tests
[i
].exp_status
));
1403 /* Lock both locks. */
1404 io
.lockx
.in
.ulock_cnt
= 0;
1405 io
.lockx
.in
.lock_cnt
= 1;
1407 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock1
;
1408 status
= smb_raw_lock(cli
->tree
, &io
);
1409 CHECK_STATUS(status
, NT_STATUS_OK
);
1411 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock2
;
1412 status
= smb_raw_lock(cli
->tree
, &io
);
1414 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1415 NT_STATUS_LOCK_NOT_GRANTED
)) {
1416 /* Allow either of the failure messages and keep going
1417 * if we see the wrong status. */
1418 CHECK_STATUS_OR_CONT(status
,
1419 NT_STATUS_LOCK_NOT_GRANTED
,
1420 NT_STATUS_FILE_LOCK_CONFLICT
);
1423 CHECK_STATUS_CONT(status
,
1424 zero_byte_tests
[i
].exp_status
);
1427 /* Unlock both locks. */
1428 io
.lockx
.in
.ulock_cnt
= 1;
1429 io
.lockx
.in
.lock_cnt
= 0;
1431 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1432 status
= smb_raw_lock(cli
->tree
, &io
);
1433 CHECK_STATUS(status
, NT_STATUS_OK
);
1436 io
.lockx
.in
.locks
= &zero_byte_tests
[i
].lock1
;
1437 status
= smb_raw_lock(cli
->tree
, &io
);
1438 CHECK_STATUS(status
, NT_STATUS_OK
);
1442 smbcli_close(cli
->tree
, fnum
);
1443 smb_raw_exit(cli
->session
);
1444 smbcli_deltree(cli
->tree
, BASEDIR
);
1448 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1454 const char *fname
= BASEDIR
"\\unlock.txt";
1455 struct smb_lock_entry lock1
;
1456 struct smb_lock_entry lock2
;
1458 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1460 if (!torture_setup_dir(cli
, BASEDIR
)) {
1464 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1465 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1466 "Failed to create %s - %s\n",
1467 fname
, smbcli_errstr(cli
->tree
)));
1469 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1470 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1471 "Failed to create %s - %s\n",
1472 fname
, smbcli_errstr(cli
->tree
)));
1474 /* Setup initial parameters */
1475 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1476 io
.lockx
.in
.timeout
= 0;
1478 lock1
.pid
= cli
->session
->pid
;
1481 lock2
.pid
= cli
->session
->pid
- 1;
1486 * Take exclusive lock, then unlock it with a shared-unlock call.
1488 torture_comment(tctx
, " taking exclusive lock.\n");
1489 io
.lockx
.in
.ulock_cnt
= 0;
1490 io
.lockx
.in
.lock_cnt
= 1;
1491 io
.lockx
.in
.mode
= 0;
1492 io
.lockx
.in
.file
.fnum
= fnum1
;
1493 io
.lockx
.in
.locks
= &lock1
;
1494 status
= smb_raw_lock(cli
->tree
, &io
);
1495 CHECK_STATUS(status
, NT_STATUS_OK
);
1497 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1498 io
.lockx
.in
.ulock_cnt
= 1;
1499 io
.lockx
.in
.lock_cnt
= 0;
1500 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1501 io
.lockx
.in
.file
.fnum
= fnum1
;
1502 io
.lockx
.in
.locks
= &lock1
;
1503 status
= smb_raw_lock(cli
->tree
, &io
);
1504 CHECK_STATUS(status
, NT_STATUS_OK
);
1506 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1507 io
.lockx
.in
.ulock_cnt
= 0;
1508 io
.lockx
.in
.lock_cnt
= 1;
1509 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1510 io
.lockx
.in
.file
.fnum
= fnum2
;
1511 io
.lockx
.in
.locks
= &lock2
;
1512 status
= smb_raw_lock(cli
->tree
, &io
);
1513 CHECK_STATUS(status
, NT_STATUS_OK
);
1516 * Unlock a shared lock with an exclusive-unlock call.
1518 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1519 io
.lockx
.in
.ulock_cnt
= 1;
1520 io
.lockx
.in
.lock_cnt
= 0;
1521 io
.lockx
.in
.mode
= 0;
1522 io
.lockx
.in
.file
.fnum
= fnum2
;
1523 io
.lockx
.in
.locks
= &lock2
;
1524 status
= smb_raw_lock(cli
->tree
, &io
);
1525 CHECK_STATUS(status
, NT_STATUS_OK
);
1527 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1528 io
.lockx
.in
.ulock_cnt
= 0;
1529 io
.lockx
.in
.lock_cnt
= 1;
1530 io
.lockx
.in
.mode
= 0;
1531 io
.lockx
.in
.file
.fnum
= fnum1
;
1532 io
.lockx
.in
.locks
= &lock1
;
1533 status
= smb_raw_lock(cli
->tree
, &io
);
1534 CHECK_STATUS(status
, NT_STATUS_OK
);
1537 io
.lockx
.in
.ulock_cnt
= 1;
1538 io
.lockx
.in
.lock_cnt
= 0;
1539 status
= smb_raw_lock(cli
->tree
, &io
);
1540 CHECK_STATUS(status
, NT_STATUS_OK
);
1543 * Test unlocking of 0-byte locks.
1546 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1547 "always unlocks the exclusive first.\n");
1548 lock1
.pid
= cli
->session
->pid
;
1551 lock2
.pid
= cli
->session
->pid
;
1554 io
.lockx
.in
.ulock_cnt
= 0;
1555 io
.lockx
.in
.lock_cnt
= 1;
1556 io
.lockx
.in
.file
.fnum
= fnum1
;
1557 io
.lockx
.in
.locks
= &lock1
;
1559 /* lock 0-byte shared
1560 * Note: Order of the shared/exclusive locks doesn't matter. */
1561 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1562 status
= smb_raw_lock(cli
->tree
, &io
);
1563 CHECK_STATUS(status
, NT_STATUS_OK
);
1565 /* lock 0-byte exclusive */
1566 io
.lockx
.in
.mode
= 0;
1567 status
= smb_raw_lock(cli
->tree
, &io
);
1568 CHECK_STATUS(status
, NT_STATUS_OK
);
1570 /* test contention */
1571 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1572 io
.lockx
.in
.locks
= &lock2
;
1573 io
.lockx
.in
.file
.fnum
= fnum2
;
1574 status
= smb_raw_lock(cli
->tree
, &io
);
1575 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1576 NT_STATUS_FILE_LOCK_CONFLICT
);
1579 io
.lockx
.in
.ulock_cnt
= 1;
1580 io
.lockx
.in
.lock_cnt
= 0;
1581 io
.lockx
.in
.file
.fnum
= fnum1
;
1582 io
.lockx
.in
.locks
= &lock1
;
1583 status
= smb_raw_lock(cli
->tree
, &io
);
1584 CHECK_STATUS(status
, NT_STATUS_OK
);
1586 /* test - can we take a shared lock? */
1587 io
.lockx
.in
.ulock_cnt
= 0;
1588 io
.lockx
.in
.lock_cnt
= 1;
1589 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1590 io
.lockx
.in
.file
.fnum
= fnum2
;
1591 io
.lockx
.in
.locks
= &lock2
;
1592 status
= smb_raw_lock(cli
->tree
, &io
);
1594 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1595 * new to Win7, it succeeds in WinXP too), until I can come to a
1596 * resolution as to whether Samba should support this or not. There is
1597 * code to preference unlocking exclusive locks before shared locks,
1598 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1599 if (TARGET_IS_SAMBA3(tctx
)) {
1600 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1601 NT_STATUS_FILE_LOCK_CONFLICT
);
1603 CHECK_STATUS(status
, NT_STATUS_OK
);
1607 io
.lockx
.in
.ulock_cnt
= 1;
1608 io
.lockx
.in
.lock_cnt
= 0;
1609 status
= smb_raw_lock(cli
->tree
, &io
);
1611 /* XXX Same as above. */
1612 if (TARGET_IS_SAMBA3(tctx
)) {
1613 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1615 CHECK_STATUS(status
, NT_STATUS_OK
);
1618 io
.lockx
.in
.file
.fnum
= fnum1
;
1619 io
.lockx
.in
.locks
= &lock1
;
1620 status
= smb_raw_lock(cli
->tree
, &io
);
1621 CHECK_STATUS(status
, NT_STATUS_OK
);
1624 smbcli_close(cli
->tree
, fnum1
);
1625 smbcli_close(cli
->tree
, fnum2
);
1626 smb_raw_exit(cli
->session
);
1627 smbcli_deltree(cli
->tree
, BASEDIR
);
1631 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1637 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1638 struct smb_lock_entry lock1
;
1639 struct smb_lock_entry lock2
;
1640 struct smb_lock_entry locks
[2];
1642 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1644 if (!torture_setup_dir(cli
, BASEDIR
)) {
1648 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1649 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1650 "Failed to create %s - %s\n",
1651 fname
, smbcli_errstr(cli
->tree
)));
1653 /* Setup initial parameters */
1654 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1655 io
.lockx
.in
.timeout
= 0;
1657 lock1
.pid
= cli
->session
->pid
;
1660 lock2
.pid
= cli
->session
->pid
;
1667 io
.lockx
.in
.file
.fnum
= fnum1
;
1668 io
.lockx
.in
.mode
= 0; /* exclusive */
1670 /** Test1: Take second lock, but not first. */
1671 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
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_OK
);
1680 /* Try to unlock both locks. */
1681 io
.lockx
.in
.ulock_cnt
= 2;
1682 io
.lockx
.in
.lock_cnt
= 0;
1683 io
.lockx
.in
.locks
= locks
;
1685 status
= smb_raw_lock(cli
->tree
, &io
);
1686 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1688 /* Second lock should not be unlocked. */
1689 io
.lockx
.in
.ulock_cnt
= 0;
1690 io
.lockx
.in
.lock_cnt
= 1;
1691 io
.lockx
.in
.locks
= &lock2
;
1692 status
= smb_raw_lock(cli
->tree
, &io
);
1693 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1696 io
.lockx
.in
.ulock_cnt
= 1;
1697 io
.lockx
.in
.lock_cnt
= 0;
1698 io
.lockx
.in
.locks
= &lock2
;
1699 status
= smb_raw_lock(cli
->tree
, &io
);
1700 CHECK_STATUS(status
, NT_STATUS_OK
);
1702 /** Test2: Take first lock, but not second. */
1703 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
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
);
1712 /* Try to unlock both locks. */
1713 io
.lockx
.in
.ulock_cnt
= 2;
1714 io
.lockx
.in
.lock_cnt
= 0;
1715 io
.lockx
.in
.locks
= locks
;
1717 status
= smb_raw_lock(cli
->tree
, &io
);
1718 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1720 /* First lock should be unlocked. */
1721 io
.lockx
.in
.ulock_cnt
= 0;
1722 io
.lockx
.in
.lock_cnt
= 1;
1723 io
.lockx
.in
.locks
= &lock1
;
1724 status
= smb_raw_lock(cli
->tree
, &io
);
1725 CHECK_STATUS(status
, NT_STATUS_OK
);
1728 io
.lockx
.in
.ulock_cnt
= 1;
1729 io
.lockx
.in
.lock_cnt
= 0;
1730 io
.lockx
.in
.locks
= &lock1
;
1731 status
= smb_raw_lock(cli
->tree
, &io
);
1732 CHECK_STATUS(status
, NT_STATUS_OK
);
1735 smbcli_close(cli
->tree
, fnum1
);
1736 smb_raw_exit(cli
->session
);
1737 smbcli_deltree(cli
->tree
, BASEDIR
);
1742 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1743 * - stacking an exclusive on top of shared fails
1744 * - stacking two exclusives fail
1746 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1752 const char *fname
= BASEDIR
"\\stacking.txt";
1753 struct smb_lock_entry lock1
;
1754 struct smb_lock_entry lock2
;
1756 torture_comment(tctx
, "Testing stacking:\n");
1758 if (!torture_setup_dir(cli
, BASEDIR
)) {
1762 io
.generic
.level
= RAW_LOCK_LOCKX
;
1764 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1765 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1766 "Failed to create %s - %s\n",
1767 fname
, smbcli_errstr(cli
->tree
)));
1769 /* Setup initial parameters */
1770 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1771 io
.lockx
.in
.timeout
= 0;
1773 lock1
.pid
= cli
->session
->pid
;
1776 lock2
.pid
= cli
->session
->pid
- 1;
1781 * Try to take a shared lock, then stack an exclusive.
1783 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
1784 io
.lockx
.in
.file
.fnum
= fnum1
;
1785 io
.lockx
.in
.locks
= &lock1
;
1787 io
.lockx
.in
.ulock_cnt
= 0;
1788 io
.lockx
.in
.lock_cnt
= 1;
1789 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1790 status
= smb_raw_lock(cli
->tree
, &io
);
1791 CHECK_STATUS(status
, NT_STATUS_OK
);
1793 io
.lockx
.in
.ulock_cnt
= 0;
1794 io
.lockx
.in
.lock_cnt
= 1;
1795 io
.lockx
.in
.mode
= 0;
1796 status
= smb_raw_lock(cli
->tree
, &io
);
1797 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1798 NT_STATUS_FILE_LOCK_CONFLICT
);
1801 io
.lockx
.in
.ulock_cnt
= 1;
1802 io
.lockx
.in
.lock_cnt
= 0;
1803 status
= smb_raw_lock(cli
->tree
, &io
);
1804 CHECK_STATUS(status
, NT_STATUS_OK
);
1807 * Prove that two exclusive locks do not stack.
1809 torture_comment(tctx
, " two exclusive locks do not stack.\n");
1810 io
.lockx
.in
.ulock_cnt
= 0;
1811 io
.lockx
.in
.lock_cnt
= 1;
1812 io
.lockx
.in
.mode
= 0;
1813 status
= smb_raw_lock(cli
->tree
, &io
);
1814 CHECK_STATUS(status
, NT_STATUS_OK
);
1815 status
= smb_raw_lock(cli
->tree
, &io
);
1816 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1817 NT_STATUS_FILE_LOCK_CONFLICT
);
1820 io
.lockx
.in
.ulock_cnt
= 1;
1821 io
.lockx
.in
.lock_cnt
= 0;
1822 status
= smb_raw_lock(cli
->tree
, &io
);
1823 CHECK_STATUS(status
, NT_STATUS_OK
);
1826 smbcli_close(cli
->tree
, fnum1
);
1827 smb_raw_exit(cli
->session
);
1828 smbcli_deltree(cli
->tree
, BASEDIR
);
1833 basic testing of lock calls
1835 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
1837 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "LOCK");
1839 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
1840 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
1841 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
1842 torture_suite_add_1smb_test(suite
, "async", test_async
);
1843 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
1844 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
1846 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
1847 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
1848 torture_suite_add_1smb_test(suite
, "multiple_unlock",
1849 test_multiple_unlock
);
1850 torture_suite_add_1smb_test(suite
, "zerobytelocks",
1851 test_zerobytelocks
);