2 Unix SMB/CIFS implementation.
3 basic raw test suite for oplocks
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 "torture/smbtorture.h"
23 #include "librpc/gen_ndr/security.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/raw/raw_proto.h"
27 #include "libcli/security/security.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 #include "lib/events/events.h"
31 #include "param/param.h"
32 #include "lib/cmdline/popt_common.h"
33 #include "libcli/resolve/resolve.h"
35 #define CHECK_VAL(v, correct) do { \
36 if ((v) != (correct)) { \
37 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
38 __location__, #v, (int)v, (int)correct); \
42 #define CHECK_RANGE(v, min, max) do { \
43 if ((v) < (min) || (v) > (max)) { \
44 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got %d - should be between %d and %d\n", \
45 __location__, #v, (int)v, (int)min, (int)max); \
49 #define CHECK_STRMATCH(v, correct) do { \
50 if (!v || strstr((v),(correct)) == NULL) { \
51 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
52 __location__, #v, v?v:"NULL", correct); \
57 #define CHECK_STATUS(tctx, status, correct) do { \
58 if (!NT_STATUS_EQUAL(status, correct)) { \
59 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
60 nt_errstr(status), nt_errstr(correct)); \
73 #define BASEDIR "\\test_oplock"
76 a handler function for oplock break requests. Ack it as a break to level II if possible
78 static bool oplock_handler_ack_to_given(struct smbcli_transport
*transport
,
79 uint16_t tid
, uint16_t fnum
,
80 uint8_t level
, void *private_data
)
82 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
85 break_info
.fnum
= fnum
;
86 break_info
.level
= level
;
90 case OPLOCK_BREAK_TO_LEVEL_II
:
93 case OPLOCK_BREAK_TO_NONE
:
98 break_info
.failures
++;
100 printf("Acking to %s [0x%02X] in oplock handler\n",
103 return smbcli_oplock_ack(tree
, fnum
, level
);
107 a handler function for oplock break requests. Ack it as a break to none
109 static bool oplock_handler_ack_to_none(struct smbcli_transport
*transport
,
110 uint16_t tid
, uint16_t fnum
,
111 uint8_t level
, void *private_data
)
113 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
114 break_info
.fnum
= fnum
;
115 break_info
.level
= level
;
118 printf("Acking to none in oplock handler\n");
120 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
124 a handler function for oplock break requests. Let it timeout
126 static bool oplock_handler_timeout(struct smbcli_transport
*transport
,
127 uint16_t tid
, uint16_t fnum
,
128 uint8_t level
, void *private_data
)
130 break_info
.fnum
= fnum
;
131 break_info
.level
= level
;
134 printf("Let oplock break timeout\n");
138 static void oplock_handler_close_recv(struct smbcli_request
*req
)
141 status
= smbcli_request_simple_recv(req
);
142 if (!NT_STATUS_IS_OK(status
)) {
143 printf("close failed in oplock_handler_close\n");
144 break_info
.failures
++;
149 a handler function for oplock break requests - close the file
151 static bool oplock_handler_close(struct smbcli_transport
*transport
, uint16_t tid
,
152 uint16_t fnum
, uint8_t level
, void *private_data
)
155 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
156 struct smbcli_request
*req
;
158 break_info
.fnum
= fnum
;
159 break_info
.level
= level
;
162 io
.close
.level
= RAW_CLOSE_CLOSE
;
163 io
.close
.in
.file
.fnum
= fnum
;
164 io
.close
.in
.write_time
= 0;
165 req
= smb_raw_close_send(tree
, &io
);
167 printf("failed to send close in oplock_handler_close\n");
171 req
->async
.fn
= oplock_handler_close_recv
;
172 req
->async
.private_data
= NULL
;
177 static bool open_connection_no_level2_oplocks(struct torture_context
*tctx
,
178 struct smbcli_state
**c
)
181 struct smbcli_options options
;
182 struct smbcli_session_options session_options
;
184 lp_smbcli_options(tctx
->lp_ctx
, &options
);
185 lp_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
187 options
.use_level2_oplocks
= false;
189 status
= smbcli_full_connection(tctx
, c
,
190 torture_setting_string(tctx
, "host", NULL
),
191 lp_smb_ports(tctx
->lp_ctx
),
192 torture_setting_string(tctx
, "share", NULL
),
193 NULL
, lp_socket_options(tctx
->lp_ctx
), cmdline_credentials
,
194 lp_resolve_context(tctx
->lp_ctx
),
195 tctx
->ev
, &options
, &session_options
,
196 lp_iconv_convenience(tctx
->lp_ctx
),
197 lp_gensec_settings(tctx
, tctx
->lp_ctx
));
198 if (!NT_STATUS_IS_OK(status
)) {
199 torture_comment(tctx
, "Failed to open connection - %s\n",
208 Timer handler function notifies the registering function that time is up
210 static void timeout_cb(struct tevent_context
*ev
,
211 struct tevent_timer
*te
,
212 struct timeval current_time
,
215 bool *timesup
= (bool *)private_data
;
221 Wait a short period of time to receive a single oplock break request
223 static void torture_wait_for_oplock_break(struct torture_context
*tctx
)
225 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
226 struct tevent_timer
*te
= NULL
;
228 bool timesup
= false;
229 int old_count
= break_info
.count
;
231 /* Wait .1 seconds for an oplock break */
232 ne
= tevent_timeval_current_ofs(0, 100000);
234 if ((te
= event_add_timed(tctx
->ev
, tmp_ctx
, ne
, timeout_cb
, ×up
))
237 torture_comment(tctx
, "Failed to wait for an oplock break. "
238 "test results may not be accurate.");
242 while (!timesup
&& break_info
.count
< old_count
+ 1) {
243 if (event_loop_once(tctx
->ev
) != 0) {
244 torture_comment(tctx
, "Failed to wait for an oplock "
245 "break. test results may not be "
252 /* We don't know if the timed event fired and was freed, we received
253 * our oplock break, or some other event triggered the loop. Thus,
254 * we create a tmp_ctx to be able to safely free/remove the timed
255 * event in all 3 cases. */
256 talloc_free(tmp_ctx
);
261 static bool test_raw_oplock_exclusive1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
263 const char *fname
= BASEDIR
"\\test_exclusive1.dat";
267 union smb_unlink unl
;
270 if (!torture_setup_dir(cli1
, BASEDIR
)) {
275 smbcli_unlink(cli1
->tree
, fname
);
277 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
282 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
283 io
.ntcreatex
.in
.root_fid
= 0;
284 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
285 io
.ntcreatex
.in
.alloc_size
= 0;
286 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
287 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
288 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
289 io
.ntcreatex
.in
.create_options
= 0;
290 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
291 io
.ntcreatex
.in
.security_flags
= 0;
292 io
.ntcreatex
.in
.fname
= fname
;
294 torture_comment(tctx
, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
295 ZERO_STRUCT(break_info
);
296 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
298 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
299 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
300 fnum
= io
.ntcreatex
.out
.file
.fnum
;
301 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
303 torture_comment(tctx
, "a 2nd open should not cause a break\n");
304 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
305 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
306 torture_wait_for_oplock_break(tctx
);
307 CHECK_VAL(break_info
.count
, 0);
308 CHECK_VAL(break_info
.failures
, 0);
310 torture_comment(tctx
, "unlink it - should also be no break\n");
311 unl
.unlink
.in
.pattern
= fname
;
312 unl
.unlink
.in
.attrib
= 0;
313 status
= smb_raw_unlink(cli2
->tree
, &unl
);
314 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
315 torture_wait_for_oplock_break(tctx
);
316 CHECK_VAL(break_info
.count
, 0);
317 CHECK_VAL(break_info
.failures
, 0);
319 smbcli_close(cli1
->tree
, fnum
);
322 smb_raw_exit(cli1
->session
);
323 smb_raw_exit(cli2
->session
);
324 smbcli_deltree(cli1
->tree
, BASEDIR
);
328 static bool test_raw_oplock_exclusive2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
330 const char *fname
= BASEDIR
"\\test_exclusive2.dat";
334 union smb_unlink unl
;
335 uint16_t fnum
=0, fnum2
=0;
337 if (!torture_setup_dir(cli1
, BASEDIR
)) {
342 smbcli_unlink(cli1
->tree
, fname
);
344 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
349 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
350 io
.ntcreatex
.in
.root_fid
= 0;
351 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
352 io
.ntcreatex
.in
.alloc_size
= 0;
353 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
354 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
355 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
356 io
.ntcreatex
.in
.create_options
= 0;
357 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
358 io
.ntcreatex
.in
.security_flags
= 0;
359 io
.ntcreatex
.in
.fname
= fname
;
361 torture_comment(tctx
, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
362 ZERO_STRUCT(break_info
);
363 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
364 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
365 NTCREATEX_SHARE_ACCESS_WRITE
|
366 NTCREATEX_SHARE_ACCESS_DELETE
;
368 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
369 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
370 fnum
= io
.ntcreatex
.out
.file
.fnum
;
371 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
373 torture_comment(tctx
, "a 2nd open should cause a break to level 2\n");
374 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
375 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
376 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
377 torture_wait_for_oplock_break(tctx
);
378 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
379 CHECK_VAL(break_info
.count
, 1);
380 CHECK_VAL(break_info
.fnum
, fnum
);
381 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
382 CHECK_VAL(break_info
.failures
, 0);
383 ZERO_STRUCT(break_info
);
385 /* now we have 2 level II oplocks... */
386 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
387 unl
.unlink
.in
.pattern
= fname
;
388 unl
.unlink
.in
.attrib
= 0;
389 status
= smb_raw_unlink(cli2
->tree
, &unl
);
390 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
391 torture_wait_for_oplock_break(tctx
);
392 CHECK_VAL(break_info
.count
, 0);
393 CHECK_VAL(break_info
.failures
, 0);
395 torture_comment(tctx
, "close 1st handle\n");
396 smbcli_close(cli1
->tree
, fnum
);
398 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
399 unl
.unlink
.in
.pattern
= fname
;
400 unl
.unlink
.in
.attrib
= 0;
401 status
= smb_raw_unlink(cli2
->tree
, &unl
);
402 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
403 torture_wait_for_oplock_break(tctx
);
404 CHECK_VAL(break_info
.count
, 0);
405 CHECK_VAL(break_info
.failures
, 0);
407 torture_comment(tctx
, "close 2nd handle\n");
408 smbcli_close(cli2
->tree
, fnum2
);
410 torture_comment(tctx
, "unlink it\n");
411 unl
.unlink
.in
.pattern
= fname
;
412 unl
.unlink
.in
.attrib
= 0;
413 status
= smb_raw_unlink(cli2
->tree
, &unl
);
414 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
415 torture_wait_for_oplock_break(tctx
);
416 CHECK_VAL(break_info
.count
, 0);
417 CHECK_VAL(break_info
.failures
, 0);
420 smb_raw_exit(cli1
->session
);
421 smb_raw_exit(cli2
->session
);
422 smbcli_deltree(cli1
->tree
, BASEDIR
);
426 static bool test_raw_oplock_exclusive3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
428 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
432 union smb_setfileinfo sfi
;
435 if (!torture_setup_dir(cli1
, BASEDIR
)) {
440 smbcli_unlink(cli1
->tree
, fname
);
442 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
447 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
448 io
.ntcreatex
.in
.root_fid
= 0;
449 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
450 io
.ntcreatex
.in
.alloc_size
= 0;
451 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
452 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
453 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
454 io
.ntcreatex
.in
.create_options
= 0;
455 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
456 io
.ntcreatex
.in
.security_flags
= 0;
457 io
.ntcreatex
.in
.fname
= fname
;
459 torture_comment(tctx
, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
461 ZERO_STRUCT(break_info
);
462 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
464 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
465 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
466 fnum
= io
.ntcreatex
.out
.file
.fnum
;
467 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
469 torture_comment(tctx
, "setpathinfo EOF should trigger a break to none\n");
471 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
472 sfi
.generic
.in
.file
.path
= fname
;
473 sfi
.end_of_file_info
.in
.size
= 100;
475 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
477 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
478 torture_wait_for_oplock_break(tctx
);
479 CHECK_VAL(break_info
.count
, 1);
480 CHECK_VAL(break_info
.failures
, 0);
481 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
483 smbcli_close(cli1
->tree
, fnum
);
486 smb_raw_exit(cli1
->session
);
487 smb_raw_exit(cli2
->session
);
488 smbcli_deltree(cli1
->tree
, BASEDIR
);
492 static bool test_raw_oplock_exclusive4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
494 const char *fname
= BASEDIR
"\\test_exclusive4.dat";
498 uint16_t fnum
=0, fnum2
=0;
500 if (!torture_setup_dir(cli1
, BASEDIR
)) {
505 smbcli_unlink(cli1
->tree
, fname
);
507 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
512 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
513 io
.ntcreatex
.in
.root_fid
= 0;
514 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
515 io
.ntcreatex
.in
.alloc_size
= 0;
516 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
517 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
518 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
519 io
.ntcreatex
.in
.create_options
= 0;
520 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
521 io
.ntcreatex
.in
.security_flags
= 0;
522 io
.ntcreatex
.in
.fname
= fname
;
524 torture_comment(tctx
, "EXCLUSIVE4: open with exclusive oplock\n");
525 ZERO_STRUCT(break_info
);
526 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
528 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
529 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
530 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
531 fnum
= io
.ntcreatex
.out
.file
.fnum
;
532 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
534 ZERO_STRUCT(break_info
);
535 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
537 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
538 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
539 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
540 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
541 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
542 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
543 torture_wait_for_oplock_break(tctx
);
544 CHECK_VAL(break_info
.count
, 0);
545 CHECK_VAL(break_info
.failures
, 0);
547 smbcli_close(cli1
->tree
, fnum
);
548 smbcli_close(cli2
->tree
, fnum2
);
551 smb_raw_exit(cli1
->session
);
552 smb_raw_exit(cli2
->session
);
553 smbcli_deltree(cli1
->tree
, BASEDIR
);
557 static bool test_raw_oplock_exclusive5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
559 const char *fname
= BASEDIR
"\\test_exclusive5.dat";
563 uint16_t fnum
=0, fnum2
=0;
565 if (!torture_setup_dir(cli1
, BASEDIR
)) {
570 smbcli_unlink(cli1
->tree
, fname
);
572 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
573 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
578 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
579 io
.ntcreatex
.in
.root_fid
= 0;
580 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
581 io
.ntcreatex
.in
.alloc_size
= 0;
582 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
583 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
584 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
585 io
.ntcreatex
.in
.create_options
= 0;
586 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
587 io
.ntcreatex
.in
.security_flags
= 0;
588 io
.ntcreatex
.in
.fname
= fname
;
590 torture_comment(tctx
, "EXCLUSIVE5: open with exclusive oplock\n");
591 ZERO_STRUCT(break_info
);
592 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
595 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
596 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
597 NTCREATEX_SHARE_ACCESS_WRITE
|
598 NTCREATEX_SHARE_ACCESS_DELETE
;
599 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
600 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
601 fnum
= io
.ntcreatex
.out
.file
.fnum
;
602 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
604 ZERO_STRUCT(break_info
);
606 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
608 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
609 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
610 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
611 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
612 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
613 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
614 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
615 torture_wait_for_oplock_break(tctx
);
616 CHECK_VAL(break_info
.count
, 1);
617 CHECK_VAL(break_info
.failures
, 0);
619 smbcli_close(cli1
->tree
, fnum
);
620 smbcli_close(cli2
->tree
, fnum2
);
623 smb_raw_exit(cli1
->session
);
624 smb_raw_exit(cli2
->session
);
625 smbcli_deltree(cli1
->tree
, BASEDIR
);
629 static bool test_raw_oplock_exclusive6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
631 const char *fname1
= BASEDIR
"\\test_exclusive6_1.dat";
632 const char *fname2
= BASEDIR
"\\test_exclusive6_2.dat";
639 if (!torture_setup_dir(cli1
, BASEDIR
)) {
644 smbcli_unlink(cli1
->tree
, fname1
);
645 smbcli_unlink(cli1
->tree
, fname2
);
647 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
652 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
653 io
.ntcreatex
.in
.root_fid
= 0;
654 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
655 io
.ntcreatex
.in
.alloc_size
= 0;
656 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
657 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
658 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
659 io
.ntcreatex
.in
.create_options
= 0;
660 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
661 io
.ntcreatex
.in
.security_flags
= 0;
662 io
.ntcreatex
.in
.fname
= fname1
;
664 torture_comment(tctx
, "EXCLUSIVE6: open a file with an exclusive "
665 "oplock (share mode: none)\n");
666 ZERO_STRUCT(break_info
);
667 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
669 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
670 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
671 fnum
= io
.ntcreatex
.out
.file
.fnum
;
672 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
674 torture_comment(tctx
, "rename should not generate a break but get a "
675 "sharing violation\n");
677 rn
.generic
.level
= RAW_RENAME_RENAME
;
678 rn
.rename
.in
.pattern1
= fname1
;
679 rn
.rename
.in
.pattern2
= fname2
;
680 rn
.rename
.in
.attrib
= 0;
682 torture_comment(tctx
, "trying rename while first file open\n");
683 status
= smb_raw_rename(cli2
->tree
, &rn
);
685 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
686 torture_wait_for_oplock_break(tctx
);
687 CHECK_VAL(break_info
.count
, 0);
688 CHECK_VAL(break_info
.failures
, 0);
690 smbcli_close(cli1
->tree
, fnum
);
693 smb_raw_exit(cli1
->session
);
694 smb_raw_exit(cli2
->session
);
695 smbcli_deltree(cli1
->tree
, BASEDIR
);
699 static bool test_raw_oplock_batch1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
701 const char *fname
= BASEDIR
"\\test_batch1.dat";
705 union smb_unlink unl
;
709 if (!torture_setup_dir(cli1
, BASEDIR
)) {
714 smbcli_unlink(cli1
->tree
, fname
);
716 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
721 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
722 io
.ntcreatex
.in
.root_fid
= 0;
723 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
724 io
.ntcreatex
.in
.alloc_size
= 0;
725 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
726 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
727 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
728 io
.ntcreatex
.in
.create_options
= 0;
729 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
730 io
.ntcreatex
.in
.security_flags
= 0;
731 io
.ntcreatex
.in
.fname
= fname
;
734 with a batch oplock we get a break
736 torture_comment(tctx
, "BATCH1: open with batch oplock\n");
737 ZERO_STRUCT(break_info
);
738 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
739 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
740 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
741 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
742 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
743 fnum
= io
.ntcreatex
.out
.file
.fnum
;
744 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
746 torture_comment(tctx
, "unlink should generate a break\n");
747 unl
.unlink
.in
.pattern
= fname
;
748 unl
.unlink
.in
.attrib
= 0;
749 status
= smb_raw_unlink(cli2
->tree
, &unl
);
750 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
752 torture_wait_for_oplock_break(tctx
);
753 CHECK_VAL(break_info
.count
, 1);
754 CHECK_VAL(break_info
.fnum
, fnum
);
755 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
756 CHECK_VAL(break_info
.failures
, 0);
758 torture_comment(tctx
, "2nd unlink should not generate a break\n");
759 ZERO_STRUCT(break_info
);
760 status
= smb_raw_unlink(cli2
->tree
, &unl
);
761 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
763 torture_wait_for_oplock_break(tctx
);
764 CHECK_VAL(break_info
.count
, 0);
766 torture_comment(tctx
, "writing should generate a self break to none\n");
767 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
769 torture_wait_for_oplock_break(tctx
);
770 torture_wait_for_oplock_break(tctx
);
771 CHECK_VAL(break_info
.count
, 1);
772 CHECK_VAL(break_info
.fnum
, fnum
);
773 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
774 CHECK_VAL(break_info
.failures
, 0);
776 smbcli_close(cli1
->tree
, fnum
);
779 smb_raw_exit(cli1
->session
);
780 smb_raw_exit(cli2
->session
);
781 smbcli_deltree(cli1
->tree
, BASEDIR
);
785 static bool test_raw_oplock_batch2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
787 const char *fname
= BASEDIR
"\\test_batch2.dat";
791 union smb_unlink unl
;
795 if (!torture_setup_dir(cli1
, BASEDIR
)) {
800 smbcli_unlink(cli1
->tree
, fname
);
802 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
807 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
808 io
.ntcreatex
.in
.root_fid
= 0;
809 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
810 io
.ntcreatex
.in
.alloc_size
= 0;
811 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
812 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
813 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
814 io
.ntcreatex
.in
.create_options
= 0;
815 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
816 io
.ntcreatex
.in
.security_flags
= 0;
817 io
.ntcreatex
.in
.fname
= fname
;
819 torture_comment(tctx
, "BATCH2: open with batch oplock\n");
820 ZERO_STRUCT(break_info
);
821 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
822 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
823 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
824 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
825 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
826 fnum
= io
.ntcreatex
.out
.file
.fnum
;
827 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
829 torture_comment(tctx
, "unlink should generate a break, which we ack as break to none\n");
830 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_none
, cli1
->tree
);
831 unl
.unlink
.in
.pattern
= fname
;
832 unl
.unlink
.in
.attrib
= 0;
833 status
= smb_raw_unlink(cli2
->tree
, &unl
);
834 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
836 torture_wait_for_oplock_break(tctx
);
837 CHECK_VAL(break_info
.count
, 1);
838 CHECK_VAL(break_info
.fnum
, fnum
);
839 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
840 CHECK_VAL(break_info
.failures
, 0);
842 torture_comment(tctx
, "2nd unlink should not generate a break\n");
843 ZERO_STRUCT(break_info
);
844 status
= smb_raw_unlink(cli2
->tree
, &unl
);
845 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
847 torture_wait_for_oplock_break(tctx
);
848 CHECK_VAL(break_info
.count
, 0);
850 torture_comment(tctx
, "writing should not generate a break\n");
851 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
853 torture_wait_for_oplock_break(tctx
);
854 CHECK_VAL(break_info
.count
, 0);
856 smbcli_close(cli1
->tree
, fnum
);
859 smb_raw_exit(cli1
->session
);
860 smb_raw_exit(cli2
->session
);
861 smbcli_deltree(cli1
->tree
, BASEDIR
);
865 static bool test_raw_oplock_batch3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
867 const char *fname
= BASEDIR
"\\test_batch3.dat";
871 union smb_unlink unl
;
874 if (!torture_setup_dir(cli1
, BASEDIR
)) {
879 smbcli_unlink(cli1
->tree
, fname
);
881 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
886 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
887 io
.ntcreatex
.in
.root_fid
= 0;
888 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
889 io
.ntcreatex
.in
.alloc_size
= 0;
890 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
891 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
892 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
893 io
.ntcreatex
.in
.create_options
= 0;
894 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
895 io
.ntcreatex
.in
.security_flags
= 0;
896 io
.ntcreatex
.in
.fname
= fname
;
898 torture_comment(tctx
, "BATCH3: if we close on break then the unlink can succeed\n");
899 ZERO_STRUCT(break_info
);
900 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
901 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
902 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
903 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
904 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
905 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
906 fnum
= io
.ntcreatex
.out
.file
.fnum
;
907 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
909 unl
.unlink
.in
.pattern
= fname
;
910 unl
.unlink
.in
.attrib
= 0;
911 ZERO_STRUCT(break_info
);
912 status
= smb_raw_unlink(cli2
->tree
, &unl
);
913 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
915 torture_wait_for_oplock_break(tctx
);
916 CHECK_VAL(break_info
.count
, 1);
917 CHECK_VAL(break_info
.fnum
, fnum
);
918 CHECK_VAL(break_info
.level
, 1);
919 CHECK_VAL(break_info
.failures
, 0);
921 smbcli_close(cli1
->tree
, fnum
);
924 smb_raw_exit(cli1
->session
);
925 smb_raw_exit(cli2
->session
);
926 smbcli_deltree(cli1
->tree
, BASEDIR
);
930 static bool test_raw_oplock_batch4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
932 const char *fname
= BASEDIR
"\\test_batch4.dat";
939 if (!torture_setup_dir(cli1
, BASEDIR
)) {
944 smbcli_unlink(cli1
->tree
, fname
);
946 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
951 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
952 io
.ntcreatex
.in
.root_fid
= 0;
953 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
954 io
.ntcreatex
.in
.alloc_size
= 0;
955 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
956 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
957 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
958 io
.ntcreatex
.in
.create_options
= 0;
959 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
960 io
.ntcreatex
.in
.security_flags
= 0;
961 io
.ntcreatex
.in
.fname
= fname
;
963 torture_comment(tctx
, "BATCH4: a self read should not cause a break\n");
964 ZERO_STRUCT(break_info
);
965 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
967 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
968 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
969 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
970 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
971 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
972 fnum
= io
.ntcreatex
.out
.file
.fnum
;
973 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
975 rd
.read
.level
= RAW_READ_READ
;
976 rd
.read
.in
.file
.fnum
= fnum
;
977 rd
.read
.in
.count
= 1;
978 rd
.read
.in
.offset
= 0;
979 rd
.read
.in
.remaining
= 0;
980 status
= smb_raw_read(cli1
->tree
, &rd
);
981 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
982 torture_wait_for_oplock_break(tctx
);
983 CHECK_VAL(break_info
.count
, 0);
984 CHECK_VAL(break_info
.failures
, 0);
986 smbcli_close(cli1
->tree
, fnum
);
989 smb_raw_exit(cli1
->session
);
990 smb_raw_exit(cli2
->session
);
991 smbcli_deltree(cli1
->tree
, BASEDIR
);
995 static bool test_raw_oplock_batch5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
997 const char *fname
= BASEDIR
"\\test_batch5.dat";
1003 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1008 smbcli_unlink(cli1
->tree
, fname
);
1010 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1013 base ntcreatex parms
1015 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1016 io
.ntcreatex
.in
.root_fid
= 0;
1017 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1018 io
.ntcreatex
.in
.alloc_size
= 0;
1019 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1020 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1021 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1022 io
.ntcreatex
.in
.create_options
= 0;
1023 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1024 io
.ntcreatex
.in
.security_flags
= 0;
1025 io
.ntcreatex
.in
.fname
= fname
;
1027 torture_comment(tctx
, "BATCH5: a 2nd open should give a break\n");
1028 ZERO_STRUCT(break_info
);
1029 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1031 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1032 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1033 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1034 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1035 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1036 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1037 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1039 ZERO_STRUCT(break_info
);
1041 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1042 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1043 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1045 torture_wait_for_oplock_break(tctx
);
1046 CHECK_VAL(break_info
.count
, 1);
1047 CHECK_VAL(break_info
.fnum
, fnum
);
1048 CHECK_VAL(break_info
.level
, 1);
1049 CHECK_VAL(break_info
.failures
, 0);
1051 smbcli_close(cli1
->tree
, fnum
);
1054 smb_raw_exit(cli1
->session
);
1055 smb_raw_exit(cli2
->session
);
1056 smbcli_deltree(cli1
->tree
, BASEDIR
);
1060 static bool test_raw_oplock_batch6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1062 const char *fname
= BASEDIR
"\\test_batch6.dat";
1066 uint16_t fnum
=0, fnum2
=0;
1069 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1074 smbcli_unlink(cli1
->tree
, fname
);
1076 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1077 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1080 base ntcreatex parms
1082 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1083 io
.ntcreatex
.in
.root_fid
= 0;
1084 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1085 io
.ntcreatex
.in
.alloc_size
= 0;
1086 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1087 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1088 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1089 io
.ntcreatex
.in
.create_options
= 0;
1090 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1091 io
.ntcreatex
.in
.security_flags
= 0;
1092 io
.ntcreatex
.in
.fname
= fname
;
1094 torture_comment(tctx
, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1095 ZERO_STRUCT(break_info
);
1097 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
1098 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1099 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1100 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1101 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1102 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1103 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1104 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1105 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1107 ZERO_STRUCT(break_info
);
1109 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1110 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1111 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1112 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1114 //torture_wait_for_oplock_break(tctx);
1115 CHECK_VAL(break_info
.count
, 1);
1116 CHECK_VAL(break_info
.fnum
, fnum
);
1117 CHECK_VAL(break_info
.level
, 1);
1118 CHECK_VAL(break_info
.failures
, 0);
1119 ZERO_STRUCT(break_info
);
1121 torture_comment(tctx
, "write should trigger a break to none on both\n");
1122 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1124 /* We expect two breaks */
1125 torture_wait_for_oplock_break(tctx
);
1126 torture_wait_for_oplock_break(tctx
);
1128 CHECK_VAL(break_info
.count
, 2);
1129 CHECK_VAL(break_info
.level
, 0);
1130 CHECK_VAL(break_info
.failures
, 0);
1132 smbcli_close(cli1
->tree
, fnum
);
1133 smbcli_close(cli2
->tree
, fnum2
);
1136 smb_raw_exit(cli1
->session
);
1137 smb_raw_exit(cli2
->session
);
1138 smbcli_deltree(cli1
->tree
, BASEDIR
);
1142 static bool test_raw_oplock_batch7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1144 const char *fname
= BASEDIR
"\\test_batch7.dat";
1148 uint16_t fnum
=0, fnum2
=0;
1150 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1155 smbcli_unlink(cli1
->tree
, fname
);
1157 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1160 base ntcreatex parms
1162 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1163 io
.ntcreatex
.in
.root_fid
= 0;
1164 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1165 io
.ntcreatex
.in
.alloc_size
= 0;
1166 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1167 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1168 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1169 io
.ntcreatex
.in
.create_options
= 0;
1170 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1171 io
.ntcreatex
.in
.security_flags
= 0;
1172 io
.ntcreatex
.in
.fname
= fname
;
1174 torture_comment(tctx
, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1175 ZERO_STRUCT(break_info
);
1176 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1178 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1179 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1180 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1181 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1182 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1183 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1184 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1185 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1186 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1188 ZERO_STRUCT(break_info
);
1190 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1191 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1192 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1193 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1194 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1195 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1196 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1198 torture_wait_for_oplock_break(tctx
);
1199 CHECK_VAL(break_info
.count
, 1);
1200 CHECK_VAL(break_info
.fnum
, fnum2
);
1201 CHECK_VAL(break_info
.level
, 1);
1202 CHECK_VAL(break_info
.failures
, 0);
1204 smbcli_close(cli2
->tree
, fnum
);
1207 smb_raw_exit(cli1
->session
);
1208 smb_raw_exit(cli2
->session
);
1209 smbcli_deltree(cli1
->tree
, BASEDIR
);
1213 static bool test_raw_oplock_batch8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1215 const char *fname
= BASEDIR
"\\test_batch8.dat";
1219 uint16_t fnum
=0, fnum2
=0;
1221 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1226 smbcli_unlink(cli1
->tree
, fname
);
1228 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1231 base ntcreatex parms
1233 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1234 io
.ntcreatex
.in
.root_fid
= 0;
1235 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1236 io
.ntcreatex
.in
.alloc_size
= 0;
1237 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1238 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1239 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1240 io
.ntcreatex
.in
.create_options
= 0;
1241 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1242 io
.ntcreatex
.in
.security_flags
= 0;
1243 io
.ntcreatex
.in
.fname
= fname
;
1245 torture_comment(tctx
, "BATCH8: open with batch oplock\n");
1246 ZERO_STRUCT(break_info
);
1247 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1249 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1250 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1251 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1252 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1253 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1254 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1255 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1257 ZERO_STRUCT(break_info
);
1258 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
1260 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1261 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1262 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1263 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1264 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1265 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1266 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1267 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1268 torture_wait_for_oplock_break(tctx
);
1269 CHECK_VAL(break_info
.count
, 0);
1270 CHECK_VAL(break_info
.failures
, 0);
1272 smbcli_close(cli1
->tree
, fnum
);
1273 smbcli_close(cli2
->tree
, fnum2
);
1276 smb_raw_exit(cli1
->session
);
1277 smb_raw_exit(cli2
->session
);
1278 smbcli_deltree(cli1
->tree
, BASEDIR
);
1282 static bool test_raw_oplock_batch9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1284 const char *fname
= BASEDIR
"\\test_batch9.dat";
1288 uint16_t fnum
=0, fnum2
=0;
1291 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1296 smbcli_unlink(cli1
->tree
, fname
);
1298 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1301 base ntcreatex parms
1303 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1304 io
.ntcreatex
.in
.root_fid
= 0;
1305 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1306 io
.ntcreatex
.in
.alloc_size
= 0;
1307 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1308 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1309 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1310 io
.ntcreatex
.in
.create_options
= 0;
1311 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1312 io
.ntcreatex
.in
.security_flags
= 0;
1313 io
.ntcreatex
.in
.fname
= fname
;
1315 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1317 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1318 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1319 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1320 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1321 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1322 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1323 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1324 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1325 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1327 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1329 ZERO_STRUCT(break_info
);
1330 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1332 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1333 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1334 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1335 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1336 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1337 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1338 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1339 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1340 torture_wait_for_oplock_break(tctx
);
1341 CHECK_VAL(break_info
.count
, 1);
1342 CHECK_VAL(break_info
.fnum
, fnum
);
1343 CHECK_VAL(break_info
.failures
, 0);
1344 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1345 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1346 smbcli_close(cli2
->tree
, fnum2
);
1348 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1349 ZERO_STRUCT(break_info
);
1350 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1351 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1352 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1353 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1354 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1355 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1356 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1357 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1358 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1359 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1360 torture_wait_for_oplock_break(tctx
);
1361 CHECK_VAL(break_info
.count
, 0);
1362 CHECK_VAL(break_info
.failures
, 0);
1363 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1365 ZERO_STRUCT(break_info
);
1367 torture_comment(tctx
, "write should trigger a break to none on both\n");
1368 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1370 /* We expect two breaks */
1371 torture_wait_for_oplock_break(tctx
);
1372 torture_wait_for_oplock_break(tctx
);
1374 CHECK_VAL(break_info
.count
, 2);
1375 CHECK_VAL(break_info
.level
, 0);
1376 CHECK_VAL(break_info
.failures
, 0);
1378 smbcli_close(cli1
->tree
, fnum
);
1379 smbcli_close(cli2
->tree
, fnum2
);
1382 smb_raw_exit(cli1
->session
);
1383 smb_raw_exit(cli2
->session
);
1384 smbcli_deltree(cli1
->tree
, BASEDIR
);
1388 static bool test_raw_oplock_batch10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1390 const char *fname
= BASEDIR
"\\test_batch10.dat";
1394 uint16_t fnum
=0, fnum2
=0;
1396 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1401 smbcli_unlink(cli1
->tree
, fname
);
1403 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1406 base ntcreatex parms
1408 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1409 io
.ntcreatex
.in
.root_fid
= 0;
1410 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1411 io
.ntcreatex
.in
.alloc_size
= 0;
1412 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1413 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1414 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1415 io
.ntcreatex
.in
.create_options
= 0;
1416 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1417 io
.ntcreatex
.in
.security_flags
= 0;
1418 io
.ntcreatex
.in
.fname
= fname
;
1420 torture_comment(tctx
, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1421 ZERO_STRUCT(break_info
);
1422 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1423 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1424 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1425 NTCREATEX_SHARE_ACCESS_WRITE
|
1426 NTCREATEX_SHARE_ACCESS_DELETE
;
1427 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1428 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1429 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1430 torture_wait_for_oplock_break(tctx
);
1431 CHECK_VAL(break_info
.count
, 0);
1432 CHECK_VAL(break_info
.failures
, 0);
1433 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1435 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1437 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1438 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1439 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1440 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1441 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1442 NTCREATEX_SHARE_ACCESS_WRITE
|
1443 NTCREATEX_SHARE_ACCESS_DELETE
;
1444 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1445 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1446 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1447 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1448 torture_wait_for_oplock_break(tctx
);
1449 CHECK_VAL(break_info
.count
, 0);
1450 CHECK_VAL(break_info
.failures
, 0);
1451 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1453 torture_comment(tctx
, "write should trigger a break to none\n");
1456 wr
.write
.level
= RAW_WRITE_WRITE
;
1457 wr
.write
.in
.file
.fnum
= fnum
;
1458 wr
.write
.in
.count
= 1;
1459 wr
.write
.in
.offset
= 0;
1460 wr
.write
.in
.remaining
= 0;
1461 wr
.write
.in
.data
= (const uint8_t *)"x";
1462 status
= smb_raw_write(cli1
->tree
, &wr
);
1463 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1466 torture_wait_for_oplock_break(tctx
);
1468 CHECK_VAL(break_info
.count
, 1);
1469 CHECK_VAL(break_info
.fnum
, fnum2
);
1470 CHECK_VAL(break_info
.level
, 0);
1471 CHECK_VAL(break_info
.failures
, 0);
1473 smbcli_close(cli1
->tree
, fnum
);
1474 smbcli_close(cli2
->tree
, fnum2
);
1477 smb_raw_exit(cli1
->session
);
1478 smb_raw_exit(cli2
->session
);
1479 smbcli_deltree(cli1
->tree
, BASEDIR
);
1483 static bool test_raw_oplock_batch11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1485 const char *fname
= BASEDIR
"\\test_batch11.dat";
1489 union smb_setfileinfo sfi
;
1492 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1497 smbcli_unlink(cli1
->tree
, fname
);
1499 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1502 base ntcreatex parms
1504 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1505 io
.ntcreatex
.in
.root_fid
= 0;
1506 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1507 io
.ntcreatex
.in
.alloc_size
= 0;
1508 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1509 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1510 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1511 io
.ntcreatex
.in
.create_options
= 0;
1512 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1513 io
.ntcreatex
.in
.security_flags
= 0;
1514 io
.ntcreatex
.in
.fname
= fname
;
1516 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1517 torture_comment(tctx
, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1519 ZERO_STRUCT(break_info
);
1521 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1522 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1523 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1524 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1525 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1526 NTCREATEX_SHARE_ACCESS_WRITE
|
1527 NTCREATEX_SHARE_ACCESS_DELETE
;
1528 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1529 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1530 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1531 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1532 torture_wait_for_oplock_break(tctx
);
1533 CHECK_VAL(break_info
.count
, 0);
1534 CHECK_VAL(break_info
.failures
, 0);
1535 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1538 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
1539 sfi
.generic
.in
.file
.path
= fname
;
1540 sfi
.end_of_file_info
.in
.size
= 100;
1542 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1543 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1545 torture_wait_for_oplock_break(tctx
);
1546 CHECK_VAL(break_info
.count
, 1);
1547 CHECK_VAL(break_info
.failures
, 0);
1548 CHECK_VAL(break_info
.level
, 0);
1550 smbcli_close(cli1
->tree
, fnum
);
1553 smb_raw_exit(cli1
->session
);
1554 smb_raw_exit(cli2
->session
);
1555 smbcli_deltree(cli1
->tree
, BASEDIR
);
1559 static bool test_raw_oplock_batch12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1561 const char *fname
= BASEDIR
"\\test_batch12.dat";
1565 union smb_setfileinfo sfi
;
1568 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1573 smbcli_unlink(cli1
->tree
, fname
);
1575 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1578 base ntcreatex parms
1580 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1581 io
.ntcreatex
.in
.root_fid
= 0;
1582 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1583 io
.ntcreatex
.in
.alloc_size
= 0;
1584 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1585 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1586 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1587 io
.ntcreatex
.in
.create_options
= 0;
1588 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1589 io
.ntcreatex
.in
.security_flags
= 0;
1590 io
.ntcreatex
.in
.fname
= fname
;
1592 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1593 torture_comment(tctx
, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1595 ZERO_STRUCT(break_info
);
1596 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1598 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1599 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1600 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1601 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1602 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1603 NTCREATEX_SHARE_ACCESS_WRITE
|
1604 NTCREATEX_SHARE_ACCESS_DELETE
;
1605 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1606 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1607 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1608 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1609 torture_wait_for_oplock_break(tctx
);
1610 CHECK_VAL(break_info
.count
, 0);
1611 CHECK_VAL(break_info
.failures
, 0);
1612 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1615 sfi
.generic
.level
= SMB_SFILEINFO_ALLOCATION_INFORMATION
;
1616 sfi
.generic
.in
.file
.path
= fname
;
1617 sfi
.allocation_info
.in
.alloc_size
= 65536 * 8;
1619 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1620 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1622 torture_wait_for_oplock_break(tctx
);
1623 CHECK_VAL(break_info
.count
, 1);
1624 CHECK_VAL(break_info
.failures
, 0);
1625 CHECK_VAL(break_info
.level
, 0);
1627 smbcli_close(cli1
->tree
, fnum
);
1630 smb_raw_exit(cli1
->session
);
1631 smb_raw_exit(cli2
->session
);
1632 smbcli_deltree(cli1
->tree
, BASEDIR
);
1636 static bool test_raw_oplock_batch13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1638 const char *fname
= BASEDIR
"\\test_batch13.dat";
1642 uint16_t fnum
=0, fnum2
=0;
1644 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1649 smbcli_unlink(cli1
->tree
, fname
);
1651 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1652 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1655 base ntcreatex parms
1657 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1658 io
.ntcreatex
.in
.root_fid
= 0;
1659 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1660 io
.ntcreatex
.in
.alloc_size
= 0;
1661 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1662 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1663 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1664 io
.ntcreatex
.in
.create_options
= 0;
1665 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1666 io
.ntcreatex
.in
.security_flags
= 0;
1667 io
.ntcreatex
.in
.fname
= fname
;
1669 torture_comment(tctx
, "BATCH13: open with batch oplock\n");
1670 ZERO_STRUCT(break_info
);
1672 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1673 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1674 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1675 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1676 NTCREATEX_SHARE_ACCESS_WRITE
|
1677 NTCREATEX_SHARE_ACCESS_DELETE
;
1678 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1679 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1680 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1681 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1683 ZERO_STRUCT(break_info
);
1685 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1687 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1688 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1689 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1690 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1691 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1692 NTCREATEX_SHARE_ACCESS_WRITE
|
1693 NTCREATEX_SHARE_ACCESS_DELETE
;
1694 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1695 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1696 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1697 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1698 torture_wait_for_oplock_break(tctx
);
1699 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1700 CHECK_VAL(break_info
.count
, 1);
1701 CHECK_VAL(break_info
.failures
, 0);
1703 smbcli_close(cli1
->tree
, fnum
);
1704 smbcli_close(cli2
->tree
, fnum2
);
1707 smb_raw_exit(cli1
->session
);
1708 smb_raw_exit(cli2
->session
);
1709 smbcli_deltree(cli1
->tree
, BASEDIR
);
1713 static bool test_raw_oplock_batch14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1715 const char *fname
= BASEDIR
"\\test_batch14.dat";
1719 uint16_t fnum
=0, fnum2
=0;
1721 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1726 smbcli_unlink(cli1
->tree
, fname
);
1728 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1731 base ntcreatex parms
1733 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1734 io
.ntcreatex
.in
.root_fid
= 0;
1735 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1736 io
.ntcreatex
.in
.alloc_size
= 0;
1737 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1738 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1739 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1740 io
.ntcreatex
.in
.create_options
= 0;
1741 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1742 io
.ntcreatex
.in
.security_flags
= 0;
1743 io
.ntcreatex
.in
.fname
= fname
;
1745 torture_comment(tctx
, "BATCH14: open with batch oplock\n");
1746 ZERO_STRUCT(break_info
);
1748 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1749 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1750 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1751 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1752 NTCREATEX_SHARE_ACCESS_WRITE
|
1753 NTCREATEX_SHARE_ACCESS_DELETE
;
1754 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1755 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1756 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1757 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1759 ZERO_STRUCT(break_info
);
1761 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1763 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1764 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1765 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1766 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1767 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1768 NTCREATEX_SHARE_ACCESS_WRITE
|
1769 NTCREATEX_SHARE_ACCESS_DELETE
;
1770 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1771 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1772 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1773 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1774 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1776 torture_wait_for_oplock_break(tctx
);
1777 CHECK_VAL(break_info
.count
, 1);
1778 CHECK_VAL(break_info
.failures
, 0);
1780 smbcli_close(cli1
->tree
, fnum
);
1781 smbcli_close(cli2
->tree
, fnum2
);
1783 smb_raw_exit(cli1
->session
);
1784 smb_raw_exit(cli2
->session
);
1785 smbcli_deltree(cli1
->tree
, BASEDIR
);
1789 static bool test_raw_oplock_batch15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1791 const char *fname
= BASEDIR
"\\test_batch15.dat";
1795 union smb_fileinfo qfi
;
1798 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1803 smbcli_unlink(cli1
->tree
, fname
);
1805 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1808 base ntcreatex parms
1810 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1811 io
.ntcreatex
.in
.root_fid
= 0;
1812 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1813 io
.ntcreatex
.in
.alloc_size
= 0;
1814 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1815 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1816 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1817 io
.ntcreatex
.in
.create_options
= 0;
1818 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1819 io
.ntcreatex
.in
.security_flags
= 0;
1820 io
.ntcreatex
.in
.fname
= fname
;
1822 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1823 torture_comment(tctx
, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1825 ZERO_STRUCT(break_info
);
1827 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1828 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1829 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1830 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1831 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1832 NTCREATEX_SHARE_ACCESS_WRITE
|
1833 NTCREATEX_SHARE_ACCESS_DELETE
;
1834 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1835 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1836 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1837 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1838 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1840 torture_wait_for_oplock_break(tctx
);
1841 CHECK_VAL(break_info
.count
, 0);
1842 CHECK_VAL(break_info
.failures
, 0);
1843 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1846 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
1847 qfi
.generic
.in
.file
.path
= fname
;
1849 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
1850 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1852 torture_wait_for_oplock_break(tctx
);
1853 CHECK_VAL(break_info
.count
, 0);
1855 smbcli_close(cli1
->tree
, fnum
);
1858 smb_raw_exit(cli1
->session
);
1859 smb_raw_exit(cli2
->session
);
1860 smbcli_deltree(cli1
->tree
, BASEDIR
);
1864 static bool test_raw_oplock_batch16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1866 const char *fname
= BASEDIR
"\\test_batch16.dat";
1870 uint16_t fnum
=0, fnum2
=0;
1872 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1877 smbcli_unlink(cli1
->tree
, fname
);
1879 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1880 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1883 base ntcreatex parms
1885 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1886 io
.ntcreatex
.in
.root_fid
= 0;
1887 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1888 io
.ntcreatex
.in
.alloc_size
= 0;
1889 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1890 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1891 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1892 io
.ntcreatex
.in
.create_options
= 0;
1893 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1894 io
.ntcreatex
.in
.security_flags
= 0;
1895 io
.ntcreatex
.in
.fname
= fname
;
1897 torture_comment(tctx
, "BATCH16: open with batch oplock\n");
1898 ZERO_STRUCT(break_info
);
1900 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1901 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1902 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1903 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1904 NTCREATEX_SHARE_ACCESS_WRITE
|
1905 NTCREATEX_SHARE_ACCESS_DELETE
;
1906 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1907 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1908 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1909 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1911 ZERO_STRUCT(break_info
);
1913 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
1915 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1916 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1917 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1918 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1919 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1920 NTCREATEX_SHARE_ACCESS_WRITE
|
1921 NTCREATEX_SHARE_ACCESS_DELETE
;
1922 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1923 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1924 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1925 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1926 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1928 torture_wait_for_oplock_break(tctx
);
1929 CHECK_VAL(break_info
.count
, 1);
1930 CHECK_VAL(break_info
.failures
, 0);
1932 smbcli_close(cli1
->tree
, fnum
);
1933 smbcli_close(cli2
->tree
, fnum2
);
1936 smb_raw_exit(cli1
->session
);
1937 smb_raw_exit(cli2
->session
);
1938 smbcli_deltree(cli1
->tree
, BASEDIR
);
1942 static bool test_raw_oplock_batch17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1944 const char *fname1
= BASEDIR
"\\test_batch17_1.dat";
1945 const char *fname2
= BASEDIR
"\\test_batch17_2.dat";
1949 union smb_rename rn
;
1952 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1957 smbcli_unlink(cli1
->tree
, fname1
);
1958 smbcli_unlink(cli1
->tree
, fname2
);
1960 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1963 base ntcreatex parms
1965 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1966 io
.ntcreatex
.in
.root_fid
= 0;
1967 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1968 io
.ntcreatex
.in
.alloc_size
= 0;
1969 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1970 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1971 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1972 io
.ntcreatex
.in
.create_options
= 0;
1973 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1974 io
.ntcreatex
.in
.security_flags
= 0;
1975 io
.ntcreatex
.in
.fname
= fname1
;
1977 torture_comment(tctx
, "BATCH17: open a file with an batch oplock (share mode: none)\n");
1979 ZERO_STRUCT(break_info
);
1980 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1981 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1982 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1984 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1985 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1986 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1987 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1989 torture_comment(tctx
, "rename should trigger a break\n");
1991 rn
.generic
.level
= RAW_RENAME_RENAME
;
1992 rn
.rename
.in
.pattern1
= fname1
;
1993 rn
.rename
.in
.pattern2
= fname2
;
1994 rn
.rename
.in
.attrib
= 0;
1996 torture_comment(tctx
, "trying rename while first file open\n");
1997 status
= smb_raw_rename(cli2
->tree
, &rn
);
1998 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2000 torture_wait_for_oplock_break(tctx
);
2001 CHECK_VAL(break_info
.count
, 1);
2002 CHECK_VAL(break_info
.failures
, 0);
2003 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2005 smbcli_close(cli1
->tree
, fnum
);
2008 smb_raw_exit(cli1
->session
);
2009 smb_raw_exit(cli2
->session
);
2010 smbcli_deltree(cli1
->tree
, BASEDIR
);
2014 static bool test_raw_oplock_batch18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2016 const char *fname1
= BASEDIR
"\\test_batch18_1.dat";
2017 const char *fname2
= BASEDIR
"\\test_batch18_2.dat";
2021 union smb_rename rn
;
2024 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2029 smbcli_unlink(cli1
->tree
, fname1
);
2030 smbcli_unlink(cli1
->tree
, fname2
);
2032 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2035 base ntcreatex parms
2037 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2038 io
.ntcreatex
.in
.root_fid
= 0;
2039 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2040 io
.ntcreatex
.in
.alloc_size
= 0;
2041 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2042 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2043 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2044 io
.ntcreatex
.in
.create_options
= 0;
2045 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2046 io
.ntcreatex
.in
.security_flags
= 0;
2047 io
.ntcreatex
.in
.fname
= fname1
;
2049 torture_comment(tctx
, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2051 ZERO_STRUCT(break_info
);
2052 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2053 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2054 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2056 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2057 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2058 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2059 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2061 torture_comment(tctx
, "ntrename should trigger a break\n");
2063 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
2064 rn
.ntrename
.in
.attrib
= 0;
2065 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
2066 rn
.ntrename
.in
.old_name
= fname1
;
2067 rn
.ntrename
.in
.new_name
= fname2
;
2068 torture_comment(tctx
, "trying rename while first file open\n");
2069 status
= smb_raw_rename(cli2
->tree
, &rn
);
2070 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2072 torture_wait_for_oplock_break(tctx
);
2073 CHECK_VAL(break_info
.count
, 1);
2074 CHECK_VAL(break_info
.failures
, 0);
2075 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2077 smbcli_close(cli1
->tree
, fnum
);
2080 smb_raw_exit(cli1
->session
);
2081 smb_raw_exit(cli2
->session
);
2082 smbcli_deltree(cli1
->tree
, BASEDIR
);
2086 static bool test_raw_oplock_batch19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2088 const char *fname1
= BASEDIR
"\\test_batch19_1.dat";
2089 const char *fname2
= BASEDIR
"\\test_batch19_2.dat";
2090 const char *fname3
= BASEDIR
"\\test_batch19_3.dat";
2094 union smb_fileinfo qfi
;
2095 union smb_setfileinfo sfi
;
2098 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2103 smbcli_unlink(cli1
->tree
, fname1
);
2104 smbcli_unlink(cli1
->tree
, fname2
);
2105 smbcli_unlink(cli1
->tree
, fname3
);
2107 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2110 base ntcreatex parms
2112 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2113 io
.ntcreatex
.in
.root_fid
= 0;
2114 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2115 io
.ntcreatex
.in
.alloc_size
= 0;
2116 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2117 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2118 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2119 io
.ntcreatex
.in
.create_options
= 0;
2120 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2121 io
.ntcreatex
.in
.security_flags
= 0;
2122 io
.ntcreatex
.in
.fname
= fname1
;
2124 torture_comment(tctx
, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2125 ZERO_STRUCT(break_info
);
2126 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2127 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2128 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2129 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2130 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2131 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2132 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2134 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2136 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2137 sfi
.generic
.in
.file
.path
= fname1
;
2138 sfi
.rename_information
.in
.overwrite
= 0;
2139 sfi
.rename_information
.in
.root_fid
= 0;
2140 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2142 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2143 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2145 torture_wait_for_oplock_break(tctx
);
2146 CHECK_VAL(break_info
.count
, 0);
2149 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2150 qfi
.generic
.in
.file
.fnum
= fnum
;
2152 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2153 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2154 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2156 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2158 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2159 sfi
.generic
.in
.file
.fnum
= fnum
;
2160 sfi
.rename_information
.in
.overwrite
= 0;
2161 sfi
.rename_information
.in
.root_fid
= 0;
2162 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2164 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2165 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2167 torture_wait_for_oplock_break(tctx
);
2168 CHECK_VAL(break_info
.count
, 0);
2171 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2172 qfi
.generic
.in
.file
.fnum
= fnum
;
2174 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2175 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2176 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2178 smbcli_close(cli1
->tree
, fnum
);
2181 smb_raw_exit(cli1
->session
);
2182 smb_raw_exit(cli2
->session
);
2183 smbcli_deltree(cli1
->tree
, BASEDIR
);
2187 /****************************************************
2188 Called from raw-rename - we need oplock handling for
2189 this test so this is why it's in oplock.c, not rename.c
2190 ****************************************************/
2192 bool test_trans2rename(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2194 const char *fname1
= BASEDIR
"\\test_trans2rename_1.dat";
2195 const char *fname2
= BASEDIR
"\\test_trans2rename_2.dat";
2196 const char *fname3
= BASEDIR
"\\test_trans2rename_3.dat";
2200 union smb_fileinfo qfi
;
2201 union smb_setfileinfo sfi
;
2204 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2209 smbcli_unlink(cli1
->tree
, fname1
);
2210 smbcli_unlink(cli1
->tree
, fname2
);
2211 smbcli_unlink(cli1
->tree
, fname3
);
2213 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2216 base ntcreatex parms
2218 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2219 io
.ntcreatex
.in
.root_fid
= 0;
2220 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2221 io
.ntcreatex
.in
.alloc_size
= 0;
2222 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2223 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2224 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2225 io
.ntcreatex
.in
.create_options
= 0;
2226 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2227 io
.ntcreatex
.in
.security_flags
= 0;
2228 io
.ntcreatex
.in
.fname
= fname1
;
2230 torture_comment(tctx
, "open a file with an exclusive oplock (share mode: none)\n");
2231 ZERO_STRUCT(break_info
);
2232 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2233 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2234 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2235 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2236 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2237 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2239 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2241 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2242 sfi
.generic
.in
.file
.path
= fname1
;
2243 sfi
.rename_information
.in
.overwrite
= 0;
2244 sfi
.rename_information
.in
.root_fid
= 0;
2245 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2247 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2249 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2251 torture_wait_for_oplock_break(tctx
);
2252 CHECK_VAL(break_info
.count
, 0);
2255 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2256 qfi
.generic
.in
.file
.fnum
= fnum
;
2258 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2259 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2260 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2262 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2264 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2265 sfi
.generic
.in
.file
.fnum
= fnum
;
2266 sfi
.rename_information
.in
.overwrite
= 0;
2267 sfi
.rename_information
.in
.root_fid
= 0;
2268 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2270 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2271 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2273 torture_wait_for_oplock_break(tctx
);
2274 CHECK_VAL(break_info
.count
, 0);
2277 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2278 qfi
.generic
.in
.file
.fnum
= fnum
;
2280 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2281 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2282 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2284 smbcli_close(cli1
->tree
, fnum
);
2287 smb_raw_exit(cli1
->session
);
2288 smb_raw_exit(cli2
->session
);
2289 smbcli_deltree(cli1
->tree
, BASEDIR
);
2293 /****************************************************
2294 Called from raw-rename - we need oplock handling for
2295 this test so this is why it's in oplock.c, not rename.c
2296 ****************************************************/
2298 bool test_nttransrename(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
2300 const char *fname1
= BASEDIR
"\\test_nttransrename_1.dat";
2301 const char *fname2
= BASEDIR
"\\test_nttransrename_2.dat";
2305 union smb_fileinfo qfi
, qpi
;
2306 union smb_rename rn
;
2309 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2314 smbcli_unlink(cli1
->tree
, fname1
);
2315 smbcli_unlink(cli1
->tree
, fname2
);
2317 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2320 base ntcreatex parms
2322 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2323 io
.ntcreatex
.in
.root_fid
= 0;
2324 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2325 io
.ntcreatex
.in
.alloc_size
= 0;
2326 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2327 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2328 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2329 io
.ntcreatex
.in
.create_options
= 0;
2330 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2331 io
.ntcreatex
.in
.security_flags
= 0;
2332 io
.ntcreatex
.in
.fname
= fname1
;
2334 torture_comment(tctx
, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2335 ZERO_STRUCT(break_info
);
2336 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2337 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2338 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2339 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2340 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2341 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2343 torture_comment(tctx
, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2345 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2346 rn
.nttrans
.in
.file
.fnum
= fnum
;
2347 rn
.nttrans
.in
.flags
= 0;
2348 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2350 status
= smb_raw_rename(cli1
->tree
, &rn
);
2351 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2353 torture_wait_for_oplock_break(tctx
);
2354 CHECK_VAL(break_info
.count
, 0);
2356 /* w2k3 does nothing, it doesn't rename the file */
2357 torture_comment(tctx
, "nttrans_rename: the server should have done nothing\n");
2359 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2360 qfi
.generic
.in
.file
.fnum
= fnum
;
2362 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2363 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2364 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname1
);
2367 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2368 qpi
.generic
.in
.file
.path
= fname1
;
2370 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2371 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2372 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2375 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2376 qpi
.generic
.in
.file
.path
= fname2
;
2378 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2379 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2381 torture_comment(tctx
, "nttrans_rename: after closing the file the file is still not renamed\n");
2382 status
= smbcli_close(cli1
->tree
, fnum
);
2383 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2386 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2387 qpi
.generic
.in
.file
.path
= fname1
;
2389 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2390 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2391 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2394 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2395 qpi
.generic
.in
.file
.path
= fname2
;
2397 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2398 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2400 torture_comment(tctx
, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2402 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2403 rn
.nttrans
.in
.file
.fnum
= fnum
+1;
2404 rn
.nttrans
.in
.flags
= 0;
2405 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2407 status
= smb_raw_rename(cli1
->tree
, &rn
);
2409 CHECK_STATUS(tctx
, status
, NT_STATUS_INVALID_HANDLE
);
2412 smb_raw_exit(cli1
->session
);
2413 smbcli_deltree(cli1
->tree
, BASEDIR
);
2418 static bool test_raw_oplock_batch20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2420 const char *fname1
= BASEDIR
"\\test_batch20_1.dat";
2421 const char *fname2
= BASEDIR
"\\test_batch20_2.dat";
2422 const char *fname3
= BASEDIR
"\\test_batch20_3.dat";
2426 union smb_fileinfo qfi
;
2427 union smb_setfileinfo sfi
;
2428 uint16_t fnum
=0,fnum2
=0;
2430 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2435 smbcli_unlink(cli1
->tree
, fname1
);
2436 smbcli_unlink(cli1
->tree
, fname2
);
2437 smbcli_unlink(cli1
->tree
, fname3
);
2439 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2442 base ntcreatex parms
2444 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2445 io
.ntcreatex
.in
.root_fid
= 0;
2446 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2447 io
.ntcreatex
.in
.alloc_size
= 0;
2448 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2449 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2450 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2451 io
.ntcreatex
.in
.create_options
= 0;
2452 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2453 io
.ntcreatex
.in
.security_flags
= 0;
2454 io
.ntcreatex
.in
.fname
= fname1
;
2456 torture_comment(tctx
, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2457 ZERO_STRUCT(break_info
);
2458 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2459 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2460 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2461 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2462 NTCREATEX_SHARE_ACCESS_WRITE
|
2463 NTCREATEX_SHARE_ACCESS_DELETE
;
2464 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2465 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2466 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2467 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2469 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2471 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2472 sfi
.generic
.in
.file
.path
= fname1
;
2473 sfi
.rename_information
.in
.overwrite
= 0;
2474 sfi
.rename_information
.in
.root_fid
= 0;
2475 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2477 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2478 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2480 torture_wait_for_oplock_break(tctx
);
2481 CHECK_VAL(break_info
.count
, 0);
2484 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2485 qfi
.generic
.in
.file
.fnum
= fnum
;
2487 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2488 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2489 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2491 torture_comment(tctx
, "open a file with the new name an batch oplock (share mode: all)\n");
2492 ZERO_STRUCT(break_info
);
2493 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2494 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2495 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2496 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2497 NTCREATEX_SHARE_ACCESS_WRITE
|
2498 NTCREATEX_SHARE_ACCESS_DELETE
;
2499 io
.ntcreatex
.in
.fname
= fname2
;
2500 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2501 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2502 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2503 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2505 torture_wait_for_oplock_break(tctx
);
2506 CHECK_VAL(break_info
.count
, 1);
2507 CHECK_VAL(break_info
.failures
, 0);
2508 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2510 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2512 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2513 sfi
.generic
.in
.file
.fnum
= fnum
;
2514 sfi
.rename_information
.in
.overwrite
= 0;
2515 sfi
.rename_information
.in
.root_fid
= 0;
2516 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2518 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2519 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2521 torture_wait_for_oplock_break(tctx
);
2522 CHECK_VAL(break_info
.count
, 1);
2523 CHECK_VAL(break_info
.failures
, 0);
2524 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2527 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2528 qfi
.generic
.in
.file
.fnum
= fnum
;
2530 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2531 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2532 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2535 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2536 qfi
.generic
.in
.file
.fnum
= fnum2
;
2538 status
= smb_raw_fileinfo(cli2
->tree
, tctx
, &qfi
);
2539 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2540 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2542 smbcli_close(cli1
->tree
, fnum
);
2545 smb_raw_exit(cli1
->session
);
2546 smb_raw_exit(cli2
->session
);
2547 smbcli_deltree(cli1
->tree
, BASEDIR
);
2551 static bool test_raw_oplock_batch21(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2553 const char *fname
= BASEDIR
"\\test_batch21.dat";
2562 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2567 smbcli_unlink(cli1
->tree
, fname
);
2569 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2572 base ntcreatex parms
2574 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2575 io
.ntcreatex
.in
.root_fid
= 0;
2576 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2577 io
.ntcreatex
.in
.alloc_size
= 0;
2578 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2579 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2580 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2581 io
.ntcreatex
.in
.create_options
= 0;
2582 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2583 io
.ntcreatex
.in
.security_flags
= 0;
2584 io
.ntcreatex
.in
.fname
= fname
;
2587 with a batch oplock we get a break
2589 torture_comment(tctx
, "BATCH21: open with batch oplock\n");
2590 ZERO_STRUCT(break_info
);
2591 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2592 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2593 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2594 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2595 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2596 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2597 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2599 torture_comment(tctx
, "writing should not generate a break\n");
2600 wr
= smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
2602 CHECK_STATUS(tctx
, smbcli_nt_error(cli1
->tree
), NT_STATUS_OK
);
2605 e
.in
.repeat_count
= 1;
2606 status
= smb_raw_echo(cli1
->transport
, &e
);
2607 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2609 torture_wait_for_oplock_break(tctx
);
2610 CHECK_VAL(break_info
.count
, 0);
2612 smbcli_close(cli1
->tree
, fnum
);
2615 smb_raw_exit(cli1
->session
);
2616 smb_raw_exit(cli2
->session
);
2617 smbcli_deltree(cli1
->tree
, BASEDIR
);
2621 static bool test_raw_oplock_batch22(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2623 const char *fname
= BASEDIR
"\\test_batch22.dat";
2627 uint16_t fnum
=0, fnum2
=0;
2629 int timeout
= torture_setting_int(tctx
, "oplocktimeout", 30);
2632 if (torture_setting_bool(tctx
, "samba3", false)) {
2633 torture_skip(tctx
, "BATCH22 disabled against samba3\n");
2636 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2641 smbcli_unlink(cli1
->tree
, fname
);
2643 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2646 base ntcreatex parms
2648 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2649 io
.ntcreatex
.in
.root_fid
= 0;
2650 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2651 io
.ntcreatex
.in
.alloc_size
= 0;
2652 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2653 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2654 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2655 io
.ntcreatex
.in
.create_options
= 0;
2656 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2657 io
.ntcreatex
.in
.security_flags
= 0;
2658 io
.ntcreatex
.in
.fname
= fname
;
2661 with a batch oplock we get a break
2663 torture_comment(tctx
, "BATCH22: open with batch oplock\n");
2664 ZERO_STRUCT(break_info
);
2665 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2666 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2667 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2668 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2669 NTCREATEX_SHARE_ACCESS_WRITE
|
2670 NTCREATEX_SHARE_ACCESS_DELETE
;
2671 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2672 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2673 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2674 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2676 torture_comment(tctx
, "a 2nd open should not succeed after the oplock "
2678 tv
= timeval_current();
2679 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
, cli1
->tree
);
2680 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2681 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2682 torture_wait_for_oplock_break(tctx
);
2683 te
= (int)timeval_elapsed(&tv
);
2684 CHECK_RANGE(te
, timeout
- 1, timeout
+ 15);
2686 CHECK_VAL(break_info
.count
, 1);
2687 CHECK_VAL(break_info
.fnum
, fnum
);
2688 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2689 CHECK_VAL(break_info
.failures
, 0);
2690 ZERO_STRUCT(break_info
);
2692 torture_comment(tctx
, "a 2nd open should succeed after the oplock "
2693 "release without break\n");
2694 tv
= timeval_current();
2695 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2696 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2697 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2698 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2699 torture_wait_for_oplock_break(tctx
);
2700 te
= (int)timeval_elapsed(&tv
);
2701 /* it should come in without delay */
2702 CHECK_RANGE(te
+1, 0, timeout
);
2703 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2705 CHECK_VAL(break_info
.count
, 0);
2707 smbcli_close(cli1
->tree
, fnum
);
2708 smbcli_close(cli1
->tree
, fnum2
);
2711 smb_raw_exit(cli1
->session
);
2712 smb_raw_exit(cli2
->session
);
2713 smbcli_deltree(cli1
->tree
, BASEDIR
);
2717 static bool test_raw_oplock_batch23(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2719 const char *fname
= BASEDIR
"\\test_batch23.dat";
2723 uint16_t fnum
=0, fnum2
=0,fnum3
=0;
2724 struct smbcli_state
*cli3
= NULL
;
2726 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2731 smbcli_unlink(cli1
->tree
, fname
);
2733 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
2734 CHECK_VAL(ret
, true);
2736 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2737 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
2738 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
2741 base ntcreatex parms
2743 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2744 io
.ntcreatex
.in
.root_fid
= 0;
2745 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2746 io
.ntcreatex
.in
.alloc_size
= 0;
2747 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2748 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2749 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2750 io
.ntcreatex
.in
.create_options
= 0;
2751 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2752 io
.ntcreatex
.in
.security_flags
= 0;
2753 io
.ntcreatex
.in
.fname
= fname
;
2755 torture_comment(tctx
, "BATCH23: a open and ask for a batch oplock\n");
2756 ZERO_STRUCT(break_info
);
2758 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
2759 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
2760 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2761 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2762 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2763 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2764 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2765 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2766 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2768 ZERO_STRUCT(break_info
);
2770 torture_comment(tctx
, "a 2nd open without level2 oplock support should generate a break to level2\n");
2771 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
2772 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2773 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
2774 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
2776 torture_wait_for_oplock_break(tctx
);
2777 CHECK_VAL(break_info
.count
, 1);
2778 CHECK_VAL(break_info
.fnum
, fnum
);
2779 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2780 CHECK_VAL(break_info
.failures
, 0);
2782 ZERO_STRUCT(break_info
);
2784 torture_comment(tctx
, "a 3rd open with level2 oplock support should not generate a break\n");
2785 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2786 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2787 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2788 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2790 torture_wait_for_oplock_break(tctx
);
2791 CHECK_VAL(break_info
.count
, 0);
2793 smbcli_close(cli1
->tree
, fnum
);
2794 smbcli_close(cli2
->tree
, fnum2
);
2795 smbcli_close(cli3
->tree
, fnum3
);
2798 smb_raw_exit(cli1
->session
);
2799 smb_raw_exit(cli2
->session
);
2800 smb_raw_exit(cli3
->session
);
2801 smbcli_deltree(cli1
->tree
, BASEDIR
);
2805 static bool test_raw_oplock_batch24(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2807 const char *fname
= BASEDIR
"\\test_batch24.dat";
2811 uint16_t fnum2
=0,fnum3
=0;
2812 struct smbcli_state
*cli3
= NULL
;
2814 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2819 smbcli_unlink(cli1
->tree
, fname
);
2821 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
2822 CHECK_VAL(ret
, true);
2824 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2825 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
2826 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
2829 base ntcreatex parms
2831 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2832 io
.ntcreatex
.in
.root_fid
= 0;
2833 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2834 io
.ntcreatex
.in
.alloc_size
= 0;
2835 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2836 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2837 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2838 io
.ntcreatex
.in
.create_options
= 0;
2839 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2840 io
.ntcreatex
.in
.security_flags
= 0;
2841 io
.ntcreatex
.in
.fname
= fname
;
2843 torture_comment(tctx
, "BATCH24: a open without level support and ask for a batch oplock\n");
2844 ZERO_STRUCT(break_info
);
2846 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
2847 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
2848 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2849 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2850 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2851 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
2852 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2853 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
2854 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2856 ZERO_STRUCT(break_info
);
2858 torture_comment(tctx
, "a 2nd open with level2 oplock support should generate a break to none\n");
2859 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2860 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2861 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2862 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2864 torture_wait_for_oplock_break(tctx
);
2865 CHECK_VAL(break_info
.count
, 1);
2866 CHECK_VAL(break_info
.fnum
, fnum3
);
2867 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2868 CHECK_VAL(break_info
.failures
, 0);
2870 smbcli_close(cli3
->tree
, fnum3
);
2871 smbcli_close(cli2
->tree
, fnum2
);
2874 smb_raw_exit(cli1
->session
);
2875 smb_raw_exit(cli2
->session
);
2876 smb_raw_exit(cli3
->session
);
2877 smbcli_deltree(cli1
->tree
, BASEDIR
);
2881 static bool test_raw_oplock_batch25(struct torture_context
*tctx
,
2882 struct smbcli_state
*cli1
,
2883 struct smbcli_state
*cli2
)
2885 const char *fname
= BASEDIR
"\\test_batch25.dat";
2889 union smb_setfileinfo sfi
;
2892 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2897 smbcli_unlink(cli1
->tree
, fname
);
2899 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2902 base ntcreatex parms
2904 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2905 io
.ntcreatex
.in
.root_fid
= 0;
2906 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2907 io
.ntcreatex
.in
.alloc_size
= 0;
2908 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2909 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2910 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2911 io
.ntcreatex
.in
.create_options
= 0;
2912 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2913 io
.ntcreatex
.in
.security_flags
= 0;
2914 io
.ntcreatex
.in
.fname
= fname
;
2916 torture_comment(tctx
, "BATCH25: open a file with an batch oplock "
2917 "(share mode: none)\n");
2919 ZERO_STRUCT(break_info
);
2920 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2921 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2922 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2923 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2924 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2925 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2926 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2928 torture_comment(tctx
, "setpathinfo attribute info should not trigger "
2929 "a break nor a violation\n");
2931 sfi
.generic
.level
= RAW_SFILEINFO_SETATTR
;
2932 sfi
.generic
.in
.file
.path
= fname
;
2933 sfi
.setattr
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
2934 sfi
.setattr
.in
.write_time
= 0;
2936 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2937 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2939 torture_wait_for_oplock_break(tctx
);
2940 CHECK_VAL(break_info
.count
, 0);
2942 smbcli_close(cli1
->tree
, fnum
);
2945 smb_raw_exit(cli1
->session
);
2946 smb_raw_exit(cli2
->session
);
2947 smbcli_deltree(cli1
->tree
, BASEDIR
);
2951 /* Test how oplocks work on streams. */
2952 static bool test_raw_oplock_stream1(struct torture_context
*tctx
,
2953 struct smbcli_state
*cli1
,
2954 struct smbcli_state
*cli2
)
2958 const char *fname_base
= BASEDIR
"\\test_stream1.txt";
2959 const char *stream
= "Stream One:$DATA";
2960 const char *fname_stream
, *fname_default_stream
;
2961 const char *default_stream
= "::$DATA";
2965 int stream_fnum
= -1;
2966 uint32_t batch_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2967 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
| NTCREATEX_FLAGS_EXTENDED
;
2968 uint32_t exclusive_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2969 NTCREATEX_FLAGS_EXTENDED
;
2971 #define NSTREAM_OPLOCK_RESULTS 8
2974 bool open_base_file
;
2975 uint32_t oplock_req
;
2976 uint32_t oplock_granted
;
2977 } stream_oplock_results
[NSTREAM_OPLOCK_RESULTS
] = {
2978 /* Request oplock on stream without the base file open. */
2979 {&fname_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
2980 {&fname_default_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
2981 {&fname_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
2982 {&fname_default_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
2984 /* Request oplock on stream with the base file open. */
2985 {&fname_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
2986 {&fname_default_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
2987 {&fname_stream
, true, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
2988 {&fname_default_stream
, true, exclusive_req
, LEVEL_II_OPLOCK_RETURN
},
2993 /* Only passes against windows at the moment. */
2994 if (torture_setting_bool(tctx
, "samba3", false) ||
2995 torture_setting_bool(tctx
, "samba4", false)) {
2996 torture_skip(tctx
, "STREAM1 disabled against samba3+4\n");
2999 fname_stream
= talloc_asprintf(tctx
, "%s:%s", fname_base
, stream
);
3000 fname_default_stream
= talloc_asprintf(tctx
, "%s%s", fname_base
,
3003 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3006 smbcli_unlink(cli1
->tree
, fname_base
);
3008 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3009 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3011 /* Setup generic open parameters. */
3012 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3013 io
.ntcreatex
.in
.root_fid
= 0;
3014 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
3015 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
3016 io
.ntcreatex
.in
.create_options
= 0;
3017 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3018 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3019 NTCREATEX_SHARE_ACCESS_WRITE
;
3020 io
.ntcreatex
.in
.alloc_size
= 0;
3021 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3022 io
.ntcreatex
.in
.security_flags
= 0;
3024 /* Create the file with a stream */
3025 io
.ntcreatex
.in
.fname
= fname_stream
;
3026 io
.ntcreatex
.in
.flags
= 0;
3027 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
3028 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3029 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3030 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3032 /* Change the disposition to open now that the file has been created. */
3033 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3035 /* Try some permutations of taking oplocks on streams. */
3036 for (i
= 0; i
< NSTREAM_OPLOCK_RESULTS
; i
++) {
3037 const char *fname
= *stream_oplock_results
[i
].fname
;
3038 bool open_base_file
= stream_oplock_results
[i
].open_base_file
;
3039 uint32_t oplock_req
= stream_oplock_results
[i
].oplock_req
;
3040 uint32_t oplock_granted
=
3041 stream_oplock_results
[i
].oplock_granted
;
3044 if (open_base_file
) {
3045 torture_comment(tctx
, "Opening base file: %s with "
3046 "%d\n", fname_base
, oplock_req
);
3047 io
.ntcreatex
.in
.fname
= fname_base
;
3048 io
.ntcreatex
.in
.flags
= batch_req
;
3049 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3050 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3051 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3052 BATCH_OPLOCK_RETURN
);
3053 base_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3056 torture_comment(tctx
, "%d: Opening stream: %s with %d\n", i
,
3058 io
.ntcreatex
.in
.fname
= fname
;
3059 io
.ntcreatex
.in
.flags
= oplock_req
;
3061 /* Do the open with the desired oplock on the stream. */
3062 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3063 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3064 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, oplock_granted
);
3065 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3067 /* Cleanup the base file if it was opened. */
3068 if (base_fnum
!= -1) {
3069 smbcli_close(cli2
->tree
, base_fnum
);
3073 /* Open the stream with an exclusive oplock. */
3074 torture_comment(tctx
, "Opening stream: %s with %d\n",
3075 fname_stream
, exclusive_req
);
3076 io
.ntcreatex
.in
.fname
= fname_stream
;
3077 io
.ntcreatex
.in
.flags
= exclusive_req
;
3078 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3079 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3080 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3081 stream_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3083 /* Open the base file and see if it contends. */
3084 ZERO_STRUCT(break_info
);
3085 torture_comment(tctx
, "Opening base file: %s with "
3086 "%d\n", fname_base
, batch_req
);
3087 io
.ntcreatex
.in
.fname
= fname_base
;
3088 io
.ntcreatex
.in
.flags
= batch_req
;
3089 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3090 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3091 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3092 BATCH_OPLOCK_RETURN
);
3093 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3095 torture_wait_for_oplock_break(tctx
);
3096 CHECK_VAL(break_info
.count
, 0);
3097 CHECK_VAL(break_info
.failures
, 0);
3099 /* Open the stream again to see if it contends. */
3100 ZERO_STRUCT(break_info
);
3101 torture_comment(tctx
, "Opening stream again: %s with "
3102 "%d\n", fname_base
, batch_req
);
3103 io
.ntcreatex
.in
.fname
= fname_stream
;
3104 io
.ntcreatex
.in
.flags
= exclusive_req
;
3105 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3106 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3107 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3108 LEVEL_II_OPLOCK_RETURN
);
3109 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3111 torture_wait_for_oplock_break(tctx
);
3112 CHECK_VAL(break_info
.count
, 1);
3113 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3114 CHECK_VAL(break_info
.failures
, 0);
3116 /* Close the stream. */
3117 if (stream_fnum
!= -1) {
3118 smbcli_close(cli1
->tree
, stream_fnum
);
3122 smbcli_close(cli1
->tree
, fnum
);
3123 smb_raw_exit(cli1
->session
);
3124 smb_raw_exit(cli2
->session
);
3125 smbcli_deltree(cli1
->tree
, BASEDIR
);
3129 static bool test_raw_oplock_doc(struct torture_context
*tctx
,
3130 struct smbcli_state
*cli
)
3132 const char *fname
= BASEDIR
"\\test_oplock_doc.dat";
3138 if (!torture_setup_dir(cli
, BASEDIR
)) {
3143 smbcli_unlink(cli
->tree
, fname
);
3145 smbcli_oplock_handler(cli
->transport
, oplock_handler_ack_to_given
,
3149 base ntcreatex parms
3151 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3152 io
.ntcreatex
.in
.root_fid
= 0;
3153 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3154 io
.ntcreatex
.in
.alloc_size
= 0;
3155 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3156 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3157 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3158 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
3159 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3160 io
.ntcreatex
.in
.security_flags
= 0;
3161 io
.ntcreatex
.in
.fname
= fname
;
3163 torture_comment(tctx
, "open a delete-on-close file with a batch "
3165 ZERO_STRUCT(break_info
);
3166 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3167 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3168 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3170 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
3171 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3172 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3173 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3175 smbcli_close(cli
->tree
, fnum
);
3178 smb_raw_exit(cli
->session
);
3179 smbcli_deltree(cli
->tree
, BASEDIR
);
3183 /* Open a file with a batch oplock, then open it again from a second client
3184 * requesting no oplock. Having two open file handles should break our own
3185 * oplock during BRL acquisition.
3187 static bool test_raw_oplock_brl1(struct torture_context
*tctx
,
3188 struct smbcli_state
*cli1
,
3189 struct smbcli_state
*cli2
)
3191 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3195 bool correct
= true;
3201 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3206 smbcli_unlink(cli1
->tree
, fname
);
3208 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3212 base ntcreatex parms
3214 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3215 io
.ntcreatex
.in
.root_fid
= 0;
3216 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3217 SEC_RIGHTS_FILE_WRITE
;
3218 io
.ntcreatex
.in
.alloc_size
= 0;
3219 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3220 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3221 NTCREATEX_SHARE_ACCESS_WRITE
;
3222 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3223 io
.ntcreatex
.in
.create_options
= 0;
3224 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3225 io
.ntcreatex
.in
.security_flags
= 0;
3226 io
.ntcreatex
.in
.fname
= fname
;
3229 with a batch oplock we get a break
3231 torture_comment(tctx
, "open with batch oplock\n");
3232 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3233 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3234 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3236 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3237 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3238 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3239 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3240 /* create a file with bogus data */
3241 memset(buf
, 0, sizeof(buf
));
3243 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3246 torture_comment(tctx
, "Failed to create file\n");
3251 torture_comment(tctx
, "a 2nd open should give a break\n");
3252 ZERO_STRUCT(break_info
);
3254 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3255 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3256 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3257 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3258 CHECK_VAL(break_info
.count
, 1);
3259 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3260 CHECK_VAL(break_info
.failures
, 0);
3261 CHECK_VAL(break_info
.fnum
, fnum
);
3263 ZERO_STRUCT(break_info
);
3265 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3267 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3268 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3270 torture_wait_for_oplock_break(tctx
);
3271 CHECK_VAL(break_info
.count
, 1);
3272 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3273 CHECK_VAL(break_info
.fnum
, fnum
);
3274 CHECK_VAL(break_info
.failures
, 0);
3276 /* expect no oplock break */
3277 ZERO_STRUCT(break_info
);
3278 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3279 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3281 torture_wait_for_oplock_break(tctx
);
3282 CHECK_VAL(break_info
.count
, 0);
3283 CHECK_VAL(break_info
.level
, 0);
3284 CHECK_VAL(break_info
.fnum
, 0);
3285 CHECK_VAL(break_info
.failures
, 0);
3287 smbcli_close(cli1
->tree
, fnum
);
3288 smbcli_close(cli2
->tree
, fnum2
);
3291 smb_raw_exit(cli1
->session
);
3292 smb_raw_exit(cli2
->session
);
3293 smbcli_deltree(cli1
->tree
, BASEDIR
);
3298 /* Open a file with a batch oplock on one client and then acquire a brl.
3299 * We should not contend our own oplock.
3301 static bool test_raw_oplock_brl2(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
3303 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3307 bool correct
= true;
3312 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3317 smbcli_unlink(cli1
->tree
, fname
);
3319 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3323 base ntcreatex parms
3325 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3326 io
.ntcreatex
.in
.root_fid
= 0;
3327 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3328 SEC_RIGHTS_FILE_WRITE
;
3329 io
.ntcreatex
.in
.alloc_size
= 0;
3330 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3331 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3332 NTCREATEX_SHARE_ACCESS_WRITE
;
3333 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3334 io
.ntcreatex
.in
.create_options
= 0;
3335 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3336 io
.ntcreatex
.in
.security_flags
= 0;
3337 io
.ntcreatex
.in
.fname
= fname
;
3340 with a batch oplock we get a break
3342 torture_comment(tctx
, "open with batch oplock\n");
3343 ZERO_STRUCT(break_info
);
3344 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3345 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3346 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3348 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3349 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3350 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3351 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3353 /* create a file with bogus data */
3354 memset(buf
, 0, sizeof(buf
));
3356 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3359 torture_comment(tctx
, "Failed to create file\n");
3364 torture_comment(tctx
, "a self BRL acquisition should not break to "
3367 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3368 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3370 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3371 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3373 /* With one file handle open a BRL should not contend our oplock.
3374 * Thus, no oplock break will be received and the entire break_info
3375 * struct will be 0 */
3376 torture_wait_for_oplock_break(tctx
);
3377 CHECK_VAL(break_info
.fnum
, 0);
3378 CHECK_VAL(break_info
.count
, 0);
3379 CHECK_VAL(break_info
.level
, 0);
3380 CHECK_VAL(break_info
.failures
, 0);
3382 smbcli_close(cli1
->tree
, fnum
);
3385 smb_raw_exit(cli1
->session
);
3386 smbcli_deltree(cli1
->tree
, BASEDIR
);
3390 /* Open a file with a batch oplock twice from one client and then acquire a
3391 * brl. BRL acquisition should break our own oplock.
3393 static bool test_raw_oplock_brl3(struct torture_context
*tctx
,
3394 struct smbcli_state
*cli1
)
3396 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3399 bool correct
= true;
3405 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3410 smbcli_unlink(cli1
->tree
, fname
);
3412 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3416 base ntcreatex parms
3418 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3419 io
.ntcreatex
.in
.root_fid
= 0;
3420 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3421 SEC_RIGHTS_FILE_WRITE
;
3422 io
.ntcreatex
.in
.alloc_size
= 0;
3423 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3424 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3425 NTCREATEX_SHARE_ACCESS_WRITE
;
3426 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3427 io
.ntcreatex
.in
.create_options
= 0;
3428 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3429 io
.ntcreatex
.in
.security_flags
= 0;
3430 io
.ntcreatex
.in
.fname
= fname
;
3433 with a batch oplock we get a break
3435 torture_comment(tctx
, "open with batch oplock\n");
3436 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3437 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3438 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3440 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3441 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3442 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3443 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3445 /* create a file with bogus data */
3446 memset(buf
, 0, sizeof(buf
));
3448 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3451 torture_comment(tctx
, "Failed to create file\n");
3456 torture_comment(tctx
, "a 2nd open should give a break\n");
3457 ZERO_STRUCT(break_info
);
3459 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3460 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3461 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3462 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3463 CHECK_VAL(break_info
.count
, 1);
3464 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3465 CHECK_VAL(break_info
.failures
, 0);
3466 CHECK_VAL(break_info
.fnum
, fnum
);
3468 ZERO_STRUCT(break_info
);
3470 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3472 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3473 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3475 torture_wait_for_oplock_break(tctx
);
3476 CHECK_VAL(break_info
.count
, 1);
3477 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3478 CHECK_VAL(break_info
.fnum
, fnum
);
3479 CHECK_VAL(break_info
.failures
, 0);
3481 /* expect no oplock break */
3482 ZERO_STRUCT(break_info
);
3483 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3484 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3486 torture_wait_for_oplock_break(tctx
);
3487 CHECK_VAL(break_info
.count
, 0);
3488 CHECK_VAL(break_info
.level
, 0);
3489 CHECK_VAL(break_info
.fnum
, 0);
3490 CHECK_VAL(break_info
.failures
, 0);
3492 smbcli_close(cli1
->tree
, fnum
);
3493 smbcli_close(cli1
->tree
, fnum2
);
3496 smb_raw_exit(cli1
->session
);
3497 smbcli_deltree(cli1
->tree
, BASEDIR
);
3502 basic testing of oplocks
3504 struct torture_suite
*torture_raw_oplock(TALLOC_CTX
*mem_ctx
)
3506 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "OPLOCK");
3508 torture_suite_add_2smb_test(suite
, "EXCLUSIVE1", test_raw_oplock_exclusive1
);
3509 torture_suite_add_2smb_test(suite
, "EXCLUSIVE2", test_raw_oplock_exclusive2
);
3510 torture_suite_add_2smb_test(suite
, "EXCLUSIVE3", test_raw_oplock_exclusive3
);
3511 torture_suite_add_2smb_test(suite
, "EXCLUSIVE4", test_raw_oplock_exclusive4
);
3512 torture_suite_add_2smb_test(suite
, "EXCLUSIVE5", test_raw_oplock_exclusive5
);
3513 torture_suite_add_2smb_test(suite
, "EXCLUSIVE6", test_raw_oplock_exclusive6
);
3514 torture_suite_add_2smb_test(suite
, "BATCH1", test_raw_oplock_batch1
);
3515 torture_suite_add_2smb_test(suite
, "BATCH2", test_raw_oplock_batch2
);
3516 torture_suite_add_2smb_test(suite
, "BATCH3", test_raw_oplock_batch3
);
3517 torture_suite_add_2smb_test(suite
, "BATCH4", test_raw_oplock_batch4
);
3518 torture_suite_add_2smb_test(suite
, "BATCH5", test_raw_oplock_batch5
);
3519 torture_suite_add_2smb_test(suite
, "BATCH6", test_raw_oplock_batch6
);
3520 torture_suite_add_2smb_test(suite
, "BATCH7", test_raw_oplock_batch7
);
3521 torture_suite_add_2smb_test(suite
, "BATCH8", test_raw_oplock_batch8
);
3522 torture_suite_add_2smb_test(suite
, "BATCH9", test_raw_oplock_batch9
);
3523 torture_suite_add_2smb_test(suite
, "BATCH10", test_raw_oplock_batch10
);
3524 torture_suite_add_2smb_test(suite
, "BATCH11", test_raw_oplock_batch11
);
3525 torture_suite_add_2smb_test(suite
, "BATCH12", test_raw_oplock_batch12
);
3526 torture_suite_add_2smb_test(suite
, "BATCH13", test_raw_oplock_batch13
);
3527 torture_suite_add_2smb_test(suite
, "BATCH14", test_raw_oplock_batch14
);
3528 torture_suite_add_2smb_test(suite
, "BATCH15", test_raw_oplock_batch15
);
3529 torture_suite_add_2smb_test(suite
, "BATCH16", test_raw_oplock_batch16
);
3530 torture_suite_add_2smb_test(suite
, "BATCH17", test_raw_oplock_batch17
);
3531 torture_suite_add_2smb_test(suite
, "BATCH18", test_raw_oplock_batch18
);
3532 torture_suite_add_2smb_test(suite
, "BATCH19", test_raw_oplock_batch19
);
3533 torture_suite_add_2smb_test(suite
, "BATCH20", test_raw_oplock_batch20
);
3534 torture_suite_add_2smb_test(suite
, "BATCH21", test_raw_oplock_batch21
);
3535 torture_suite_add_2smb_test(suite
, "BATCH22", test_raw_oplock_batch22
);
3536 torture_suite_add_2smb_test(suite
, "BATCH23", test_raw_oplock_batch23
);
3537 torture_suite_add_2smb_test(suite
, "BATCH24", test_raw_oplock_batch24
);
3538 torture_suite_add_2smb_test(suite
, "BATCH25", test_raw_oplock_batch25
);
3539 torture_suite_add_2smb_test(suite
, "STREAM1", test_raw_oplock_stream1
);
3540 torture_suite_add_1smb_test(suite
, "DOC1", test_raw_oplock_doc
);
3541 torture_suite_add_2smb_test(suite
, "BRL1", test_raw_oplock_brl1
);
3542 torture_suite_add_1smb_test(suite
, "BRL2", test_raw_oplock_brl2
);
3543 torture_suite_add_1smb_test(suite
, "BRL3", test_raw_oplock_brl3
);
3549 stress testing of oplocks
3551 bool torture_bench_oplock(struct torture_context
*torture
)
3553 struct smbcli_state
**cli
;
3555 TALLOC_CTX
*mem_ctx
= talloc_new(torture
);
3556 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
3558 int timelimit
= torture_setting_int(torture
, "timelimit", 10);
3562 cli
= talloc_array(mem_ctx
, struct smbcli_state
*, torture_nprocs
);
3564 torture_comment(torture
, "Opening %d connections\n", torture_nprocs
);
3565 for (i
=0;i
<torture_nprocs
;i
++) {
3566 if (!torture_open_connection_ev(&cli
[i
], i
, torture
, torture
->ev
)) {
3569 talloc_steal(mem_ctx
, cli
[i
]);
3570 smbcli_oplock_handler(cli
[i
]->transport
, oplock_handler_close
,
3574 if (!torture_setup_dir(cli
[0], BASEDIR
)) {
3579 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
3580 io
.ntcreatex
.in
.root_fid
= 0;
3581 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3582 io
.ntcreatex
.in
.alloc_size
= 0;
3583 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3584 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3585 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3586 io
.ntcreatex
.in
.create_options
= 0;
3587 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3588 io
.ntcreatex
.in
.security_flags
= 0;
3589 io
.ntcreatex
.in
.fname
= BASEDIR
"\\test.dat";
3590 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3591 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3592 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3594 tv
= timeval_current();
3597 we open the same file with SHARE_ACCESS_NONE from all the
3598 connections in a round robin fashion. Each open causes an
3599 oplock break on the previous connection, which is answered
3600 by the oplock_handler_close() to close the file.
3602 This measures how fast we can pass on oplocks, and stresses
3603 the oplock handling code
3605 torture_comment(torture
, "Running for %d seconds\n", timelimit
);
3606 while (timeval_elapsed(&tv
) < timelimit
) {
3607 for (i
=0;i
<torture_nprocs
;i
++) {
3610 status
= smb_raw_open(cli
[i
]->tree
, mem_ctx
, &io
);
3611 CHECK_STATUS(torture
, status
, NT_STATUS_OK
);
3615 if (torture_setting_bool(torture
, "progress", true)) {
3616 torture_comment(torture
, "%.2f ops/second\r", count
/timeval_elapsed(&tv
));
3620 torture_comment(torture
, "%.2f ops/second\n", count
/timeval_elapsed(&tv
));
3622 smb_raw_exit(cli
[torture_nprocs
-1]->session
);
3625 smb_raw_exit(cli
[0]->session
);
3626 smbcli_deltree(cli
[0]->tree
, BASEDIR
);
3627 talloc_free(mem_ctx
);
3632 static struct hold_oplock_info
{
3634 bool close_on_break
;
3635 uint32_t share_access
;
3638 { BASEDIR
"\\notshared_close", true,
3639 NTCREATEX_SHARE_ACCESS_NONE
, },
3640 { BASEDIR
"\\notshared_noclose", false,
3641 NTCREATEX_SHARE_ACCESS_NONE
, },
3642 { BASEDIR
"\\shared_close", true,
3643 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
3644 { BASEDIR
"\\shared_noclose", false,
3645 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
3648 static bool oplock_handler_hold(struct smbcli_transport
*transport
,
3649 uint16_t tid
, uint16_t fnum
, uint8_t level
,
3652 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
3653 struct hold_oplock_info
*info
;
3656 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
3657 if (hold_info
[i
].fnum
== fnum
) break;
3660 if (i
== ARRAY_SIZE(hold_info
)) {
3661 printf("oplock break for unknown fnum %u\n", fnum
);
3665 info
= &hold_info
[i
];
3667 if (info
->close_on_break
) {
3668 printf("oplock break on %s - closing\n",
3670 oplock_handler_close(transport
, tid
, fnum
, level
, private_data
);
3674 printf("oplock break on %s - acking break\n", info
->fname
);
3676 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
3681 used for manual testing of oplocks - especially interaction with
3682 other filesystems (such as NFS and local access)
3684 bool torture_hold_oplock(struct torture_context
*torture
,
3685 struct smbcli_state
*cli
)
3687 struct tevent_context
*ev
=
3688 (struct tevent_context
*)cli
->transport
->socket
->event
.ctx
;
3691 printf("Setting up open files with oplocks in %s\n", BASEDIR
);
3693 if (!torture_setup_dir(cli
, BASEDIR
)) {
3697 smbcli_oplock_handler(cli
->transport
, oplock_handler_hold
, cli
->tree
);
3699 /* setup the files */
3700 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
3705 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3706 io
.ntcreatex
.in
.root_fid
= 0;
3707 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3708 io
.ntcreatex
.in
.alloc_size
= 0;
3709 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3710 io
.ntcreatex
.in
.share_access
= hold_info
[i
].share_access
;
3711 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3712 io
.ntcreatex
.in
.create_options
= 0;
3713 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3714 io
.ntcreatex
.in
.security_flags
= 0;
3715 io
.ntcreatex
.in
.fname
= hold_info
[i
].fname
;
3716 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3717 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3718 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3719 printf("opening %s\n", hold_info
[i
].fname
);
3721 status
= smb_raw_open(cli
->tree
, cli
, &io
);
3722 if (!NT_STATUS_IS_OK(status
)) {
3723 printf("Failed to open %s - %s\n",
3724 hold_info
[i
].fname
, nt_errstr(status
));
3728 if (io
.ntcreatex
.out
.oplock_level
!= BATCH_OPLOCK_RETURN
) {
3729 printf("Oplock not granted for %s - expected %d but got %d\n",
3730 hold_info
[i
].fname
, BATCH_OPLOCK_RETURN
,
3731 io
.ntcreatex
.out
.oplock_level
);
3734 hold_info
[i
].fnum
= io
.ntcreatex
.out
.file
.fnum
;
3736 /* make the file non-zero size */
3737 if (smbcli_write(cli
->tree
, hold_info
[i
].fnum
, 0, &c
, 0, 1) != 1) {
3738 printf("Failed to write to file\n");
3743 printf("Waiting for oplock events\n");
3744 event_loop_wait(ev
);