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
);
2267 basic testing of lock calls
2269 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
2271 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "lock");
2273 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
2274 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
2275 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
2276 torture_suite_add_1smb_test(suite
, "async", test_async
);
2277 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
2278 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
2280 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
2281 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
2282 torture_suite_add_1smb_test(suite
, "multiple_unlock",
2283 test_multiple_unlock
);
2284 torture_suite_add_1smb_test(suite
, "zerobytelocks", test_zerobytelocks
);
2285 torture_suite_add_1smb_test(suite
, "zerobyteread", test_zerobyteread
);