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"
32 #include "torture/raw/proto.h"
34 #define CHECK_STATUS(status, correct) do { \
35 if (!NT_STATUS_EQUAL(status, correct)) { \
36 torture_result(tctx, TORTURE_FAIL, \
37 "(%s) Incorrect status %s - should be %s\n", \
38 __location__, nt_errstr(status), nt_errstr(correct)); \
43 #define CHECK_STATUS_CONT(status, correct) do { \
44 if (!NT_STATUS_EQUAL(status, correct)) { \
45 torture_result(tctx, TORTURE_FAIL, \
46 "(%s) Incorrect status %s - should be %s\n", \
47 __location__, nt_errstr(status), nt_errstr(correct)); \
51 #define CHECK_STATUS_OR(status, correct1, correct2) do { \
52 if ((!NT_STATUS_EQUAL(status, correct1)) && \
53 (!NT_STATUS_EQUAL(status, correct2))) { \
54 torture_result(tctx, TORTURE_FAIL, \
55 "(%s) Incorrect status %s - should be %s or %s\n", \
56 __location__, nt_errstr(status), nt_errstr(correct1), \
57 nt_errstr(correct2)); \
62 #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
63 if ((!NT_STATUS_EQUAL(status, correct1)) && \
64 (!NT_STATUS_EQUAL(status, correct2))) { \
65 torture_result(tctx, TORTURE_FAIL, \
66 "(%s) Incorrect status %s - should be %s or %s\n", \
67 __location__, nt_errstr(status), nt_errstr(correct1), \
68 nt_errstr(correct2)); \
71 #define BASEDIR "\\testlock"
73 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
74 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
75 #define TARGET_IS_WINDOWS(_tctx) \
76 ((torture_setting_bool(_tctx, "w2k3", false)) || \
77 (torture_setting_bool(_tctx, "w2k8", false)) || \
78 (torture_setting_bool(_tctx, "win7", false)))
79 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
80 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
82 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
83 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
84 #define TARGET_SUPPORTS_SMBEXIT(_tctx) \
85 (torture_setting_bool(_tctx, "smbexit_pdu_support", true))
86 #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
87 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
88 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
89 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
90 #define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \
91 (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true))
93 test SMBlock and SMBunlock ops
95 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
101 const char *fname
= BASEDIR
"\\test.txt";
103 if (!TARGET_SUPPORTS_SMBLOCK(tctx
))
104 torture_skip(tctx
, "Target does not support the SMBlock PDU");
106 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
108 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
109 io
.generic
.level
= RAW_LOCK_LOCK
;
111 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
112 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
113 "Failed to create %s - %s\n",
114 fname
, smbcli_errstr(cli
->tree
)));
116 torture_comment(tctx
, "Trying 0/0 lock\n");
117 io
.lock
.level
= RAW_LOCK_LOCK
;
118 io
.lock
.in
.file
.fnum
= fnum
;
119 io
.lock
.in
.count
= 0;
120 io
.lock
.in
.offset
= 0;
121 status
= smb_raw_lock(cli
->tree
, &io
);
122 CHECK_STATUS(status
, NT_STATUS_OK
);
124 status
= smb_raw_lock(cli
->tree
, &io
);
125 CHECK_STATUS(status
, NT_STATUS_OK
);
127 io
.lock
.level
= RAW_LOCK_UNLOCK
;
128 status
= smb_raw_lock(cli
->tree
, &io
);
129 CHECK_STATUS(status
, NT_STATUS_OK
);
131 torture_comment(tctx
, "Trying 0/1 lock\n");
132 io
.lock
.level
= RAW_LOCK_LOCK
;
133 io
.lock
.in
.file
.fnum
= fnum
;
134 io
.lock
.in
.count
= 1;
135 io
.lock
.in
.offset
= 0;
136 status
= smb_raw_lock(cli
->tree
, &io
);
137 CHECK_STATUS(status
, NT_STATUS_OK
);
139 status
= smb_raw_lock(cli
->tree
, &io
);
140 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
142 io
.lock
.level
= RAW_LOCK_UNLOCK
;
143 status
= smb_raw_lock(cli
->tree
, &io
);
144 CHECK_STATUS(status
, NT_STATUS_OK
);
145 io
.lock
.level
= RAW_LOCK_UNLOCK
;
146 status
= smb_raw_lock(cli
->tree
, &io
);
147 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
149 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
150 io
.lock
.level
= RAW_LOCK_LOCK
;
151 io
.lock
.in
.file
.fnum
= fnum
;
152 io
.lock
.in
.count
= 4000;
153 io
.lock
.in
.offset
= 0xEEFFFFFF;
154 status
= smb_raw_lock(cli
->tree
, &io
);
155 CHECK_STATUS(status
, NT_STATUS_OK
);
157 status
= smb_raw_lock(cli
->tree
, &io
);
158 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
160 io
.lock
.level
= RAW_LOCK_UNLOCK
;
161 status
= smb_raw_lock(cli
->tree
, &io
);
162 CHECK_STATUS(status
, NT_STATUS_OK
);
163 io
.lock
.level
= RAW_LOCK_UNLOCK
;
164 status
= smb_raw_lock(cli
->tree
, &io
);
165 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
167 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
168 io
.lock
.level
= RAW_LOCK_LOCK
;
169 io
.lock
.in
.file
.fnum
= fnum
;
170 io
.lock
.in
.count
= 4000;
171 io
.lock
.in
.offset
= 0xEEFFFFFF;
172 status
= smb_raw_lock(cli
->tree
, &io
);
173 CHECK_STATUS(status
, NT_STATUS_OK
);
175 status
= smb_raw_lock(cli
->tree
, &io
);
176 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
178 io
.lock
.level
= RAW_LOCK_UNLOCK
;
179 status
= smb_raw_lock(cli
->tree
, &io
);
180 CHECK_STATUS(status
, NT_STATUS_OK
);
181 io
.lock
.level
= RAW_LOCK_UNLOCK
;
182 status
= smb_raw_lock(cli
->tree
, &io
);
183 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
185 torture_comment(tctx
, "Trying max lock\n");
186 io
.lock
.level
= RAW_LOCK_LOCK
;
187 io
.lock
.in
.file
.fnum
= fnum
;
188 io
.lock
.in
.count
= 4000;
189 io
.lock
.in
.offset
= 0xEF000000;
190 status
= smb_raw_lock(cli
->tree
, &io
);
191 CHECK_STATUS(status
, NT_STATUS_OK
);
193 status
= smb_raw_lock(cli
->tree
, &io
);
194 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
196 io
.lock
.level
= RAW_LOCK_UNLOCK
;
197 status
= smb_raw_lock(cli
->tree
, &io
);
198 CHECK_STATUS(status
, NT_STATUS_OK
);
199 io
.lock
.level
= RAW_LOCK_UNLOCK
;
200 status
= smb_raw_lock(cli
->tree
, &io
);
201 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
203 torture_comment(tctx
, "Trying wrong pid unlock\n");
204 io
.lock
.level
= RAW_LOCK_LOCK
;
205 io
.lock
.in
.file
.fnum
= fnum
;
206 io
.lock
.in
.count
= 4002;
207 io
.lock
.in
.offset
= 10001;
208 status
= smb_raw_lock(cli
->tree
, &io
);
209 CHECK_STATUS(status
, NT_STATUS_OK
);
211 io
.lock
.level
= RAW_LOCK_UNLOCK
;
212 status
= smb_raw_lock(cli
->tree
, &io
);
213 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
215 status
= smb_raw_lock(cli
->tree
, &io
);
216 CHECK_STATUS(status
, NT_STATUS_OK
);
219 smbcli_close(cli
->tree
, fnum
);
220 smb_raw_exit(cli
->session
);
221 smbcli_deltree(cli
->tree
, BASEDIR
);
229 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
232 struct smb_lock_entry lock
[1];
236 const char *fname
= BASEDIR
"\\test.txt";
238 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
240 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
241 io
.generic
.level
= RAW_LOCK_LOCKX
;
243 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
244 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
245 "Failed to create %s - %s\n",
246 fname
, smbcli_errstr(cli
->tree
)));
248 io
.lockx
.level
= RAW_LOCK_LOCKX
;
249 io
.lockx
.in
.file
.fnum
= fnum
;
250 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
251 io
.lockx
.in
.timeout
= 0;
252 io
.lockx
.in
.ulock_cnt
= 0;
253 io
.lockx
.in
.lock_cnt
= 1;
254 lock
[0].pid
= cli
->session
->pid
;
257 io
.lockx
.in
.locks
= &lock
[0];
258 status
= smb_raw_lock(cli
->tree
, &io
);
259 CHECK_STATUS(status
, NT_STATUS_OK
);
262 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
263 io
.lockx
.in
.ulock_cnt
= 0;
264 io
.lockx
.in
.lock_cnt
= 1;
265 lock
[0].count
= 4000;
266 lock
[0].offset
= 0xEEFFFFFF;
267 status
= smb_raw_lock(cli
->tree
, &io
);
268 CHECK_STATUS(status
, NT_STATUS_OK
);
270 status
= smb_raw_lock(cli
->tree
, &io
);
271 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
273 io
.lockx
.in
.ulock_cnt
= 1;
274 io
.lockx
.in
.lock_cnt
= 0;
275 status
= smb_raw_lock(cli
->tree
, &io
);
276 CHECK_STATUS(status
, NT_STATUS_OK
);
277 status
= smb_raw_lock(cli
->tree
, &io
);
278 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
280 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
281 io
.lockx
.in
.ulock_cnt
= 0;
282 io
.lockx
.in
.lock_cnt
= 1;
283 lock
[0].count
= 4000;
284 lock
[0].offset
= 0xEF000000;
285 status
= smb_raw_lock(cli
->tree
, &io
);
286 CHECK_STATUS(status
, NT_STATUS_OK
);
288 status
= smb_raw_lock(cli
->tree
, &io
);
289 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
291 io
.lockx
.in
.ulock_cnt
= 1;
292 io
.lockx
.in
.lock_cnt
= 0;
293 status
= smb_raw_lock(cli
->tree
, &io
);
294 CHECK_STATUS(status
, NT_STATUS_OK
);
295 status
= smb_raw_lock(cli
->tree
, &io
);
296 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
298 torture_comment(tctx
, "Trying zero lock\n");
299 io
.lockx
.in
.ulock_cnt
= 0;
300 io
.lockx
.in
.lock_cnt
= 1;
303 status
= smb_raw_lock(cli
->tree
, &io
);
304 CHECK_STATUS(status
, NT_STATUS_OK
);
306 status
= smb_raw_lock(cli
->tree
, &io
);
307 CHECK_STATUS(status
, NT_STATUS_OK
);
309 io
.lockx
.in
.ulock_cnt
= 1;
310 io
.lockx
.in
.lock_cnt
= 0;
311 status
= smb_raw_lock(cli
->tree
, &io
);
312 CHECK_STATUS(status
, NT_STATUS_OK
);
313 status
= smb_raw_lock(cli
->tree
, &io
);
314 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
316 torture_comment(tctx
, "Trying max lock\n");
317 io
.lockx
.in
.ulock_cnt
= 0;
318 io
.lockx
.in
.lock_cnt
= 1;
321 status
= smb_raw_lock(cli
->tree
, &io
);
322 CHECK_STATUS(status
, NT_STATUS_OK
);
324 status
= smb_raw_lock(cli
->tree
, &io
);
325 CHECK_STATUS(status
, NT_STATUS_OK
);
327 io
.lockx
.in
.ulock_cnt
= 1;
328 io
.lockx
.in
.lock_cnt
= 0;
329 status
= smb_raw_lock(cli
->tree
, &io
);
330 CHECK_STATUS(status
, NT_STATUS_OK
);
331 status
= smb_raw_lock(cli
->tree
, &io
);
332 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
334 torture_comment(tctx
, "Trying 2^63\n");
335 io
.lockx
.in
.ulock_cnt
= 0;
336 io
.lockx
.in
.lock_cnt
= 1;
339 lock
[0].offset
<<= 63;
340 status
= smb_raw_lock(cli
->tree
, &io
);
341 CHECK_STATUS(status
, NT_STATUS_OK
);
343 status
= smb_raw_lock(cli
->tree
, &io
);
344 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
346 io
.lockx
.in
.ulock_cnt
= 1;
347 io
.lockx
.in
.lock_cnt
= 0;
348 status
= smb_raw_lock(cli
->tree
, &io
);
349 CHECK_STATUS(status
, NT_STATUS_OK
);
350 status
= smb_raw_lock(cli
->tree
, &io
);
351 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
353 torture_comment(tctx
, "Trying 2^63 - 1\n");
354 io
.lockx
.in
.ulock_cnt
= 0;
355 io
.lockx
.in
.lock_cnt
= 1;
358 lock
[0].offset
<<= 63;
360 status
= smb_raw_lock(cli
->tree
, &io
);
361 CHECK_STATUS(status
, NT_STATUS_OK
);
363 status
= smb_raw_lock(cli
->tree
, &io
);
364 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
366 io
.lockx
.in
.ulock_cnt
= 1;
367 io
.lockx
.in
.lock_cnt
= 0;
368 status
= smb_raw_lock(cli
->tree
, &io
);
369 CHECK_STATUS(status
, NT_STATUS_OK
);
370 status
= smb_raw_lock(cli
->tree
, &io
);
371 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
373 torture_comment(tctx
, "Trying max lock 2\n");
374 io
.lockx
.in
.ulock_cnt
= 0;
375 io
.lockx
.in
.lock_cnt
= 1;
378 status
= smb_raw_lock(cli
->tree
, &io
);
379 CHECK_STATUS(status
, NT_STATUS_OK
);
382 status
= smb_raw_lock(cli
->tree
, &io
);
383 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx
))
384 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
386 CHECK_STATUS(status
, NT_STATUS_OK
);
388 io
.lockx
.in
.ulock_cnt
= 1;
389 io
.lockx
.in
.lock_cnt
= 0;
391 status
= smb_raw_lock(cli
->tree
, &io
);
393 CHECK_STATUS(status
, NT_STATUS_OK
);
394 status
= smb_raw_lock(cli
->tree
, &io
);
395 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
398 smbcli_close(cli
->tree
, fnum
);
399 smb_raw_exit(cli
->session
);
400 smbcli_deltree(cli
->tree
, BASEDIR
);
407 static bool test_pidhigh(struct torture_context
*tctx
,
408 struct smbcli_state
*cli
)
411 struct smb_lock_entry lock
[1];
415 const char *fname
= BASEDIR
"\\test.txt";
418 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
420 torture_comment(tctx
, "Testing high pid\n");
421 io
.generic
.level
= RAW_LOCK_LOCKX
;
423 cli
->session
->pid
= 1;
425 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
426 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
427 "Failed to create %s - %s\n",
428 fname
, smbcli_errstr(cli
->tree
)));
430 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
431 torture_result(tctx
, TORTURE_FAIL
,
432 "Failed to write 1 byte - %s\n",
433 smbcli_errstr(cli
->tree
));
438 io
.lockx
.level
= RAW_LOCK_LOCKX
;
439 io
.lockx
.in
.file
.fnum
= fnum
;
440 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
441 io
.lockx
.in
.timeout
= 0;
442 io
.lockx
.in
.ulock_cnt
= 0;
443 io
.lockx
.in
.lock_cnt
= 1;
444 lock
[0].pid
= cli
->session
->pid
;
446 lock
[0].count
= 0xFFFFFFFF;
447 io
.lockx
.in
.locks
= &lock
[0];
448 status
= smb_raw_lock(cli
->tree
, &io
);
449 CHECK_STATUS(status
, NT_STATUS_OK
);
451 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
452 torture_result(tctx
, TORTURE_FAIL
,
453 "Failed to read 1 byte - %s\n",
454 smbcli_errstr(cli
->tree
));
459 cli
->session
->pid
= 2;
461 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
462 torture_result(tctx
, TORTURE_FAIL
,
463 "pid is incorrect handled for read with lock!\n");
468 cli
->session
->pid
= 0x10001;
470 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
471 torture_result(tctx
, TORTURE_FAIL
,
472 "High pid is used on this server!\n");
475 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
479 smbcli_close(cli
->tree
, fnum
);
480 smb_raw_exit(cli
->session
);
481 smbcli_deltree(cli
->tree
, BASEDIR
);
487 test locking&X async operation
489 static bool test_async(struct torture_context
*tctx
,
490 struct smbcli_state
*cli
)
492 struct smbcli_session
*session
;
493 struct smb_composite_sesssetup setup
;
494 struct smbcli_tree
*tree
;
496 const char *host
, *share
;
498 struct smb_lock_entry lock
[2];
502 const char *fname
= BASEDIR
"\\test.txt";
504 struct smbcli_request
*req
, *req2
;
505 struct smbcli_session_options options
;
507 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
509 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
511 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
512 io
.generic
.level
= RAW_LOCK_LOCKX
;
514 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
515 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
516 "Failed to create %s - %s\n",
517 fname
, smbcli_errstr(cli
->tree
)));
519 io
.lockx
.level
= RAW_LOCK_LOCKX
;
520 io
.lockx
.in
.file
.fnum
= fnum
;
521 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
522 io
.lockx
.in
.timeout
= 0;
523 io
.lockx
.in
.ulock_cnt
= 0;
524 io
.lockx
.in
.lock_cnt
= 1;
525 lock
[0].pid
= cli
->session
->pid
;
526 lock
[0].offset
= 100;
528 lock
[1].pid
= cli
->session
->pid
;
529 lock
[1].offset
= 110;
531 io
.lockx
.in
.locks
= &lock
[0];
532 status
= smb_raw_lock(cli
->tree
, &io
);
533 CHECK_STATUS(status
, NT_STATUS_OK
);
537 torture_comment(tctx
, "Testing cancel by CANCEL_LOCK\n");
539 /* setup a timed lock */
540 io
.lockx
.in
.timeout
= 10000;
541 req
= smb_raw_lock_send(cli
->tree
, &io
);
542 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
543 "Failed to setup timed lock (%s)\n", __location__
));
545 /* cancel the wrong range */
547 io
.lockx
.in
.timeout
= 0;
548 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
549 status
= smb_raw_lock(cli
->tree
, &io
);
550 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
552 /* cancel with the wrong bits set */
553 lock
[0].offset
= 100;
554 io
.lockx
.in
.timeout
= 0;
555 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
556 status
= smb_raw_lock(cli
->tree
, &io
);
557 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
559 /* cancel the right range */
560 lock
[0].offset
= 100;
561 io
.lockx
.in
.timeout
= 0;
562 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
563 status
= smb_raw_lock(cli
->tree
, &io
);
564 CHECK_STATUS(status
, NT_STATUS_OK
);
566 /* receive the failed lock request */
567 status
= smbcli_request_simple_recv(req
);
568 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
570 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
571 "lock cancel was not immediate (%s)\n", __location__
));
573 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
574 * if the lock vector contains one entry. When given mutliple cancel
575 * requests in a single PDU we expect the server to return an
576 * error. Samba4 handles this correctly. Windows servers seem to
577 * accept the request but only cancel the first lock. Samba3
578 * now does what Windows does (JRA).
580 torture_comment(tctx
, "Testing multiple cancel\n");
582 /* acquire second lock */
583 io
.lockx
.in
.timeout
= 0;
584 io
.lockx
.in
.ulock_cnt
= 0;
585 io
.lockx
.in
.lock_cnt
= 1;
586 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
587 io
.lockx
.in
.locks
= &lock
[1];
588 status
= smb_raw_lock(cli
->tree
, &io
);
589 CHECK_STATUS(status
, NT_STATUS_OK
);
591 /* setup 2 timed locks */
593 io
.lockx
.in
.timeout
= 10000;
594 io
.lockx
.in
.lock_cnt
= 1;
595 io
.lockx
.in
.locks
= &lock
[0];
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__
));
599 io
.lockx
.in
.locks
= &lock
[1];
600 req2
= smb_raw_lock_send(cli
->tree
, &io
);
601 torture_assert(tctx
,(req2
!= NULL
), talloc_asprintf(tctx
,
602 "Failed to setup timed lock (%s)\n", __location__
));
604 /* try to cancel both locks in the same packet */
605 io
.lockx
.in
.timeout
= 0;
606 io
.lockx
.in
.lock_cnt
= 2;
607 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
608 io
.lockx
.in
.locks
= lock
;
609 status
= smb_raw_lock(cli
->tree
, &io
);
610 CHECK_STATUS(status
, NT_STATUS_OK
);
612 torture_warning(tctx
, "Target server accepted a lock cancel "
613 "request with multiple locks. This violates "
614 "MS-CIFS 2.2.4.32.1.\n");
616 /* receive the failed lock requests */
617 status
= smbcli_request_simple_recv(req
);
618 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
620 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
621 "first lock was not cancelled immediately (%s)\n",
624 /* send cancel to second lock */
625 io
.lockx
.in
.timeout
= 0;
626 io
.lockx
.in
.lock_cnt
= 1;
627 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
|
628 LOCKING_ANDX_LARGE_FILES
;
629 io
.lockx
.in
.locks
= &lock
[1];
630 status
= smb_raw_lock(cli
->tree
, &io
);
631 CHECK_STATUS(status
, NT_STATUS_OK
);
633 status
= smbcli_request_simple_recv(req2
);
634 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
636 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
637 "second lock was not cancelled immediately (%s)\n",
640 /* cleanup the second lock */
641 io
.lockx
.in
.ulock_cnt
= 1;
642 io
.lockx
.in
.lock_cnt
= 0;
643 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
644 io
.lockx
.in
.locks
= &lock
[1];
645 status
= smb_raw_lock(cli
->tree
, &io
);
646 CHECK_STATUS(status
, NT_STATUS_OK
);
648 /* If a lock request contained multiple ranges and we are cancelling
649 * one while it's still pending, what happens? */
650 torture_comment(tctx
, "Testing cancel 1/2 lock request\n");
652 /* Send request with two ranges */
653 io
.lockx
.in
.timeout
= -1;
654 io
.lockx
.in
.ulock_cnt
= 0;
655 io
.lockx
.in
.lock_cnt
= 2;
656 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
657 io
.lockx
.in
.locks
= lock
;
658 req
= smb_raw_lock_send(cli
->tree
, &io
);
659 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
660 "Failed to setup pending lock (%s)\n", __location__
));
662 /* Try to cancel the first lock range */
663 io
.lockx
.in
.timeout
= 0;
664 io
.lockx
.in
.lock_cnt
= 1;
665 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
666 io
.lockx
.in
.locks
= &lock
[0];
667 status
= smb_raw_lock(cli
->tree
, &io
);
668 CHECK_STATUS(status
, NT_STATUS_OK
);
670 /* Locking request should've failed and second range should be
672 status
= smbcli_request_simple_recv(req
);
673 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
675 io
.lockx
.in
.timeout
= 0;
676 io
.lockx
.in
.ulock_cnt
= 0;
677 io
.lockx
.in
.lock_cnt
= 1;
678 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
679 io
.lockx
.in
.locks
= &lock
[1];
680 status
= smb_raw_lock(cli
->tree
, &io
);
681 CHECK_STATUS(status
, NT_STATUS_OK
);
683 /* Cleanup both locks */
684 io
.lockx
.in
.ulock_cnt
= 2;
685 io
.lockx
.in
.lock_cnt
= 0;
686 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
687 io
.lockx
.in
.locks
= lock
;
688 status
= smb_raw_lock(cli
->tree
, &io
);
689 CHECK_STATUS(status
, NT_STATUS_OK
);
691 torture_comment(tctx
, "Testing cancel 2/2 lock request\n");
693 /* Lock second range so it contends */
694 io
.lockx
.in
.timeout
= 0;
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
.locks
= &lock
[1];
699 status
= smb_raw_lock(cli
->tree
, &io
);
700 CHECK_STATUS(status
, NT_STATUS_OK
);
702 /* Send request with two ranges */
703 io
.lockx
.in
.timeout
= -1;
704 io
.lockx
.in
.ulock_cnt
= 0;
705 io
.lockx
.in
.lock_cnt
= 2;
706 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
707 io
.lockx
.in
.locks
= lock
;
708 req
= smb_raw_lock_send(cli
->tree
, &io
);
709 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
710 "Failed to setup pending lock (%s)\n", __location__
));
712 /* Try to cancel the second lock range */
713 io
.lockx
.in
.timeout
= 0;
714 io
.lockx
.in
.lock_cnt
= 1;
715 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
716 io
.lockx
.in
.locks
= &lock
[1];
717 status
= smb_raw_lock(cli
->tree
, &io
);
718 CHECK_STATUS(status
, NT_STATUS_OK
);
720 /* Locking request should've failed and first range should be
722 status
= smbcli_request_simple_recv(req
);
723 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
725 io
.lockx
.in
.timeout
= 0;
726 io
.lockx
.in
.ulock_cnt
= 0;
727 io
.lockx
.in
.lock_cnt
= 1;
728 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
729 io
.lockx
.in
.locks
= &lock
[0];
730 status
= smb_raw_lock(cli
->tree
, &io
);
731 CHECK_STATUS(status
, NT_STATUS_OK
);
733 /* Cleanup both locks */
734 io
.lockx
.in
.ulock_cnt
= 2;
735 io
.lockx
.in
.lock_cnt
= 0;
736 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
737 io
.lockx
.in
.locks
= lock
;
738 status
= smb_raw_lock(cli
->tree
, &io
);
739 CHECK_STATUS(status
, NT_STATUS_OK
);
741 torture_comment(tctx
, "Testing cancel by unlock\n");
742 io
.lockx
.in
.ulock_cnt
= 0;
743 io
.lockx
.in
.lock_cnt
= 1;
744 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
745 io
.lockx
.in
.timeout
= 0;
746 io
.lockx
.in
.locks
= &lock
[0];
747 status
= smb_raw_lock(cli
->tree
, &io
);
748 CHECK_STATUS(status
, NT_STATUS_OK
);
750 io
.lockx
.in
.timeout
= 5000;
751 req
= smb_raw_lock_send(cli
->tree
, &io
);
752 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
753 "Failed to setup timed lock (%s)\n", __location__
));
755 io
.lockx
.in
.ulock_cnt
= 1;
756 io
.lockx
.in
.lock_cnt
= 0;
757 status
= smb_raw_lock(cli
->tree
, &io
);
758 CHECK_STATUS(status
, NT_STATUS_OK
);
761 status
= smbcli_request_simple_recv(req
);
762 CHECK_STATUS(status
, NT_STATUS_OK
);
764 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
765 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
766 __location__
, (int)(time_mono(NULL
)-t
)));
768 torture_comment(tctx
, "Testing cancel by close\n");
769 io
.lockx
.in
.ulock_cnt
= 0;
770 io
.lockx
.in
.lock_cnt
= 1;
771 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
772 io
.lockx
.in
.timeout
= 0;
773 status
= smb_raw_lock(cli
->tree
, &io
);
774 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
778 * Make the test block on the second lock
779 * request. This is to regression-test 64c0367.
781 uint64_t tmp
= lock
[1].offset
;
782 lock
[1].offset
= lock
[0].offset
;
783 lock
[0].offset
= tmp
;
787 io
.lockx
.in
.timeout
= 10000;
788 io
.lockx
.in
.lock_cnt
= 2;
789 req
= smb_raw_lock_send(cli
->tree
, &io
);
790 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
791 "Failed to setup timed lock (%s)\n", __location__
));
793 status
= smbcli_close(cli
->tree
, fnum
);
794 CHECK_STATUS(status
, NT_STATUS_OK
);
796 status
= smbcli_request_simple_recv(req
);
797 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
798 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
800 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
802 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
803 "lock cancel by close was not immediate (%s)\n", __location__
));
807 * Undo the change for 64c0367
809 uint64_t tmp
= lock
[1].offset
;
810 lock
[1].offset
= lock
[0].offset
;
811 lock
[0].offset
= tmp
;
814 torture_comment(tctx
, "create a new sessions\n");
815 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
816 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
817 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
818 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
819 setup
.in
.credentials
= cmdline_credentials
;
820 setup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
821 status
= smb_composite_sesssetup(session
, &setup
);
822 CHECK_STATUS(status
, NT_STATUS_OK
);
823 session
->vuid
= setup
.out
.vuid
;
825 torture_comment(tctx
, "create new tree context\n");
826 share
= torture_setting_string(tctx
, "share", NULL
);
827 host
= torture_setting_string(tctx
, "host", NULL
);
828 tree
= smbcli_tree_init(session
, tctx
, false);
829 tcon
.generic
.level
= RAW_TCON_TCONX
;
830 tcon
.tconx
.in
.flags
= TCONX_FLAG_EXTENDED_RESPONSE
;
831 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
832 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
833 tcon
.tconx
.in
.device
= "A:";
834 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
835 CHECK_STATUS(status
, NT_STATUS_OK
);
836 tree
->tid
= tcon
.tconx
.out
.tid
;
838 torture_comment(tctx
, "Testing cancel by exit\n");
839 if (TARGET_SUPPORTS_SMBEXIT(tctx
)) {
840 fname
= BASEDIR
"\\test_exit.txt";
841 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
842 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
843 "Failed to reopen %s - %s\n",
844 fname
, smbcli_errstr(tree
)));
846 io
.lockx
.level
= RAW_LOCK_LOCKX
;
847 io
.lockx
.in
.file
.fnum
= fnum
;
848 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
849 io
.lockx
.in
.timeout
= 0;
850 io
.lockx
.in
.ulock_cnt
= 0;
851 io
.lockx
.in
.lock_cnt
= 1;
852 lock
[0].pid
= session
->pid
;
853 lock
[0].offset
= 100;
855 io
.lockx
.in
.locks
= &lock
[0];
856 status
= smb_raw_lock(tree
, &io
);
857 CHECK_STATUS(status
, NT_STATUS_OK
);
859 io
.lockx
.in
.ulock_cnt
= 0;
860 io
.lockx
.in
.lock_cnt
= 1;
861 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
862 io
.lockx
.in
.timeout
= 0;
863 status
= smb_raw_lock(tree
, &io
);
864 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
866 io
.lockx
.in
.timeout
= 10000;
868 req
= smb_raw_lock_send(tree
, &io
);
869 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
870 "Failed to setup timed lock (%s)\n",
873 status
= smb_raw_exit(session
);
874 CHECK_STATUS(status
, NT_STATUS_OK
);
876 status
= smbcli_request_simple_recv(req
);
877 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
878 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
880 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
882 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
883 "lock cancel by exit was not immediate (%s)\n",
887 torture_comment(tctx
,
888 " skipping test, SMBExit not supported\n");
891 torture_comment(tctx
, "Testing cancel by ulogoff\n");
892 fname
= BASEDIR
"\\test_ulogoff.txt";
893 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
894 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
895 "Failed to reopen %s - %s\n",
896 fname
, smbcli_errstr(tree
)));
898 io
.lockx
.level
= RAW_LOCK_LOCKX
;
899 io
.lockx
.in
.file
.fnum
= fnum
;
900 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
901 io
.lockx
.in
.timeout
= 0;
902 io
.lockx
.in
.ulock_cnt
= 0;
903 io
.lockx
.in
.lock_cnt
= 1;
904 lock
[0].pid
= session
->pid
;
905 lock
[0].offset
= 100;
907 io
.lockx
.in
.locks
= &lock
[0];
908 status
= smb_raw_lock(tree
, &io
);
909 CHECK_STATUS(status
, NT_STATUS_OK
);
911 io
.lockx
.in
.ulock_cnt
= 0;
912 io
.lockx
.in
.lock_cnt
= 1;
913 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
914 io
.lockx
.in
.timeout
= 0;
915 status
= smb_raw_lock(tree
, &io
);
916 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
918 io
.lockx
.in
.timeout
= 10000;
920 req
= smb_raw_lock_send(tree
, &io
);
921 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
922 "Failed to setup timed lock (%s)\n", __location__
));
924 status
= smb_raw_ulogoff(session
);
925 CHECK_STATUS(status
, NT_STATUS_OK
);
927 status
= smbcli_request_simple_recv(req
);
928 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
)) {
929 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
930 torture_result(tctx
, TORTURE_FAIL
,
931 "lock not canceled by ulogoff - %s "
932 "(ignored because of vfs_vifs fails it)\n",
934 smb_tree_disconnect(tree
);
935 smb_raw_exit(session
);
938 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
940 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
943 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
944 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
946 torture_comment(tctx
, "Testing cancel by tdis\n");
947 tree
->session
= cli
->session
;
949 fname
= BASEDIR
"\\test_tdis.txt";
950 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
951 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
952 "Failed to reopen %s - %s\n",
953 fname
, smbcli_errstr(tree
)));
955 io
.lockx
.level
= RAW_LOCK_LOCKX
;
956 io
.lockx
.in
.file
.fnum
= fnum
;
957 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
958 io
.lockx
.in
.timeout
= 0;
959 io
.lockx
.in
.ulock_cnt
= 0;
960 io
.lockx
.in
.lock_cnt
= 1;
961 lock
[0].pid
= cli
->session
->pid
;
962 lock
[0].offset
= 100;
964 io
.lockx
.in
.locks
= &lock
[0];
965 status
= smb_raw_lock(tree
, &io
);
966 CHECK_STATUS(status
, NT_STATUS_OK
);
968 status
= smb_raw_lock(tree
, &io
);
969 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
971 io
.lockx
.in
.timeout
= 10000;
973 req
= smb_raw_lock_send(tree
, &io
);
974 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
975 "Failed to setup timed lock (%s)\n", __location__
));
977 status
= smb_tree_disconnect(tree
);
978 CHECK_STATUS(status
, NT_STATUS_OK
);
980 status
= smbcli_request_simple_recv(req
);
981 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
982 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
984 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
986 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
987 "lock cancel by tdis was not immediate (%s)\n", __location__
));
990 smb_raw_exit(cli
->session
);
991 smbcli_deltree(cli
->tree
, BASEDIR
);
996 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
998 static bool test_errorcode(struct torture_context
*tctx
,
999 struct smbcli_state
*cli
)
1003 struct smb_lock_entry lock
[2];
1008 struct smbcli_request
*req
;
1012 uint16_t deny_mode
= 0;
1014 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
1016 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
1018 torture_comment(tctx
, "Testing with timeout = 0\n");
1019 fname
= BASEDIR
"\\test0.txt";
1023 * the first run is with t = 0,
1024 * the second with t > 0 (=1)
1028 * use the DENY_DOS mode, that creates two fnum's of one low-level
1029 * file handle, this demonstrates that the cache is per fnum, not
1032 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx
))
1033 deny_mode
= OPENX_MODE_DENY_DOS
;
1035 deny_mode
= OPENX_MODE_DENY_NONE
;
1037 op
.openx
.level
= RAW_OPEN_OPENX
;
1038 op
.openx
.in
.fname
= fname
;
1039 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1040 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| deny_mode
;
1041 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
1042 op
.openx
.in
.search_attrs
= 0;
1043 op
.openx
.in
.file_attrs
= 0;
1044 op
.openx
.in
.write_time
= 0;
1045 op
.openx
.in
.size
= 0;
1046 op
.openx
.in
.timeout
= 0;
1048 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1049 CHECK_STATUS(status
, NT_STATUS_OK
);
1050 fnum
= op
.openx
.out
.file
.fnum
;
1052 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1053 CHECK_STATUS(status
, NT_STATUS_OK
);
1054 fnum2
= op
.openx
.out
.file
.fnum
;
1056 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1057 io
.lockx
.in
.file
.fnum
= fnum
;
1058 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1059 io
.lockx
.in
.timeout
= t
;
1060 io
.lockx
.in
.ulock_cnt
= 0;
1061 io
.lockx
.in
.lock_cnt
= 1;
1062 lock
[0].pid
= cli
->session
->pid
;
1063 lock
[0].offset
= 100;
1065 io
.lockx
.in
.locks
= &lock
[0];
1066 status
= smb_raw_lock(cli
->tree
, &io
);
1067 CHECK_STATUS(status
, NT_STATUS_OK
);
1070 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
1071 * this also demonstrates that the error code cache is per file handle
1072 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
1074 io
.lockx
.in
.file
.fnum
= fnum2
;
1075 status
= smb_raw_lock(cli
->tree
, &io
);
1076 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1078 io
.lockx
.in
.file
.fnum
= fnum
;
1079 status
= smb_raw_lock(cli
->tree
, &io
);
1080 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1082 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
1083 io
.lockx
.in
.file
.fnum
= fnum
;
1084 status
= smb_raw_lock(cli
->tree
, &io
);
1085 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1087 io
.lockx
.in
.file
.fnum
= fnum2
;
1088 status
= smb_raw_lock(cli
->tree
, &io
);
1089 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1091 io
.lockx
.in
.file
.fnum
= fnum
;
1092 status
= smb_raw_lock(cli
->tree
, &io
);
1093 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1095 io
.lockx
.in
.file
.fnum
= fnum2
;
1096 status
= smb_raw_lock(cli
->tree
, &io
);
1097 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1099 /* demonstrate that the smbpid doesn't matter */
1101 io
.lockx
.in
.file
.fnum
= fnum
;
1102 status
= smb_raw_lock(cli
->tree
, &io
);
1103 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1105 io
.lockx
.in
.file
.fnum
= fnum2
;
1106 status
= smb_raw_lock(cli
->tree
, &io
);
1107 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1111 * demonstrate the a successful lock with count = 0 and the same offset,
1112 * doesn't reset the error cache
1114 lock
[0].offset
= 100;
1116 io
.lockx
.in
.file
.fnum
= fnum
;
1117 status
= smb_raw_lock(cli
->tree
, &io
);
1118 CHECK_STATUS(status
, NT_STATUS_OK
);
1120 io
.lockx
.in
.file
.fnum
= fnum2
;
1121 status
= smb_raw_lock(cli
->tree
, &io
);
1122 CHECK_STATUS(status
, NT_STATUS_OK
);
1124 lock
[0].offset
= 100;
1126 io
.lockx
.in
.file
.fnum
= fnum
;
1127 status
= smb_raw_lock(cli
->tree
, &io
);
1128 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1130 io
.lockx
.in
.file
.fnum
= fnum2
;
1131 status
= smb_raw_lock(cli
->tree
, &io
);
1132 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1135 * demonstrate the a successful lock with count = 0 and outside the locked range,
1136 * doesn't reset the error cache
1138 lock
[0].offset
= 110;
1140 io
.lockx
.in
.file
.fnum
= fnum
;
1141 status
= smb_raw_lock(cli
->tree
, &io
);
1142 CHECK_STATUS(status
, NT_STATUS_OK
);
1144 io
.lockx
.in
.file
.fnum
= fnum2
;
1145 status
= smb_raw_lock(cli
->tree
, &io
);
1146 CHECK_STATUS(status
, NT_STATUS_OK
);
1148 lock
[0].offset
= 100;
1150 io
.lockx
.in
.file
.fnum
= fnum
;
1151 status
= smb_raw_lock(cli
->tree
, &io
);
1152 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1154 io
.lockx
.in
.file
.fnum
= fnum2
;
1155 status
= smb_raw_lock(cli
->tree
, &io
);
1156 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1158 lock
[0].offset
= 99;
1160 io
.lockx
.in
.file
.fnum
= fnum
;
1161 status
= smb_raw_lock(cli
->tree
, &io
);
1162 CHECK_STATUS(status
, NT_STATUS_OK
);
1164 io
.lockx
.in
.file
.fnum
= fnum2
;
1165 status
= smb_raw_lock(cli
->tree
, &io
);
1166 CHECK_STATUS(status
, NT_STATUS_OK
);
1168 lock
[0].offset
= 100;
1170 io
.lockx
.in
.file
.fnum
= fnum
;
1171 status
= smb_raw_lock(cli
->tree
, &io
);
1172 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1174 io
.lockx
.in
.file
.fnum
= fnum2
;
1175 status
= smb_raw_lock(cli
->tree
, &io
);
1176 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1178 /* demonstrate that a changing count doesn't reset the error cache */
1179 lock
[0].offset
= 100;
1181 io
.lockx
.in
.file
.fnum
= fnum
;
1182 status
= smb_raw_lock(cli
->tree
, &io
);
1183 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1185 io
.lockx
.in
.file
.fnum
= fnum2
;
1186 status
= smb_raw_lock(cli
->tree
, &io
);
1187 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1189 lock
[0].offset
= 100;
1191 io
.lockx
.in
.file
.fnum
= fnum
;
1192 status
= smb_raw_lock(cli
->tree
, &io
);
1193 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1195 io
.lockx
.in
.file
.fnum
= fnum2
;
1196 status
= smb_raw_lock(cli
->tree
, &io
);
1197 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1200 * demonstrate the a lock with count = 0 and inside the locked range,
1201 * fails and resets the error cache
1203 lock
[0].offset
= 101;
1205 io
.lockx
.in
.file
.fnum
= fnum
;
1206 status
= smb_raw_lock(cli
->tree
, &io
);
1207 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1208 status
= smb_raw_lock(cli
->tree
, &io
);
1209 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1211 io
.lockx
.in
.file
.fnum
= fnum2
;
1212 status
= smb_raw_lock(cli
->tree
, &io
);
1213 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1214 status
= smb_raw_lock(cli
->tree
, &io
);
1215 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1217 lock
[0].offset
= 100;
1219 io
.lockx
.in
.file
.fnum
= fnum
;
1220 status
= smb_raw_lock(cli
->tree
, &io
);
1221 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1222 status
= smb_raw_lock(cli
->tree
, &io
);
1223 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1225 io
.lockx
.in
.file
.fnum
= fnum2
;
1226 status
= smb_raw_lock(cli
->tree
, &io
);
1227 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1228 status
= smb_raw_lock(cli
->tree
, &io
);
1229 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1231 /* demonstrate the a changing offset, resets the error cache */
1232 lock
[0].offset
= 105;
1234 io
.lockx
.in
.file
.fnum
= fnum
;
1235 status
= smb_raw_lock(cli
->tree
, &io
);
1236 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1237 status
= smb_raw_lock(cli
->tree
, &io
);
1238 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1240 io
.lockx
.in
.file
.fnum
= fnum2
;
1241 status
= smb_raw_lock(cli
->tree
, &io
);
1242 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1243 status
= smb_raw_lock(cli
->tree
, &io
);
1244 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1246 lock
[0].offset
= 100;
1248 io
.lockx
.in
.file
.fnum
= fnum
;
1249 status
= smb_raw_lock(cli
->tree
, &io
);
1250 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1251 status
= smb_raw_lock(cli
->tree
, &io
);
1252 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1254 io
.lockx
.in
.file
.fnum
= fnum2
;
1255 status
= smb_raw_lock(cli
->tree
, &io
);
1256 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1257 status
= smb_raw_lock(cli
->tree
, &io
);
1258 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1260 lock
[0].offset
= 95;
1262 io
.lockx
.in
.file
.fnum
= fnum
;
1263 status
= smb_raw_lock(cli
->tree
, &io
);
1264 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1265 status
= smb_raw_lock(cli
->tree
, &io
);
1266 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1268 io
.lockx
.in
.file
.fnum
= fnum2
;
1269 status
= smb_raw_lock(cli
->tree
, &io
);
1270 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1271 status
= smb_raw_lock(cli
->tree
, &io
);
1272 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1274 lock
[0].offset
= 100;
1276 io
.lockx
.in
.file
.fnum
= fnum
;
1277 status
= smb_raw_lock(cli
->tree
, &io
);
1278 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1279 status
= smb_raw_lock(cli
->tree
, &io
);
1280 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1282 io
.lockx
.in
.file
.fnum
= fnum2
;
1283 status
= smb_raw_lock(cli
->tree
, &io
);
1284 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1285 status
= smb_raw_lock(cli
->tree
, &io
);
1286 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1289 * demonstrate the a successful lock in a different range,
1290 * doesn't reset the cache, the failing lock on the 2nd handle
1293 lock
[0].offset
= 120;
1295 io
.lockx
.in
.file
.fnum
= fnum
;
1296 status
= smb_raw_lock(cli
->tree
, &io
);
1297 CHECK_STATUS(status
, NT_STATUS_OK
);
1299 io
.lockx
.in
.file
.fnum
= fnum2
;
1300 status
= smb_raw_lock(cli
->tree
, &io
);
1301 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1303 lock
[0].offset
= 100;
1305 io
.lockx
.in
.file
.fnum
= fnum
;
1306 status
= smb_raw_lock(cli
->tree
, &io
);
1307 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1308 status
= smb_raw_lock(cli
->tree
, &io
);
1309 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1311 io
.lockx
.in
.file
.fnum
= fnum2
;
1312 status
= smb_raw_lock(cli
->tree
, &io
);
1313 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1314 status
= smb_raw_lock(cli
->tree
, &io
);
1315 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1317 /* end of the loop */
1319 smb_raw_exit(cli
->session
);
1321 torture_comment(tctx
, "Testing with timeout > 0 (=%d)\n",
1323 fname
= BASEDIR
"\\test1.txt";
1328 torture_comment(tctx
, "Testing special cases with timeout > 0 (=%d)\n",
1332 * the following 3 test sections demonstrate that
1333 * the cache is only set when the error is reported
1334 * to the client (after the timeout went by)
1336 smb_raw_exit(cli
->session
);
1337 torture_comment(tctx
, "Testing a conflict while a lock is pending\n");
1338 fname
= BASEDIR
"\\test2.txt";
1339 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1340 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1341 "Failed to reopen %s - %s\n",
1342 fname
, smbcli_errstr(cli
->tree
)));
1344 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1345 io
.lockx
.in
.file
.fnum
= fnum
;
1346 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1347 io
.lockx
.in
.timeout
= 0;
1348 io
.lockx
.in
.ulock_cnt
= 0;
1349 io
.lockx
.in
.lock_cnt
= 1;
1350 lock
[0].pid
= cli
->session
->pid
;
1351 lock
[0].offset
= 100;
1353 io
.lockx
.in
.locks
= &lock
[0];
1354 status
= smb_raw_lock(cli
->tree
, &io
);
1355 CHECK_STATUS(status
, NT_STATUS_OK
);
1357 start
= time_mono(NULL
);
1358 io
.lockx
.in
.timeout
= t
;
1359 req
= smb_raw_lock_send(cli
->tree
, &io
);
1360 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1361 "Failed to setup timed lock (%s)\n", __location__
));
1363 io
.lockx
.in
.timeout
= 0;
1364 lock
[0].offset
= 105;
1366 status
= smb_raw_lock(cli
->tree
, &io
);
1367 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1369 status
= smbcli_request_simple_recv(req
);
1370 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1373 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1377 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1378 "lock comes back to early timeout[%d] delay[%d]"
1379 "(%s)\n", t
, delay
, __location__
));
1381 status
= smb_raw_lock(cli
->tree
, &io
);
1382 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1384 smbcli_close(cli
->tree
, fnum
);
1385 fname
= BASEDIR
"\\test3.txt";
1386 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1387 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1388 "Failed to reopen %s - %s\n",
1389 fname
, smbcli_errstr(cli
->tree
)));
1391 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1392 io
.lockx
.in
.file
.fnum
= fnum
;
1393 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1394 io
.lockx
.in
.timeout
= 0;
1395 io
.lockx
.in
.ulock_cnt
= 0;
1396 io
.lockx
.in
.lock_cnt
= 1;
1397 lock
[0].pid
= cli
->session
->pid
;
1398 lock
[0].offset
= 100;
1400 io
.lockx
.in
.locks
= &lock
[0];
1401 status
= smb_raw_lock(cli
->tree
, &io
);
1402 CHECK_STATUS(status
, NT_STATUS_OK
);
1404 start
= time_mono(NULL
);
1405 io
.lockx
.in
.timeout
= t
;
1406 req
= smb_raw_lock_send(cli
->tree
, &io
);
1407 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1408 "Failed to setup timed lock (%s)\n", __location__
));
1410 io
.lockx
.in
.timeout
= 0;
1411 lock
[0].offset
= 105;
1413 status
= smb_raw_lock(cli
->tree
, &io
);
1414 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1416 status
= smbcli_request_simple_recv(req
);
1417 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1420 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1424 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1425 "lock comes back to early timeout[%d] delay[%d]"
1426 "(%s)\n", t
, delay
, __location__
));
1428 lock
[0].offset
= 100;
1430 status
= smb_raw_lock(cli
->tree
, &io
);
1431 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1433 smbcli_close(cli
->tree
, fnum
);
1434 fname
= BASEDIR
"\\test4.txt";
1435 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1436 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1437 "Failed to reopen %s - %s\n",
1438 fname
, smbcli_errstr(cli
->tree
)));
1440 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1441 io
.lockx
.in
.file
.fnum
= fnum
;
1442 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1443 io
.lockx
.in
.timeout
= 0;
1444 io
.lockx
.in
.ulock_cnt
= 0;
1445 io
.lockx
.in
.lock_cnt
= 1;
1446 lock
[0].pid
= cli
->session
->pid
;
1447 lock
[0].offset
= 100;
1449 io
.lockx
.in
.locks
= &lock
[0];
1450 status
= smb_raw_lock(cli
->tree
, &io
);
1451 CHECK_STATUS(status
, NT_STATUS_OK
);
1453 start
= time_mono(NULL
);
1454 io
.lockx
.in
.timeout
= t
;
1455 req
= smb_raw_lock_send(cli
->tree
, &io
);
1456 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1457 "Failed to setup timed lock (%s)\n", __location__
));
1459 io
.lockx
.in
.timeout
= 0;
1460 status
= smb_raw_lock(cli
->tree
, &io
);
1461 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1463 status
= smbcli_request_simple_recv(req
);
1464 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1467 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1471 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1472 "lock comes back to early timeout[%d] delay[%d]"
1473 "(%s)\n", t
, delay
, __location__
));
1475 status
= smb_raw_lock(cli
->tree
, &io
);
1476 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1479 smb_raw_exit(cli
->session
);
1480 smbcli_deltree(cli
->tree
, BASEDIR
);
1486 test LOCKING_ANDX_CHANGE_LOCKTYPE
1488 static bool test_changetype(struct torture_context
*tctx
,
1489 struct smbcli_state
*cli
)
1492 struct smb_lock_entry lock
[2];
1497 const char *fname
= BASEDIR
"\\test.txt";
1499 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
1501 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1502 io
.generic
.level
= RAW_LOCK_LOCKX
;
1504 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1505 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1506 "Failed to create %s - %s\n",
1507 fname
, smbcli_errstr(cli
->tree
)));
1509 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1510 io
.lockx
.in
.file
.fnum
= fnum
;
1511 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1512 io
.lockx
.in
.timeout
= 0;
1513 io
.lockx
.in
.ulock_cnt
= 0;
1514 io
.lockx
.in
.lock_cnt
= 1;
1515 lock
[0].pid
= cli
->session
->pid
;
1516 lock
[0].offset
= 100;
1518 io
.lockx
.in
.locks
= &lock
[0];
1519 status
= smb_raw_lock(cli
->tree
, &io
);
1520 CHECK_STATUS(status
, NT_STATUS_OK
);
1522 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1523 torture_result(tctx
, TORTURE_FAIL
,
1524 "allowed write on read locked region (%s)\n", __location__
);
1529 /* windows server don't seem to support this */
1530 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1531 status
= smb_raw_lock(cli
->tree
, &io
);
1532 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1534 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1535 torture_result(tctx
, TORTURE_FAIL
,
1536 "allowed write after lock change (%s)\n", __location__
);
1542 smbcli_close(cli
->tree
, fnum
);
1543 smb_raw_exit(cli
->session
);
1544 smbcli_deltree(cli
->tree
, BASEDIR
);
1548 struct double_lock_test
{
1549 struct smb_lock_entry lock1
;
1550 struct smb_lock_entry lock2
;
1551 NTSTATUS exp_status
;
1555 * Tests zero byte locks.
1557 static struct double_lock_test zero_byte_tests
[] = {
1558 /* {pid, offset, count}, {pid, offset, count}, status */
1560 /** First, takes a zero byte lock at offset 10. Then:
1561 * - Taking 0 byte lock at 10 should succeed.
1562 * - Taking 1 byte locks at 9,10,11 should succeed.
1563 * - Taking 2 byte lock at 9 should fail.
1564 * - Taking 2 byte lock at 10 should succeed.
1565 * - Taking 3 byte lock at 9 should fail.
1567 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1568 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1569 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1570 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1571 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1572 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1573 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1575 /** Same, but opposite order. */
1576 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1577 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1578 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1579 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1580 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1581 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1582 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1584 /** Zero zero case. */
1585 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1588 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1594 const char *fname
= BASEDIR
"\\zero.txt";
1596 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1598 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
1600 io
.generic
.level
= RAW_LOCK_LOCKX
;
1602 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1603 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1604 "Failed to create %s - %s\n",
1605 fname
, smbcli_errstr(cli
->tree
)));
1607 /* Setup initial parameters */
1608 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1609 io
.lockx
.in
.file
.fnum
= fnum
;
1610 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1611 io
.lockx
.in
.timeout
= 0;
1613 /* Try every combination of locks in zero_byte_tests. The first lock is
1614 * assumed to succeed. The second lock may contend, depending on the
1615 * expected status. */
1617 i
< ARRAY_SIZE(zero_byte_tests
);
1619 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1620 zero_byte_tests
[i
].lock1
.pid
,
1621 (unsigned long long) zero_byte_tests
[i
].lock1
.offset
,
1622 (unsigned long long) zero_byte_tests
[i
].lock1
.count
,
1623 zero_byte_tests
[i
].lock2
.pid
,
1624 (unsigned long long) zero_byte_tests
[i
].lock2
.offset
,
1625 (unsigned long long) zero_byte_tests
[i
].lock2
.count
,
1626 nt_errstr(zero_byte_tests
[i
].exp_status
));
1628 /* Lock both locks. */
1629 io
.lockx
.in
.ulock_cnt
= 0;
1630 io
.lockx
.in
.lock_cnt
= 1;
1632 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1633 &zero_byte_tests
[i
].lock1
);
1634 status
= smb_raw_lock(cli
->tree
, &io
);
1635 CHECK_STATUS(status
, NT_STATUS_OK
);
1637 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1638 &zero_byte_tests
[i
].lock2
);
1639 status
= smb_raw_lock(cli
->tree
, &io
);
1641 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1642 NT_STATUS_LOCK_NOT_GRANTED
)) {
1643 /* Allow either of the failure messages and keep going
1644 * if we see the wrong status. */
1645 CHECK_STATUS_OR_CONT(status
,
1646 NT_STATUS_LOCK_NOT_GRANTED
,
1647 NT_STATUS_FILE_LOCK_CONFLICT
);
1650 CHECK_STATUS_CONT(status
,
1651 zero_byte_tests
[i
].exp_status
);
1654 /* Unlock both locks. */
1655 io
.lockx
.in
.ulock_cnt
= 1;
1656 io
.lockx
.in
.lock_cnt
= 0;
1658 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1659 status
= smb_raw_lock(cli
->tree
, &io
);
1660 CHECK_STATUS(status
, NT_STATUS_OK
);
1663 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1664 &zero_byte_tests
[i
].lock1
);
1665 status
= smb_raw_lock(cli
->tree
, &io
);
1666 CHECK_STATUS(status
, NT_STATUS_OK
);
1670 smbcli_close(cli
->tree
, fnum
);
1671 smb_raw_exit(cli
->session
);
1672 smbcli_deltree(cli
->tree
, BASEDIR
);
1676 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1682 const char *fname
= BASEDIR
"\\unlock.txt";
1683 struct smb_lock_entry lock1
;
1684 struct smb_lock_entry lock2
;
1686 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1688 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
1690 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1691 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1692 "Failed to create %s - %s\n",
1693 fname
, smbcli_errstr(cli
->tree
)));
1695 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1696 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1697 "Failed to create %s - %s\n",
1698 fname
, smbcli_errstr(cli
->tree
)));
1700 /* Setup initial parameters */
1701 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1702 io
.lockx
.in
.timeout
= 0;
1704 lock1
.pid
= cli
->session
->pid
;
1707 lock2
.pid
= cli
->session
->pid
- 1;
1712 * Take exclusive lock, then unlock it with a shared-unlock call.
1714 torture_comment(tctx
, " taking exclusive lock.\n");
1715 io
.lockx
.in
.ulock_cnt
= 0;
1716 io
.lockx
.in
.lock_cnt
= 1;
1717 io
.lockx
.in
.mode
= 0;
1718 io
.lockx
.in
.file
.fnum
= fnum1
;
1719 io
.lockx
.in
.locks
= &lock1
;
1720 status
= smb_raw_lock(cli
->tree
, &io
);
1721 CHECK_STATUS(status
, NT_STATUS_OK
);
1723 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1724 io
.lockx
.in
.ulock_cnt
= 1;
1725 io
.lockx
.in
.lock_cnt
= 0;
1726 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1727 io
.lockx
.in
.file
.fnum
= fnum1
;
1728 io
.lockx
.in
.locks
= &lock1
;
1729 status
= smb_raw_lock(cli
->tree
, &io
);
1730 CHECK_STATUS(status
, NT_STATUS_OK
);
1732 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1733 io
.lockx
.in
.ulock_cnt
= 0;
1734 io
.lockx
.in
.lock_cnt
= 1;
1735 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1736 io
.lockx
.in
.file
.fnum
= fnum2
;
1737 io
.lockx
.in
.locks
= &lock2
;
1738 status
= smb_raw_lock(cli
->tree
, &io
);
1739 CHECK_STATUS(status
, NT_STATUS_OK
);
1742 * Unlock a shared lock with an exclusive-unlock call.
1744 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1745 io
.lockx
.in
.ulock_cnt
= 1;
1746 io
.lockx
.in
.lock_cnt
= 0;
1747 io
.lockx
.in
.mode
= 0;
1748 io
.lockx
.in
.file
.fnum
= fnum2
;
1749 io
.lockx
.in
.locks
= &lock2
;
1750 status
= smb_raw_lock(cli
->tree
, &io
);
1751 CHECK_STATUS(status
, NT_STATUS_OK
);
1753 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1754 io
.lockx
.in
.ulock_cnt
= 0;
1755 io
.lockx
.in
.lock_cnt
= 1;
1756 io
.lockx
.in
.mode
= 0;
1757 io
.lockx
.in
.file
.fnum
= fnum1
;
1758 io
.lockx
.in
.locks
= &lock1
;
1759 status
= smb_raw_lock(cli
->tree
, &io
);
1760 CHECK_STATUS(status
, NT_STATUS_OK
);
1763 io
.lockx
.in
.ulock_cnt
= 1;
1764 io
.lockx
.in
.lock_cnt
= 0;
1765 status
= smb_raw_lock(cli
->tree
, &io
);
1766 CHECK_STATUS(status
, NT_STATUS_OK
);
1769 * Test unlocking of 0-byte locks.
1772 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1773 "always unlocks the exclusive first.\n");
1774 lock1
.pid
= cli
->session
->pid
;
1777 lock2
.pid
= cli
->session
->pid
;
1780 io
.lockx
.in
.ulock_cnt
= 0;
1781 io
.lockx
.in
.lock_cnt
= 1;
1782 io
.lockx
.in
.file
.fnum
= fnum1
;
1783 io
.lockx
.in
.locks
= &lock1
;
1785 /* lock 0-byte shared
1786 * Note: Order of the shared/exclusive locks doesn't matter. */
1787 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1788 status
= smb_raw_lock(cli
->tree
, &io
);
1789 CHECK_STATUS(status
, NT_STATUS_OK
);
1791 /* lock 0-byte exclusive */
1792 io
.lockx
.in
.mode
= 0;
1793 status
= smb_raw_lock(cli
->tree
, &io
);
1794 CHECK_STATUS(status
, NT_STATUS_OK
);
1796 /* test contention */
1797 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1798 io
.lockx
.in
.locks
= &lock2
;
1799 io
.lockx
.in
.file
.fnum
= fnum2
;
1800 status
= smb_raw_lock(cli
->tree
, &io
);
1801 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1802 NT_STATUS_FILE_LOCK_CONFLICT
);
1805 io
.lockx
.in
.ulock_cnt
= 1;
1806 io
.lockx
.in
.lock_cnt
= 0;
1807 io
.lockx
.in
.file
.fnum
= fnum1
;
1808 io
.lockx
.in
.locks
= &lock1
;
1809 status
= smb_raw_lock(cli
->tree
, &io
);
1810 CHECK_STATUS(status
, NT_STATUS_OK
);
1812 /* test - can we take a shared lock? */
1813 io
.lockx
.in
.ulock_cnt
= 0;
1814 io
.lockx
.in
.lock_cnt
= 1;
1815 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1816 io
.lockx
.in
.file
.fnum
= fnum2
;
1817 io
.lockx
.in
.locks
= &lock2
;
1818 status
= smb_raw_lock(cli
->tree
, &io
);
1820 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1821 * new to Win7, it succeeds in WinXP too), until I can come to a
1822 * resolution as to whether Samba should support this or not. There is
1823 * code to preference unlocking exclusive locks before shared locks,
1824 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1825 if (TARGET_IS_SAMBA3(tctx
)) {
1826 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1827 NT_STATUS_FILE_LOCK_CONFLICT
);
1829 CHECK_STATUS(status
, NT_STATUS_OK
);
1833 io
.lockx
.in
.ulock_cnt
= 1;
1834 io
.lockx
.in
.lock_cnt
= 0;
1835 status
= smb_raw_lock(cli
->tree
, &io
);
1837 /* XXX Same as above. */
1838 if (TARGET_IS_SAMBA3(tctx
)) {
1839 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1841 CHECK_STATUS(status
, NT_STATUS_OK
);
1844 io
.lockx
.in
.file
.fnum
= fnum1
;
1845 io
.lockx
.in
.locks
= &lock1
;
1846 status
= smb_raw_lock(cli
->tree
, &io
);
1847 CHECK_STATUS(status
, NT_STATUS_OK
);
1850 smbcli_close(cli
->tree
, fnum1
);
1851 smbcli_close(cli
->tree
, fnum2
);
1852 smb_raw_exit(cli
->session
);
1853 smbcli_deltree(cli
->tree
, BASEDIR
);
1857 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1863 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1864 struct smb_lock_entry lock1
;
1865 struct smb_lock_entry lock2
;
1866 struct smb_lock_entry locks
[2];
1868 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1870 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
1872 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1873 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1874 "Failed to create %s - %s\n",
1875 fname
, smbcli_errstr(cli
->tree
)));
1877 /* Setup initial parameters */
1878 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1879 io
.lockx
.in
.timeout
= 0;
1881 lock1
.pid
= cli
->session
->pid
;
1884 lock2
.pid
= cli
->session
->pid
;
1891 io
.lockx
.in
.file
.fnum
= fnum1
;
1892 io
.lockx
.in
.mode
= 0; /* exclusive */
1894 /** Test1: Take second lock, but not first. */
1895 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
1898 io
.lockx
.in
.ulock_cnt
= 0;
1899 io
.lockx
.in
.lock_cnt
= 1;
1900 io
.lockx
.in
.locks
= &lock2
;
1901 status
= smb_raw_lock(cli
->tree
, &io
);
1902 CHECK_STATUS(status
, NT_STATUS_OK
);
1904 /* Try to unlock both locks. */
1905 io
.lockx
.in
.ulock_cnt
= 2;
1906 io
.lockx
.in
.lock_cnt
= 0;
1907 io
.lockx
.in
.locks
= locks
;
1909 status
= smb_raw_lock(cli
->tree
, &io
);
1910 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1912 /* Second lock should not be unlocked. */
1913 io
.lockx
.in
.ulock_cnt
= 0;
1914 io
.lockx
.in
.lock_cnt
= 1;
1915 io
.lockx
.in
.locks
= &lock2
;
1916 status
= smb_raw_lock(cli
->tree
, &io
);
1917 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1920 io
.lockx
.in
.ulock_cnt
= 1;
1921 io
.lockx
.in
.lock_cnt
= 0;
1922 io
.lockx
.in
.locks
= &lock2
;
1923 status
= smb_raw_lock(cli
->tree
, &io
);
1924 CHECK_STATUS(status
, NT_STATUS_OK
);
1926 /** Test2: Take first lock, but not second. */
1927 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
1930 io
.lockx
.in
.ulock_cnt
= 0;
1931 io
.lockx
.in
.lock_cnt
= 1;
1932 io
.lockx
.in
.locks
= &lock1
;
1933 status
= smb_raw_lock(cli
->tree
, &io
);
1934 CHECK_STATUS(status
, NT_STATUS_OK
);
1936 /* Try to unlock both locks. */
1937 io
.lockx
.in
.ulock_cnt
= 2;
1938 io
.lockx
.in
.lock_cnt
= 0;
1939 io
.lockx
.in
.locks
= locks
;
1941 status
= smb_raw_lock(cli
->tree
, &io
);
1942 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1944 /* First lock should be unlocked. */
1945 io
.lockx
.in
.ulock_cnt
= 0;
1946 io
.lockx
.in
.lock_cnt
= 1;
1947 io
.lockx
.in
.locks
= &lock1
;
1948 status
= smb_raw_lock(cli
->tree
, &io
);
1949 CHECK_STATUS(status
, NT_STATUS_OK
);
1952 io
.lockx
.in
.ulock_cnt
= 1;
1953 io
.lockx
.in
.lock_cnt
= 0;
1954 io
.lockx
.in
.locks
= &lock1
;
1955 status
= smb_raw_lock(cli
->tree
, &io
);
1956 CHECK_STATUS(status
, NT_STATUS_OK
);
1958 /* Test3: Request 2 locks, second will contend. What happens to the
1960 torture_comment(tctx
, " request 2 locks, second one will contend. "
1961 "Expect both to fail.\n");
1963 /* Lock the second range */
1964 io
.lockx
.in
.ulock_cnt
= 0;
1965 io
.lockx
.in
.lock_cnt
= 1;
1966 io
.lockx
.in
.locks
= &lock2
;
1967 status
= smb_raw_lock(cli
->tree
, &io
);
1968 CHECK_STATUS(status
, NT_STATUS_OK
);
1970 /* Request both locks */
1971 io
.lockx
.in
.ulock_cnt
= 0;
1972 io
.lockx
.in
.lock_cnt
= 2;
1973 io
.lockx
.in
.locks
= locks
;
1975 status
= smb_raw_lock(cli
->tree
, &io
);
1976 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1978 /* First lock should be unlocked. */
1979 io
.lockx
.in
.ulock_cnt
= 0;
1980 io
.lockx
.in
.lock_cnt
= 1;
1981 io
.lockx
.in
.locks
= &lock1
;
1982 status
= smb_raw_lock(cli
->tree
, &io
);
1983 CHECK_STATUS(status
, NT_STATUS_OK
);
1986 io
.lockx
.in
.ulock_cnt
= 2;
1987 io
.lockx
.in
.lock_cnt
= 0;
1988 io
.lockx
.in
.locks
= locks
;
1989 status
= smb_raw_lock(cli
->tree
, &io
);
1990 CHECK_STATUS(status
, NT_STATUS_OK
);
1992 /* Test4: Request unlock and lock. The lock contends, is the unlock
1993 * then re-locked? */
1994 torture_comment(tctx
, " request unlock and lock, second one will "
1995 "contend. Expect the unlock to succeed.\n");
1997 /* Lock both ranges */
1998 io
.lockx
.in
.ulock_cnt
= 0;
1999 io
.lockx
.in
.lock_cnt
= 2;
2000 io
.lockx
.in
.locks
= locks
;
2001 status
= smb_raw_lock(cli
->tree
, &io
);
2002 CHECK_STATUS(status
, NT_STATUS_OK
);
2004 /* Attempt to unlock the first range and lock the second */
2005 io
.lockx
.in
.ulock_cnt
= 1;
2006 io
.lockx
.in
.lock_cnt
= 1;
2007 io
.lockx
.in
.locks
= locks
;
2008 status
= smb_raw_lock(cli
->tree
, &io
);
2009 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
2011 /* The first lock should've been unlocked */
2012 io
.lockx
.in
.ulock_cnt
= 0;
2013 io
.lockx
.in
.lock_cnt
= 1;
2014 io
.lockx
.in
.locks
= &lock1
;
2015 status
= smb_raw_lock(cli
->tree
, &io
);
2016 CHECK_STATUS(status
, NT_STATUS_OK
);
2019 io
.lockx
.in
.ulock_cnt
= 2;
2020 io
.lockx
.in
.lock_cnt
= 0;
2021 io
.lockx
.in
.locks
= locks
;
2022 status
= smb_raw_lock(cli
->tree
, &io
);
2023 CHECK_STATUS(status
, NT_STATUS_OK
);
2026 smbcli_close(cli
->tree
, fnum1
);
2027 smb_raw_exit(cli
->session
);
2028 smbcli_deltree(cli
->tree
, BASEDIR
);
2033 * torture_locktest5 covers stacking pretty well, but its missing two tests:
2034 * - stacking an exclusive on top of shared fails
2035 * - stacking two exclusives fail
2037 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
2043 const char *fname
= BASEDIR
"\\stacking.txt";
2044 struct smb_lock_entry lock1
;
2046 torture_comment(tctx
, "Testing stacking:\n");
2048 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
2050 io
.generic
.level
= RAW_LOCK_LOCKX
;
2052 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2053 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2054 "Failed to create %s - %s\n",
2055 fname
, smbcli_errstr(cli
->tree
)));
2057 /* Setup initial parameters */
2058 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2059 io
.lockx
.in
.timeout
= 0;
2061 lock1
.pid
= cli
->session
->pid
;
2066 * Try to take a shared lock, then stack an exclusive.
2068 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
2069 io
.lockx
.in
.file
.fnum
= fnum1
;
2070 io
.lockx
.in
.locks
= &lock1
;
2072 io
.lockx
.in
.ulock_cnt
= 0;
2073 io
.lockx
.in
.lock_cnt
= 1;
2074 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
2075 status
= smb_raw_lock(cli
->tree
, &io
);
2076 CHECK_STATUS(status
, NT_STATUS_OK
);
2078 io
.lockx
.in
.ulock_cnt
= 0;
2079 io
.lockx
.in
.lock_cnt
= 1;
2080 io
.lockx
.in
.mode
= 0;
2081 status
= smb_raw_lock(cli
->tree
, &io
);
2082 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2083 NT_STATUS_FILE_LOCK_CONFLICT
);
2086 io
.lockx
.in
.ulock_cnt
= 1;
2087 io
.lockx
.in
.lock_cnt
= 0;
2088 status
= smb_raw_lock(cli
->tree
, &io
);
2089 CHECK_STATUS(status
, NT_STATUS_OK
);
2092 * Prove that two exclusive locks do not stack.
2094 torture_comment(tctx
, " two exclusive locks do not stack.\n");
2095 io
.lockx
.in
.ulock_cnt
= 0;
2096 io
.lockx
.in
.lock_cnt
= 1;
2097 io
.lockx
.in
.mode
= 0;
2098 status
= smb_raw_lock(cli
->tree
, &io
);
2099 CHECK_STATUS(status
, NT_STATUS_OK
);
2100 status
= smb_raw_lock(cli
->tree
, &io
);
2101 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2102 NT_STATUS_FILE_LOCK_CONFLICT
);
2105 io
.lockx
.in
.ulock_cnt
= 1;
2106 io
.lockx
.in
.lock_cnt
= 0;
2107 status
= smb_raw_lock(cli
->tree
, &io
);
2108 CHECK_STATUS(status
, NT_STATUS_OK
);
2111 smbcli_close(cli
->tree
, fnum1
);
2112 smb_raw_exit(cli
->session
);
2113 smbcli_deltree(cli
->tree
, BASEDIR
);
2118 * Test how 0-byte read requests contend with byte range locks
2120 static bool test_zerobyteread(struct torture_context
*tctx
,
2121 struct smbcli_state
*cli
)
2128 const char *fname
= BASEDIR
"\\zerobyteread.txt";
2129 struct smb_lock_entry lock1
;
2132 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
2134 io
.generic
.level
= RAW_LOCK_LOCKX
;
2136 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2137 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2138 "Failed to create %s - %s\n",
2139 fname
, smbcli_errstr(cli
->tree
)));
2141 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2142 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
2143 "Failed to create %s - %s\n",
2144 fname
, smbcli_errstr(cli
->tree
)));
2146 /* Setup initial parameters */
2147 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2148 io
.lockx
.in
.timeout
= 0;
2150 lock1
.pid
= cli
->session
->pid
;
2155 rd
.readx
.level
= RAW_READ_READX
;
2157 torture_comment(tctx
, "Testing zero byte read on lock range:\n");
2159 /* Take an exclusive lock */
2160 torture_comment(tctx
, " taking exclusive lock.\n");
2161 io
.lockx
.in
.ulock_cnt
= 0;
2162 io
.lockx
.in
.lock_cnt
= 1;
2163 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2164 io
.lockx
.in
.file
.fnum
= fnum1
;
2165 io
.lockx
.in
.locks
= &lock1
;
2166 status
= smb_raw_lock(cli
->tree
, &io
);
2167 CHECK_STATUS(status
, NT_STATUS_OK
);
2169 /* Try a zero byte read */
2170 torture_comment(tctx
, " reading 0 bytes.\n");
2171 rd
.readx
.in
.file
.fnum
= fnum2
;
2172 rd
.readx
.in
.offset
= 5;
2173 rd
.readx
.in
.mincnt
= 0;
2174 rd
.readx
.in
.maxcnt
= 0;
2175 rd
.readx
.in
.remaining
= 0;
2176 rd
.readx
.in
.read_for_execute
= false;
2177 rd
.readx
.out
.data
= &c
;
2178 status
= smb_raw_read(cli
->tree
, &rd
);
2179 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2180 "zero byte read did not return 0 bytes");
2181 CHECK_STATUS(status
, NT_STATUS_OK
);
2184 io
.lockx
.in
.ulock_cnt
= 1;
2185 io
.lockx
.in
.lock_cnt
= 0;
2186 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2187 io
.lockx
.in
.file
.fnum
= fnum1
;
2188 io
.lockx
.in
.locks
= &lock1
;
2189 status
= smb_raw_lock(cli
->tree
, &io
);
2190 CHECK_STATUS(status
, NT_STATUS_OK
);
2192 torture_comment(tctx
, "Testing zero byte read on zero byte lock "
2195 /* Take an exclusive lock */
2196 torture_comment(tctx
, " taking exclusive 0-byte lock.\n");
2197 io
.lockx
.in
.ulock_cnt
= 0;
2198 io
.lockx
.in
.lock_cnt
= 1;
2199 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2200 io
.lockx
.in
.file
.fnum
= fnum1
;
2201 io
.lockx
.in
.locks
= &lock1
;
2204 status
= smb_raw_lock(cli
->tree
, &io
);
2205 CHECK_STATUS(status
, NT_STATUS_OK
);
2207 /* Try a zero byte read before the lock */
2208 torture_comment(tctx
, " reading 0 bytes before the lock.\n");
2209 rd
.readx
.in
.file
.fnum
= fnum2
;
2210 rd
.readx
.in
.offset
= 4;
2211 rd
.readx
.in
.mincnt
= 0;
2212 rd
.readx
.in
.maxcnt
= 0;
2213 rd
.readx
.in
.remaining
= 0;
2214 rd
.readx
.in
.read_for_execute
= false;
2215 rd
.readx
.out
.data
= &c
;
2216 status
= smb_raw_read(cli
->tree
, &rd
);
2217 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2218 "zero byte read did not return 0 bytes");
2219 CHECK_STATUS(status
, NT_STATUS_OK
);
2221 /* Try a zero byte read on the lock */
2222 torture_comment(tctx
, " reading 0 bytes on the lock.\n");
2223 rd
.readx
.in
.file
.fnum
= fnum2
;
2224 rd
.readx
.in
.offset
= 5;
2225 rd
.readx
.in
.mincnt
= 0;
2226 rd
.readx
.in
.maxcnt
= 0;
2227 rd
.readx
.in
.remaining
= 0;
2228 rd
.readx
.in
.read_for_execute
= false;
2229 rd
.readx
.out
.data
= &c
;
2230 status
= smb_raw_read(cli
->tree
, &rd
);
2231 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2232 "zero byte read did not return 0 bytes");
2233 CHECK_STATUS(status
, NT_STATUS_OK
);
2235 /* Try a zero byte read after the lock */
2236 torture_comment(tctx
, " reading 0 bytes after the lock.\n");
2237 rd
.readx
.in
.file
.fnum
= fnum2
;
2238 rd
.readx
.in
.offset
= 6;
2239 rd
.readx
.in
.mincnt
= 0;
2240 rd
.readx
.in
.maxcnt
= 0;
2241 rd
.readx
.in
.remaining
= 0;
2242 rd
.readx
.in
.read_for_execute
= false;
2243 rd
.readx
.out
.data
= &c
;
2244 status
= smb_raw_read(cli
->tree
, &rd
);
2245 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2246 "zero byte read did not return 0 bytes");
2247 CHECK_STATUS(status
, NT_STATUS_OK
);
2250 io
.lockx
.in
.ulock_cnt
= 1;
2251 io
.lockx
.in
.lock_cnt
= 0;
2252 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2253 io
.lockx
.in
.file
.fnum
= fnum1
;
2254 io
.lockx
.in
.locks
= &lock1
;
2255 status
= smb_raw_lock(cli
->tree
, &io
);
2256 CHECK_STATUS(status
, NT_STATUS_OK
);
2259 smbcli_close(cli
->tree
, fnum1
);
2260 smbcli_close(cli
->tree
, fnum2
);
2261 smb_raw_exit(cli
->session
);
2262 smbcli_deltree(cli
->tree
, BASEDIR
);
2266 test multi Locking&X operation
2268 static bool test_multilock(struct torture_context
*tctx
,
2269 struct smbcli_state
*cli
)
2272 struct smb_lock_entry lock
[2];
2276 const char *fname
= BASEDIR
"\\multilock_test.txt";
2278 struct smbcli_request
*req
;
2279 struct smbcli_session_options options
;
2281 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
2283 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
2285 torture_comment(tctx
, "Testing LOCKING_ANDX multi-lock\n");
2286 io
.generic
.level
= RAW_LOCK_LOCKX
;
2288 /* Create the test file. */
2289 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2290 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
2291 "Failed to create %s - %s\n",
2292 fname
, smbcli_errstr(cli
->tree
)));
2295 * Lock regions 100->109, 120->129 as
2296 * two separate write locks in one request.
2298 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2299 io
.lockx
.in
.file
.fnum
= fnum
;
2300 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
2301 io
.lockx
.in
.timeout
= 0;
2302 io
.lockx
.in
.ulock_cnt
= 0;
2303 io
.lockx
.in
.lock_cnt
= 2;
2304 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2305 lock
[0].pid
= cli
->session
->pid
;
2306 lock
[0].offset
= 100;
2308 lock
[1].pid
= cli
->session
->pid
;
2309 lock
[1].offset
= 120;
2311 io
.lockx
.in
.locks
= &lock
[0];
2312 status
= smb_raw_lock(cli
->tree
, &io
);
2313 CHECK_STATUS(status
, NT_STATUS_OK
);
2316 * Now request the same locks on a different
2317 * context as blocking locks with infinite timeout.
2320 io
.lockx
.in
.timeout
= 20000;
2321 lock
[0].pid
= cli
->session
->pid
+1;
2322 lock
[1].pid
= cli
->session
->pid
+1;
2323 req
= smb_raw_lock_send(cli
->tree
, &io
);
2324 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
2325 "Failed to setup timed locks (%s)\n", __location__
));
2327 /* Unlock lock[0] */
2328 io
.lockx
.in
.timeout
= 0;
2329 io
.lockx
.in
.ulock_cnt
= 1;
2330 io
.lockx
.in
.lock_cnt
= 0;
2331 io
.lockx
.in
.locks
= &lock
[0];
2332 lock
[0].pid
= cli
->session
->pid
;
2333 status
= smb_raw_lock(cli
->tree
, &io
);
2334 CHECK_STATUS(status
, NT_STATUS_OK
);
2336 /* Start the clock. */
2337 t
= time_mono(NULL
);
2339 /* Unlock lock[1] */
2340 io
.lockx
.in
.timeout
= 0;
2341 io
.lockx
.in
.ulock_cnt
= 1;
2342 io
.lockx
.in
.lock_cnt
= 0;
2343 io
.lockx
.in
.locks
= &lock
[1];
2344 lock
[1].pid
= cli
->session
->pid
;
2345 status
= smb_raw_lock(cli
->tree
, &io
);
2346 CHECK_STATUS(status
, NT_STATUS_OK
);
2348 /* receive the successful blocked lock requests */
2349 status
= smbcli_request_simple_recv(req
);
2350 CHECK_STATUS(status
, NT_STATUS_OK
);
2352 /* Fail if this took more than 2 seconds. */
2353 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
2354 "Blocking locks were not granted immediately (%s)\n",
2357 smb_raw_exit(cli
->session
);
2358 smbcli_deltree(cli
->tree
, BASEDIR
);
2363 test multi2 Locking&X operation
2364 This test is designed to show that
2365 lock precedence on the server is based
2366 on the order received, not on the ability
2367 to grant. For example:
2369 A blocked lock request containing 2 locks
2370 will be satified before a subsequent blocked
2371 lock request over one of the same regions,
2372 even if that region is then unlocked. E.g.
2374 (a) lock 100->109, 120->129 (granted)
2375 (b) lock 100->109, 120-129 (blocks)
2376 (c) lock 100->109 (blocks)
2379 lock (c) will not be granted as lock (b)
2380 will take precedence.
2382 static bool test_multilock2(struct torture_context
*tctx
,
2383 struct smbcli_state
*cli
)
2386 struct smb_lock_entry lock
[2];
2390 const char *fname
= BASEDIR
"\\multilock2_test.txt";
2392 struct smbcli_request
*req
;
2393 struct smbcli_request
*req2
;
2394 struct smbcli_session_options options
;
2396 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
2398 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
2400 torture_comment(tctx
, "Testing LOCKING_ANDX multi-lock 2\n");
2401 io
.generic
.level
= RAW_LOCK_LOCKX
;
2403 /* Create the test file. */
2404 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2405 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
2406 "Failed to create %s - %s\n",
2407 fname
, smbcli_errstr(cli
->tree
)));
2410 * Lock regions 100->109, 120->129 as
2411 * two separate write locks in one request.
2413 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2414 io
.lockx
.in
.file
.fnum
= fnum
;
2415 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
2416 io
.lockx
.in
.timeout
= 0;
2417 io
.lockx
.in
.ulock_cnt
= 0;
2418 io
.lockx
.in
.lock_cnt
= 2;
2419 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2420 lock
[0].pid
= cli
->session
->pid
;
2421 lock
[0].offset
= 100;
2423 lock
[1].pid
= cli
->session
->pid
;
2424 lock
[1].offset
= 120;
2426 io
.lockx
.in
.locks
= &lock
[0];
2427 status
= smb_raw_lock(cli
->tree
, &io
);
2428 CHECK_STATUS(status
, NT_STATUS_OK
);
2431 * Now request the same locks on a different
2432 * context as blocking locks.
2435 io
.lockx
.in
.timeout
= 20000;
2436 lock
[0].pid
= cli
->session
->pid
+1;
2437 lock
[1].pid
= cli
->session
->pid
+1;
2438 req
= smb_raw_lock_send(cli
->tree
, &io
);
2439 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
2440 "Failed to setup timed locks (%s)\n", __location__
));
2443 * Request the first lock again on a separate context.
2444 * Wait 2 seconds. This should time out (the previous
2445 * multi-lock request should take precedence).
2448 io
.lockx
.in
.timeout
= 2000;
2449 lock
[0].pid
= cli
->session
->pid
+2;
2450 io
.lockx
.in
.lock_cnt
= 1;
2451 req2
= smb_raw_lock_send(cli
->tree
, &io
);
2452 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
2453 "Failed to setup timed locks (%s)\n", __location__
));
2455 /* Unlock lock[0] */
2456 io
.lockx
.in
.timeout
= 0;
2457 io
.lockx
.in
.ulock_cnt
= 1;
2458 io
.lockx
.in
.lock_cnt
= 0;
2459 io
.lockx
.in
.locks
= &lock
[0];
2460 lock
[0].pid
= cli
->session
->pid
;
2461 status
= smb_raw_lock(cli
->tree
, &io
);
2462 CHECK_STATUS(status
, NT_STATUS_OK
);
2464 /* Did the second lock complete (should time out) ? */
2465 status
= smbcli_request_simple_recv(req2
);
2466 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
2468 /* Start the clock. */
2469 t
= time_mono(NULL
);
2471 /* Unlock lock[1] */
2472 io
.lockx
.in
.timeout
= 0;
2473 io
.lockx
.in
.ulock_cnt
= 1;
2474 io
.lockx
.in
.lock_cnt
= 0;
2475 io
.lockx
.in
.locks
= &lock
[1];
2476 lock
[1].pid
= cli
->session
->pid
;
2477 status
= smb_raw_lock(cli
->tree
, &io
);
2478 CHECK_STATUS(status
, NT_STATUS_OK
);
2480 /* receive the successful blocked lock requests */
2481 status
= smbcli_request_simple_recv(req
);
2482 CHECK_STATUS(status
, NT_STATUS_OK
);
2484 /* Fail if this took more than 2 seconds. */
2485 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
2486 "Blocking locks were not granted immediately (%s)\n",
2489 smb_raw_exit(cli
->session
);
2490 smbcli_deltree(cli
->tree
, BASEDIR
);
2496 basic testing of lock calls
2498 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
2500 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "lock");
2502 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
2503 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
2504 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
2505 torture_suite_add_1smb_test(suite
, "async", test_async
);
2506 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
2507 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
2509 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
2510 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
2511 torture_suite_add_1smb_test(suite
, "multiple_unlock",
2512 test_multiple_unlock
);
2513 torture_suite_add_1smb_test(suite
, "zerobytelocks", test_zerobytelocks
);
2514 torture_suite_add_1smb_test(suite
, "zerobyteread", test_zerobyteread
);
2515 torture_suite_add_1smb_test(suite
, "multilock", test_multilock
);
2516 torture_suite_add_1smb_test(suite
, "multilock2", test_multilock2
);