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 "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "lib/events/events.h"
26 #include "param/param.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "libcli/resolve/resolve.h"
29 #include "torture/raw/proto.h"
31 #define CHECK_VAL(v, correct) do { \
32 if ((v) != (correct)) { \
33 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34 __location__, #v, (int)v, (int)correct); \
38 #define CHECK_RANGE(v, min, max) do { \
39 if ((v) < (min) || (v) > (max)) { \
40 torture_warning(tctx, "(%s): wrong value for %s got " \
41 "%d - should be between %d and %d\n", \
42 __location__, #v, (int)v, (int)min, (int)max); \
45 #define CHECK_STRMATCH(v, correct) do { \
46 if (!v || strstr((v),(correct)) == NULL) { \
47 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48 __location__, #v, v?v:"NULL", correct); \
53 #define CHECK_STATUS(tctx, status, correct) do { \
54 if (!NT_STATUS_EQUAL(status, correct)) { \
55 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56 nt_errstr(status), nt_errstr(correct)); \
69 #define BASEDIR "\\test_oplock"
72 a handler function for oplock break requests. Ack it as a break to level II if possible
74 static bool oplock_handler_ack_to_given(struct smbcli_transport
*transport
,
75 uint16_t tid
, uint16_t fnum
,
76 uint8_t level
, void *private_data
)
78 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
81 break_info
.fnum
= fnum
;
82 break_info
.level
= level
;
86 case OPLOCK_BREAK_TO_LEVEL_II
:
89 case OPLOCK_BREAK_TO_NONE
:
94 break_info
.failures
++;
96 printf("Acking to %s [0x%02X] in oplock handler\n",
99 return smbcli_oplock_ack(tree
, fnum
, level
);
103 a handler function for oplock break requests. Ack it as a break to none
105 static bool oplock_handler_ack_to_none(struct smbcli_transport
*transport
,
106 uint16_t tid
, uint16_t fnum
,
107 uint8_t level
, void *private_data
)
109 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
110 break_info
.fnum
= fnum
;
111 break_info
.level
= level
;
114 printf("Acking to none in oplock handler\n");
116 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
120 a handler function for oplock break requests. Let it timeout
122 static bool oplock_handler_timeout(struct smbcli_transport
*transport
,
123 uint16_t tid
, uint16_t fnum
,
124 uint8_t level
, void *private_data
)
126 break_info
.fnum
= fnum
;
127 break_info
.level
= level
;
130 printf("Let oplock break timeout\n");
134 static void oplock_handler_close_recv(struct smbcli_request
*req
)
137 status
= smbcli_request_simple_recv(req
);
138 if (!NT_STATUS_IS_OK(status
)) {
139 printf("close failed in oplock_handler_close\n");
140 break_info
.failures
++;
145 a handler function for oplock break requests - close the file
147 static bool oplock_handler_close(struct smbcli_transport
*transport
, uint16_t tid
,
148 uint16_t fnum
, uint8_t level
, void *private_data
)
151 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
152 struct smbcli_request
*req
;
154 break_info
.fnum
= fnum
;
155 break_info
.level
= level
;
158 io
.close
.level
= RAW_CLOSE_CLOSE
;
159 io
.close
.in
.file
.fnum
= fnum
;
160 io
.close
.in
.write_time
= 0;
161 req
= smb_raw_close_send(tree
, &io
);
163 printf("failed to send close in oplock_handler_close\n");
167 req
->async
.fn
= oplock_handler_close_recv
;
168 req
->async
.private_data
= NULL
;
173 static bool open_connection_no_level2_oplocks(struct torture_context
*tctx
,
174 struct smbcli_state
**c
)
177 struct smbcli_options options
;
178 struct smbcli_session_options session_options
;
180 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
181 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
183 options
.use_level2_oplocks
= false;
185 status
= smbcli_full_connection(tctx
, c
,
186 torture_setting_string(tctx
, "host", NULL
),
187 lpcfg_smb_ports(tctx
->lp_ctx
),
188 torture_setting_string(tctx
, "share", NULL
),
189 NULL
, lpcfg_socket_options(tctx
->lp_ctx
), cmdline_credentials
,
190 lpcfg_resolve_context(tctx
->lp_ctx
),
191 tctx
->ev
, &options
, &session_options
,
192 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
193 if (!NT_STATUS_IS_OK(status
)) {
194 torture_comment(tctx
, "Failed to open connection - %s\n",
203 Timer handler function notifies the registering function that time is up
205 static void timeout_cb(struct tevent_context
*ev
,
206 struct tevent_timer
*te
,
207 struct timeval current_time
,
210 bool *timesup
= (bool *)private_data
;
216 Wait a short period of time to receive a single oplock break request
218 static void torture_wait_for_oplock_break(struct torture_context
*tctx
)
220 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
221 struct tevent_timer
*te
= NULL
;
223 bool timesup
= false;
224 int old_count
= break_info
.count
;
226 /* Wait .1 seconds for an oplock break */
227 ne
= tevent_timeval_current_ofs(0, 100000);
229 if ((te
= tevent_add_timer(tctx
->ev
, tmp_ctx
, ne
, timeout_cb
, ×up
))
232 torture_comment(tctx
, "Failed to wait for an oplock break. "
233 "test results may not be accurate.");
237 while (!timesup
&& break_info
.count
< old_count
+ 1) {
238 if (tevent_loop_once(tctx
->ev
) != 0) {
239 torture_comment(tctx
, "Failed to wait for an oplock "
240 "break. test results may not be "
247 /* We don't know if the timed event fired and was freed, we received
248 * our oplock break, or some other event triggered the loop. Thus,
249 * we create a tmp_ctx to be able to safely free/remove the timed
250 * event in all 3 cases. */
251 talloc_free(tmp_ctx
);
256 static uint8_t get_break_level1_to_none_count(struct torture_context
*tctx
)
258 return torture_setting_bool(tctx
, "2_step_break_to_none", false) ?
262 static uint8_t get_setinfo_break_count(struct torture_context
*tctx
)
264 if (TARGET_IS_W2K12(tctx
)) {
267 if (TARGET_IS_SAMBA3(tctx
)) {
273 static bool test_raw_oplock_exclusive1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
275 const char *fname
= BASEDIR
"\\test_exclusive1.dat";
279 union smb_unlink unl
;
282 if (!torture_setup_dir(cli1
, BASEDIR
)) {
287 smbcli_unlink(cli1
->tree
, fname
);
289 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
294 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
295 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
296 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
297 io
.ntcreatex
.in
.alloc_size
= 0;
298 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
299 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
300 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
301 io
.ntcreatex
.in
.create_options
= 0;
302 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
303 io
.ntcreatex
.in
.security_flags
= 0;
304 io
.ntcreatex
.in
.fname
= fname
;
306 torture_comment(tctx
, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
307 ZERO_STRUCT(break_info
);
308 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
310 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
311 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
312 fnum
= io
.ntcreatex
.out
.file
.fnum
;
313 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
315 torture_comment(tctx
, "a 2nd open should not cause a break\n");
316 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
317 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
318 torture_wait_for_oplock_break(tctx
);
319 CHECK_VAL(break_info
.count
, 0);
320 CHECK_VAL(break_info
.failures
, 0);
322 torture_comment(tctx
, "unlink it - should also be no break\n");
323 unl
.unlink
.in
.pattern
= fname
;
324 unl
.unlink
.in
.attrib
= 0;
325 status
= smb_raw_unlink(cli2
->tree
, &unl
);
326 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
327 torture_wait_for_oplock_break(tctx
);
328 CHECK_VAL(break_info
.count
, 0);
329 CHECK_VAL(break_info
.failures
, 0);
331 smbcli_close(cli1
->tree
, fnum
);
334 smb_raw_exit(cli1
->session
);
335 smb_raw_exit(cli2
->session
);
336 smbcli_deltree(cli1
->tree
, BASEDIR
);
340 static bool test_raw_oplock_exclusive2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
342 const char *fname
= BASEDIR
"\\test_exclusive2.dat";
346 union smb_unlink unl
;
347 uint16_t fnum
=0, fnum2
=0;
349 if (!torture_setup_dir(cli1
, BASEDIR
)) {
354 smbcli_unlink(cli1
->tree
, fname
);
356 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
361 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
362 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
363 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
364 io
.ntcreatex
.in
.alloc_size
= 0;
365 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
366 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
367 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
368 io
.ntcreatex
.in
.create_options
= 0;
369 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
370 io
.ntcreatex
.in
.security_flags
= 0;
371 io
.ntcreatex
.in
.fname
= fname
;
373 torture_comment(tctx
, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
374 ZERO_STRUCT(break_info
);
375 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
376 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
377 NTCREATEX_SHARE_ACCESS_WRITE
|
378 NTCREATEX_SHARE_ACCESS_DELETE
;
380 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
381 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
382 fnum
= io
.ntcreatex
.out
.file
.fnum
;
383 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
385 torture_comment(tctx
, "a 2nd open should cause a break to level 2\n");
386 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
387 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
388 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
389 torture_wait_for_oplock_break(tctx
);
390 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
391 CHECK_VAL(break_info
.count
, 1);
392 CHECK_VAL(break_info
.fnum
, fnum
);
393 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
394 CHECK_VAL(break_info
.failures
, 0);
395 ZERO_STRUCT(break_info
);
397 /* now we have 2 level II oplocks... */
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 1st handle\n");
408 smbcli_close(cli1
->tree
, fnum
);
410 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\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_SHARING_VIOLATION
);
415 torture_wait_for_oplock_break(tctx
);
416 CHECK_VAL(break_info
.count
, 0);
417 CHECK_VAL(break_info
.failures
, 0);
419 torture_comment(tctx
, "close 2nd handle\n");
420 smbcli_close(cli2
->tree
, fnum2
);
422 torture_comment(tctx
, "unlink it\n");
423 unl
.unlink
.in
.pattern
= fname
;
424 unl
.unlink
.in
.attrib
= 0;
425 status
= smb_raw_unlink(cli2
->tree
, &unl
);
426 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
427 torture_wait_for_oplock_break(tctx
);
428 CHECK_VAL(break_info
.count
, 0);
429 CHECK_VAL(break_info
.failures
, 0);
432 smb_raw_exit(cli1
->session
);
433 smb_raw_exit(cli2
->session
);
434 smbcli_deltree(cli1
->tree
, BASEDIR
);
438 static bool test_raw_oplock_exclusive3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
440 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
444 union smb_setfileinfo sfi
;
447 if (!torture_setup_dir(cli1
, BASEDIR
)) {
452 smbcli_unlink(cli1
->tree
, fname
);
454 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
459 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
460 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
461 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
462 io
.ntcreatex
.in
.alloc_size
= 0;
463 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
464 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
465 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
466 io
.ntcreatex
.in
.create_options
= 0;
467 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
468 io
.ntcreatex
.in
.security_flags
= 0;
469 io
.ntcreatex
.in
.fname
= fname
;
471 torture_comment(tctx
, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
473 ZERO_STRUCT(break_info
);
474 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
476 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
477 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
478 fnum
= io
.ntcreatex
.out
.file
.fnum
;
479 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
481 torture_comment(tctx
, "setpathinfo EOF should trigger a break to none\n");
483 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
484 sfi
.generic
.in
.file
.path
= fname
;
485 sfi
.end_of_file_info
.in
.size
= 100;
487 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
489 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
490 torture_wait_for_oplock_break(tctx
);
491 CHECK_VAL(break_info
.count
, get_setinfo_break_count(tctx
));
492 CHECK_VAL(break_info
.failures
, 0);
493 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
495 smbcli_close(cli1
->tree
, fnum
);
498 smb_raw_exit(cli1
->session
);
499 smb_raw_exit(cli2
->session
);
500 smbcli_deltree(cli1
->tree
, BASEDIR
);
504 static bool test_raw_oplock_exclusive4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
506 const char *fname
= BASEDIR
"\\test_exclusive4.dat";
510 uint16_t fnum
=0, fnum2
=0;
512 if (!torture_setup_dir(cli1
, BASEDIR
)) {
517 smbcli_unlink(cli1
->tree
, fname
);
519 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
524 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
525 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
526 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
527 io
.ntcreatex
.in
.alloc_size
= 0;
528 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
529 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
530 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
531 io
.ntcreatex
.in
.create_options
= 0;
532 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
533 io
.ntcreatex
.in
.security_flags
= 0;
534 io
.ntcreatex
.in
.fname
= fname
;
536 torture_comment(tctx
, "EXCLUSIVE4: open with exclusive oplock\n");
537 ZERO_STRUCT(break_info
);
538 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
540 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
541 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
542 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
543 fnum
= io
.ntcreatex
.out
.file
.fnum
;
544 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
546 ZERO_STRUCT(break_info
);
547 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
549 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
550 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
551 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
552 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
553 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
554 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
555 torture_wait_for_oplock_break(tctx
);
556 CHECK_VAL(break_info
.count
, 0);
557 CHECK_VAL(break_info
.failures
, 0);
560 * Open another non-stat open. This reproduces bug 10216. Make sure it
561 * won't happen again...
563 io
.ntcreatex
.in
.flags
= 0;
564 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
565 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
566 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
567 torture_wait_for_oplock_break(tctx
);
568 CHECK_VAL(break_info
.count
, 0);
569 CHECK_VAL(break_info
.failures
, 0);
571 smbcli_close(cli1
->tree
, fnum
);
572 smbcli_close(cli2
->tree
, fnum2
);
575 smb_raw_exit(cli1
->session
);
576 smb_raw_exit(cli2
->session
);
577 smbcli_deltree(cli1
->tree
, BASEDIR
);
581 static bool test_raw_oplock_exclusive5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
583 const char *fname
= BASEDIR
"\\test_exclusive5.dat";
587 uint16_t fnum
=0, fnum2
=0;
589 if (!torture_setup_dir(cli1
, BASEDIR
)) {
594 smbcli_unlink(cli1
->tree
, fname
);
596 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
597 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
602 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
603 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
604 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
605 io
.ntcreatex
.in
.alloc_size
= 0;
606 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
607 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
608 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
609 io
.ntcreatex
.in
.create_options
= 0;
610 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
611 io
.ntcreatex
.in
.security_flags
= 0;
612 io
.ntcreatex
.in
.fname
= fname
;
614 torture_comment(tctx
, "EXCLUSIVE5: open with exclusive oplock\n");
615 ZERO_STRUCT(break_info
);
616 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
619 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
620 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
621 NTCREATEX_SHARE_ACCESS_WRITE
|
622 NTCREATEX_SHARE_ACCESS_DELETE
;
623 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
624 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
625 fnum
= io
.ntcreatex
.out
.file
.fnum
;
626 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
628 ZERO_STRUCT(break_info
);
630 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
632 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
633 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
634 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
635 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
636 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
637 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
638 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
639 torture_wait_for_oplock_break(tctx
);
640 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
641 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
642 CHECK_VAL(break_info
.failures
, 0);
644 smbcli_close(cli1
->tree
, fnum
);
645 smbcli_close(cli2
->tree
, fnum2
);
648 smb_raw_exit(cli1
->session
);
649 smb_raw_exit(cli2
->session
);
650 smbcli_deltree(cli1
->tree
, BASEDIR
);
654 static bool test_raw_oplock_exclusive6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
656 const char *fname1
= BASEDIR
"\\test_exclusive6_1.dat";
657 const char *fname2
= BASEDIR
"\\test_exclusive6_2.dat";
664 if (!torture_setup_dir(cli1
, BASEDIR
)) {
669 smbcli_unlink(cli1
->tree
, fname1
);
670 smbcli_unlink(cli1
->tree
, fname2
);
672 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
677 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
678 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
679 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
680 io
.ntcreatex
.in
.alloc_size
= 0;
681 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
682 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
683 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
684 io
.ntcreatex
.in
.create_options
= 0;
685 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
686 io
.ntcreatex
.in
.security_flags
= 0;
687 io
.ntcreatex
.in
.fname
= fname1
;
689 torture_comment(tctx
, "EXCLUSIVE6: open a file with an exclusive "
690 "oplock (share mode: none)\n");
691 ZERO_STRUCT(break_info
);
692 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
694 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
695 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
696 fnum
= io
.ntcreatex
.out
.file
.fnum
;
697 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
699 torture_comment(tctx
, "rename should not generate a break but get a "
700 "sharing violation\n");
702 rn
.generic
.level
= RAW_RENAME_RENAME
;
703 rn
.rename
.in
.pattern1
= fname1
;
704 rn
.rename
.in
.pattern2
= fname2
;
705 rn
.rename
.in
.attrib
= 0;
707 torture_comment(tctx
, "trying rename while first file open\n");
708 status
= smb_raw_rename(cli2
->tree
, &rn
);
710 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
711 torture_wait_for_oplock_break(tctx
);
712 CHECK_VAL(break_info
.count
, 0);
713 CHECK_VAL(break_info
.failures
, 0);
715 smbcli_close(cli1
->tree
, fnum
);
718 smb_raw_exit(cli1
->session
);
719 smb_raw_exit(cli2
->session
);
720 smbcli_deltree(cli1
->tree
, BASEDIR
);
725 * Exclusive version of batch19
727 static bool test_raw_oplock_exclusive7(struct torture_context
*tctx
,
728 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
730 const char *fname1
= BASEDIR
"\\test_exclusiv6_1.dat";
731 const char *fname2
= BASEDIR
"\\test_exclusiv6_2.dat";
732 const char *fname3
= BASEDIR
"\\test_exclusiv6_3.dat";
736 union smb_fileinfo qfi
;
737 union smb_setfileinfo sfi
;
741 if (!torture_setup_dir(cli1
, BASEDIR
)) {
746 smbcli_unlink(cli1
->tree
, fname1
);
747 smbcli_unlink(cli1
->tree
, fname2
);
748 smbcli_unlink(cli1
->tree
, fname3
);
750 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
756 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
757 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
758 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
759 io
.ntcreatex
.in
.alloc_size
= 0;
760 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
761 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
762 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
763 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
764 io
.ntcreatex
.in
.create_options
= 0;
765 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
766 io
.ntcreatex
.in
.security_flags
= 0;
767 io
.ntcreatex
.in
.fname
= fname1
;
769 torture_comment(tctx
, "open a file with an exclusive oplock (share "
771 ZERO_STRUCT(break_info
);
772 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
773 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
774 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
775 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
776 fnum
= io
.ntcreatex
.out
.file
.fnum
;
777 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
779 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
782 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
783 sfi
.generic
.in
.file
.path
= fname1
;
784 sfi
.rename_information
.in
.overwrite
= 0;
785 sfi
.rename_information
.in
.root_fid
= 0;
786 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
788 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
789 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
791 torture_wait_for_oplock_break(tctx
);
792 CHECK_VAL(break_info
.failures
, 0);
794 if (TARGET_IS_WINXP(tctx
) || TARGET_IS_W2K12(tctx
)) {
795 /* XP incorrectly breaks to level2. */
796 CHECK_VAL(break_info
.count
, 1);
797 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
799 /* Exclusive oplocks should not be broken on rename. */
800 CHECK_VAL(break_info
.failures
, 0);
801 CHECK_VAL(break_info
.count
, 0);
805 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
806 qfi
.generic
.in
.file
.fnum
= fnum
;
808 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
809 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
810 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
812 /* Try breaking to level2 and then see if rename breaks the level2.*/
813 ZERO_STRUCT(break_info
);
814 io
.ntcreatex
.in
.fname
= fname2
;
815 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
816 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
817 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
818 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
820 torture_wait_for_oplock_break(tctx
);
821 CHECK_VAL(break_info
.failures
, 0);
823 if (TARGET_IS_WINXP(tctx
)) {
824 /* XP already broke to level2. */
825 CHECK_VAL(break_info
.failures
, 0);
826 CHECK_VAL(break_info
.count
, 0);
827 } else if (TARGET_IS_W2K12(tctx
)) {
829 CHECK_VAL(break_info
.count
, 0);
830 CHECK_VAL(break_info
.level
, 0);
832 /* Break to level 2 expected. */
833 CHECK_VAL(break_info
.count
, 1);
834 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
837 ZERO_STRUCT(break_info
);
838 sfi
.generic
.in
.file
.path
= fname2
;
839 sfi
.rename_information
.in
.overwrite
= 0;
840 sfi
.rename_information
.in
.root_fid
= 0;
841 sfi
.rename_information
.in
.new_name
= fname1
+strlen(BASEDIR
)+1;
843 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
844 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
846 /* Level2 oplocks are not broken on rename. */
847 torture_wait_for_oplock_break(tctx
);
848 CHECK_VAL(break_info
.failures
, 0);
849 CHECK_VAL(break_info
.count
, 0);
851 /* Close and re-open file with oplock. */
852 smbcli_close(cli1
->tree
, fnum
);
853 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
854 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
855 fnum
= io
.ntcreatex
.out
.file
.fnum
;
856 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
858 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
859 "should not trigger a break nor a violation\n");
860 ZERO_STRUCT(break_info
);
862 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
863 sfi
.generic
.in
.file
.fnum
= fnum
;
864 sfi
.rename_information
.in
.overwrite
= 0;
865 sfi
.rename_information
.in
.root_fid
= 0;
866 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
868 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
869 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
871 torture_wait_for_oplock_break(tctx
);
872 if (TARGET_IS_WINXP(tctx
)) {
873 /* XP incorrectly breaks to level2. */
874 CHECK_VAL(break_info
.count
, 1);
875 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
877 CHECK_VAL(break_info
.count
, 0);
881 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
882 qfi
.generic
.in
.file
.fnum
= fnum
;
884 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
885 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
886 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
889 smbcli_close(cli1
->tree
, fnum
);
890 smbcli_close(cli2
->tree
, fnum2
);
892 smb_raw_exit(cli1
->session
);
893 smb_raw_exit(cli2
->session
);
894 smbcli_deltree(cli1
->tree
, BASEDIR
);
898 static bool test_raw_oplock_exclusive8(struct torture_context
*tctx
,
899 struct smbcli_state
*cli1
,
900 struct smbcli_state
*cli2
)
902 const char *fname
= BASEDIR
"\\test_exclusive8.dat";
910 if (!torture_setup_dir(cli1
, BASEDIR
)) {
915 smbcli_unlink(cli1
->tree
, fname
);
917 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
923 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
924 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
925 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
926 io
.ntcreatex
.in
.alloc_size
= 0;
927 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
928 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
929 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
930 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
931 io
.ntcreatex
.in
.create_options
= 0;
932 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
933 io
.ntcreatex
.in
.security_flags
= 0;
934 io
.ntcreatex
.in
.fname
= fname
;
936 torture_comment(tctx
, "open a file with an exclusive oplock (share "
938 ZERO_STRUCT(break_info
);
939 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
940 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
941 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
942 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
943 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
944 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
946 torture_comment(tctx
, "second open with delete should trigger a "
949 io
.ntcreatex
.in
.access_mask
= SEC_STD_DELETE
;
950 io
.ntcreatex
.in
.flags
= 0;
951 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
952 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
953 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
954 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
955 CHECK_VAL(break_info
.failures
, 0);
956 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
958 /* Trigger a little panic in "old" samba code.. */
959 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
960 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
961 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
963 smbcli_close(cli2
->tree
, fnum3
);
964 smbcli_close(cli2
->tree
, fnum2
);
965 smbcli_close(cli1
->tree
, fnum1
);
968 smbcli_deltree(cli1
->tree
, BASEDIR
);
969 smb_raw_exit(cli1
->session
);
970 smb_raw_exit(cli2
->session
);
974 static bool test_raw_oplock_exclusive9(struct torture_context
*tctx
,
975 struct smbcli_state
*cli1
,
976 struct smbcli_state
*cli2
)
978 const char *fname
= BASEDIR
"\\test_exclusive9.dat";
982 uint16_t fnum
=0, fnum2
=0;
986 uint32_t create_disposition
;
987 uint32_t break_level
;
989 { NTCREATEX_DISP_SUPERSEDE
, OPLOCK_BREAK_TO_NONE
},
990 { NTCREATEX_DISP_OPEN
, OPLOCK_BREAK_TO_LEVEL_II
},
991 { NTCREATEX_DISP_OVERWRITE_IF
, OPLOCK_BREAK_TO_NONE
},
992 { NTCREATEX_DISP_OPEN_IF
, OPLOCK_BREAK_TO_LEVEL_II
},
995 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1000 smbcli_unlink(cli1
->tree
, fname
);
1002 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
1004 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
,
1008 base ntcreatex parms
1010 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1011 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1012 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1013 io
.ntcreatex
.in
.alloc_size
= 0;
1014 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1015 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1016 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1017 io
.ntcreatex
.in
.create_options
= 0;
1018 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1019 io
.ntcreatex
.in
.security_flags
= 0;
1020 io
.ntcreatex
.in
.fname
= fname
;
1022 ZERO_STRUCT(break_info
);
1023 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
1026 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
1028 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1029 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1030 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1031 NTCREATEX_SHARE_ACCESS_WRITE
|
1032 NTCREATEX_SHARE_ACCESS_DELETE
;
1033 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
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
,
1038 EXCLUSIVE_OPLOCK_RETURN
);
1040 ZERO_STRUCT(break_info
);
1042 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1043 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1044 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
1045 io
.ntcreatex
.in
.open_disposition
=
1046 levels
[i
].create_disposition
;
1047 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1048 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1049 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1050 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
1051 LEVEL_II_OPLOCK_RETURN
);
1052 torture_wait_for_oplock_break(tctx
);
1053 CHECK_VAL(break_info
.count
, 1);
1054 CHECK_VAL(break_info
.level
, levels
[i
].break_level
);
1055 CHECK_VAL(break_info
.failures
, 0);
1057 smbcli_close(cli1
->tree
, fnum
);
1058 smbcli_close(cli2
->tree
, fnum2
);
1062 smb_raw_exit(cli1
->session
);
1063 smb_raw_exit(cli2
->session
);
1064 smbcli_deltree(cli1
->tree
, BASEDIR
);
1068 static bool test_raw_oplock_level_ii_1(struct torture_context
*tctx
,
1069 struct smbcli_state
*cli1
,
1070 struct smbcli_state
*cli2
)
1072 const char *fname
= BASEDIR
"\\test_level_ii_1.dat";
1076 uint16_t fnum
=0, fnum2
=0;
1080 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1085 smbcli_unlink(cli1
->tree
, fname
);
1087 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
1089 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
,
1093 base ntcreatex parms
1095 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1096 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1097 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1098 io
.ntcreatex
.in
.alloc_size
= 0;
1099 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1100 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1101 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1102 io
.ntcreatex
.in
.create_options
= 0;
1103 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1104 io
.ntcreatex
.in
.security_flags
= 0;
1105 io
.ntcreatex
.in
.fname
= fname
;
1107 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1108 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1109 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1110 NTCREATEX_SHARE_ACCESS_WRITE
|
1111 NTCREATEX_SHARE_ACCESS_DELETE
;
1112 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1113 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1114 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1115 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1116 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
1118 ZERO_STRUCT(break_info
);
1120 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1121 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1122 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
;
1123 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1124 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1125 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1126 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1127 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1128 torture_wait_for_oplock_break(tctx
);
1129 CHECK_VAL(break_info
.count
, 1);
1130 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1131 CHECK_VAL(break_info
.failures
, 0);
1133 status
= smbcli_close(cli2
->tree
, fnum2
);
1134 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1137 * fnum1 has a level2 oplock now
1140 ZERO_STRUCT(break_info
);
1143 * Don't answer the break to none that will come in
1146 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
,
1149 io
.ntcreatex
.in
.flags
= 0;
1150 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1152 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1153 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1154 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1155 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1156 torture_wait_for_oplock_break(tctx
);
1157 CHECK_VAL(break_info
.count
, 1);
1158 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
1159 CHECK_VAL(break_info
.failures
, 0);
1162 * Check that a write does not cause another break. This used to be a
1166 ZERO_STRUCT(break_info
);
1167 written
= smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1168 CHECK_VAL(written
, 1);
1169 torture_wait_for_oplock_break(tctx
);
1170 CHECK_VAL(break_info
.count
, 0);
1171 CHECK_VAL(break_info
.failures
, 0);
1173 status
= smbcli_close(cli2
->tree
, fnum2
);
1174 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1175 status
= smbcli_close(cli1
->tree
, fnum
);
1176 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1179 smb_raw_exit(cli1
->session
);
1180 smb_raw_exit(cli2
->session
);
1181 smbcli_deltree(cli1
->tree
, BASEDIR
);
1185 static bool test_raw_oplock_batch1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1187 const char *fname
= BASEDIR
"\\test_batch1.dat";
1191 union smb_unlink unl
;
1195 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1200 smbcli_unlink(cli1
->tree
, fname
);
1202 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1205 base ntcreatex parms
1207 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1208 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1209 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1210 io
.ntcreatex
.in
.alloc_size
= 0;
1211 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1212 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1213 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1214 io
.ntcreatex
.in
.create_options
= 0;
1215 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1216 io
.ntcreatex
.in
.security_flags
= 0;
1217 io
.ntcreatex
.in
.fname
= fname
;
1220 with a batch oplock we get a break
1222 torture_comment(tctx
, "BATCH1: open with batch oplock\n");
1223 ZERO_STRUCT(break_info
);
1224 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1225 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1226 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1227 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1228 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1229 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1230 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1232 torture_comment(tctx
, "unlink should generate a break\n");
1233 unl
.unlink
.in
.pattern
= fname
;
1234 unl
.unlink
.in
.attrib
= 0;
1235 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1236 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1238 torture_wait_for_oplock_break(tctx
);
1239 CHECK_VAL(break_info
.count
, 1);
1240 CHECK_VAL(break_info
.fnum
, fnum
);
1241 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1242 CHECK_VAL(break_info
.failures
, 0);
1244 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1245 ZERO_STRUCT(break_info
);
1246 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1247 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1249 torture_wait_for_oplock_break(tctx
);
1250 CHECK_VAL(break_info
.count
, 0);
1252 torture_comment(tctx
, "writing should generate a self break to none\n");
1253 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1255 torture_wait_for_oplock_break(tctx
);
1256 torture_wait_for_oplock_break(tctx
);
1257 CHECK_VAL(break_info
.count
, 1);
1258 CHECK_VAL(break_info
.fnum
, fnum
);
1259 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
1260 CHECK_VAL(break_info
.failures
, 0);
1262 smbcli_close(cli1
->tree
, fnum
);
1265 smb_raw_exit(cli1
->session
);
1266 smb_raw_exit(cli2
->session
);
1267 smbcli_deltree(cli1
->tree
, BASEDIR
);
1271 static bool test_raw_oplock_batch2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1273 const char *fname
= BASEDIR
"\\test_batch2.dat";
1277 union smb_unlink unl
;
1281 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1286 smbcli_unlink(cli1
->tree
, fname
);
1288 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1291 base ntcreatex parms
1293 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1294 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1295 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1296 io
.ntcreatex
.in
.alloc_size
= 0;
1297 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1298 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1299 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1300 io
.ntcreatex
.in
.create_options
= 0;
1301 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1302 io
.ntcreatex
.in
.security_flags
= 0;
1303 io
.ntcreatex
.in
.fname
= fname
;
1305 torture_comment(tctx
, "BATCH2: open with batch oplock\n");
1306 ZERO_STRUCT(break_info
);
1307 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1308 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1309 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1310 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1311 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1312 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1313 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1315 torture_comment(tctx
, "unlink should generate a break, which we ack as break to none\n");
1316 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_none
, cli1
->tree
);
1317 unl
.unlink
.in
.pattern
= fname
;
1318 unl
.unlink
.in
.attrib
= 0;
1319 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1320 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1322 torture_wait_for_oplock_break(tctx
);
1323 CHECK_VAL(break_info
.count
, 1);
1324 CHECK_VAL(break_info
.fnum
, fnum
);
1325 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1326 CHECK_VAL(break_info
.failures
, 0);
1328 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1329 ZERO_STRUCT(break_info
);
1330 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1331 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1333 torture_wait_for_oplock_break(tctx
);
1334 CHECK_VAL(break_info
.count
, 0);
1336 torture_comment(tctx
, "writing should not generate a break\n");
1337 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1339 torture_wait_for_oplock_break(tctx
);
1340 CHECK_VAL(break_info
.count
, 0);
1342 smbcli_close(cli1
->tree
, fnum
);
1345 smb_raw_exit(cli1
->session
);
1346 smb_raw_exit(cli2
->session
);
1347 smbcli_deltree(cli1
->tree
, BASEDIR
);
1351 static bool test_raw_oplock_batch3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1353 const char *fname
= BASEDIR
"\\test_batch3.dat";
1357 union smb_unlink unl
;
1360 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1365 smbcli_unlink(cli1
->tree
, fname
);
1367 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1370 base ntcreatex parms
1372 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1373 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1374 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1375 io
.ntcreatex
.in
.alloc_size
= 0;
1376 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1377 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1378 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1379 io
.ntcreatex
.in
.create_options
= 0;
1380 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1381 io
.ntcreatex
.in
.security_flags
= 0;
1382 io
.ntcreatex
.in
.fname
= fname
;
1384 torture_comment(tctx
, "BATCH3: if we close on break then the unlink can succeed\n");
1385 ZERO_STRUCT(break_info
);
1386 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1387 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1388 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1389 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1390 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1391 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1392 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1393 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1395 unl
.unlink
.in
.pattern
= fname
;
1396 unl
.unlink
.in
.attrib
= 0;
1397 ZERO_STRUCT(break_info
);
1398 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1399 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1401 torture_wait_for_oplock_break(tctx
);
1402 CHECK_VAL(break_info
.count
, 1);
1403 CHECK_VAL(break_info
.fnum
, fnum
);
1404 CHECK_VAL(break_info
.level
, 1);
1405 CHECK_VAL(break_info
.failures
, 0);
1407 smbcli_close(cli1
->tree
, fnum
);
1410 smb_raw_exit(cli1
->session
);
1411 smb_raw_exit(cli2
->session
);
1412 smbcli_deltree(cli1
->tree
, BASEDIR
);
1416 static bool test_raw_oplock_batch4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1418 const char *fname
= BASEDIR
"\\test_batch4.dat";
1425 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1430 smbcli_unlink(cli1
->tree
, fname
);
1432 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1435 base ntcreatex parms
1437 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1438 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1439 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1440 io
.ntcreatex
.in
.alloc_size
= 0;
1441 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1442 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1443 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1444 io
.ntcreatex
.in
.create_options
= 0;
1445 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1446 io
.ntcreatex
.in
.security_flags
= 0;
1447 io
.ntcreatex
.in
.fname
= fname
;
1449 torture_comment(tctx
, "BATCH4: a self read should not cause a break\n");
1450 ZERO_STRUCT(break_info
);
1451 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1453 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1454 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1455 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1456 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1457 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1458 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1459 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1461 rd
.readx
.level
= RAW_READ_READX
;
1462 rd
.readx
.in
.file
.fnum
= fnum
;
1463 rd
.readx
.in
.mincnt
= 1;
1464 rd
.readx
.in
.maxcnt
= 1;
1465 rd
.readx
.in
.offset
= 0;
1466 rd
.readx
.in
.remaining
= 0;
1467 rd
.readx
.in
.read_for_execute
= false;
1468 status
= smb_raw_read(cli1
->tree
, &rd
);
1469 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1470 torture_wait_for_oplock_break(tctx
);
1471 CHECK_VAL(break_info
.count
, 0);
1472 CHECK_VAL(break_info
.failures
, 0);
1474 smbcli_close(cli1
->tree
, fnum
);
1477 smb_raw_exit(cli1
->session
);
1478 smb_raw_exit(cli2
->session
);
1479 smbcli_deltree(cli1
->tree
, BASEDIR
);
1483 static bool test_raw_oplock_batch5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1485 const char *fname
= BASEDIR
"\\test_batch5.dat";
1491 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1496 smbcli_unlink(cli1
->tree
, fname
);
1498 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1501 base ntcreatex parms
1503 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1504 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1505 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1506 io
.ntcreatex
.in
.alloc_size
= 0;
1507 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1508 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1509 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1510 io
.ntcreatex
.in
.create_options
= 0;
1511 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1512 io
.ntcreatex
.in
.security_flags
= 0;
1513 io
.ntcreatex
.in
.fname
= fname
;
1515 torture_comment(tctx
, "BATCH5: a 2nd open should give a break\n");
1516 ZERO_STRUCT(break_info
);
1517 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1519 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1520 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1521 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1522 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1523 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1524 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1525 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1527 ZERO_STRUCT(break_info
);
1529 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1530 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1531 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1533 torture_wait_for_oplock_break(tctx
);
1534 CHECK_VAL(break_info
.count
, 1);
1535 CHECK_VAL(break_info
.fnum
, fnum
);
1536 CHECK_VAL(break_info
.level
, 1);
1537 CHECK_VAL(break_info
.failures
, 0);
1539 smbcli_close(cli1
->tree
, fnum
);
1542 smb_raw_exit(cli1
->session
);
1543 smb_raw_exit(cli2
->session
);
1544 smbcli_deltree(cli1
->tree
, BASEDIR
);
1548 static bool test_raw_oplock_batch6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1550 const char *fname
= BASEDIR
"\\test_batch6.dat";
1554 uint16_t fnum
=0, fnum2
=0;
1557 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1562 smbcli_unlink(cli1
->tree
, fname
);
1564 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1565 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1568 base ntcreatex parms
1570 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1571 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1572 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1573 io
.ntcreatex
.in
.alloc_size
= 0;
1574 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1575 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1576 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1577 io
.ntcreatex
.in
.create_options
= 0;
1578 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1579 io
.ntcreatex
.in
.security_flags
= 0;
1580 io
.ntcreatex
.in
.fname
= fname
;
1582 torture_comment(tctx
, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1583 ZERO_STRUCT(break_info
);
1585 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
1586 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1587 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1588 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1589 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1590 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1591 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1592 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1593 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1595 ZERO_STRUCT(break_info
);
1597 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1598 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1599 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1600 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1602 //torture_wait_for_oplock_break(tctx);
1603 CHECK_VAL(break_info
.count
, 1);
1604 CHECK_VAL(break_info
.fnum
, fnum
);
1605 CHECK_VAL(break_info
.level
, 1);
1606 CHECK_VAL(break_info
.failures
, 0);
1607 ZERO_STRUCT(break_info
);
1609 torture_comment(tctx
, "write should trigger a break to none on both\n");
1610 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1612 /* We expect two breaks */
1613 torture_wait_for_oplock_break(tctx
);
1614 torture_wait_for_oplock_break(tctx
);
1616 CHECK_VAL(break_info
.count
, 2);
1617 CHECK_VAL(break_info
.level
, 0);
1618 CHECK_VAL(break_info
.failures
, 0);
1620 smbcli_close(cli1
->tree
, fnum
);
1621 smbcli_close(cli2
->tree
, fnum2
);
1624 smb_raw_exit(cli1
->session
);
1625 smb_raw_exit(cli2
->session
);
1626 smbcli_deltree(cli1
->tree
, BASEDIR
);
1630 static bool test_raw_oplock_batch7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1632 const char *fname
= BASEDIR
"\\test_batch7.dat";
1636 uint16_t fnum
=0, fnum2
=0;
1638 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1643 smbcli_unlink(cli1
->tree
, fname
);
1645 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1648 base ntcreatex parms
1650 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1651 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1652 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1653 io
.ntcreatex
.in
.alloc_size
= 0;
1654 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1655 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1656 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1657 io
.ntcreatex
.in
.create_options
= 0;
1658 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1659 io
.ntcreatex
.in
.security_flags
= 0;
1660 io
.ntcreatex
.in
.fname
= fname
;
1662 torture_comment(tctx
, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1663 ZERO_STRUCT(break_info
);
1664 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1666 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1667 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1668 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1669 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1670 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1671 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1672 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1673 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1674 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1676 ZERO_STRUCT(break_info
);
1678 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1679 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1680 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1681 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1682 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1683 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1684 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1686 torture_wait_for_oplock_break(tctx
);
1687 CHECK_VAL(break_info
.count
, 1);
1688 CHECK_VAL(break_info
.fnum
, fnum2
);
1689 CHECK_VAL(break_info
.level
, 1);
1690 CHECK_VAL(break_info
.failures
, 0);
1692 smbcli_close(cli2
->tree
, fnum
);
1695 smb_raw_exit(cli1
->session
);
1696 smb_raw_exit(cli2
->session
);
1697 smbcli_deltree(cli1
->tree
, BASEDIR
);
1701 static bool test_raw_oplock_batch8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1703 const char *fname
= BASEDIR
"\\test_batch8.dat";
1707 uint16_t fnum
=0, fnum2
=0;
1709 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1714 smbcli_unlink(cli1
->tree
, fname
);
1716 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1719 base ntcreatex parms
1721 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1722 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1723 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1724 io
.ntcreatex
.in
.alloc_size
= 0;
1725 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1726 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1727 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1728 io
.ntcreatex
.in
.create_options
= 0;
1729 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1730 io
.ntcreatex
.in
.security_flags
= 0;
1731 io
.ntcreatex
.in
.fname
= fname
;
1733 torture_comment(tctx
, "BATCH8: open with batch oplock\n");
1734 ZERO_STRUCT(break_info
);
1735 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1737 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1738 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1739 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1740 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1741 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1742 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1743 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1745 ZERO_STRUCT(break_info
);
1746 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
1748 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1749 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1750 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1751 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1752 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1753 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1754 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1755 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1756 torture_wait_for_oplock_break(tctx
);
1757 CHECK_VAL(break_info
.count
, 0);
1758 CHECK_VAL(break_info
.failures
, 0);
1760 smbcli_close(cli1
->tree
, fnum
);
1761 smbcli_close(cli2
->tree
, fnum2
);
1764 smb_raw_exit(cli1
->session
);
1765 smb_raw_exit(cli2
->session
);
1766 smbcli_deltree(cli1
->tree
, BASEDIR
);
1770 static bool test_raw_oplock_batch9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1772 const char *fname
= BASEDIR
"\\test_batch9.dat";
1776 uint16_t fnum
=0, fnum2
=0;
1779 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1784 smbcli_unlink(cli1
->tree
, fname
);
1786 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1789 base ntcreatex parms
1791 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1792 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1793 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1794 io
.ntcreatex
.in
.alloc_size
= 0;
1795 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1796 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1797 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1798 io
.ntcreatex
.in
.create_options
= 0;
1799 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1800 io
.ntcreatex
.in
.security_flags
= 0;
1801 io
.ntcreatex
.in
.fname
= fname
;
1803 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1805 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1806 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1807 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1808 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1809 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1810 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1811 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1812 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1813 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1815 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1817 ZERO_STRUCT(break_info
);
1818 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1820 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1821 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1822 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1823 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1824 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1825 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1826 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1827 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1828 torture_wait_for_oplock_break(tctx
);
1829 CHECK_VAL(break_info
.count
, 1);
1830 CHECK_VAL(break_info
.fnum
, fnum
);
1831 CHECK_VAL(break_info
.failures
, 0);
1832 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1833 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1834 smbcli_close(cli2
->tree
, fnum2
);
1836 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1837 ZERO_STRUCT(break_info
);
1838 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1839 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1840 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1841 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1842 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1843 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1844 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1845 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1846 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1847 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1848 torture_wait_for_oplock_break(tctx
);
1849 CHECK_VAL(break_info
.count
, 0);
1850 CHECK_VAL(break_info
.failures
, 0);
1851 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1853 ZERO_STRUCT(break_info
);
1855 torture_comment(tctx
, "write should trigger a break to none on both\n");
1856 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1858 /* We expect two breaks */
1859 torture_wait_for_oplock_break(tctx
);
1860 torture_wait_for_oplock_break(tctx
);
1862 CHECK_VAL(break_info
.count
, 2);
1863 CHECK_VAL(break_info
.level
, 0);
1864 CHECK_VAL(break_info
.failures
, 0);
1866 smbcli_close(cli1
->tree
, fnum
);
1867 smbcli_close(cli2
->tree
, fnum2
);
1870 smb_raw_exit(cli1
->session
);
1871 smb_raw_exit(cli2
->session
);
1872 smbcli_deltree(cli1
->tree
, BASEDIR
);
1876 static bool test_raw_oplock_batch9a(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1878 const char *fname
= BASEDIR
"\\test_batch9a.dat";
1882 uint16_t fnum
=0, fnum2
=0;
1885 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1890 smbcli_unlink(cli1
->tree
, fname
);
1892 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1895 base ntcreatex parms
1897 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1898 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1899 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1900 io
.ntcreatex
.in
.alloc_size
= 0;
1901 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1902 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1903 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1904 io
.ntcreatex
.in
.create_options
= 0;
1905 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1906 io
.ntcreatex
.in
.security_flags
= 0;
1907 io
.ntcreatex
.in
.fname
= fname
;
1909 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1911 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1912 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1913 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1914 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1915 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1916 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1917 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1918 CHECK_VAL(io
.ntcreatex
.out
.create_action
, FILE_WAS_CREATED
);
1919 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1921 torture_comment(tctx
, "Subsequent attributes open should not break\n");
1923 ZERO_STRUCT(break_info
);
1924 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1926 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1927 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1928 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1929 torture_wait_for_oplock_break(tctx
);
1930 CHECK_VAL(break_info
.count
, 0);
1931 CHECK_VAL(io
.ntcreatex
.out
.create_action
, FILE_WAS_OPENED
);
1932 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1933 smbcli_close(cli2
->tree
, fnum2
);
1935 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1937 ZERO_STRUCT(break_info
);
1938 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1940 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1941 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1942 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1943 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1944 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1945 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1946 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1947 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1948 torture_wait_for_oplock_break(tctx
);
1949 CHECK_VAL(break_info
.count
, 1);
1950 CHECK_VAL(break_info
.fnum
, fnum
);
1951 CHECK_VAL(break_info
.failures
, 0);
1952 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1953 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1954 smbcli_close(cli2
->tree
, fnum2
);
1956 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1957 ZERO_STRUCT(break_info
);
1958 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1959 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1960 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1961 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1962 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1963 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1964 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1965 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1966 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1967 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1968 torture_wait_for_oplock_break(tctx
);
1969 CHECK_VAL(break_info
.count
, 0);
1970 CHECK_VAL(break_info
.failures
, 0);
1971 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1973 ZERO_STRUCT(break_info
);
1975 torture_comment(tctx
, "write should trigger a break to none on both\n");
1976 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1978 /* We expect two breaks */
1979 torture_wait_for_oplock_break(tctx
);
1980 torture_wait_for_oplock_break(tctx
);
1982 CHECK_VAL(break_info
.count
, 2);
1983 CHECK_VAL(break_info
.level
, 0);
1984 CHECK_VAL(break_info
.failures
, 0);
1986 smbcli_close(cli1
->tree
, fnum
);
1987 smbcli_close(cli2
->tree
, fnum2
);
1990 smb_raw_exit(cli1
->session
);
1991 smb_raw_exit(cli2
->session
);
1992 smbcli_deltree(cli1
->tree
, BASEDIR
);
1996 static bool test_raw_oplock_batch10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1998 const char *fname
= BASEDIR
"\\test_batch10.dat";
2002 uint16_t fnum
=0, fnum2
=0;
2004 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2009 smbcli_unlink(cli1
->tree
, fname
);
2011 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2014 base ntcreatex parms
2016 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2017 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2018 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2019 io
.ntcreatex
.in
.alloc_size
= 0;
2020 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2021 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2022 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2023 io
.ntcreatex
.in
.create_options
= 0;
2024 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2025 io
.ntcreatex
.in
.security_flags
= 0;
2026 io
.ntcreatex
.in
.fname
= fname
;
2028 torture_comment(tctx
, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
2029 ZERO_STRUCT(break_info
);
2030 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
2031 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2032 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2033 NTCREATEX_SHARE_ACCESS_WRITE
|
2034 NTCREATEX_SHARE_ACCESS_DELETE
;
2035 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2036 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2037 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2038 torture_wait_for_oplock_break(tctx
);
2039 CHECK_VAL(break_info
.count
, 0);
2040 CHECK_VAL(break_info
.failures
, 0);
2041 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
2045 wr
.write
.level
= RAW_WRITE_WRITE
;
2046 wr
.write
.in
.file
.fnum
= fnum
;
2047 wr
.write
.in
.count
= 1;
2048 wr
.write
.in
.offset
= 0;
2049 wr
.write
.in
.remaining
= 0;
2050 wr
.write
.in
.data
= (const uint8_t *)"x";
2051 status
= smb_raw_write(cli1
->tree
, &wr
);
2052 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2055 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
2057 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2058 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2059 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2060 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2061 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2062 NTCREATEX_SHARE_ACCESS_WRITE
|
2063 NTCREATEX_SHARE_ACCESS_DELETE
;
2064 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
2065 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2066 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2067 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2068 torture_wait_for_oplock_break(tctx
);
2069 CHECK_VAL(break_info
.count
, 0);
2070 CHECK_VAL(break_info
.failures
, 0);
2071 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2073 torture_comment(tctx
, "write should trigger a break to none\n");
2076 wr
.write
.level
= RAW_WRITE_WRITE
;
2077 wr
.write
.in
.file
.fnum
= fnum
;
2078 wr
.write
.in
.count
= 1;
2079 wr
.write
.in
.offset
= 0;
2080 wr
.write
.in
.remaining
= 0;
2081 wr
.write
.in
.data
= (const uint8_t *)"x";
2082 status
= smb_raw_write(cli1
->tree
, &wr
);
2083 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2086 torture_wait_for_oplock_break(tctx
);
2088 CHECK_VAL(break_info
.count
, 1);
2089 CHECK_VAL(break_info
.fnum
, fnum2
);
2090 CHECK_VAL(break_info
.level
, 0);
2091 CHECK_VAL(break_info
.failures
, 0);
2093 smbcli_close(cli1
->tree
, fnum
);
2094 smbcli_close(cli2
->tree
, fnum2
);
2097 smb_raw_exit(cli1
->session
);
2098 smb_raw_exit(cli2
->session
);
2099 smbcli_deltree(cli1
->tree
, BASEDIR
);
2103 static bool test_raw_oplock_batch11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2105 const char *fname
= BASEDIR
"\\test_batch11.dat";
2109 union smb_setfileinfo sfi
;
2112 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2117 smbcli_unlink(cli1
->tree
, fname
);
2119 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2122 base ntcreatex parms
2124 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2125 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2126 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2127 io
.ntcreatex
.in
.alloc_size
= 0;
2128 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2129 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
2130 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2131 io
.ntcreatex
.in
.create_options
= 0;
2132 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2133 io
.ntcreatex
.in
.security_flags
= 0;
2134 io
.ntcreatex
.in
.fname
= fname
;
2136 /* Test if a set-eof on pathname breaks an exclusive oplock. */
2137 torture_comment(tctx
, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
2139 ZERO_STRUCT(break_info
);
2141 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2142 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2143 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2144 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2145 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2146 NTCREATEX_SHARE_ACCESS_WRITE
|
2147 NTCREATEX_SHARE_ACCESS_DELETE
;
2148 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2149 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2150 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2151 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2152 torture_wait_for_oplock_break(tctx
);
2153 CHECK_VAL(break_info
.count
, 0);
2154 CHECK_VAL(break_info
.failures
, 0);
2155 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2158 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
2159 sfi
.generic
.in
.file
.path
= fname
;
2160 sfi
.end_of_file_info
.in
.size
= 100;
2162 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2163 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2165 torture_wait_for_oplock_break(tctx
);
2166 CHECK_VAL(break_info
.count
, get_setinfo_break_count(tctx
));
2167 CHECK_VAL(break_info
.failures
, 0);
2168 CHECK_VAL(break_info
.level
, 0);
2170 smbcli_close(cli1
->tree
, fnum
);
2173 smb_raw_exit(cli1
->session
);
2174 smb_raw_exit(cli2
->session
);
2175 smbcli_deltree(cli1
->tree
, BASEDIR
);
2179 static bool test_raw_oplock_batch12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2181 const char *fname
= BASEDIR
"\\test_batch12.dat";
2185 union smb_setfileinfo sfi
;
2188 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2193 smbcli_unlink(cli1
->tree
, fname
);
2195 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2198 base ntcreatex parms
2200 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2201 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2202 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2203 io
.ntcreatex
.in
.alloc_size
= 0;
2204 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2205 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2206 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2207 io
.ntcreatex
.in
.create_options
= 0;
2208 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2209 io
.ntcreatex
.in
.security_flags
= 0;
2210 io
.ntcreatex
.in
.fname
= fname
;
2212 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
2213 torture_comment(tctx
, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
2215 ZERO_STRUCT(break_info
);
2216 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2218 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2219 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2220 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2221 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2222 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2223 NTCREATEX_SHARE_ACCESS_WRITE
|
2224 NTCREATEX_SHARE_ACCESS_DELETE
;
2225 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2226 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2227 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2228 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2229 torture_wait_for_oplock_break(tctx
);
2230 CHECK_VAL(break_info
.count
, 0);
2231 CHECK_VAL(break_info
.failures
, 0);
2232 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2235 sfi
.generic
.level
= SMB_SFILEINFO_ALLOCATION_INFORMATION
;
2236 sfi
.generic
.in
.file
.path
= fname
;
2237 sfi
.allocation_info
.in
.alloc_size
= 65536 * 8;
2239 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2240 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2242 torture_wait_for_oplock_break(tctx
);
2243 CHECK_VAL(break_info
.count
, get_setinfo_break_count(tctx
));
2244 CHECK_VAL(break_info
.failures
, 0);
2245 CHECK_VAL(break_info
.level
, 0);
2247 smbcli_close(cli1
->tree
, fnum
);
2250 smb_raw_exit(cli1
->session
);
2251 smb_raw_exit(cli2
->session
);
2252 smbcli_deltree(cli1
->tree
, BASEDIR
);
2256 static bool test_raw_oplock_batch13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2258 const char *fname
= BASEDIR
"\\test_batch13.dat";
2262 uint16_t fnum
=0, fnum2
=0;
2264 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2269 smbcli_unlink(cli1
->tree
, fname
);
2271 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2272 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2275 base ntcreatex parms
2277 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2278 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2279 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2280 io
.ntcreatex
.in
.alloc_size
= 0;
2281 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2282 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2283 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2284 io
.ntcreatex
.in
.create_options
= 0;
2285 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2286 io
.ntcreatex
.in
.security_flags
= 0;
2287 io
.ntcreatex
.in
.fname
= fname
;
2289 torture_comment(tctx
, "BATCH13: open with batch oplock\n");
2290 ZERO_STRUCT(break_info
);
2292 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2293 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2294 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2295 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2296 NTCREATEX_SHARE_ACCESS_WRITE
|
2297 NTCREATEX_SHARE_ACCESS_DELETE
;
2298 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2299 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2300 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2301 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2303 ZERO_STRUCT(break_info
);
2305 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
2307 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2308 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2309 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2310 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2311 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2312 NTCREATEX_SHARE_ACCESS_WRITE
|
2313 NTCREATEX_SHARE_ACCESS_DELETE
;
2314 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
2315 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2316 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2317 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2318 torture_wait_for_oplock_break(tctx
);
2319 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2320 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2321 CHECK_VAL(break_info
.failures
, 0);
2323 smbcli_close(cli1
->tree
, fnum
);
2324 smbcli_close(cli2
->tree
, fnum2
);
2327 smb_raw_exit(cli1
->session
);
2328 smb_raw_exit(cli2
->session
);
2329 smbcli_deltree(cli1
->tree
, BASEDIR
);
2333 static bool test_raw_oplock_batch14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2335 const char *fname
= BASEDIR
"\\test_batch14.dat";
2339 uint16_t fnum
=0, fnum2
=0;
2341 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2346 smbcli_unlink(cli1
->tree
, fname
);
2348 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2351 base ntcreatex parms
2353 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2354 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2355 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2356 io
.ntcreatex
.in
.alloc_size
= 0;
2357 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2358 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2359 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2360 io
.ntcreatex
.in
.create_options
= 0;
2361 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2362 io
.ntcreatex
.in
.security_flags
= 0;
2363 io
.ntcreatex
.in
.fname
= fname
;
2365 torture_comment(tctx
, "BATCH14: open with batch oplock\n");
2366 ZERO_STRUCT(break_info
);
2368 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2369 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2370 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2371 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2372 NTCREATEX_SHARE_ACCESS_WRITE
|
2373 NTCREATEX_SHARE_ACCESS_DELETE
;
2374 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2375 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2376 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2377 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2379 ZERO_STRUCT(break_info
);
2381 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
2383 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2384 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2385 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2386 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2387 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2388 NTCREATEX_SHARE_ACCESS_WRITE
|
2389 NTCREATEX_SHARE_ACCESS_DELETE
;
2390 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
2391 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2392 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2393 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2394 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2396 torture_wait_for_oplock_break(tctx
);
2397 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2398 CHECK_VAL(break_info
.failures
, 0);
2400 smbcli_close(cli1
->tree
, fnum
);
2401 smbcli_close(cli2
->tree
, fnum2
);
2403 smb_raw_exit(cli1
->session
);
2404 smb_raw_exit(cli2
->session
);
2405 smbcli_deltree(cli1
->tree
, BASEDIR
);
2409 static bool test_raw_oplock_batch15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2411 const char *fname
= BASEDIR
"\\test_batch15.dat";
2415 union smb_fileinfo qfi
;
2418 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2423 smbcli_unlink(cli1
->tree
, fname
);
2425 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2428 base ntcreatex parms
2430 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2431 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2432 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2433 io
.ntcreatex
.in
.alloc_size
= 0;
2434 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2435 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2436 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2437 io
.ntcreatex
.in
.create_options
= 0;
2438 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2439 io
.ntcreatex
.in
.security_flags
= 0;
2440 io
.ntcreatex
.in
.fname
= fname
;
2442 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2443 torture_comment(tctx
, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
2445 ZERO_STRUCT(break_info
);
2447 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2448 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2449 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2450 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2451 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2452 NTCREATEX_SHARE_ACCESS_WRITE
|
2453 NTCREATEX_SHARE_ACCESS_DELETE
;
2454 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2455 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2456 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2457 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2458 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2460 torture_wait_for_oplock_break(tctx
);
2461 CHECK_VAL(break_info
.count
, 0);
2462 CHECK_VAL(break_info
.failures
, 0);
2463 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2466 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2467 qfi
.generic
.in
.file
.path
= fname
;
2469 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
2470 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2472 torture_wait_for_oplock_break(tctx
);
2473 CHECK_VAL(break_info
.count
, 0);
2475 smbcli_close(cli1
->tree
, fnum
);
2478 smb_raw_exit(cli1
->session
);
2479 smb_raw_exit(cli2
->session
);
2480 smbcli_deltree(cli1
->tree
, BASEDIR
);
2484 static bool test_raw_oplock_batch16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2486 const char *fname
= BASEDIR
"\\test_batch16.dat";
2490 uint16_t fnum
=0, fnum2
=0;
2492 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2497 smbcli_unlink(cli1
->tree
, fname
);
2499 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2500 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2503 base ntcreatex parms
2505 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2506 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2507 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2508 io
.ntcreatex
.in
.alloc_size
= 0;
2509 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2510 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2511 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2512 io
.ntcreatex
.in
.create_options
= 0;
2513 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2514 io
.ntcreatex
.in
.security_flags
= 0;
2515 io
.ntcreatex
.in
.fname
= fname
;
2517 torture_comment(tctx
, "BATCH16: open with batch oplock\n");
2518 ZERO_STRUCT(break_info
);
2520 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2521 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2522 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2523 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2524 NTCREATEX_SHARE_ACCESS_WRITE
|
2525 NTCREATEX_SHARE_ACCESS_DELETE
;
2526 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2527 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2528 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2529 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2531 ZERO_STRUCT(break_info
);
2533 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2535 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2536 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2537 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2538 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2539 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2540 NTCREATEX_SHARE_ACCESS_WRITE
|
2541 NTCREATEX_SHARE_ACCESS_DELETE
;
2542 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
2543 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2544 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2545 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2546 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2548 torture_wait_for_oplock_break(tctx
);
2549 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2550 CHECK_VAL(break_info
.failures
, 0);
2552 smbcli_close(cli1
->tree
, fnum
);
2553 smbcli_close(cli2
->tree
, fnum2
);
2556 smb_raw_exit(cli1
->session
);
2557 smb_raw_exit(cli2
->session
);
2558 smbcli_deltree(cli1
->tree
, BASEDIR
);
2562 static bool test_raw_oplock_batch17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2564 const char *fname1
= BASEDIR
"\\test_batch17_1.dat";
2565 const char *fname2
= BASEDIR
"\\test_batch17_2.dat";
2569 union smb_rename rn
;
2572 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2577 smbcli_unlink(cli1
->tree
, fname1
);
2578 smbcli_unlink(cli1
->tree
, fname2
);
2580 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2583 base ntcreatex parms
2585 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2586 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2587 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2588 io
.ntcreatex
.in
.alloc_size
= 0;
2589 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2590 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2591 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2592 io
.ntcreatex
.in
.create_options
= 0;
2593 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2594 io
.ntcreatex
.in
.security_flags
= 0;
2595 io
.ntcreatex
.in
.fname
= fname1
;
2597 torture_comment(tctx
, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2599 ZERO_STRUCT(break_info
);
2600 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2601 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2602 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2604 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2605 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2606 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2607 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2609 torture_comment(tctx
, "rename should trigger a break\n");
2611 rn
.generic
.level
= RAW_RENAME_RENAME
;
2612 rn
.rename
.in
.pattern1
= fname1
;
2613 rn
.rename
.in
.pattern2
= fname2
;
2614 rn
.rename
.in
.attrib
= 0;
2616 torture_comment(tctx
, "trying rename while first file open\n");
2617 status
= smb_raw_rename(cli2
->tree
, &rn
);
2618 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2620 torture_wait_for_oplock_break(tctx
);
2621 CHECK_VAL(break_info
.count
, 1);
2622 CHECK_VAL(break_info
.failures
, 0);
2623 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2625 smbcli_close(cli1
->tree
, fnum
);
2628 smb_raw_exit(cli1
->session
);
2629 smb_raw_exit(cli2
->session
);
2630 smbcli_deltree(cli1
->tree
, BASEDIR
);
2634 static bool test_raw_oplock_batch18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2636 const char *fname1
= BASEDIR
"\\test_batch18_1.dat";
2637 const char *fname2
= BASEDIR
"\\test_batch18_2.dat";
2641 union smb_rename rn
;
2644 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2649 smbcli_unlink(cli1
->tree
, fname1
);
2650 smbcli_unlink(cli1
->tree
, fname2
);
2652 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2655 base ntcreatex parms
2657 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2658 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2659 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2660 io
.ntcreatex
.in
.alloc_size
= 0;
2661 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2662 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2663 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2664 io
.ntcreatex
.in
.create_options
= 0;
2665 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2666 io
.ntcreatex
.in
.security_flags
= 0;
2667 io
.ntcreatex
.in
.fname
= fname1
;
2669 torture_comment(tctx
, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2671 ZERO_STRUCT(break_info
);
2672 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2673 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2674 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2676 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2677 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2678 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2679 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2681 torture_comment(tctx
, "ntrename should trigger a break\n");
2683 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
2684 rn
.ntrename
.in
.attrib
= 0;
2685 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
2686 rn
.ntrename
.in
.old_name
= fname1
;
2687 rn
.ntrename
.in
.new_name
= fname2
;
2688 torture_comment(tctx
, "trying rename while first file open\n");
2689 status
= smb_raw_rename(cli2
->tree
, &rn
);
2690 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2692 torture_wait_for_oplock_break(tctx
);
2693 CHECK_VAL(break_info
.count
, 1);
2694 CHECK_VAL(break_info
.failures
, 0);
2695 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2697 smbcli_close(cli1
->tree
, fnum
);
2700 smb_raw_exit(cli1
->session
);
2701 smb_raw_exit(cli2
->session
);
2702 smbcli_deltree(cli1
->tree
, BASEDIR
);
2706 static bool test_raw_oplock_batch19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2708 const char *fname1
= BASEDIR
"\\test_batch19_1.dat";
2709 const char *fname2
= BASEDIR
"\\test_batch19_2.dat";
2710 const char *fname3
= BASEDIR
"\\test_batch19_3.dat";
2714 union smb_fileinfo qfi
;
2715 union smb_setfileinfo sfi
;
2718 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2723 smbcli_unlink(cli1
->tree
, fname1
);
2724 smbcli_unlink(cli1
->tree
, fname2
);
2725 smbcli_unlink(cli1
->tree
, fname3
);
2727 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2730 base ntcreatex parms
2732 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2733 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2734 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2735 io
.ntcreatex
.in
.alloc_size
= 0;
2736 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2737 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2738 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2739 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2740 io
.ntcreatex
.in
.create_options
= 0;
2741 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2742 io
.ntcreatex
.in
.security_flags
= 0;
2743 io
.ntcreatex
.in
.fname
= fname1
;
2745 torture_comment(tctx
, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2746 ZERO_STRUCT(break_info
);
2747 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2748 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2749 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2750 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2751 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2752 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2753 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2755 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
2758 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2759 sfi
.generic
.in
.file
.path
= fname1
;
2760 sfi
.rename_information
.in
.overwrite
= 0;
2761 sfi
.rename_information
.in
.root_fid
= 0;
2762 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2764 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2765 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2767 torture_wait_for_oplock_break(tctx
);
2769 CHECK_VAL(break_info
.failures
, 0);
2771 if (TARGET_IS_WINXP(tctx
) || TARGET_IS_W2K12(tctx
)) {
2772 /* Win XP breaks to level2. */
2773 CHECK_VAL(break_info
.count
, 1);
2774 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2775 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2776 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2777 /* Win2K3/2k8 incorrectly doesn't break at all. */
2778 CHECK_VAL(break_info
.count
, 0);
2780 /* win7/2k8r2 break to none. */
2781 CHECK_VAL(break_info
.count
, 1);
2782 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2786 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2787 qfi
.generic
.in
.file
.fnum
= fnum
;
2789 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2790 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2791 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2793 /* Close and re-open file with oplock. */
2794 smbcli_close(cli1
->tree
, fnum
);
2795 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2796 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2797 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2798 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2800 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
2801 "should not trigger a break nor a violation\n");
2802 ZERO_STRUCT(break_info
);
2804 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2805 sfi
.generic
.in
.file
.fnum
= fnum
;
2806 sfi
.rename_information
.in
.overwrite
= 0;
2807 sfi
.rename_information
.in
.root_fid
= 0;
2808 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2810 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2811 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2813 torture_wait_for_oplock_break(tctx
);
2814 if (TARGET_IS_WINXP(tctx
)) {
2815 /* XP incorrectly breaks to level2. */
2816 CHECK_VAL(break_info
.count
, 1);
2817 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2819 CHECK_VAL(break_info
.count
, 0);
2823 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2824 qfi
.generic
.in
.file
.fnum
= fnum
;
2826 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2827 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2828 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2831 smbcli_close(cli1
->tree
, fnum
);
2832 smb_raw_exit(cli1
->session
);
2833 smb_raw_exit(cli2
->session
);
2834 smbcli_deltree(cli1
->tree
, BASEDIR
);
2838 /****************************************************
2839 Called from raw-rename - we need oplock handling for
2840 this test so this is why it's in oplock.c, not rename.c
2841 ****************************************************/
2843 bool test_trans2rename(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2845 const char *fname1
= BASEDIR
"\\test_trans2rename_1.dat";
2846 const char *fname2
= BASEDIR
"\\test_trans2rename_2.dat";
2847 const char *fname3
= BASEDIR
"\\test_trans2rename_3.dat";
2851 union smb_fileinfo qfi
;
2852 union smb_setfileinfo sfi
;
2855 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2860 smbcli_unlink(cli1
->tree
, fname1
);
2861 smbcli_unlink(cli1
->tree
, fname2
);
2862 smbcli_unlink(cli1
->tree
, fname3
);
2864 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2867 base ntcreatex parms
2869 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2870 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2871 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2872 io
.ntcreatex
.in
.alloc_size
= 0;
2873 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2874 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2875 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2876 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2877 io
.ntcreatex
.in
.create_options
= 0;
2878 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2879 io
.ntcreatex
.in
.security_flags
= 0;
2880 io
.ntcreatex
.in
.fname
= fname1
;
2882 torture_comment(tctx
, "open a file with an exclusive oplock (share mode: none)\n");
2883 ZERO_STRUCT(break_info
);
2884 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2885 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2886 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2887 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2888 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2889 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2891 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2893 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2894 sfi
.generic
.in
.file
.path
= fname1
;
2895 sfi
.rename_information
.in
.overwrite
= 0;
2896 sfi
.rename_information
.in
.root_fid
= 0;
2897 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2899 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2901 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2903 torture_wait_for_oplock_break(tctx
);
2904 CHECK_VAL(break_info
.count
, 0);
2907 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2908 qfi
.generic
.in
.file
.fnum
= fnum
;
2910 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2911 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2912 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2914 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2916 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2917 sfi
.generic
.in
.file
.fnum
= fnum
;
2918 sfi
.rename_information
.in
.overwrite
= 0;
2919 sfi
.rename_information
.in
.root_fid
= 0;
2920 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2922 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2923 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2925 torture_wait_for_oplock_break(tctx
);
2926 CHECK_VAL(break_info
.count
, 0);
2929 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2930 qfi
.generic
.in
.file
.fnum
= fnum
;
2932 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2933 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2934 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2937 smbcli_close(cli1
->tree
, fnum
);
2938 smb_raw_exit(cli1
->session
);
2939 smb_raw_exit(cli2
->session
);
2940 smbcli_deltree(cli1
->tree
, BASEDIR
);
2944 /****************************************************
2945 Called from raw-rename - we need oplock handling for
2946 this test so this is why it's in oplock.c, not rename.c
2947 ****************************************************/
2949 bool test_nttransrename(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
2951 const char *fname1
= BASEDIR
"\\test_nttransrename_1.dat";
2952 const char *fname2
= BASEDIR
"\\test_nttransrename_2.dat";
2956 union smb_fileinfo qfi
, qpi
;
2957 union smb_rename rn
;
2960 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2965 smbcli_unlink(cli1
->tree
, fname1
);
2966 smbcli_unlink(cli1
->tree
, fname2
);
2968 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2971 base ntcreatex parms
2973 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2974 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2975 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2976 io
.ntcreatex
.in
.alloc_size
= 0;
2977 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2978 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2979 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2980 io
.ntcreatex
.in
.create_options
= 0;
2981 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2982 io
.ntcreatex
.in
.security_flags
= 0;
2983 io
.ntcreatex
.in
.fname
= fname1
;
2985 torture_comment(tctx
, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2986 ZERO_STRUCT(break_info
);
2987 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2988 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2989 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2990 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2991 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2992 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2994 torture_comment(tctx
, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2996 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2997 rn
.nttrans
.in
.file
.fnum
= fnum
;
2998 rn
.nttrans
.in
.flags
= 0;
2999 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
3001 status
= smb_raw_rename(cli1
->tree
, &rn
);
3002 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3004 torture_wait_for_oplock_break(tctx
);
3005 CHECK_VAL(break_info
.count
, 0);
3007 /* w2k3 does nothing, it doesn't rename the file */
3008 torture_comment(tctx
, "nttrans_rename: the server should have done nothing\n");
3010 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3011 qfi
.generic
.in
.file
.fnum
= fnum
;
3013 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
3014 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3015 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname1
);
3018 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3019 qpi
.generic
.in
.file
.path
= fname1
;
3021 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3022 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3023 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
3026 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3027 qpi
.generic
.in
.file
.path
= fname2
;
3029 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3030 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
3032 torture_comment(tctx
, "nttrans_rename: after closing the file the file is still not renamed\n");
3033 status
= smbcli_close(cli1
->tree
, fnum
);
3034 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3037 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3038 qpi
.generic
.in
.file
.path
= fname1
;
3040 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3041 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3042 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
3045 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3046 qpi
.generic
.in
.file
.path
= fname2
;
3048 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3049 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
3051 torture_comment(tctx
, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
3053 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
3054 rn
.nttrans
.in
.file
.fnum
= fnum
+1;
3055 rn
.nttrans
.in
.flags
= 0;
3056 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
3058 status
= smb_raw_rename(cli1
->tree
, &rn
);
3060 CHECK_STATUS(tctx
, status
, NT_STATUS_INVALID_HANDLE
);
3063 smb_raw_exit(cli1
->session
);
3064 smbcli_deltree(cli1
->tree
, BASEDIR
);
3069 static bool test_raw_oplock_batch20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3071 const char *fname1
= BASEDIR
"\\test_batch20_1.dat";
3072 const char *fname2
= BASEDIR
"\\test_batch20_2.dat";
3073 const char *fname3
= BASEDIR
"\\test_batch20_3.dat";
3077 union smb_fileinfo qfi
;
3078 union smb_setfileinfo sfi
;
3079 uint16_t fnum
=0,fnum2
=0;
3081 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3086 smbcli_unlink(cli1
->tree
, fname1
);
3087 smbcli_unlink(cli1
->tree
, fname2
);
3088 smbcli_unlink(cli1
->tree
, fname3
);
3090 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3093 base ntcreatex parms
3095 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3096 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3097 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3098 io
.ntcreatex
.in
.alloc_size
= 0;
3099 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3100 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3101 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3102 io
.ntcreatex
.in
.create_options
= 0;
3103 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3104 io
.ntcreatex
.in
.security_flags
= 0;
3105 io
.ntcreatex
.in
.fname
= fname1
;
3107 torture_comment(tctx
, "BATCH20: open a file with an batch oplock (share mode: all)\n");
3108 ZERO_STRUCT(break_info
);
3109 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3110 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3111 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3112 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3113 NTCREATEX_SHARE_ACCESS_WRITE
|
3114 NTCREATEX_SHARE_ACCESS_DELETE
;
3115 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3116 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3117 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3118 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3121 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
3122 sfi
.generic
.in
.file
.path
= fname1
;
3123 sfi
.rename_information
.in
.overwrite
= 0;
3124 sfi
.rename_information
.in
.root_fid
= 0;
3125 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
3127 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
3128 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3130 torture_wait_for_oplock_break(tctx
);
3131 CHECK_VAL(break_info
.failures
, 0);
3133 if (TARGET_IS_WINXP(tctx
) || TARGET_IS_W2K12(tctx
)) {
3134 /* Win XP breaks to level2. */
3135 CHECK_VAL(break_info
.count
, 1);
3136 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3137 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
3138 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
3139 /* Win2K3/2k8 incorrectly doesn't break at all. */
3140 CHECK_VAL(break_info
.count
, 0);
3142 /* win7/2k8r2 break to none. */
3143 CHECK_VAL(break_info
.count
, 1);
3144 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3148 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3149 qfi
.generic
.in
.file
.fnum
= fnum
;
3151 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
3152 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3153 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
3155 torture_comment(tctx
, "open a file with the new name an batch oplock (share mode: all)\n");
3156 ZERO_STRUCT(break_info
);
3157 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3158 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3159 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3160 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3161 NTCREATEX_SHARE_ACCESS_WRITE
|
3162 NTCREATEX_SHARE_ACCESS_DELETE
;
3163 io
.ntcreatex
.in
.fname
= fname2
;
3164 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3165 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3166 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3167 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3169 torture_wait_for_oplock_break(tctx
);
3171 if (TARGET_IS_WINXP(tctx
)) {
3172 /* XP broke to level2, and doesn't break again. */
3173 CHECK_VAL(break_info
.count
, 0);
3174 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
3175 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
3176 /* Win2K3 incorrectly didn't break before so break now. */
3177 CHECK_VAL(break_info
.count
, 1);
3178 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3180 /* win7/2k8r2 broke to none, and doesn't break again. */
3181 CHECK_VAL(break_info
.count
, 0);
3184 ZERO_STRUCT(break_info
);
3187 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
3188 sfi
.generic
.in
.file
.fnum
= fnum
;
3189 sfi
.rename_information
.in
.overwrite
= 0;
3190 sfi
.rename_information
.in
.root_fid
= 0;
3191 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
3193 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
3194 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3196 torture_wait_for_oplock_break(tctx
);
3197 CHECK_VAL(break_info
.count
, 0);
3200 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3201 qfi
.generic
.in
.file
.fnum
= fnum
;
3203 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
3204 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3205 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
3208 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3209 qfi
.generic
.in
.file
.fnum
= fnum2
;
3211 status
= smb_raw_fileinfo(cli2
->tree
, tctx
, &qfi
);
3212 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3213 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
3217 smbcli_close(cli1
->tree
, fnum
);
3218 smbcli_close(cli2
->tree
, fnum2
);
3219 smb_raw_exit(cli1
->session
);
3220 smb_raw_exit(cli2
->session
);
3221 smbcli_deltree(cli1
->tree
, BASEDIR
);
3225 static bool test_raw_oplock_batch21(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3227 const char *fname
= BASEDIR
"\\test_batch21.dat";
3236 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3241 smbcli_unlink(cli1
->tree
, fname
);
3243 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3246 base ntcreatex parms
3248 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3249 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3250 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3251 io
.ntcreatex
.in
.alloc_size
= 0;
3252 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3253 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3254 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3255 io
.ntcreatex
.in
.create_options
= 0;
3256 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3257 io
.ntcreatex
.in
.security_flags
= 0;
3258 io
.ntcreatex
.in
.fname
= fname
;
3261 with a batch oplock we get a break
3263 torture_comment(tctx
, "BATCH21: open with batch oplock\n");
3264 ZERO_STRUCT(break_info
);
3265 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3266 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3267 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3268 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3269 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3270 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3271 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3273 torture_comment(tctx
, "writing should not generate a break\n");
3274 wr
= smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
3276 CHECK_STATUS(tctx
, smbcli_nt_error(cli1
->tree
), NT_STATUS_OK
);
3279 e
.in
.repeat_count
= 1;
3280 status
= smb_raw_echo(cli1
->transport
, &e
);
3281 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3283 torture_wait_for_oplock_break(tctx
);
3284 CHECK_VAL(break_info
.count
, 0);
3286 smbcli_close(cli1
->tree
, fnum
);
3289 smb_raw_exit(cli1
->session
);
3290 smb_raw_exit(cli2
->session
);
3291 smbcli_deltree(cli1
->tree
, BASEDIR
);
3295 static bool test_raw_oplock_batch22(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3297 const char *fname
= BASEDIR
"\\test_batch22.dat";
3301 uint16_t fnum
= 0, fnum2
= 0, fnum3
= 0;
3303 int timeout
= torture_setting_int(tctx
, "oplocktimeout", 30);
3306 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3311 smbcli_unlink(cli1
->tree
, fname
);
3313 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3315 base ntcreatex parms
3317 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3318 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3319 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3320 io
.ntcreatex
.in
.alloc_size
= 0;
3321 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3322 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3323 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3324 io
.ntcreatex
.in
.create_options
= 0;
3325 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3326 io
.ntcreatex
.in
.security_flags
= 0;
3327 io
.ntcreatex
.in
.fname
= fname
;
3330 with a batch oplock we get a break
3332 torture_comment(tctx
, "BATCH22: open with batch oplock\n");
3333 ZERO_STRUCT(break_info
);
3334 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3335 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3336 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3337 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3338 NTCREATEX_SHARE_ACCESS_WRITE
|
3339 NTCREATEX_SHARE_ACCESS_DELETE
;
3340 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3341 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3342 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3343 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3345 torture_comment(tctx
, "a 2nd open should not succeed after the oplock "
3347 tv
= timeval_current();
3348 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
, cli1
->tree
);
3349 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3351 if (TARGET_IS_W2K3(tctx
)) {
3352 /* 2k3 has an issue here. xp/win7 are ok. */
3353 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3355 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3358 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3360 torture_wait_for_oplock_break(tctx
);
3361 te
= (int)timeval_elapsed(&tv
);
3364 * Some servers detect clients that let oplocks timeout, so this check
3365 * only shows a warning message instead failing the test to eliminate
3366 * failures from repeated runs of the test. This isn't ideal, but
3367 * it's better than not running the test at all.
3369 CHECK_RANGE(te
, timeout
- 1, timeout
+ 15);
3371 CHECK_VAL(break_info
.count
, 1);
3372 CHECK_VAL(break_info
.fnum
, fnum
);
3373 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3374 CHECK_VAL(break_info
.failures
, 0);
3375 ZERO_STRUCT(break_info
);
3377 torture_comment(tctx
, "a 2nd open should succeed after the oplock "
3378 "release without break\n");
3379 tv
= timeval_current();
3380 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3381 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3382 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3384 /* Samba 3.6.0 and above behave as Windows. */
3385 if (TARGET_IS_SAMBA3(tctx
)) {
3386 /* samba3 doesn't grant additional oplocks to bad clients. */
3387 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3389 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3390 LEVEL_II_OPLOCK_RETURN
);
3393 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3394 LEVEL_II_OPLOCK_RETURN
);
3396 torture_wait_for_oplock_break(tctx
);
3397 te
= (int)timeval_elapsed(&tv
);
3398 /* it should come in without delay */
3399 CHECK_RANGE(te
+1, 0, timeout
);
3400 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3402 CHECK_VAL(break_info
.count
, 0);
3404 smbcli_close(cli1
->tree
, fnum
);
3405 smbcli_close(cli1
->tree
, fnum2
);
3406 smbcli_close(cli1
->tree
, fnum3
);
3409 smb_raw_exit(cli1
->session
);
3410 smb_raw_exit(cli2
->session
);
3411 smbcli_deltree(cli1
->tree
, BASEDIR
);
3415 static bool test_raw_oplock_batch23(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3417 const char *fname
= BASEDIR
"\\test_batch23.dat";
3421 uint16_t fnum
=0, fnum2
=0,fnum3
=0;
3422 struct smbcli_state
*cli3
= NULL
;
3424 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3429 smbcli_unlink(cli1
->tree
, fname
);
3431 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3432 CHECK_VAL(ret
, true);
3434 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3435 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3436 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3439 base ntcreatex parms
3441 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3442 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3443 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3444 io
.ntcreatex
.in
.alloc_size
= 0;
3445 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3446 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3447 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3448 io
.ntcreatex
.in
.create_options
= 0;
3449 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3450 io
.ntcreatex
.in
.security_flags
= 0;
3451 io
.ntcreatex
.in
.fname
= fname
;
3453 torture_comment(tctx
, "BATCH23: a open and ask for a batch oplock\n");
3454 ZERO_STRUCT(break_info
);
3456 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3457 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3458 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3459 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3460 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3461 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3462 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3463 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3464 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3466 ZERO_STRUCT(break_info
);
3468 torture_comment(tctx
, "a 2nd open without level2 oplock support should generate a break to level2\n");
3469 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3470 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3471 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3472 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3474 torture_wait_for_oplock_break(tctx
);
3475 CHECK_VAL(break_info
.count
, 1);
3476 CHECK_VAL(break_info
.fnum
, fnum
);
3477 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3478 CHECK_VAL(break_info
.failures
, 0);
3480 ZERO_STRUCT(break_info
);
3482 torture_comment(tctx
, "a 3rd open with level2 oplock support should not generate a break\n");
3483 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3484 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3485 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3486 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3488 torture_wait_for_oplock_break(tctx
);
3489 CHECK_VAL(break_info
.count
, 0);
3491 smbcli_close(cli1
->tree
, fnum
);
3492 smbcli_close(cli2
->tree
, fnum2
);
3493 smbcli_close(cli3
->tree
, fnum3
);
3496 smb_raw_exit(cli1
->session
);
3497 smb_raw_exit(cli2
->session
);
3498 smb_raw_exit(cli3
->session
);
3499 smbcli_deltree(cli1
->tree
, BASEDIR
);
3503 static bool test_raw_oplock_batch24(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3505 const char *fname
= BASEDIR
"\\test_batch24.dat";
3509 uint16_t fnum2
=0,fnum3
=0;
3510 struct smbcli_state
*cli3
= NULL
;
3512 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3517 smbcli_unlink(cli1
->tree
, fname
);
3519 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3520 CHECK_VAL(ret
, true);
3522 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3523 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3524 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3527 base ntcreatex parms
3529 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3530 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3531 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3532 io
.ntcreatex
.in
.alloc_size
= 0;
3533 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3534 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3535 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3536 io
.ntcreatex
.in
.create_options
= 0;
3537 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3538 io
.ntcreatex
.in
.security_flags
= 0;
3539 io
.ntcreatex
.in
.fname
= fname
;
3541 torture_comment(tctx
, "BATCH24: a open without level support and ask for a batch oplock\n");
3542 ZERO_STRUCT(break_info
);
3544 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3545 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3546 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3547 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3548 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3549 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3550 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3551 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3552 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3554 ZERO_STRUCT(break_info
);
3556 torture_comment(tctx
, "a 2nd open with level2 oplock support should generate a break to none\n");
3557 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3558 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3559 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3560 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3562 torture_wait_for_oplock_break(tctx
);
3563 CHECK_VAL(break_info
.count
, 1);
3564 CHECK_VAL(break_info
.fnum
, fnum3
);
3565 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3566 CHECK_VAL(break_info
.failures
, 0);
3568 smbcli_close(cli3
->tree
, fnum3
);
3569 smbcli_close(cli2
->tree
, fnum2
);
3572 smb_raw_exit(cli1
->session
);
3573 smb_raw_exit(cli2
->session
);
3574 smb_raw_exit(cli3
->session
);
3575 smbcli_deltree(cli1
->tree
, BASEDIR
);
3579 static bool test_raw_oplock_batch25(struct torture_context
*tctx
,
3580 struct smbcli_state
*cli1
,
3581 struct smbcli_state
*cli2
)
3583 const char *fname
= BASEDIR
"\\test_batch25.dat";
3587 union smb_setfileinfo sfi
;
3590 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3595 smbcli_unlink(cli1
->tree
, fname
);
3597 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3600 base ntcreatex parms
3602 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3603 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3604 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3605 io
.ntcreatex
.in
.alloc_size
= 0;
3606 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3607 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3608 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3609 io
.ntcreatex
.in
.create_options
= 0;
3610 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3611 io
.ntcreatex
.in
.security_flags
= 0;
3612 io
.ntcreatex
.in
.fname
= fname
;
3614 torture_comment(tctx
, "BATCH25: open a file with an batch oplock "
3615 "(share mode: none)\n");
3617 ZERO_STRUCT(break_info
);
3618 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3619 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3620 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3621 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3622 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3623 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3624 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3626 torture_comment(tctx
, "setpathinfo attribute info should not trigger "
3627 "a break nor a violation\n");
3629 sfi
.generic
.level
= RAW_SFILEINFO_SETATTR
;
3630 sfi
.generic
.in
.file
.path
= fname
;
3631 sfi
.setattr
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
3632 sfi
.setattr
.in
.write_time
= 0;
3634 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
3635 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3637 torture_wait_for_oplock_break(tctx
);
3638 CHECK_VAL(break_info
.count
, 0);
3640 smbcli_close(cli1
->tree
, fnum
);
3643 smb_raw_exit(cli1
->session
);
3644 smb_raw_exit(cli2
->session
);
3645 smbcli_deltree(cli1
->tree
, BASEDIR
);
3650 * Similar to batch17/18, but test with open share mode rather than
3653 static bool test_raw_oplock_batch26(struct torture_context
*tctx
,
3654 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3656 const char *fname1
= BASEDIR
"\\test_batch26_1.dat";
3657 const char *fname2
= BASEDIR
"\\test_batch26_2.dat";
3661 union smb_rename rn
;
3664 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3669 smbcli_unlink(cli1
->tree
, fname1
);
3670 smbcli_unlink(cli1
->tree
, fname2
);
3672 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3676 base ntcreatex parms
3678 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3679 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3680 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3681 io
.ntcreatex
.in
.alloc_size
= 0;
3682 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3683 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3684 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
3685 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3686 io
.ntcreatex
.in
.create_options
= 0;
3687 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3688 io
.ntcreatex
.in
.security_flags
= 0;
3689 io
.ntcreatex
.in
.fname
= fname1
;
3691 torture_comment(tctx
, "BATCH26: open a file with an batch oplock "
3692 "(share mode: none)\n");
3694 ZERO_STRUCT(break_info
);
3695 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3696 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3697 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3700 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3701 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3702 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3703 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3705 torture_comment(tctx
, "rename should trigger a break\n");
3707 rn
.generic
.level
= RAW_RENAME_RENAME
;
3708 rn
.rename
.in
.pattern1
= fname1
;
3709 rn
.rename
.in
.pattern2
= fname2
;
3710 rn
.rename
.in
.attrib
= 0;
3712 torture_comment(tctx
, "trying rename while first file open\n");
3713 status
= smb_raw_rename(cli2
->tree
, &rn
);
3714 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3716 torture_wait_for_oplock_break(tctx
);
3717 CHECK_VAL(break_info
.count
, 1);
3718 CHECK_VAL(break_info
.failures
, 0);
3719 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3721 /* Close and reopen with batch again. */
3722 smbcli_close(cli1
->tree
, fnum
);
3723 ZERO_STRUCT(break_info
);
3725 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3726 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3727 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3728 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3730 /* Now try ntrename. */
3731 torture_comment(tctx
, "ntrename should trigger a break\n");
3733 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
3734 rn
.ntrename
.in
.attrib
= 0;
3735 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
3736 rn
.ntrename
.in
.old_name
= fname1
;
3737 rn
.ntrename
.in
.new_name
= fname2
;
3738 torture_comment(tctx
, "trying rename while first file open\n");
3739 status
= smb_raw_rename(cli2
->tree
, &rn
);
3740 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3742 torture_wait_for_oplock_break(tctx
);
3743 CHECK_VAL(break_info
.count
, 1);
3744 CHECK_VAL(break_info
.failures
, 0);
3745 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3747 smbcli_close(cli1
->tree
, fnum
);
3750 smb_raw_exit(cli1
->session
);
3751 smb_raw_exit(cli2
->session
);
3752 smbcli_deltree(cli1
->tree
, BASEDIR
);
3756 /* Test how oplocks work on streams. */
3757 static bool test_raw_oplock_stream1(struct torture_context
*tctx
,
3758 struct smbcli_state
*cli1
,
3759 struct smbcli_state
*cli2
)
3763 const char *fname_base
= BASEDIR
"\\test_stream1.txt";
3764 const char *stream
= "Stream One:$DATA";
3765 const char *fname_stream
, *fname_default_stream
;
3766 const char *default_stream
= "::$DATA";
3770 int stream_fnum
= -1;
3771 uint32_t batch_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3772 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
| NTCREATEX_FLAGS_EXTENDED
;
3773 uint32_t exclusive_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3774 NTCREATEX_FLAGS_EXTENDED
;
3776 #define NSTREAM_OPLOCK_RESULTS 8
3779 bool open_base_file
;
3780 uint32_t oplock_req
;
3781 uint32_t oplock_granted
;
3782 } stream_oplock_results
[NSTREAM_OPLOCK_RESULTS
] = {
3783 /* Request oplock on stream without the base file open. */
3784 {&fname_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3785 {&fname_default_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3786 {&fname_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3787 {&fname_default_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3789 /* Request oplock on stream with the base file open. */
3790 {&fname_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3791 {&fname_default_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3792 {&fname_stream
, true, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3793 {&fname_default_stream
, true, exclusive_req
, LEVEL_II_OPLOCK_RETURN
},
3798 /* Only passes against windows at the moment. */
3799 if (torture_setting_bool(tctx
, "samba3", false) ||
3800 torture_setting_bool(tctx
, "samba4", false)) {
3801 torture_skip(tctx
, "STREAM1 disabled against samba3+4\n");
3804 fname_stream
= talloc_asprintf(tctx
, "%s:%s", fname_base
, stream
);
3805 fname_default_stream
= talloc_asprintf(tctx
, "%s%s", fname_base
,
3808 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3811 smbcli_unlink(cli1
->tree
, fname_base
);
3813 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3814 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3816 /* Setup generic open parameters. */
3817 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3818 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3819 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
3820 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
3821 io
.ntcreatex
.in
.create_options
= 0;
3822 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3823 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3824 NTCREATEX_SHARE_ACCESS_WRITE
;
3825 io
.ntcreatex
.in
.alloc_size
= 0;
3826 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3827 io
.ntcreatex
.in
.security_flags
= 0;
3829 /* Create the file with a stream */
3830 io
.ntcreatex
.in
.fname
= fname_stream
;
3831 io
.ntcreatex
.in
.flags
= 0;
3832 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
3833 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3834 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3835 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3837 /* Change the disposition to open now that the file has been created. */
3838 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3840 /* Try some permutations of taking oplocks on streams. */
3841 for (i
= 0; i
< NSTREAM_OPLOCK_RESULTS
; i
++) {
3842 const char *fname
= *stream_oplock_results
[i
].fname
;
3843 bool open_base_file
= stream_oplock_results
[i
].open_base_file
;
3844 uint32_t oplock_req
= stream_oplock_results
[i
].oplock_req
;
3845 uint32_t oplock_granted
=
3846 stream_oplock_results
[i
].oplock_granted
;
3849 if (open_base_file
) {
3850 torture_comment(tctx
, "Opening base file: %s with "
3851 "%d\n", fname_base
, batch_req
);
3852 io
.ntcreatex
.in
.fname
= fname_base
;
3853 io
.ntcreatex
.in
.flags
= batch_req
;
3854 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3855 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3856 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3857 BATCH_OPLOCK_RETURN
);
3858 base_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3861 torture_comment(tctx
, "%d: Opening stream: %s with %d\n", i
,
3863 io
.ntcreatex
.in
.fname
= fname
;
3864 io
.ntcreatex
.in
.flags
= oplock_req
;
3866 /* Do the open with the desired oplock on the stream. */
3867 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3868 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3869 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, oplock_granted
);
3870 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3872 /* Cleanup the base file if it was opened. */
3873 if (base_fnum
!= -1) {
3874 smbcli_close(cli2
->tree
, base_fnum
);
3878 /* Open the stream with an exclusive oplock. */
3879 torture_comment(tctx
, "Opening stream: %s with %d\n",
3880 fname_stream
, exclusive_req
);
3881 io
.ntcreatex
.in
.fname
= fname_stream
;
3882 io
.ntcreatex
.in
.flags
= exclusive_req
;
3883 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3884 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3885 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3886 stream_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3888 /* Open the base file and see if it contends. */
3889 ZERO_STRUCT(break_info
);
3890 torture_comment(tctx
, "Opening base file: %s with "
3891 "%d\n", fname_base
, batch_req
);
3892 io
.ntcreatex
.in
.fname
= fname_base
;
3893 io
.ntcreatex
.in
.flags
= batch_req
;
3894 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3895 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3896 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3897 BATCH_OPLOCK_RETURN
);
3898 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3900 torture_wait_for_oplock_break(tctx
);
3901 CHECK_VAL(break_info
.count
, 0);
3902 CHECK_VAL(break_info
.failures
, 0);
3904 /* Open the stream again to see if it contends. */
3905 ZERO_STRUCT(break_info
);
3906 torture_comment(tctx
, "Opening stream again: %s with "
3907 "%d\n", fname_base
, batch_req
);
3908 io
.ntcreatex
.in
.fname
= fname_stream
;
3909 io
.ntcreatex
.in
.flags
= exclusive_req
;
3910 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3911 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3912 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3913 LEVEL_II_OPLOCK_RETURN
);
3914 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3916 torture_wait_for_oplock_break(tctx
);
3917 CHECK_VAL(break_info
.count
, 1);
3918 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3919 CHECK_VAL(break_info
.failures
, 0);
3921 /* Close the stream. */
3922 if (stream_fnum
!= -1) {
3923 smbcli_close(cli1
->tree
, stream_fnum
);
3927 smbcli_close(cli1
->tree
, fnum
);
3928 smb_raw_exit(cli1
->session
);
3929 smb_raw_exit(cli2
->session
);
3930 smbcli_deltree(cli1
->tree
, BASEDIR
);
3934 static bool test_raw_oplock_doc(struct torture_context
*tctx
,
3935 struct smbcli_state
*cli
,
3936 struct smbcli_state
*cli2
)
3938 const char *fname
= BASEDIR
"\\test_oplock_doc.dat";
3944 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
3947 smbcli_unlink(cli
->tree
, fname
);
3949 smbcli_oplock_handler(cli
->transport
, oplock_handler_ack_to_given
,
3953 base ntcreatex parms
3955 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3956 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3957 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3958 io
.ntcreatex
.in
.alloc_size
= 0;
3959 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3960 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3961 NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
;
3962 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3963 io
.ntcreatex
.in
.create_options
= 0;
3964 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3965 io
.ntcreatex
.in
.security_flags
= 0;
3966 io
.ntcreatex
.in
.fname
= fname
;
3968 torture_comment(tctx
, "open a file with a batch oplock\n");
3969 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3970 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3971 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3973 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
3974 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3975 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3976 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3978 torture_comment(tctx
, "Set delete-on-close\n");
3979 status
= smbcli_nt_delete_on_close(cli
->tree
, fnum
, true);
3980 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3982 torture_comment(tctx
, "2nd open should not break and get "
3983 "DELETE_PENDING\n");
3984 ZERO_STRUCT(break_info
);
3985 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3986 io
.ntcreatex
.in
.create_options
= 0;
3987 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
3988 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3989 CHECK_STATUS(tctx
, status
, NT_STATUS_DELETE_PENDING
);
3990 CHECK_VAL(break_info
.count
, 0);
3992 smbcli_close(cli
->tree
, fnum
);
3995 smb_raw_exit(cli
->session
);
3996 smbcli_deltree(cli
->tree
, BASEDIR
);
4000 /* Open a file with a batch oplock, then open it again from a second client
4001 * requesting no oplock. Having two open file handles should break our own
4002 * oplock during BRL acquisition.
4004 static bool test_raw_oplock_brl1(struct torture_context
*tctx
,
4005 struct smbcli_state
*cli1
,
4006 struct smbcli_state
*cli2
)
4008 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4017 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4022 smbcli_unlink(cli1
->tree
, fname
);
4024 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4028 base ntcreatex parms
4030 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4031 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4032 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4033 SEC_RIGHTS_FILE_WRITE
;
4034 io
.ntcreatex
.in
.alloc_size
= 0;
4035 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4036 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4037 NTCREATEX_SHARE_ACCESS_WRITE
;
4038 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4039 io
.ntcreatex
.in
.create_options
= 0;
4040 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4041 io
.ntcreatex
.in
.security_flags
= 0;
4042 io
.ntcreatex
.in
.fname
= fname
;
4045 with a batch oplock we get a break
4047 torture_comment(tctx
, "open with batch oplock\n");
4048 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4049 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4050 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4052 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4053 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4054 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4055 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
4056 /* create a file with bogus data */
4057 memset(buf
, 0, sizeof(buf
));
4059 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4062 torture_comment(tctx
, "Failed to create file\n");
4066 torture_comment(tctx
, "a 2nd open should give a break\n");
4067 ZERO_STRUCT(break_info
);
4069 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
4070 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
4071 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
4072 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4073 CHECK_VAL(break_info
.count
, 1);
4074 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
4075 CHECK_VAL(break_info
.failures
, 0);
4076 CHECK_VAL(break_info
.fnum
, fnum
);
4078 ZERO_STRUCT(break_info
);
4080 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
4082 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
4083 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4085 torture_wait_for_oplock_break(tctx
);
4086 CHECK_VAL(break_info
.count
, 1);
4087 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
4088 CHECK_VAL(break_info
.fnum
, fnum
);
4089 CHECK_VAL(break_info
.failures
, 0);
4091 /* expect no oplock break */
4092 ZERO_STRUCT(break_info
);
4093 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
4094 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
4096 torture_wait_for_oplock_break(tctx
);
4097 CHECK_VAL(break_info
.count
, 0);
4098 CHECK_VAL(break_info
.level
, 0);
4099 CHECK_VAL(break_info
.fnum
, 0);
4100 CHECK_VAL(break_info
.failures
, 0);
4102 smbcli_close(cli1
->tree
, fnum
);
4103 smbcli_close(cli2
->tree
, fnum2
);
4106 smb_raw_exit(cli1
->session
);
4107 smb_raw_exit(cli2
->session
);
4108 smbcli_deltree(cli1
->tree
, BASEDIR
);
4113 /* Open a file with a batch oplock on one client and then acquire a brl.
4114 * We should not contend our own oplock.
4116 static bool test_raw_oplock_brl2(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
4118 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4126 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4131 smbcli_unlink(cli1
->tree
, fname
);
4133 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4137 base ntcreatex parms
4139 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4140 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4141 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4142 SEC_RIGHTS_FILE_WRITE
;
4143 io
.ntcreatex
.in
.alloc_size
= 0;
4144 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4145 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4146 NTCREATEX_SHARE_ACCESS_WRITE
;
4147 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4148 io
.ntcreatex
.in
.create_options
= 0;
4149 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4150 io
.ntcreatex
.in
.security_flags
= 0;
4151 io
.ntcreatex
.in
.fname
= fname
;
4154 with a batch oplock we get a break
4156 torture_comment(tctx
, "open with batch oplock\n");
4157 ZERO_STRUCT(break_info
);
4158 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4159 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4160 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4162 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4163 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4164 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4165 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
4167 /* create a file with bogus data */
4168 memset(buf
, 0, sizeof(buf
));
4170 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4173 torture_comment(tctx
, "Failed to create file\n");
4177 torture_comment(tctx
, "a self BRL acquisition should not break to "
4180 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
4181 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4183 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
4184 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
4186 /* With one file handle open a BRL should not contend our oplock.
4187 * Thus, no oplock break will be received and the entire break_info
4188 * struct will be 0 */
4189 torture_wait_for_oplock_break(tctx
);
4190 CHECK_VAL(break_info
.fnum
, 0);
4191 CHECK_VAL(break_info
.count
, 0);
4192 CHECK_VAL(break_info
.level
, 0);
4193 CHECK_VAL(break_info
.failures
, 0);
4195 smbcli_close(cli1
->tree
, fnum
);
4198 smb_raw_exit(cli1
->session
);
4199 smbcli_deltree(cli1
->tree
, BASEDIR
);
4203 /* Open a file with a batch oplock twice from one client and then acquire a
4204 * brl. BRL acquisition should break our own oplock.
4206 static bool test_raw_oplock_brl3(struct torture_context
*tctx
,
4207 struct smbcli_state
*cli1
)
4209 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4217 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4222 smbcli_unlink(cli1
->tree
, fname
);
4224 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4228 base ntcreatex parms
4230 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4231 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4232 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4233 SEC_RIGHTS_FILE_WRITE
;
4234 io
.ntcreatex
.in
.alloc_size
= 0;
4235 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4236 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4237 NTCREATEX_SHARE_ACCESS_WRITE
;
4238 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4239 io
.ntcreatex
.in
.create_options
= 0;
4240 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4241 io
.ntcreatex
.in
.security_flags
= 0;
4242 io
.ntcreatex
.in
.fname
= fname
;
4245 with a batch oplock we get a break
4247 torture_comment(tctx
, "open with batch oplock\n");
4248 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4249 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4250 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4252 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4253 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4254 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4255 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
4257 /* create a file with bogus data */
4258 memset(buf
, 0, sizeof(buf
));
4260 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4263 torture_comment(tctx
, "Failed to create file\n");
4268 torture_comment(tctx
, "a 2nd open should give a break\n");
4269 ZERO_STRUCT(break_info
);
4271 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
4272 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4273 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
4274 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4275 CHECK_VAL(break_info
.count
, 1);
4276 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
4277 CHECK_VAL(break_info
.failures
, 0);
4278 CHECK_VAL(break_info
.fnum
, fnum
);
4280 ZERO_STRUCT(break_info
);
4282 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
4284 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
4285 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4287 torture_wait_for_oplock_break(tctx
);
4288 CHECK_VAL(break_info
.count
, 1);
4289 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
4290 CHECK_VAL(break_info
.fnum
, fnum
);
4291 CHECK_VAL(break_info
.failures
, 0);
4293 /* expect no oplock break */
4294 ZERO_STRUCT(break_info
);
4295 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
4296 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
4298 torture_wait_for_oplock_break(tctx
);
4299 CHECK_VAL(break_info
.count
, 0);
4300 CHECK_VAL(break_info
.level
, 0);
4301 CHECK_VAL(break_info
.fnum
, 0);
4302 CHECK_VAL(break_info
.failures
, 0);
4304 smbcli_close(cli1
->tree
, fnum
);
4305 smbcli_close(cli1
->tree
, fnum2
);
4308 smb_raw_exit(cli1
->session
);
4309 smbcli_deltree(cli1
->tree
, BASEDIR
);
4314 * Open a file with an exclusive oplock from the 1st client and acquire a
4315 * brl. Then open the same file from the 2nd client that should give oplock
4316 * break with level2 to the 1st and return no oplock to the 2nd.
4318 static bool test_raw_oplock_brl4(struct torture_context
*tctx
,
4319 struct smbcli_state
*cli1
,
4320 struct smbcli_state
*cli2
)
4322 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4330 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4335 smbcli_unlink(cli1
->tree
, fname
);
4337 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4341 base ntcreatex parms
4343 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4344 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4345 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4346 SEC_RIGHTS_FILE_WRITE
;
4347 io
.ntcreatex
.in
.alloc_size
= 0;
4348 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4349 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4350 NTCREATEX_SHARE_ACCESS_WRITE
;
4351 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4352 io
.ntcreatex
.in
.create_options
= 0;
4353 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4354 io
.ntcreatex
.in
.security_flags
= 0;
4355 io
.ntcreatex
.in
.fname
= fname
;
4357 torture_comment(tctx
, "open with exclusive oplock\n");
4358 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4359 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
4361 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4363 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4364 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4365 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
4367 /* create a file with bogus data */
4368 memset(buf
, 0, sizeof(buf
));
4370 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4373 torture_comment(tctx
, "Failed to create file\n");
4377 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 1, 0, WRITE_LOCK
);
4378 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4380 torture_comment(tctx
, "a 2nd open should give a break to the 1st\n");
4381 ZERO_STRUCT(break_info
);
4383 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
4385 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4386 CHECK_VAL(break_info
.count
, 1);
4387 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
4388 CHECK_VAL(break_info
.failures
, 0);
4389 CHECK_VAL(break_info
.fnum
, fnum
);
4391 torture_comment(tctx
, "and return no oplock to the 2nd\n");
4392 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
4393 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
4395 smbcli_close(cli1
->tree
, fnum
);
4396 smbcli_close(cli2
->tree
, fnum2
);
4399 smb_raw_exit(cli1
->session
);
4400 smb_raw_exit(cli2
->session
);
4401 smbcli_deltree(cli1
->tree
, BASEDIR
);
4406 basic testing of oplocks
4408 struct torture_suite
*torture_raw_oplock(TALLOC_CTX
*mem_ctx
)
4410 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "oplock");
4412 torture_suite_add_2smb_test(suite
, "exclusive1", test_raw_oplock_exclusive1
);
4413 torture_suite_add_2smb_test(suite
, "exclusive2", test_raw_oplock_exclusive2
);
4414 torture_suite_add_2smb_test(suite
, "exclusive3", test_raw_oplock_exclusive3
);
4415 torture_suite_add_2smb_test(suite
, "exclusive4", test_raw_oplock_exclusive4
);
4416 torture_suite_add_2smb_test(suite
, "exclusive5", test_raw_oplock_exclusive5
);
4417 torture_suite_add_2smb_test(suite
, "exclusive6", test_raw_oplock_exclusive6
);
4418 torture_suite_add_2smb_test(suite
, "exclusive7", test_raw_oplock_exclusive7
);
4419 torture_suite_add_2smb_test(suite
, "exclusive8",
4420 test_raw_oplock_exclusive8
);
4421 torture_suite_add_2smb_test(suite
, "exclusive9",
4422 test_raw_oplock_exclusive9
);
4423 torture_suite_add_2smb_test(suite
, "level_ii_1",
4424 test_raw_oplock_level_ii_1
);
4425 torture_suite_add_2smb_test(suite
, "batch1", test_raw_oplock_batch1
);
4426 torture_suite_add_2smb_test(suite
, "batch2", test_raw_oplock_batch2
);
4427 torture_suite_add_2smb_test(suite
, "batch3", test_raw_oplock_batch3
);
4428 torture_suite_add_2smb_test(suite
, "batch4", test_raw_oplock_batch4
);
4429 torture_suite_add_2smb_test(suite
, "batch5", test_raw_oplock_batch5
);
4430 torture_suite_add_2smb_test(suite
, "batch6", test_raw_oplock_batch6
);
4431 torture_suite_add_2smb_test(suite
, "batch7", test_raw_oplock_batch7
);
4432 torture_suite_add_2smb_test(suite
, "batch8", test_raw_oplock_batch8
);
4433 torture_suite_add_2smb_test(suite
, "batch9", test_raw_oplock_batch9
);
4434 torture_suite_add_2smb_test(suite
, "batch9a", test_raw_oplock_batch9a
);
4435 torture_suite_add_2smb_test(suite
, "batch10", test_raw_oplock_batch10
);
4436 torture_suite_add_2smb_test(suite
, "batch11", test_raw_oplock_batch11
);
4437 torture_suite_add_2smb_test(suite
, "batch12", test_raw_oplock_batch12
);
4438 torture_suite_add_2smb_test(suite
, "batch13", test_raw_oplock_batch13
);
4439 torture_suite_add_2smb_test(suite
, "batch14", test_raw_oplock_batch14
);
4440 torture_suite_add_2smb_test(suite
, "batch15", test_raw_oplock_batch15
);
4441 torture_suite_add_2smb_test(suite
, "batch16", test_raw_oplock_batch16
);
4442 torture_suite_add_2smb_test(suite
, "batch17", test_raw_oplock_batch17
);
4443 torture_suite_add_2smb_test(suite
, "batch18", test_raw_oplock_batch18
);
4444 torture_suite_add_2smb_test(suite
, "batch19", test_raw_oplock_batch19
);
4445 torture_suite_add_2smb_test(suite
, "batch20", test_raw_oplock_batch20
);
4446 torture_suite_add_2smb_test(suite
, "batch21", test_raw_oplock_batch21
);
4447 torture_suite_add_2smb_test(suite
, "batch22", test_raw_oplock_batch22
);
4448 torture_suite_add_2smb_test(suite
, "batch23", test_raw_oplock_batch23
);
4449 torture_suite_add_2smb_test(suite
, "batch24", test_raw_oplock_batch24
);
4450 torture_suite_add_2smb_test(suite
, "batch25", test_raw_oplock_batch25
);
4451 torture_suite_add_2smb_test(suite
, "batch26", test_raw_oplock_batch26
);
4452 torture_suite_add_2smb_test(suite
, "stream1", test_raw_oplock_stream1
);
4453 torture_suite_add_2smb_test(suite
, "doc1", test_raw_oplock_doc
);
4454 torture_suite_add_2smb_test(suite
, "brl1", test_raw_oplock_brl1
);
4455 torture_suite_add_1smb_test(suite
, "brl2", test_raw_oplock_brl2
);
4456 torture_suite_add_1smb_test(suite
, "brl3", test_raw_oplock_brl3
);
4457 torture_suite_add_2smb_test(suite
, "brl4", test_raw_oplock_brl4
);
4463 stress testing of oplocks
4465 bool torture_bench_oplock(struct torture_context
*torture
)
4467 struct smbcli_state
**cli
;
4469 TALLOC_CTX
*mem_ctx
= talloc_new(torture
);
4470 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
4472 int timelimit
= torture_setting_int(torture
, "timelimit", 10);
4476 cli
= talloc_array(mem_ctx
, struct smbcli_state
*, torture_nprocs
);
4478 torture_comment(torture
, "Opening %d connections\n", torture_nprocs
);
4479 for (i
=0;i
<torture_nprocs
;i
++) {
4480 if (!torture_open_connection_ev(&cli
[i
], i
, torture
, torture
->ev
)) {
4483 talloc_steal(mem_ctx
, cli
[i
]);
4484 smbcli_oplock_handler(cli
[i
]->transport
, oplock_handler_close
,
4488 if (!torture_setup_dir(cli
[0], BASEDIR
)) {
4493 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
4494 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4495 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4496 io
.ntcreatex
.in
.alloc_size
= 0;
4497 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4498 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
4499 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4500 io
.ntcreatex
.in
.create_options
= 0;
4501 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4502 io
.ntcreatex
.in
.security_flags
= 0;
4503 io
.ntcreatex
.in
.fname
= BASEDIR
"\\test.dat";
4504 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4505 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4506 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4508 tv
= timeval_current();
4511 we open the same file with SHARE_ACCESS_NONE from all the
4512 connections in a round robin fashion. Each open causes an
4513 oplock break on the previous connection, which is answered
4514 by the oplock_handler_close() to close the file.
4516 This measures how fast we can pass on oplocks, and stresses
4517 the oplock handling code
4519 torture_comment(torture
, "Running for %d seconds\n", timelimit
);
4520 while (timeval_elapsed(&tv
) < timelimit
) {
4521 for (i
=0;i
<torture_nprocs
;i
++) {
4524 status
= smb_raw_open(cli
[i
]->tree
, mem_ctx
, &io
);
4525 CHECK_STATUS(torture
, status
, NT_STATUS_OK
);
4529 if (torture_setting_bool(torture
, "progress", true)) {
4530 torture_comment(torture
, "%.2f ops/second\r", count
/timeval_elapsed(&tv
));
4534 torture_comment(torture
, "%.2f ops/second\n", count
/timeval_elapsed(&tv
));
4536 smb_raw_exit(cli
[torture_nprocs
-1]->session
);
4539 smb_raw_exit(cli
[0]->session
);
4540 smbcli_deltree(cli
[0]->tree
, BASEDIR
);
4541 talloc_free(mem_ctx
);
4546 static struct hold_oplock_info
{
4548 bool close_on_break
;
4549 uint32_t share_access
;
4552 { BASEDIR
"\\notshared_close", true,
4553 NTCREATEX_SHARE_ACCESS_NONE
, },
4554 { BASEDIR
"\\notshared_noclose", false,
4555 NTCREATEX_SHARE_ACCESS_NONE
, },
4556 { BASEDIR
"\\shared_close", true,
4557 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4558 { BASEDIR
"\\shared_noclose", false,
4559 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4562 static bool oplock_handler_hold(struct smbcli_transport
*transport
,
4563 uint16_t tid
, uint16_t fnum
, uint8_t level
,
4566 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
4567 struct hold_oplock_info
*info
;
4570 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4571 if (hold_info
[i
].fnum
== fnum
) break;
4574 if (i
== ARRAY_SIZE(hold_info
)) {
4575 printf("oplock break for unknown fnum %u\n", fnum
);
4579 info
= &hold_info
[i
];
4581 if (info
->close_on_break
) {
4582 printf("oplock break on %s - closing\n",
4584 oplock_handler_close(transport
, tid
, fnum
, level
, private_data
);
4588 printf("oplock break on %s - acking break\n", info
->fname
);
4590 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
4595 used for manual testing of oplocks - especially interaction with
4596 other filesystems (such as NFS and local access)
4598 bool torture_hold_oplock(struct torture_context
*torture
,
4599 struct smbcli_state
*cli
)
4601 struct tevent_context
*ev
= torture
->ev
;
4604 printf("Setting up open files with oplocks in %s\n", BASEDIR
);
4606 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
4608 smbcli_oplock_handler(cli
->transport
, oplock_handler_hold
, cli
->tree
);
4610 /* setup the files */
4611 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4616 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4617 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4618 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4619 io
.ntcreatex
.in
.alloc_size
= 0;
4620 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4621 io
.ntcreatex
.in
.share_access
= hold_info
[i
].share_access
;
4622 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4623 io
.ntcreatex
.in
.create_options
= 0;
4624 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4625 io
.ntcreatex
.in
.security_flags
= 0;
4626 io
.ntcreatex
.in
.fname
= hold_info
[i
].fname
;
4627 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4628 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4629 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4630 printf("opening %s\n", hold_info
[i
].fname
);
4632 status
= smb_raw_open(cli
->tree
, cli
, &io
);
4633 if (!NT_STATUS_IS_OK(status
)) {
4634 printf("Failed to open %s - %s\n",
4635 hold_info
[i
].fname
, nt_errstr(status
));
4639 if (io
.ntcreatex
.out
.oplock_level
!= BATCH_OPLOCK_RETURN
) {
4640 printf("Oplock not granted for %s - expected %d but got %d\n",
4641 hold_info
[i
].fname
, BATCH_OPLOCK_RETURN
,
4642 io
.ntcreatex
.out
.oplock_level
);
4645 hold_info
[i
].fnum
= io
.ntcreatex
.out
.file
.fnum
;
4647 /* make the file non-zero size */
4648 if (smbcli_write(cli
->tree
, hold_info
[i
].fnum
, 0, &c
, 0, 1) != 1) {
4649 printf("Failed to write to file\n");
4654 printf("Waiting for oplock events\n");
4655 tevent_loop_wait(ev
);