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
),
190 popt_get_cmdline_credentials(),
191 lpcfg_resolve_context(tctx
->lp_ctx
),
192 tctx
->ev
, &options
, &session_options
,
193 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
194 if (!NT_STATUS_IS_OK(status
)) {
195 torture_comment(tctx
, "Failed to open connection - %s\n",
204 Timer handler function notifies the registering function that time is up
206 static void timeout_cb(struct tevent_context
*ev
,
207 struct tevent_timer
*te
,
208 struct timeval current_time
,
211 bool *timesup
= (bool *)private_data
;
217 Wait a short period of time to receive a single oplock break request
219 static void torture_wait_for_oplock_break(struct torture_context
*tctx
)
221 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
222 struct tevent_timer
*te
= NULL
;
224 bool timesup
= false;
225 int old_count
= break_info
.count
;
227 /* Wait .1 seconds for an oplock break */
228 ne
= tevent_timeval_current_ofs(0, 100000);
230 if ((te
= tevent_add_timer(tctx
->ev
, tmp_ctx
, ne
, timeout_cb
, ×up
))
233 torture_comment(tctx
, "Failed to wait for an oplock break. "
234 "test results may not be accurate.");
238 while (!timesup
&& break_info
.count
< old_count
+ 1) {
239 if (tevent_loop_once(tctx
->ev
) != 0) {
240 torture_comment(tctx
, "Failed to wait for an oplock "
241 "break. test results may not be "
248 /* We don't know if the timed event fired and was freed, we received
249 * our oplock break, or some other event triggered the loop. Thus,
250 * we create a tmp_ctx to be able to safely free/remove the timed
251 * event in all 3 cases. */
252 talloc_free(tmp_ctx
);
257 static uint8_t get_break_level1_to_none_count(struct torture_context
*tctx
)
259 return torture_setting_bool(tctx
, "2_step_break_to_none", false) ?
263 static uint8_t get_setinfo_break_count(struct torture_context
*tctx
)
265 if (TARGET_IS_W2K12(tctx
)) {
268 if (TARGET_IS_SAMBA3(tctx
)) {
274 static bool test_raw_oplock_exclusive1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
276 const char *fname
= BASEDIR
"\\test_exclusive1.dat";
280 union smb_unlink unl
;
283 if (!torture_setup_dir(cli1
, BASEDIR
)) {
288 smbcli_unlink(cli1
->tree
, fname
);
290 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
295 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
296 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
297 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
298 io
.ntcreatex
.in
.alloc_size
= 0;
299 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
300 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
301 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
302 io
.ntcreatex
.in
.create_options
= 0;
303 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
304 io
.ntcreatex
.in
.security_flags
= 0;
305 io
.ntcreatex
.in
.fname
= fname
;
307 torture_comment(tctx
, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
308 ZERO_STRUCT(break_info
);
309 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
311 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
312 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
313 fnum
= io
.ntcreatex
.out
.file
.fnum
;
314 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
316 torture_comment(tctx
, "a 2nd open should not cause a break\n");
317 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
318 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
319 torture_wait_for_oplock_break(tctx
);
320 CHECK_VAL(break_info
.count
, 0);
321 CHECK_VAL(break_info
.failures
, 0);
323 torture_comment(tctx
, "unlink it - should also be no break\n");
324 unl
.unlink
.in
.pattern
= fname
;
325 unl
.unlink
.in
.attrib
= 0;
326 status
= smb_raw_unlink(cli2
->tree
, &unl
);
327 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
328 torture_wait_for_oplock_break(tctx
);
329 CHECK_VAL(break_info
.count
, 0);
330 CHECK_VAL(break_info
.failures
, 0);
332 smbcli_close(cli1
->tree
, fnum
);
335 smb_raw_exit(cli1
->session
);
336 smb_raw_exit(cli2
->session
);
337 smbcli_deltree(cli1
->tree
, BASEDIR
);
341 static bool test_raw_oplock_exclusive2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
343 const char *fname
= BASEDIR
"\\test_exclusive2.dat";
347 union smb_unlink unl
;
348 uint16_t fnum
=0, fnum2
=0;
350 if (!torture_setup_dir(cli1
, BASEDIR
)) {
355 smbcli_unlink(cli1
->tree
, fname
);
357 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
362 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
363 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
364 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
365 io
.ntcreatex
.in
.alloc_size
= 0;
366 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
367 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
368 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
369 io
.ntcreatex
.in
.create_options
= 0;
370 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
371 io
.ntcreatex
.in
.security_flags
= 0;
372 io
.ntcreatex
.in
.fname
= fname
;
374 torture_comment(tctx
, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
375 ZERO_STRUCT(break_info
);
376 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
377 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
378 NTCREATEX_SHARE_ACCESS_WRITE
|
379 NTCREATEX_SHARE_ACCESS_DELETE
;
381 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
382 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
383 fnum
= io
.ntcreatex
.out
.file
.fnum
;
384 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
386 torture_comment(tctx
, "a 2nd open should cause a break to level 2\n");
387 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
388 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
389 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
390 torture_wait_for_oplock_break(tctx
);
391 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
392 CHECK_VAL(break_info
.count
, 1);
393 CHECK_VAL(break_info
.fnum
, fnum
);
394 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
395 CHECK_VAL(break_info
.failures
, 0);
396 ZERO_STRUCT(break_info
);
398 /* now we have 2 level II oplocks... */
399 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
400 unl
.unlink
.in
.pattern
= fname
;
401 unl
.unlink
.in
.attrib
= 0;
402 status
= smb_raw_unlink(cli2
->tree
, &unl
);
403 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
404 torture_wait_for_oplock_break(tctx
);
405 CHECK_VAL(break_info
.count
, 0);
406 CHECK_VAL(break_info
.failures
, 0);
408 torture_comment(tctx
, "close 1st handle\n");
409 smbcli_close(cli1
->tree
, fnum
);
411 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
412 unl
.unlink
.in
.pattern
= fname
;
413 unl
.unlink
.in
.attrib
= 0;
414 status
= smb_raw_unlink(cli2
->tree
, &unl
);
415 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
416 torture_wait_for_oplock_break(tctx
);
417 CHECK_VAL(break_info
.count
, 0);
418 CHECK_VAL(break_info
.failures
, 0);
420 torture_comment(tctx
, "close 2nd handle\n");
421 smbcli_close(cli2
->tree
, fnum2
);
423 torture_comment(tctx
, "unlink it\n");
424 unl
.unlink
.in
.pattern
= fname
;
425 unl
.unlink
.in
.attrib
= 0;
426 status
= smb_raw_unlink(cli2
->tree
, &unl
);
427 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
428 torture_wait_for_oplock_break(tctx
);
429 CHECK_VAL(break_info
.count
, 0);
430 CHECK_VAL(break_info
.failures
, 0);
433 smb_raw_exit(cli1
->session
);
434 smb_raw_exit(cli2
->session
);
435 smbcli_deltree(cli1
->tree
, BASEDIR
);
439 static bool test_raw_oplock_exclusive3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
441 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
445 union smb_setfileinfo sfi
;
448 if (!torture_setup_dir(cli1
, BASEDIR
)) {
453 smbcli_unlink(cli1
->tree
, fname
);
455 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
460 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
461 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
462 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
463 io
.ntcreatex
.in
.alloc_size
= 0;
464 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
465 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
466 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
467 io
.ntcreatex
.in
.create_options
= 0;
468 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
469 io
.ntcreatex
.in
.security_flags
= 0;
470 io
.ntcreatex
.in
.fname
= fname
;
472 torture_comment(tctx
, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
474 ZERO_STRUCT(break_info
);
475 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
477 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
478 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
479 fnum
= io
.ntcreatex
.out
.file
.fnum
;
480 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
482 torture_comment(tctx
, "setpathinfo EOF should trigger a break to none\n");
484 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
485 sfi
.generic
.in
.file
.path
= fname
;
486 sfi
.end_of_file_info
.in
.size
= 100;
488 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
490 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
491 torture_wait_for_oplock_break(tctx
);
492 CHECK_VAL(break_info
.count
, get_setinfo_break_count(tctx
));
493 CHECK_VAL(break_info
.failures
, 0);
494 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
496 smbcli_close(cli1
->tree
, fnum
);
499 smb_raw_exit(cli1
->session
);
500 smb_raw_exit(cli2
->session
);
501 smbcli_deltree(cli1
->tree
, BASEDIR
);
505 static bool test_raw_oplock_exclusive4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
507 const char *fname
= BASEDIR
"\\test_exclusive4.dat";
511 uint16_t fnum
=0, fnum2
=0;
513 if (!torture_setup_dir(cli1
, BASEDIR
)) {
518 smbcli_unlink(cli1
->tree
, fname
);
520 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
525 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
526 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
527 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
528 io
.ntcreatex
.in
.alloc_size
= 0;
529 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
530 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
531 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
532 io
.ntcreatex
.in
.create_options
= 0;
533 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
534 io
.ntcreatex
.in
.security_flags
= 0;
535 io
.ntcreatex
.in
.fname
= fname
;
537 torture_comment(tctx
, "EXCLUSIVE4: open with exclusive oplock\n");
538 ZERO_STRUCT(break_info
);
539 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
541 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
542 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
543 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
544 fnum
= io
.ntcreatex
.out
.file
.fnum
;
545 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
547 ZERO_STRUCT(break_info
);
548 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
550 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
551 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
552 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
553 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
554 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
555 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
556 torture_wait_for_oplock_break(tctx
);
557 CHECK_VAL(break_info
.count
, 0);
558 CHECK_VAL(break_info
.failures
, 0);
561 * Open another non-stat open. This reproduces bug 10216. Make sure it
562 * won't happen again...
564 io
.ntcreatex
.in
.flags
= 0;
565 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
566 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
567 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
568 torture_wait_for_oplock_break(tctx
);
569 CHECK_VAL(break_info
.count
, 0);
570 CHECK_VAL(break_info
.failures
, 0);
572 smbcli_close(cli1
->tree
, fnum
);
573 smbcli_close(cli2
->tree
, fnum2
);
576 smb_raw_exit(cli1
->session
);
577 smb_raw_exit(cli2
->session
);
578 smbcli_deltree(cli1
->tree
, BASEDIR
);
582 static bool test_raw_oplock_exclusive5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
584 const char *fname
= BASEDIR
"\\test_exclusive5.dat";
588 uint16_t fnum
=0, fnum2
=0;
590 if (!torture_setup_dir(cli1
, BASEDIR
)) {
595 smbcli_unlink(cli1
->tree
, fname
);
597 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
598 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
603 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
604 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
605 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
606 io
.ntcreatex
.in
.alloc_size
= 0;
607 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
608 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
609 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
610 io
.ntcreatex
.in
.create_options
= 0;
611 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
612 io
.ntcreatex
.in
.security_flags
= 0;
613 io
.ntcreatex
.in
.fname
= fname
;
615 torture_comment(tctx
, "EXCLUSIVE5: open with exclusive oplock\n");
616 ZERO_STRUCT(break_info
);
617 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
620 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
621 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
622 NTCREATEX_SHARE_ACCESS_WRITE
|
623 NTCREATEX_SHARE_ACCESS_DELETE
;
624 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
625 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
626 fnum
= io
.ntcreatex
.out
.file
.fnum
;
627 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
629 ZERO_STRUCT(break_info
);
631 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
633 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
634 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
635 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
636 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
637 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
638 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
639 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
640 torture_wait_for_oplock_break(tctx
);
641 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
642 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
643 CHECK_VAL(break_info
.failures
, 0);
645 smbcli_close(cli1
->tree
, fnum
);
646 smbcli_close(cli2
->tree
, fnum2
);
649 smb_raw_exit(cli1
->session
);
650 smb_raw_exit(cli2
->session
);
651 smbcli_deltree(cli1
->tree
, BASEDIR
);
655 static bool test_raw_oplock_exclusive6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
657 const char *fname1
= BASEDIR
"\\test_exclusive6_1.dat";
658 const char *fname2
= BASEDIR
"\\test_exclusive6_2.dat";
665 if (!torture_setup_dir(cli1
, BASEDIR
)) {
670 smbcli_unlink(cli1
->tree
, fname1
);
671 smbcli_unlink(cli1
->tree
, fname2
);
673 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
678 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
679 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
680 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
681 io
.ntcreatex
.in
.alloc_size
= 0;
682 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
683 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
684 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
685 io
.ntcreatex
.in
.create_options
= 0;
686 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
687 io
.ntcreatex
.in
.security_flags
= 0;
688 io
.ntcreatex
.in
.fname
= fname1
;
690 torture_comment(tctx
, "EXCLUSIVE6: open a file with an exclusive "
691 "oplock (share mode: none)\n");
692 ZERO_STRUCT(break_info
);
693 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
695 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
696 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
697 fnum
= io
.ntcreatex
.out
.file
.fnum
;
698 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
700 torture_comment(tctx
, "rename should not generate a break but get a "
701 "sharing violation\n");
703 rn
.generic
.level
= RAW_RENAME_RENAME
;
704 rn
.rename
.in
.pattern1
= fname1
;
705 rn
.rename
.in
.pattern2
= fname2
;
706 rn
.rename
.in
.attrib
= 0;
708 torture_comment(tctx
, "trying rename while first file open\n");
709 status
= smb_raw_rename(cli2
->tree
, &rn
);
711 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
712 torture_wait_for_oplock_break(tctx
);
713 CHECK_VAL(break_info
.count
, 0);
714 CHECK_VAL(break_info
.failures
, 0);
716 smbcli_close(cli1
->tree
, fnum
);
719 smb_raw_exit(cli1
->session
);
720 smb_raw_exit(cli2
->session
);
721 smbcli_deltree(cli1
->tree
, BASEDIR
);
726 * Exclusive version of batch19
728 static bool test_raw_oplock_exclusive7(struct torture_context
*tctx
,
729 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
731 const char *fname1
= BASEDIR
"\\test_exclusiv6_1.dat";
732 const char *fname2
= BASEDIR
"\\test_exclusiv6_2.dat";
733 const char *fname3
= BASEDIR
"\\test_exclusiv6_3.dat";
737 union smb_fileinfo qfi
;
738 union smb_setfileinfo sfi
;
742 if (!torture_setup_dir(cli1
, BASEDIR
)) {
747 smbcli_unlink(cli1
->tree
, fname1
);
748 smbcli_unlink(cli1
->tree
, fname2
);
749 smbcli_unlink(cli1
->tree
, fname3
);
751 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
757 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
758 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
759 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
760 io
.ntcreatex
.in
.alloc_size
= 0;
761 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
762 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
763 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
764 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
765 io
.ntcreatex
.in
.create_options
= 0;
766 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
767 io
.ntcreatex
.in
.security_flags
= 0;
768 io
.ntcreatex
.in
.fname
= fname1
;
770 torture_comment(tctx
, "open a file with an exclusive oplock (share "
772 ZERO_STRUCT(break_info
);
773 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
774 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
775 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
776 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
777 fnum
= io
.ntcreatex
.out
.file
.fnum
;
778 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
780 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
783 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
784 sfi
.generic
.in
.file
.path
= fname1
;
785 sfi
.rename_information
.in
.overwrite
= 0;
786 sfi
.rename_information
.in
.root_fid
= 0;
787 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
789 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
790 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
792 torture_wait_for_oplock_break(tctx
);
793 CHECK_VAL(break_info
.failures
, 0);
795 if (TARGET_IS_WINXP(tctx
) || TARGET_IS_W2K12(tctx
)) {
796 /* XP incorrectly breaks to level2. */
797 CHECK_VAL(break_info
.count
, 1);
798 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
800 /* Exclusive oplocks should not be broken on rename. */
801 CHECK_VAL(break_info
.failures
, 0);
802 CHECK_VAL(break_info
.count
, 0);
806 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
807 qfi
.generic
.in
.file
.fnum
= fnum
;
809 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
810 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
811 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
813 /* Try breaking to level2 and then see if rename breaks the level2.*/
814 ZERO_STRUCT(break_info
);
815 io
.ntcreatex
.in
.fname
= fname2
;
816 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
817 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
818 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
819 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
821 torture_wait_for_oplock_break(tctx
);
822 CHECK_VAL(break_info
.failures
, 0);
824 if (TARGET_IS_WINXP(tctx
)) {
825 /* XP already broke to level2. */
826 CHECK_VAL(break_info
.failures
, 0);
827 CHECK_VAL(break_info
.count
, 0);
828 } else if (TARGET_IS_W2K12(tctx
)) {
830 CHECK_VAL(break_info
.count
, 0);
831 CHECK_VAL(break_info
.level
, 0);
833 /* Break to level 2 expected. */
834 CHECK_VAL(break_info
.count
, 1);
835 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
838 ZERO_STRUCT(break_info
);
839 sfi
.generic
.in
.file
.path
= fname2
;
840 sfi
.rename_information
.in
.overwrite
= 0;
841 sfi
.rename_information
.in
.root_fid
= 0;
842 sfi
.rename_information
.in
.new_name
= fname1
+strlen(BASEDIR
)+1;
844 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
845 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
847 /* Level2 oplocks are not broken on rename. */
848 torture_wait_for_oplock_break(tctx
);
849 CHECK_VAL(break_info
.failures
, 0);
850 CHECK_VAL(break_info
.count
, 0);
852 /* Close and re-open file with oplock. */
853 smbcli_close(cli1
->tree
, fnum
);
854 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
855 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
856 fnum
= io
.ntcreatex
.out
.file
.fnum
;
857 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
859 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
860 "should not trigger a break nor a violation\n");
861 ZERO_STRUCT(break_info
);
863 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
864 sfi
.generic
.in
.file
.fnum
= fnum
;
865 sfi
.rename_information
.in
.overwrite
= 0;
866 sfi
.rename_information
.in
.root_fid
= 0;
867 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
869 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
870 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
872 torture_wait_for_oplock_break(tctx
);
873 if (TARGET_IS_WINXP(tctx
)) {
874 /* XP incorrectly breaks to level2. */
875 CHECK_VAL(break_info
.count
, 1);
876 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
878 CHECK_VAL(break_info
.count
, 0);
882 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
883 qfi
.generic
.in
.file
.fnum
= fnum
;
885 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
886 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
887 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
890 smbcli_close(cli1
->tree
, fnum
);
891 smbcli_close(cli2
->tree
, fnum2
);
893 smb_raw_exit(cli1
->session
);
894 smb_raw_exit(cli2
->session
);
895 smbcli_deltree(cli1
->tree
, BASEDIR
);
899 static bool test_raw_oplock_exclusive8(struct torture_context
*tctx
,
900 struct smbcli_state
*cli1
,
901 struct smbcli_state
*cli2
)
903 const char *fname
= BASEDIR
"\\test_exclusive8.dat";
911 if (!torture_setup_dir(cli1
, BASEDIR
)) {
916 smbcli_unlink(cli1
->tree
, fname
);
918 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
924 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
925 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
926 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
927 io
.ntcreatex
.in
.alloc_size
= 0;
928 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
929 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
930 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
931 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
932 io
.ntcreatex
.in
.create_options
= 0;
933 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
934 io
.ntcreatex
.in
.security_flags
= 0;
935 io
.ntcreatex
.in
.fname
= fname
;
937 torture_comment(tctx
, "open a file with an exclusive oplock (share "
939 ZERO_STRUCT(break_info
);
940 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
941 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
942 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
943 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
944 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
945 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
947 torture_comment(tctx
, "second open with delete should trigger a "
950 io
.ntcreatex
.in
.access_mask
= SEC_STD_DELETE
;
951 io
.ntcreatex
.in
.flags
= 0;
952 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
953 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
954 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
955 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
956 CHECK_VAL(break_info
.failures
, 0);
957 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
959 /* Trigger a little panic in "old" samba code.. */
960 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
961 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
962 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
964 smbcli_close(cli2
->tree
, fnum3
);
965 smbcli_close(cli2
->tree
, fnum2
);
966 smbcli_close(cli1
->tree
, fnum1
);
969 smbcli_deltree(cli1
->tree
, BASEDIR
);
970 smb_raw_exit(cli1
->session
);
971 smb_raw_exit(cli2
->session
);
975 static bool test_raw_oplock_exclusive9(struct torture_context
*tctx
,
976 struct smbcli_state
*cli1
,
977 struct smbcli_state
*cli2
)
979 const char *fname
= BASEDIR
"\\test_exclusive9.dat";
983 uint16_t fnum
=0, fnum2
=0;
987 uint32_t create_disposition
;
988 uint32_t break_level
;
990 { NTCREATEX_DISP_SUPERSEDE
, OPLOCK_BREAK_TO_NONE
},
991 { NTCREATEX_DISP_OPEN
, OPLOCK_BREAK_TO_LEVEL_II
},
992 { NTCREATEX_DISP_OVERWRITE_IF
, OPLOCK_BREAK_TO_NONE
},
993 { NTCREATEX_DISP_OPEN_IF
, OPLOCK_BREAK_TO_LEVEL_II
},
996 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1001 smbcli_unlink(cli1
->tree
, fname
);
1003 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
1005 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
,
1009 base ntcreatex parms
1011 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1012 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1013 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1014 io
.ntcreatex
.in
.alloc_size
= 0;
1015 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1016 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1017 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1018 io
.ntcreatex
.in
.create_options
= 0;
1019 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1020 io
.ntcreatex
.in
.security_flags
= 0;
1021 io
.ntcreatex
.in
.fname
= fname
;
1023 ZERO_STRUCT(break_info
);
1024 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
1027 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
1029 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1030 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1031 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1032 NTCREATEX_SHARE_ACCESS_WRITE
|
1033 NTCREATEX_SHARE_ACCESS_DELETE
;
1034 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1035 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1036 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1037 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1038 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
1039 EXCLUSIVE_OPLOCK_RETURN
);
1041 ZERO_STRUCT(break_info
);
1043 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1044 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1045 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
1046 io
.ntcreatex
.in
.open_disposition
=
1047 levels
[i
].create_disposition
;
1048 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1049 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1050 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1051 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
1052 LEVEL_II_OPLOCK_RETURN
);
1053 torture_wait_for_oplock_break(tctx
);
1054 CHECK_VAL(break_info
.count
, 1);
1055 CHECK_VAL(break_info
.level
, levels
[i
].break_level
);
1056 CHECK_VAL(break_info
.failures
, 0);
1058 smbcli_close(cli1
->tree
, fnum
);
1059 smbcli_close(cli2
->tree
, fnum2
);
1063 smb_raw_exit(cli1
->session
);
1064 smb_raw_exit(cli2
->session
);
1065 smbcli_deltree(cli1
->tree
, BASEDIR
);
1069 static bool test_raw_oplock_level_ii_1(struct torture_context
*tctx
,
1070 struct smbcli_state
*cli1
,
1071 struct smbcli_state
*cli2
)
1073 const char *fname
= BASEDIR
"\\test_level_ii_1.dat";
1077 uint16_t fnum
=0, fnum2
=0;
1081 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1086 smbcli_unlink(cli1
->tree
, fname
);
1088 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
1090 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
,
1094 base ntcreatex parms
1096 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1097 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1098 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1099 io
.ntcreatex
.in
.alloc_size
= 0;
1100 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1101 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1102 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1103 io
.ntcreatex
.in
.create_options
= 0;
1104 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1105 io
.ntcreatex
.in
.security_flags
= 0;
1106 io
.ntcreatex
.in
.fname
= fname
;
1108 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1109 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1110 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1111 NTCREATEX_SHARE_ACCESS_WRITE
|
1112 NTCREATEX_SHARE_ACCESS_DELETE
;
1113 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1114 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1115 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1116 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1117 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
1119 ZERO_STRUCT(break_info
);
1121 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1122 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
1123 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
;
1124 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1125 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1126 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1127 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1128 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1129 torture_wait_for_oplock_break(tctx
);
1130 CHECK_VAL(break_info
.count
, 1);
1131 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1132 CHECK_VAL(break_info
.failures
, 0);
1134 status
= smbcli_close(cli2
->tree
, fnum2
);
1135 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1138 * fnum1 has a level2 oplock now
1141 ZERO_STRUCT(break_info
);
1144 * Don't answer the break to none that will come in
1147 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
,
1150 io
.ntcreatex
.in
.flags
= 0;
1151 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1153 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1154 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1155 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1156 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1157 torture_wait_for_oplock_break(tctx
);
1158 CHECK_VAL(break_info
.count
, 1);
1159 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
1160 CHECK_VAL(break_info
.failures
, 0);
1163 * Check that a write does not cause another break. This used to be a
1167 ZERO_STRUCT(break_info
);
1168 written
= smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1169 CHECK_VAL(written
, 1);
1170 torture_wait_for_oplock_break(tctx
);
1171 CHECK_VAL(break_info
.count
, 0);
1172 CHECK_VAL(break_info
.failures
, 0);
1174 status
= smbcli_close(cli2
->tree
, fnum2
);
1175 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1176 status
= smbcli_close(cli1
->tree
, fnum
);
1177 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1180 smb_raw_exit(cli1
->session
);
1181 smb_raw_exit(cli2
->session
);
1182 smbcli_deltree(cli1
->tree
, BASEDIR
);
1186 static bool test_raw_oplock_batch1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1188 const char *fname
= BASEDIR
"\\test_batch1.dat";
1192 union smb_unlink unl
;
1196 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1201 smbcli_unlink(cli1
->tree
, fname
);
1203 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1206 base ntcreatex parms
1208 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1209 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1210 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1211 io
.ntcreatex
.in
.alloc_size
= 0;
1212 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1213 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1214 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1215 io
.ntcreatex
.in
.create_options
= 0;
1216 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1217 io
.ntcreatex
.in
.security_flags
= 0;
1218 io
.ntcreatex
.in
.fname
= fname
;
1221 with a batch oplock we get a break
1223 torture_comment(tctx
, "BATCH1: open with batch oplock\n");
1224 ZERO_STRUCT(break_info
);
1225 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1226 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1227 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1228 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1229 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1230 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1231 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1233 torture_comment(tctx
, "unlink should generate a break\n");
1234 unl
.unlink
.in
.pattern
= fname
;
1235 unl
.unlink
.in
.attrib
= 0;
1236 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1237 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1239 torture_wait_for_oplock_break(tctx
);
1240 CHECK_VAL(break_info
.count
, 1);
1241 CHECK_VAL(break_info
.fnum
, fnum
);
1242 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1243 CHECK_VAL(break_info
.failures
, 0);
1245 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1246 ZERO_STRUCT(break_info
);
1247 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1248 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1250 torture_wait_for_oplock_break(tctx
);
1251 CHECK_VAL(break_info
.count
, 0);
1253 torture_comment(tctx
, "writing should generate a self break to none\n");
1254 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1256 torture_wait_for_oplock_break(tctx
);
1257 torture_wait_for_oplock_break(tctx
);
1258 CHECK_VAL(break_info
.count
, 1);
1259 CHECK_VAL(break_info
.fnum
, fnum
);
1260 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
1261 CHECK_VAL(break_info
.failures
, 0);
1263 smbcli_close(cli1
->tree
, fnum
);
1266 smb_raw_exit(cli1
->session
);
1267 smb_raw_exit(cli2
->session
);
1268 smbcli_deltree(cli1
->tree
, BASEDIR
);
1272 static bool test_raw_oplock_batch2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1274 const char *fname
= BASEDIR
"\\test_batch2.dat";
1278 union smb_unlink unl
;
1282 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1287 smbcli_unlink(cli1
->tree
, fname
);
1289 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1292 base ntcreatex parms
1294 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1295 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1296 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1297 io
.ntcreatex
.in
.alloc_size
= 0;
1298 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1299 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1300 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1301 io
.ntcreatex
.in
.create_options
= 0;
1302 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1303 io
.ntcreatex
.in
.security_flags
= 0;
1304 io
.ntcreatex
.in
.fname
= fname
;
1306 torture_comment(tctx
, "BATCH2: open with batch oplock\n");
1307 ZERO_STRUCT(break_info
);
1308 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1309 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1310 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1311 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1312 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1313 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1314 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1316 torture_comment(tctx
, "unlink should generate a break, which we ack as break to none\n");
1317 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_none
, cli1
->tree
);
1318 unl
.unlink
.in
.pattern
= fname
;
1319 unl
.unlink
.in
.attrib
= 0;
1320 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1321 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1323 torture_wait_for_oplock_break(tctx
);
1324 CHECK_VAL(break_info
.count
, 1);
1325 CHECK_VAL(break_info
.fnum
, fnum
);
1326 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1327 CHECK_VAL(break_info
.failures
, 0);
1329 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1330 ZERO_STRUCT(break_info
);
1331 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1332 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1334 torture_wait_for_oplock_break(tctx
);
1335 CHECK_VAL(break_info
.count
, 0);
1337 torture_comment(tctx
, "writing should not generate a break\n");
1338 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1340 torture_wait_for_oplock_break(tctx
);
1341 CHECK_VAL(break_info
.count
, 0);
1343 smbcli_close(cli1
->tree
, fnum
);
1346 smb_raw_exit(cli1
->session
);
1347 smb_raw_exit(cli2
->session
);
1348 smbcli_deltree(cli1
->tree
, BASEDIR
);
1352 static bool test_raw_oplock_batch3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1354 const char *fname
= BASEDIR
"\\test_batch3.dat";
1358 union smb_unlink unl
;
1361 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1366 smbcli_unlink(cli1
->tree
, fname
);
1368 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1371 base ntcreatex parms
1373 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1374 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1375 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1376 io
.ntcreatex
.in
.alloc_size
= 0;
1377 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1378 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1379 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1380 io
.ntcreatex
.in
.create_options
= 0;
1381 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1382 io
.ntcreatex
.in
.security_flags
= 0;
1383 io
.ntcreatex
.in
.fname
= fname
;
1385 torture_comment(tctx
, "BATCH3: if we close on break then the unlink can succeed\n");
1386 ZERO_STRUCT(break_info
);
1387 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1388 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1389 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1390 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1391 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1392 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1393 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1394 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1396 unl
.unlink
.in
.pattern
= fname
;
1397 unl
.unlink
.in
.attrib
= 0;
1398 ZERO_STRUCT(break_info
);
1399 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1400 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1402 torture_wait_for_oplock_break(tctx
);
1403 CHECK_VAL(break_info
.count
, 1);
1404 CHECK_VAL(break_info
.fnum
, fnum
);
1405 CHECK_VAL(break_info
.level
, 1);
1406 CHECK_VAL(break_info
.failures
, 0);
1408 smbcli_close(cli1
->tree
, fnum
);
1411 smb_raw_exit(cli1
->session
);
1412 smb_raw_exit(cli2
->session
);
1413 smbcli_deltree(cli1
->tree
, BASEDIR
);
1417 static bool test_raw_oplock_batch4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1419 const char *fname
= BASEDIR
"\\test_batch4.dat";
1426 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1431 smbcli_unlink(cli1
->tree
, fname
);
1433 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1436 base ntcreatex parms
1438 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1439 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1440 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1441 io
.ntcreatex
.in
.alloc_size
= 0;
1442 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1443 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1444 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1445 io
.ntcreatex
.in
.create_options
= 0;
1446 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1447 io
.ntcreatex
.in
.security_flags
= 0;
1448 io
.ntcreatex
.in
.fname
= fname
;
1450 torture_comment(tctx
, "BATCH4: a self read should not cause a break\n");
1451 ZERO_STRUCT(break_info
);
1452 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1454 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1455 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1456 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1457 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1458 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1459 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1460 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1462 rd
.readx
.level
= RAW_READ_READX
;
1463 rd
.readx
.in
.file
.fnum
= fnum
;
1464 rd
.readx
.in
.mincnt
= 1;
1465 rd
.readx
.in
.maxcnt
= 1;
1466 rd
.readx
.in
.offset
= 0;
1467 rd
.readx
.in
.remaining
= 0;
1468 rd
.readx
.in
.read_for_execute
= false;
1469 status
= smb_raw_read(cli1
->tree
, &rd
);
1470 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1471 torture_wait_for_oplock_break(tctx
);
1472 CHECK_VAL(break_info
.count
, 0);
1473 CHECK_VAL(break_info
.failures
, 0);
1475 smbcli_close(cli1
->tree
, fnum
);
1478 smb_raw_exit(cli1
->session
);
1479 smb_raw_exit(cli2
->session
);
1480 smbcli_deltree(cli1
->tree
, BASEDIR
);
1484 static bool test_raw_oplock_batch5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1486 const char *fname
= BASEDIR
"\\test_batch5.dat";
1492 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1497 smbcli_unlink(cli1
->tree
, fname
);
1499 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1502 base ntcreatex parms
1504 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1505 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1506 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1507 io
.ntcreatex
.in
.alloc_size
= 0;
1508 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1509 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1510 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1511 io
.ntcreatex
.in
.create_options
= 0;
1512 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1513 io
.ntcreatex
.in
.security_flags
= 0;
1514 io
.ntcreatex
.in
.fname
= fname
;
1516 torture_comment(tctx
, "BATCH5: a 2nd open should give a break\n");
1517 ZERO_STRUCT(break_info
);
1518 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1520 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1521 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1522 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1523 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1524 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1525 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1526 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1528 ZERO_STRUCT(break_info
);
1530 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1531 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1532 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1534 torture_wait_for_oplock_break(tctx
);
1535 CHECK_VAL(break_info
.count
, 1);
1536 CHECK_VAL(break_info
.fnum
, fnum
);
1537 CHECK_VAL(break_info
.level
, 1);
1538 CHECK_VAL(break_info
.failures
, 0);
1540 smbcli_close(cli1
->tree
, fnum
);
1543 smb_raw_exit(cli1
->session
);
1544 smb_raw_exit(cli2
->session
);
1545 smbcli_deltree(cli1
->tree
, BASEDIR
);
1549 static bool test_raw_oplock_batch6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1551 const char *fname
= BASEDIR
"\\test_batch6.dat";
1555 uint16_t fnum
=0, fnum2
=0;
1558 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1563 smbcli_unlink(cli1
->tree
, fname
);
1565 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1566 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1569 base ntcreatex parms
1571 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1572 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1573 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1574 io
.ntcreatex
.in
.alloc_size
= 0;
1575 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1576 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1577 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1578 io
.ntcreatex
.in
.create_options
= 0;
1579 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1580 io
.ntcreatex
.in
.security_flags
= 0;
1581 io
.ntcreatex
.in
.fname
= fname
;
1583 torture_comment(tctx
, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1584 ZERO_STRUCT(break_info
);
1586 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
1587 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1588 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1589 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1590 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1591 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1592 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1593 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1594 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1596 ZERO_STRUCT(break_info
);
1598 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1599 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1600 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1601 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1603 //torture_wait_for_oplock_break(tctx);
1604 CHECK_VAL(break_info
.count
, 1);
1605 CHECK_VAL(break_info
.fnum
, fnum
);
1606 CHECK_VAL(break_info
.level
, 1);
1607 CHECK_VAL(break_info
.failures
, 0);
1608 ZERO_STRUCT(break_info
);
1610 torture_comment(tctx
, "write should trigger a break to none on both\n");
1611 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1613 /* We expect two breaks */
1614 torture_wait_for_oplock_break(tctx
);
1615 torture_wait_for_oplock_break(tctx
);
1617 CHECK_VAL(break_info
.count
, 2);
1618 CHECK_VAL(break_info
.level
, 0);
1619 CHECK_VAL(break_info
.failures
, 0);
1621 smbcli_close(cli1
->tree
, fnum
);
1622 smbcli_close(cli2
->tree
, fnum2
);
1625 smb_raw_exit(cli1
->session
);
1626 smb_raw_exit(cli2
->session
);
1627 smbcli_deltree(cli1
->tree
, BASEDIR
);
1631 static bool test_raw_oplock_batch7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1633 const char *fname
= BASEDIR
"\\test_batch7.dat";
1637 uint16_t fnum
=0, fnum2
=0;
1639 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1644 smbcli_unlink(cli1
->tree
, fname
);
1646 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1649 base ntcreatex parms
1651 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1652 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1653 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1654 io
.ntcreatex
.in
.alloc_size
= 0;
1655 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1656 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1657 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1658 io
.ntcreatex
.in
.create_options
= 0;
1659 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1660 io
.ntcreatex
.in
.security_flags
= 0;
1661 io
.ntcreatex
.in
.fname
= fname
;
1663 torture_comment(tctx
, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1664 ZERO_STRUCT(break_info
);
1665 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1667 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1668 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1669 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1670 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1671 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1672 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1673 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1674 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1675 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1677 ZERO_STRUCT(break_info
);
1679 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1680 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1681 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1682 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1683 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1684 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1685 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1687 torture_wait_for_oplock_break(tctx
);
1688 CHECK_VAL(break_info
.count
, 1);
1689 CHECK_VAL(break_info
.fnum
, fnum2
);
1690 CHECK_VAL(break_info
.level
, 1);
1691 CHECK_VAL(break_info
.failures
, 0);
1693 smbcli_close(cli2
->tree
, fnum
);
1696 smb_raw_exit(cli1
->session
);
1697 smb_raw_exit(cli2
->session
);
1698 smbcli_deltree(cli1
->tree
, BASEDIR
);
1702 static bool test_raw_oplock_batch8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1704 const char *fname
= BASEDIR
"\\test_batch8.dat";
1708 uint16_t fnum
=0, fnum2
=0;
1710 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1715 smbcli_unlink(cli1
->tree
, fname
);
1717 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1720 base ntcreatex parms
1722 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1723 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1724 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1725 io
.ntcreatex
.in
.alloc_size
= 0;
1726 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1727 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1728 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1729 io
.ntcreatex
.in
.create_options
= 0;
1730 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1731 io
.ntcreatex
.in
.security_flags
= 0;
1732 io
.ntcreatex
.in
.fname
= fname
;
1734 torture_comment(tctx
, "BATCH8: open with batch oplock\n");
1735 ZERO_STRUCT(break_info
);
1736 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1738 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1739 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1740 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1741 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1742 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1743 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1744 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1746 ZERO_STRUCT(break_info
);
1747 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
1749 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1750 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1751 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1752 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1753 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1754 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1755 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1756 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1757 torture_wait_for_oplock_break(tctx
);
1758 CHECK_VAL(break_info
.count
, 0);
1759 CHECK_VAL(break_info
.failures
, 0);
1761 smbcli_close(cli1
->tree
, fnum
);
1762 smbcli_close(cli2
->tree
, fnum2
);
1765 smb_raw_exit(cli1
->session
);
1766 smb_raw_exit(cli2
->session
);
1767 smbcli_deltree(cli1
->tree
, BASEDIR
);
1771 static bool test_raw_oplock_batch9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1773 const char *fname
= BASEDIR
"\\test_batch9.dat";
1777 uint16_t fnum
=0, fnum2
=0;
1780 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1785 smbcli_unlink(cli1
->tree
, fname
);
1787 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1790 base ntcreatex parms
1792 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1793 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1794 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1795 io
.ntcreatex
.in
.alloc_size
= 0;
1796 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1797 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1798 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1799 io
.ntcreatex
.in
.create_options
= 0;
1800 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1801 io
.ntcreatex
.in
.security_flags
= 0;
1802 io
.ntcreatex
.in
.fname
= fname
;
1804 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1806 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1807 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1808 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1809 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1810 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1811 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1812 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1813 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1814 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1816 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1818 ZERO_STRUCT(break_info
);
1819 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1821 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1822 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1823 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1824 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1825 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1826 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1827 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1828 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1829 torture_wait_for_oplock_break(tctx
);
1830 CHECK_VAL(break_info
.count
, 1);
1831 CHECK_VAL(break_info
.fnum
, fnum
);
1832 CHECK_VAL(break_info
.failures
, 0);
1833 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1834 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1835 smbcli_close(cli2
->tree
, fnum2
);
1837 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1838 ZERO_STRUCT(break_info
);
1839 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1840 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1841 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1842 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1843 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1844 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1845 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1846 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1847 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1848 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1849 torture_wait_for_oplock_break(tctx
);
1850 CHECK_VAL(break_info
.count
, 0);
1851 CHECK_VAL(break_info
.failures
, 0);
1852 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1854 ZERO_STRUCT(break_info
);
1856 torture_comment(tctx
, "write should trigger a break to none on both\n");
1857 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1859 /* We expect two breaks */
1860 torture_wait_for_oplock_break(tctx
);
1861 torture_wait_for_oplock_break(tctx
);
1863 CHECK_VAL(break_info
.count
, 2);
1864 CHECK_VAL(break_info
.level
, 0);
1865 CHECK_VAL(break_info
.failures
, 0);
1867 smbcli_close(cli1
->tree
, fnum
);
1868 smbcli_close(cli2
->tree
, fnum2
);
1871 smb_raw_exit(cli1
->session
);
1872 smb_raw_exit(cli2
->session
);
1873 smbcli_deltree(cli1
->tree
, BASEDIR
);
1877 static bool test_raw_oplock_batch9a(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1879 const char *fname
= BASEDIR
"\\test_batch9a.dat";
1883 uint16_t fnum
=0, fnum2
=0;
1886 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1891 smbcli_unlink(cli1
->tree
, fname
);
1893 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1896 base ntcreatex parms
1898 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1899 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1900 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1901 io
.ntcreatex
.in
.alloc_size
= 0;
1902 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1903 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1904 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1905 io
.ntcreatex
.in
.create_options
= 0;
1906 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1907 io
.ntcreatex
.in
.security_flags
= 0;
1908 io
.ntcreatex
.in
.fname
= fname
;
1910 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1912 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1913 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1914 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1915 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1916 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1917 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1918 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1919 CHECK_VAL(io
.ntcreatex
.out
.create_action
, FILE_WAS_CREATED
);
1920 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1922 torture_comment(tctx
, "Subsequent attributes open should not break\n");
1924 ZERO_STRUCT(break_info
);
1925 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1927 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1928 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1929 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1930 torture_wait_for_oplock_break(tctx
);
1931 CHECK_VAL(break_info
.count
, 0);
1932 CHECK_VAL(io
.ntcreatex
.out
.create_action
, FILE_WAS_OPENED
);
1933 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1934 smbcli_close(cli2
->tree
, fnum2
);
1936 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1938 ZERO_STRUCT(break_info
);
1939 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1941 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1942 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1943 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1944 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1945 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1946 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1947 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1948 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1949 torture_wait_for_oplock_break(tctx
);
1950 CHECK_VAL(break_info
.count
, 1);
1951 CHECK_VAL(break_info
.fnum
, fnum
);
1952 CHECK_VAL(break_info
.failures
, 0);
1953 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1954 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1955 smbcli_close(cli2
->tree
, fnum2
);
1957 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1958 ZERO_STRUCT(break_info
);
1959 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1960 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1961 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1962 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1963 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1964 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1965 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1966 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1967 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1968 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1969 torture_wait_for_oplock_break(tctx
);
1970 CHECK_VAL(break_info
.count
, 0);
1971 CHECK_VAL(break_info
.failures
, 0);
1972 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1974 ZERO_STRUCT(break_info
);
1976 torture_comment(tctx
, "write should trigger a break to none on both\n");
1977 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1979 /* We expect two breaks */
1980 torture_wait_for_oplock_break(tctx
);
1981 torture_wait_for_oplock_break(tctx
);
1983 CHECK_VAL(break_info
.count
, 2);
1984 CHECK_VAL(break_info
.level
, 0);
1985 CHECK_VAL(break_info
.failures
, 0);
1987 smbcli_close(cli1
->tree
, fnum
);
1988 smbcli_close(cli2
->tree
, fnum2
);
1991 smb_raw_exit(cli1
->session
);
1992 smb_raw_exit(cli2
->session
);
1993 smbcli_deltree(cli1
->tree
, BASEDIR
);
1997 static bool test_raw_oplock_batch10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1999 const char *fname
= BASEDIR
"\\test_batch10.dat";
2003 uint16_t fnum
=0, fnum2
=0;
2005 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2010 smbcli_unlink(cli1
->tree
, fname
);
2012 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2015 base ntcreatex parms
2017 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2018 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2019 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2020 io
.ntcreatex
.in
.alloc_size
= 0;
2021 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2022 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2023 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2024 io
.ntcreatex
.in
.create_options
= 0;
2025 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2026 io
.ntcreatex
.in
.security_flags
= 0;
2027 io
.ntcreatex
.in
.fname
= fname
;
2029 torture_comment(tctx
, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
2030 ZERO_STRUCT(break_info
);
2031 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
2032 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2033 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2034 NTCREATEX_SHARE_ACCESS_WRITE
|
2035 NTCREATEX_SHARE_ACCESS_DELETE
;
2036 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2037 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2038 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2039 torture_wait_for_oplock_break(tctx
);
2040 CHECK_VAL(break_info
.count
, 0);
2041 CHECK_VAL(break_info
.failures
, 0);
2042 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
2046 wr
.write
.level
= RAW_WRITE_WRITE
;
2047 wr
.write
.in
.file
.fnum
= fnum
;
2048 wr
.write
.in
.count
= 1;
2049 wr
.write
.in
.offset
= 0;
2050 wr
.write
.in
.remaining
= 0;
2051 wr
.write
.in
.data
= (const uint8_t *)"x";
2052 status
= smb_raw_write(cli1
->tree
, &wr
);
2053 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2056 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
2058 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2059 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2060 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2061 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2062 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2063 NTCREATEX_SHARE_ACCESS_WRITE
|
2064 NTCREATEX_SHARE_ACCESS_DELETE
;
2065 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
2066 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2067 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2068 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2069 torture_wait_for_oplock_break(tctx
);
2070 CHECK_VAL(break_info
.count
, 0);
2071 CHECK_VAL(break_info
.failures
, 0);
2072 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2074 torture_comment(tctx
, "write should trigger a break to none\n");
2077 wr
.write
.level
= RAW_WRITE_WRITE
;
2078 wr
.write
.in
.file
.fnum
= fnum
;
2079 wr
.write
.in
.count
= 1;
2080 wr
.write
.in
.offset
= 0;
2081 wr
.write
.in
.remaining
= 0;
2082 wr
.write
.in
.data
= (const uint8_t *)"x";
2083 status
= smb_raw_write(cli1
->tree
, &wr
);
2084 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2087 torture_wait_for_oplock_break(tctx
);
2089 CHECK_VAL(break_info
.count
, 1);
2090 CHECK_VAL(break_info
.fnum
, fnum2
);
2091 CHECK_VAL(break_info
.level
, 0);
2092 CHECK_VAL(break_info
.failures
, 0);
2094 smbcli_close(cli1
->tree
, fnum
);
2095 smbcli_close(cli2
->tree
, fnum2
);
2098 smb_raw_exit(cli1
->session
);
2099 smb_raw_exit(cli2
->session
);
2100 smbcli_deltree(cli1
->tree
, BASEDIR
);
2104 static bool test_raw_oplock_batch11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2106 const char *fname
= BASEDIR
"\\test_batch11.dat";
2110 union smb_setfileinfo sfi
;
2113 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2118 smbcli_unlink(cli1
->tree
, fname
);
2120 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2123 base ntcreatex parms
2125 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2126 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2127 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2128 io
.ntcreatex
.in
.alloc_size
= 0;
2129 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2130 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
2131 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2132 io
.ntcreatex
.in
.create_options
= 0;
2133 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2134 io
.ntcreatex
.in
.security_flags
= 0;
2135 io
.ntcreatex
.in
.fname
= fname
;
2137 /* Test if a set-eof on pathname breaks an exclusive oplock. */
2138 torture_comment(tctx
, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
2140 ZERO_STRUCT(break_info
);
2142 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2143 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2144 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2145 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2146 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2147 NTCREATEX_SHARE_ACCESS_WRITE
|
2148 NTCREATEX_SHARE_ACCESS_DELETE
;
2149 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2150 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2151 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2152 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2153 torture_wait_for_oplock_break(tctx
);
2154 CHECK_VAL(break_info
.count
, 0);
2155 CHECK_VAL(break_info
.failures
, 0);
2156 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2159 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
2160 sfi
.generic
.in
.file
.path
= fname
;
2161 sfi
.end_of_file_info
.in
.size
= 100;
2163 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2164 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2166 torture_wait_for_oplock_break(tctx
);
2167 CHECK_VAL(break_info
.count
, get_setinfo_break_count(tctx
));
2168 CHECK_VAL(break_info
.failures
, 0);
2169 CHECK_VAL(break_info
.level
, 0);
2171 smbcli_close(cli1
->tree
, fnum
);
2174 smb_raw_exit(cli1
->session
);
2175 smb_raw_exit(cli2
->session
);
2176 smbcli_deltree(cli1
->tree
, BASEDIR
);
2180 static bool test_raw_oplock_batch12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2182 const char *fname
= BASEDIR
"\\test_batch12.dat";
2186 union smb_setfileinfo sfi
;
2189 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2194 smbcli_unlink(cli1
->tree
, fname
);
2196 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2199 base ntcreatex parms
2201 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2202 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2203 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2204 io
.ntcreatex
.in
.alloc_size
= 0;
2205 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2206 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2207 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2208 io
.ntcreatex
.in
.create_options
= 0;
2209 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2210 io
.ntcreatex
.in
.security_flags
= 0;
2211 io
.ntcreatex
.in
.fname
= fname
;
2213 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
2214 torture_comment(tctx
, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
2216 ZERO_STRUCT(break_info
);
2217 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2219 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2220 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2221 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2222 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2223 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2224 NTCREATEX_SHARE_ACCESS_WRITE
|
2225 NTCREATEX_SHARE_ACCESS_DELETE
;
2226 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2227 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2228 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2229 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2230 torture_wait_for_oplock_break(tctx
);
2231 CHECK_VAL(break_info
.count
, 0);
2232 CHECK_VAL(break_info
.failures
, 0);
2233 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2236 sfi
.generic
.level
= SMB_SFILEINFO_ALLOCATION_INFORMATION
;
2237 sfi
.generic
.in
.file
.path
= fname
;
2238 sfi
.allocation_info
.in
.alloc_size
= 65536 * 8;
2240 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2241 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2243 torture_wait_for_oplock_break(tctx
);
2244 CHECK_VAL(break_info
.count
, get_setinfo_break_count(tctx
));
2245 CHECK_VAL(break_info
.failures
, 0);
2246 CHECK_VAL(break_info
.level
, 0);
2248 smbcli_close(cli1
->tree
, fnum
);
2251 smb_raw_exit(cli1
->session
);
2252 smb_raw_exit(cli2
->session
);
2253 smbcli_deltree(cli1
->tree
, BASEDIR
);
2257 static bool test_raw_oplock_batch13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2259 const char *fname
= BASEDIR
"\\test_batch13.dat";
2263 uint16_t fnum
=0, fnum2
=0;
2265 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2270 smbcli_unlink(cli1
->tree
, fname
);
2272 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2273 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2276 base ntcreatex parms
2278 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2279 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2280 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2281 io
.ntcreatex
.in
.alloc_size
= 0;
2282 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2283 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2284 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2285 io
.ntcreatex
.in
.create_options
= 0;
2286 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2287 io
.ntcreatex
.in
.security_flags
= 0;
2288 io
.ntcreatex
.in
.fname
= fname
;
2290 torture_comment(tctx
, "BATCH13: open with batch oplock\n");
2291 ZERO_STRUCT(break_info
);
2293 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2294 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2295 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2296 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2297 NTCREATEX_SHARE_ACCESS_WRITE
|
2298 NTCREATEX_SHARE_ACCESS_DELETE
;
2299 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2300 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2301 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2302 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2304 ZERO_STRUCT(break_info
);
2306 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
2308 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2309 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2310 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2311 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2312 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2313 NTCREATEX_SHARE_ACCESS_WRITE
|
2314 NTCREATEX_SHARE_ACCESS_DELETE
;
2315 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
2316 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2317 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2318 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2319 torture_wait_for_oplock_break(tctx
);
2320 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2321 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2322 CHECK_VAL(break_info
.failures
, 0);
2324 smbcli_close(cli1
->tree
, fnum
);
2325 smbcli_close(cli2
->tree
, fnum2
);
2328 smb_raw_exit(cli1
->session
);
2329 smb_raw_exit(cli2
->session
);
2330 smbcli_deltree(cli1
->tree
, BASEDIR
);
2334 static bool test_raw_oplock_batch14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2336 const char *fname
= BASEDIR
"\\test_batch14.dat";
2340 uint16_t fnum
=0, fnum2
=0;
2342 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2347 smbcli_unlink(cli1
->tree
, fname
);
2349 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2352 base ntcreatex parms
2354 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2355 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2356 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2357 io
.ntcreatex
.in
.alloc_size
= 0;
2358 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2359 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2360 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2361 io
.ntcreatex
.in
.create_options
= 0;
2362 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2363 io
.ntcreatex
.in
.security_flags
= 0;
2364 io
.ntcreatex
.in
.fname
= fname
;
2366 torture_comment(tctx
, "BATCH14: open with batch oplock\n");
2367 ZERO_STRUCT(break_info
);
2369 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2370 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2371 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2372 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2373 NTCREATEX_SHARE_ACCESS_WRITE
|
2374 NTCREATEX_SHARE_ACCESS_DELETE
;
2375 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2376 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2377 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2378 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2380 ZERO_STRUCT(break_info
);
2382 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
2384 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2385 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2386 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2387 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2388 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2389 NTCREATEX_SHARE_ACCESS_WRITE
|
2390 NTCREATEX_SHARE_ACCESS_DELETE
;
2391 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
2392 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2393 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2394 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2395 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2397 torture_wait_for_oplock_break(tctx
);
2398 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2399 CHECK_VAL(break_info
.failures
, 0);
2401 smbcli_close(cli1
->tree
, fnum
);
2402 smbcli_close(cli2
->tree
, fnum2
);
2404 smb_raw_exit(cli1
->session
);
2405 smb_raw_exit(cli2
->session
);
2406 smbcli_deltree(cli1
->tree
, BASEDIR
);
2410 static bool test_raw_oplock_batch15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2412 const char *fname
= BASEDIR
"\\test_batch15.dat";
2416 union smb_fileinfo qfi
;
2419 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2424 smbcli_unlink(cli1
->tree
, fname
);
2426 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2429 base ntcreatex parms
2431 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2432 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2433 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2434 io
.ntcreatex
.in
.alloc_size
= 0;
2435 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2436 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2437 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2438 io
.ntcreatex
.in
.create_options
= 0;
2439 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2440 io
.ntcreatex
.in
.security_flags
= 0;
2441 io
.ntcreatex
.in
.fname
= fname
;
2443 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
2444 torture_comment(tctx
, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
2446 ZERO_STRUCT(break_info
);
2448 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2449 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2450 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2451 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2452 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2453 NTCREATEX_SHARE_ACCESS_WRITE
|
2454 NTCREATEX_SHARE_ACCESS_DELETE
;
2455 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2456 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2457 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2458 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2459 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2461 torture_wait_for_oplock_break(tctx
);
2462 CHECK_VAL(break_info
.count
, 0);
2463 CHECK_VAL(break_info
.failures
, 0);
2464 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2467 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2468 qfi
.generic
.in
.file
.path
= fname
;
2470 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
2471 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2473 torture_wait_for_oplock_break(tctx
);
2474 CHECK_VAL(break_info
.count
, 0);
2476 smbcli_close(cli1
->tree
, fnum
);
2479 smb_raw_exit(cli1
->session
);
2480 smb_raw_exit(cli2
->session
);
2481 smbcli_deltree(cli1
->tree
, BASEDIR
);
2485 static bool test_raw_oplock_batch16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2487 const char *fname
= BASEDIR
"\\test_batch16.dat";
2491 uint16_t fnum
=0, fnum2
=0;
2493 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2498 smbcli_unlink(cli1
->tree
, fname
);
2500 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2501 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2504 base ntcreatex parms
2506 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2507 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2508 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2509 io
.ntcreatex
.in
.alloc_size
= 0;
2510 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2511 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2512 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2513 io
.ntcreatex
.in
.create_options
= 0;
2514 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2515 io
.ntcreatex
.in
.security_flags
= 0;
2516 io
.ntcreatex
.in
.fname
= fname
;
2518 torture_comment(tctx
, "BATCH16: open with batch oplock\n");
2519 ZERO_STRUCT(break_info
);
2521 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2522 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2523 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2524 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2525 NTCREATEX_SHARE_ACCESS_WRITE
|
2526 NTCREATEX_SHARE_ACCESS_DELETE
;
2527 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2528 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2529 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2530 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2532 ZERO_STRUCT(break_info
);
2534 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2536 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2537 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2538 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2539 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2540 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2541 NTCREATEX_SHARE_ACCESS_WRITE
|
2542 NTCREATEX_SHARE_ACCESS_DELETE
;
2543 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
2544 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2545 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2546 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2547 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2549 torture_wait_for_oplock_break(tctx
);
2550 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2551 CHECK_VAL(break_info
.failures
, 0);
2553 smbcli_close(cli1
->tree
, fnum
);
2554 smbcli_close(cli2
->tree
, fnum2
);
2557 smb_raw_exit(cli1
->session
);
2558 smb_raw_exit(cli2
->session
);
2559 smbcli_deltree(cli1
->tree
, BASEDIR
);
2563 static bool test_raw_oplock_batch17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2565 const char *fname1
= BASEDIR
"\\test_batch17_1.dat";
2566 const char *fname2
= BASEDIR
"\\test_batch17_2.dat";
2570 union smb_rename rn
;
2573 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2578 smbcli_unlink(cli1
->tree
, fname1
);
2579 smbcli_unlink(cli1
->tree
, fname2
);
2581 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2584 base ntcreatex parms
2586 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2587 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2588 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2589 io
.ntcreatex
.in
.alloc_size
= 0;
2590 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2591 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2592 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2593 io
.ntcreatex
.in
.create_options
= 0;
2594 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2595 io
.ntcreatex
.in
.security_flags
= 0;
2596 io
.ntcreatex
.in
.fname
= fname1
;
2598 torture_comment(tctx
, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2600 ZERO_STRUCT(break_info
);
2601 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2602 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2603 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2605 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2606 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2607 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2608 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2610 torture_comment(tctx
, "rename should trigger a break\n");
2612 rn
.generic
.level
= RAW_RENAME_RENAME
;
2613 rn
.rename
.in
.pattern1
= fname1
;
2614 rn
.rename
.in
.pattern2
= fname2
;
2615 rn
.rename
.in
.attrib
= 0;
2617 torture_comment(tctx
, "trying rename while first file open\n");
2618 status
= smb_raw_rename(cli2
->tree
, &rn
);
2619 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2621 torture_wait_for_oplock_break(tctx
);
2622 CHECK_VAL(break_info
.count
, 1);
2623 CHECK_VAL(break_info
.failures
, 0);
2624 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2626 smbcli_close(cli1
->tree
, fnum
);
2629 smb_raw_exit(cli1
->session
);
2630 smb_raw_exit(cli2
->session
);
2631 smbcli_deltree(cli1
->tree
, BASEDIR
);
2635 static bool test_raw_oplock_batch18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2637 const char *fname1
= BASEDIR
"\\test_batch18_1.dat";
2638 const char *fname2
= BASEDIR
"\\test_batch18_2.dat";
2642 union smb_rename rn
;
2645 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2650 smbcli_unlink(cli1
->tree
, fname1
);
2651 smbcli_unlink(cli1
->tree
, fname2
);
2653 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2656 base ntcreatex parms
2658 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2659 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2660 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2661 io
.ntcreatex
.in
.alloc_size
= 0;
2662 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2663 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2664 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2665 io
.ntcreatex
.in
.create_options
= 0;
2666 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2667 io
.ntcreatex
.in
.security_flags
= 0;
2668 io
.ntcreatex
.in
.fname
= fname1
;
2670 torture_comment(tctx
, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2672 ZERO_STRUCT(break_info
);
2673 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2674 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2675 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2677 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2678 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2679 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2680 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2682 torture_comment(tctx
, "ntrename should trigger a break\n");
2684 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
2685 rn
.ntrename
.in
.attrib
= 0;
2686 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
2687 rn
.ntrename
.in
.old_name
= fname1
;
2688 rn
.ntrename
.in
.new_name
= fname2
;
2689 torture_comment(tctx
, "trying rename while first file open\n");
2690 status
= smb_raw_rename(cli2
->tree
, &rn
);
2691 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2693 torture_wait_for_oplock_break(tctx
);
2694 CHECK_VAL(break_info
.count
, 1);
2695 CHECK_VAL(break_info
.failures
, 0);
2696 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2698 smbcli_close(cli1
->tree
, fnum
);
2701 smb_raw_exit(cli1
->session
);
2702 smb_raw_exit(cli2
->session
);
2703 smbcli_deltree(cli1
->tree
, BASEDIR
);
2707 static bool test_raw_oplock_batch19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2709 const char *fname1
= BASEDIR
"\\test_batch19_1.dat";
2710 const char *fname2
= BASEDIR
"\\test_batch19_2.dat";
2711 const char *fname3
= BASEDIR
"\\test_batch19_3.dat";
2715 union smb_fileinfo qfi
;
2716 union smb_setfileinfo sfi
;
2719 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2724 smbcli_unlink(cli1
->tree
, fname1
);
2725 smbcli_unlink(cli1
->tree
, fname2
);
2726 smbcli_unlink(cli1
->tree
, fname3
);
2728 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2731 base ntcreatex parms
2733 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2734 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2735 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2736 io
.ntcreatex
.in
.alloc_size
= 0;
2737 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2738 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2739 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2740 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2741 io
.ntcreatex
.in
.create_options
= 0;
2742 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2743 io
.ntcreatex
.in
.security_flags
= 0;
2744 io
.ntcreatex
.in
.fname
= fname1
;
2746 torture_comment(tctx
, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2747 ZERO_STRUCT(break_info
);
2748 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2749 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2750 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2751 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2752 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2753 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2754 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2756 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
2759 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2760 sfi
.generic
.in
.file
.path
= fname1
;
2761 sfi
.rename_information
.in
.overwrite
= 0;
2762 sfi
.rename_information
.in
.root_fid
= 0;
2763 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2765 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2766 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2768 torture_wait_for_oplock_break(tctx
);
2770 CHECK_VAL(break_info
.failures
, 0);
2772 if (TARGET_IS_WINXP(tctx
) || TARGET_IS_W2K12(tctx
)) {
2773 /* Win XP breaks to level2. */
2774 CHECK_VAL(break_info
.count
, 1);
2775 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2776 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2777 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2778 /* Win2K3/2k8 incorrectly doesn't break at all. */
2779 CHECK_VAL(break_info
.count
, 0);
2781 /* win7/2k8r2 break to none. */
2782 CHECK_VAL(break_info
.count
, 1);
2783 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2787 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2788 qfi
.generic
.in
.file
.fnum
= fnum
;
2790 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2791 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2792 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2794 /* Close and re-open file with oplock. */
2795 smbcli_close(cli1
->tree
, fnum
);
2796 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2797 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2798 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2799 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2801 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
2802 "should not trigger a break nor a violation\n");
2803 ZERO_STRUCT(break_info
);
2805 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2806 sfi
.generic
.in
.file
.fnum
= fnum
;
2807 sfi
.rename_information
.in
.overwrite
= 0;
2808 sfi
.rename_information
.in
.root_fid
= 0;
2809 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2811 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2812 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2814 torture_wait_for_oplock_break(tctx
);
2815 if (TARGET_IS_WINXP(tctx
)) {
2816 /* XP incorrectly breaks to level2. */
2817 CHECK_VAL(break_info
.count
, 1);
2818 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2820 CHECK_VAL(break_info
.count
, 0);
2824 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2825 qfi
.generic
.in
.file
.fnum
= fnum
;
2827 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2828 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2829 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2832 smbcli_close(cli1
->tree
, fnum
);
2833 smb_raw_exit(cli1
->session
);
2834 smb_raw_exit(cli2
->session
);
2835 smbcli_deltree(cli1
->tree
, BASEDIR
);
2839 /****************************************************
2840 Called from raw-rename - we need oplock handling for
2841 this test so this is why it's in oplock.c, not rename.c
2842 ****************************************************/
2844 bool test_trans2rename(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2846 const char *fname1
= BASEDIR
"\\test_trans2rename_1.dat";
2847 const char *fname2
= BASEDIR
"\\test_trans2rename_2.dat";
2848 const char *fname3
= BASEDIR
"\\test_trans2rename_3.dat";
2852 union smb_fileinfo qfi
;
2853 union smb_setfileinfo sfi
;
2856 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2861 smbcli_unlink(cli1
->tree
, fname1
);
2862 smbcli_unlink(cli1
->tree
, fname2
);
2863 smbcli_unlink(cli1
->tree
, fname3
);
2865 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2868 base ntcreatex parms
2870 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2871 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2872 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2873 io
.ntcreatex
.in
.alloc_size
= 0;
2874 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2875 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2876 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2877 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2878 io
.ntcreatex
.in
.create_options
= 0;
2879 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2880 io
.ntcreatex
.in
.security_flags
= 0;
2881 io
.ntcreatex
.in
.fname
= fname1
;
2883 torture_comment(tctx
, "open a file with an exclusive oplock (share mode: none)\n");
2884 ZERO_STRUCT(break_info
);
2885 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2886 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2887 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2888 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2889 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2890 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2892 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2894 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2895 sfi
.generic
.in
.file
.path
= fname1
;
2896 sfi
.rename_information
.in
.overwrite
= 0;
2897 sfi
.rename_information
.in
.root_fid
= 0;
2898 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2900 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2902 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2904 torture_wait_for_oplock_break(tctx
);
2905 CHECK_VAL(break_info
.count
, 0);
2908 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2909 qfi
.generic
.in
.file
.fnum
= fnum
;
2911 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2912 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2913 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2915 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2917 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2918 sfi
.generic
.in
.file
.fnum
= fnum
;
2919 sfi
.rename_information
.in
.overwrite
= 0;
2920 sfi
.rename_information
.in
.root_fid
= 0;
2921 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2923 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2924 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2926 torture_wait_for_oplock_break(tctx
);
2927 CHECK_VAL(break_info
.count
, 0);
2930 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2931 qfi
.generic
.in
.file
.fnum
= fnum
;
2933 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2934 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2935 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2938 smbcli_close(cli1
->tree
, fnum
);
2939 smb_raw_exit(cli1
->session
);
2940 smb_raw_exit(cli2
->session
);
2941 smbcli_deltree(cli1
->tree
, BASEDIR
);
2945 /****************************************************
2946 Called from raw-rename - we need oplock handling for
2947 this test so this is why it's in oplock.c, not rename.c
2948 ****************************************************/
2950 bool test_nttransrename(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
2952 const char *fname1
= BASEDIR
"\\test_nttransrename_1.dat";
2953 const char *fname2
= BASEDIR
"\\test_nttransrename_2.dat";
2957 union smb_fileinfo qfi
, qpi
;
2958 union smb_rename rn
;
2961 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2966 smbcli_unlink(cli1
->tree
, fname1
);
2967 smbcli_unlink(cli1
->tree
, fname2
);
2969 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2972 base ntcreatex parms
2974 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2975 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2976 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2977 io
.ntcreatex
.in
.alloc_size
= 0;
2978 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2979 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2980 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2981 io
.ntcreatex
.in
.create_options
= 0;
2982 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2983 io
.ntcreatex
.in
.security_flags
= 0;
2984 io
.ntcreatex
.in
.fname
= fname1
;
2986 torture_comment(tctx
, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2987 ZERO_STRUCT(break_info
);
2988 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2989 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2990 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2991 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2992 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2993 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2995 torture_comment(tctx
, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2997 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2998 rn
.nttrans
.in
.file
.fnum
= fnum
;
2999 rn
.nttrans
.in
.flags
= 0;
3000 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
3002 status
= smb_raw_rename(cli1
->tree
, &rn
);
3003 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3005 torture_wait_for_oplock_break(tctx
);
3006 CHECK_VAL(break_info
.count
, 0);
3008 /* w2k3 does nothing, it doesn't rename the file */
3009 torture_comment(tctx
, "nttrans_rename: the server should have done nothing\n");
3011 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3012 qfi
.generic
.in
.file
.fnum
= fnum
;
3014 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
3015 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3016 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname1
);
3019 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3020 qpi
.generic
.in
.file
.path
= fname1
;
3022 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3023 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3024 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
3027 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3028 qpi
.generic
.in
.file
.path
= fname2
;
3030 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3031 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
3033 torture_comment(tctx
, "nttrans_rename: after closing the file the file is still not renamed\n");
3034 status
= smbcli_close(cli1
->tree
, fnum
);
3035 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3038 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3039 qpi
.generic
.in
.file
.path
= fname1
;
3041 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3042 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3043 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
3046 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3047 qpi
.generic
.in
.file
.path
= fname2
;
3049 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
3050 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
3052 torture_comment(tctx
, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
3054 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
3055 rn
.nttrans
.in
.file
.fnum
= fnum
+1;
3056 rn
.nttrans
.in
.flags
= 0;
3057 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
3059 status
= smb_raw_rename(cli1
->tree
, &rn
);
3061 CHECK_STATUS(tctx
, status
, NT_STATUS_INVALID_HANDLE
);
3064 smb_raw_exit(cli1
->session
);
3065 smbcli_deltree(cli1
->tree
, BASEDIR
);
3070 static bool test_raw_oplock_batch20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3072 const char *fname1
= BASEDIR
"\\test_batch20_1.dat";
3073 const char *fname2
= BASEDIR
"\\test_batch20_2.dat";
3074 const char *fname3
= BASEDIR
"\\test_batch20_3.dat";
3078 union smb_fileinfo qfi
;
3079 union smb_setfileinfo sfi
;
3080 uint16_t fnum
=0,fnum2
=0;
3082 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3087 smbcli_unlink(cli1
->tree
, fname1
);
3088 smbcli_unlink(cli1
->tree
, fname2
);
3089 smbcli_unlink(cli1
->tree
, fname3
);
3091 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3094 base ntcreatex parms
3096 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3097 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3098 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3099 io
.ntcreatex
.in
.alloc_size
= 0;
3100 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3101 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3102 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3103 io
.ntcreatex
.in
.create_options
= 0;
3104 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3105 io
.ntcreatex
.in
.security_flags
= 0;
3106 io
.ntcreatex
.in
.fname
= fname1
;
3108 torture_comment(tctx
, "BATCH20: open a file with an batch oplock (share mode: all)\n");
3109 ZERO_STRUCT(break_info
);
3110 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3111 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3112 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3113 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3114 NTCREATEX_SHARE_ACCESS_WRITE
|
3115 NTCREATEX_SHARE_ACCESS_DELETE
;
3116 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3117 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3118 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3119 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3122 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
3123 sfi
.generic
.in
.file
.path
= fname1
;
3124 sfi
.rename_information
.in
.overwrite
= 0;
3125 sfi
.rename_information
.in
.root_fid
= 0;
3126 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
3128 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
3129 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3131 torture_wait_for_oplock_break(tctx
);
3132 CHECK_VAL(break_info
.failures
, 0);
3134 if (TARGET_IS_WINXP(tctx
) || TARGET_IS_W2K12(tctx
)) {
3135 /* Win XP breaks to level2. */
3136 CHECK_VAL(break_info
.count
, 1);
3137 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3138 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
3139 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
3140 /* Win2K3/2k8 incorrectly doesn't break at all. */
3141 CHECK_VAL(break_info
.count
, 0);
3143 /* win7/2k8r2 break to none. */
3144 CHECK_VAL(break_info
.count
, 1);
3145 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3149 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3150 qfi
.generic
.in
.file
.fnum
= fnum
;
3152 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
3153 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3154 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
3156 torture_comment(tctx
, "open a file with the new name an batch oplock (share mode: all)\n");
3157 ZERO_STRUCT(break_info
);
3158 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3159 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3160 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3161 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3162 NTCREATEX_SHARE_ACCESS_WRITE
|
3163 NTCREATEX_SHARE_ACCESS_DELETE
;
3164 io
.ntcreatex
.in
.fname
= fname2
;
3165 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3166 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3167 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3168 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3170 torture_wait_for_oplock_break(tctx
);
3172 if (TARGET_IS_WINXP(tctx
)) {
3173 /* XP broke to level2, and doesn't break again. */
3174 CHECK_VAL(break_info
.count
, 0);
3175 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
3176 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
3177 /* Win2K3 incorrectly didn't break before so break now. */
3178 CHECK_VAL(break_info
.count
, 1);
3179 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3181 /* win7/2k8r2 broke to none, and doesn't break again. */
3182 CHECK_VAL(break_info
.count
, 0);
3185 ZERO_STRUCT(break_info
);
3188 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
3189 sfi
.generic
.in
.file
.fnum
= fnum
;
3190 sfi
.rename_information
.in
.overwrite
= 0;
3191 sfi
.rename_information
.in
.root_fid
= 0;
3192 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
3194 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
3195 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3197 torture_wait_for_oplock_break(tctx
);
3198 CHECK_VAL(break_info
.count
, 0);
3201 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3202 qfi
.generic
.in
.file
.fnum
= fnum
;
3204 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
3205 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3206 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
3209 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
3210 qfi
.generic
.in
.file
.fnum
= fnum2
;
3212 status
= smb_raw_fileinfo(cli2
->tree
, tctx
, &qfi
);
3213 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3214 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
3218 smbcli_close(cli1
->tree
, fnum
);
3219 smbcli_close(cli2
->tree
, fnum2
);
3220 smb_raw_exit(cli1
->session
);
3221 smb_raw_exit(cli2
->session
);
3222 smbcli_deltree(cli1
->tree
, BASEDIR
);
3226 static bool test_raw_oplock_batch21(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3228 const char *fname
= BASEDIR
"\\test_batch21.dat";
3237 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3242 smbcli_unlink(cli1
->tree
, fname
);
3244 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3247 base ntcreatex parms
3249 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3250 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3251 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3252 io
.ntcreatex
.in
.alloc_size
= 0;
3253 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3254 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3255 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3256 io
.ntcreatex
.in
.create_options
= 0;
3257 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3258 io
.ntcreatex
.in
.security_flags
= 0;
3259 io
.ntcreatex
.in
.fname
= fname
;
3262 with a batch oplock we get a break
3264 torture_comment(tctx
, "BATCH21: open with batch oplock\n");
3265 ZERO_STRUCT(break_info
);
3266 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3267 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3268 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3269 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3270 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3271 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3272 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3274 torture_comment(tctx
, "writing should not generate a break\n");
3275 wr
= smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
3277 CHECK_STATUS(tctx
, smbcli_nt_error(cli1
->tree
), NT_STATUS_OK
);
3280 e
.in
.repeat_count
= 1;
3281 status
= smb_raw_echo(cli1
->transport
, &e
);
3282 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3284 torture_wait_for_oplock_break(tctx
);
3285 CHECK_VAL(break_info
.count
, 0);
3287 smbcli_close(cli1
->tree
, fnum
);
3290 smb_raw_exit(cli1
->session
);
3291 smb_raw_exit(cli2
->session
);
3292 smbcli_deltree(cli1
->tree
, BASEDIR
);
3296 static bool test_raw_oplock_batch22(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3298 const char *fname
= BASEDIR
"\\test_batch22.dat";
3302 uint16_t fnum
= 0, fnum2
= 0, fnum3
= 0;
3304 int timeout
= torture_setting_int(tctx
, "oplocktimeout", 30);
3307 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3312 smbcli_unlink(cli1
->tree
, fname
);
3314 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3316 base ntcreatex parms
3318 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3319 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3320 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3321 io
.ntcreatex
.in
.alloc_size
= 0;
3322 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3323 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3324 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3325 io
.ntcreatex
.in
.create_options
= 0;
3326 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3327 io
.ntcreatex
.in
.security_flags
= 0;
3328 io
.ntcreatex
.in
.fname
= fname
;
3331 with a batch oplock we get a break
3333 torture_comment(tctx
, "BATCH22: open with batch oplock\n");
3334 ZERO_STRUCT(break_info
);
3335 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3336 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3337 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3338 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3339 NTCREATEX_SHARE_ACCESS_WRITE
|
3340 NTCREATEX_SHARE_ACCESS_DELETE
;
3341 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3342 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3343 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3344 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3346 torture_comment(tctx
, "a 2nd open should not succeed after the oplock "
3348 tv
= timeval_current();
3349 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
, cli1
->tree
);
3350 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3352 if (TARGET_IS_W2K3(tctx
)) {
3353 /* 2k3 has an issue here. xp/win7 are ok. */
3354 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3356 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3359 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3361 torture_wait_for_oplock_break(tctx
);
3362 te
= (int)timeval_elapsed(&tv
);
3365 * Some servers detect clients that let oplocks timeout, so this check
3366 * only shows a warning message instead failing the test to eliminate
3367 * failures from repeated runs of the test. This isn't ideal, but
3368 * it's better than not running the test at all.
3370 CHECK_RANGE(te
, timeout
- 1, timeout
+ 15);
3372 CHECK_VAL(break_info
.count
, 1);
3373 CHECK_VAL(break_info
.fnum
, fnum
);
3374 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3375 CHECK_VAL(break_info
.failures
, 0);
3376 ZERO_STRUCT(break_info
);
3378 torture_comment(tctx
, "a 2nd open should succeed after the oplock "
3379 "release without break\n");
3380 tv
= timeval_current();
3381 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3382 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3383 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3385 /* Samba 3.6.0 and above behave as Windows. */
3386 if (TARGET_IS_SAMBA3(tctx
)) {
3387 /* samba3 doesn't grant additional oplocks to bad clients. */
3388 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3390 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3391 LEVEL_II_OPLOCK_RETURN
);
3394 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3395 LEVEL_II_OPLOCK_RETURN
);
3397 torture_wait_for_oplock_break(tctx
);
3398 te
= (int)timeval_elapsed(&tv
);
3399 /* it should come in without delay */
3400 CHECK_RANGE(te
+1, 0, timeout
);
3401 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3403 CHECK_VAL(break_info
.count
, 0);
3405 smbcli_close(cli1
->tree
, fnum
);
3406 smbcli_close(cli1
->tree
, fnum2
);
3407 smbcli_close(cli1
->tree
, fnum3
);
3410 smb_raw_exit(cli1
->session
);
3411 smb_raw_exit(cli2
->session
);
3412 smbcli_deltree(cli1
->tree
, BASEDIR
);
3416 static bool test_raw_oplock_batch23(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3418 const char *fname
= BASEDIR
"\\test_batch23.dat";
3422 uint16_t fnum
=0, fnum2
=0,fnum3
=0;
3423 struct smbcli_state
*cli3
= NULL
;
3425 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3430 smbcli_unlink(cli1
->tree
, fname
);
3432 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3433 CHECK_VAL(ret
, true);
3435 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3436 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3437 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3440 base ntcreatex parms
3442 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3443 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3444 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3445 io
.ntcreatex
.in
.alloc_size
= 0;
3446 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3447 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3448 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3449 io
.ntcreatex
.in
.create_options
= 0;
3450 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3451 io
.ntcreatex
.in
.security_flags
= 0;
3452 io
.ntcreatex
.in
.fname
= fname
;
3454 torture_comment(tctx
, "BATCH23: a open and ask for a batch oplock\n");
3455 ZERO_STRUCT(break_info
);
3457 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3458 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3459 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3460 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3461 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3462 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3463 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3464 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3465 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3467 ZERO_STRUCT(break_info
);
3469 torture_comment(tctx
, "a 2nd open without level2 oplock support should generate a break to level2\n");
3470 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3471 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3472 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3473 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3475 torture_wait_for_oplock_break(tctx
);
3476 CHECK_VAL(break_info
.count
, 1);
3477 CHECK_VAL(break_info
.fnum
, fnum
);
3478 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3479 CHECK_VAL(break_info
.failures
, 0);
3481 ZERO_STRUCT(break_info
);
3483 torture_comment(tctx
, "a 3rd open with level2 oplock support should not generate a break\n");
3484 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3485 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3486 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3487 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3489 torture_wait_for_oplock_break(tctx
);
3490 CHECK_VAL(break_info
.count
, 0);
3492 smbcli_close(cli1
->tree
, fnum
);
3493 smbcli_close(cli2
->tree
, fnum2
);
3494 smbcli_close(cli3
->tree
, fnum3
);
3497 smb_raw_exit(cli1
->session
);
3498 smb_raw_exit(cli2
->session
);
3499 smb_raw_exit(cli3
->session
);
3500 smbcli_deltree(cli1
->tree
, BASEDIR
);
3504 static bool test_raw_oplock_batch24(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3506 const char *fname
= BASEDIR
"\\test_batch24.dat";
3510 uint16_t fnum2
=0,fnum3
=0;
3511 struct smbcli_state
*cli3
= NULL
;
3513 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3518 smbcli_unlink(cli1
->tree
, fname
);
3520 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3521 CHECK_VAL(ret
, true);
3523 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3524 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3525 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3528 base ntcreatex parms
3530 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3531 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3532 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3533 io
.ntcreatex
.in
.alloc_size
= 0;
3534 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3535 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3536 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3537 io
.ntcreatex
.in
.create_options
= 0;
3538 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3539 io
.ntcreatex
.in
.security_flags
= 0;
3540 io
.ntcreatex
.in
.fname
= fname
;
3542 torture_comment(tctx
, "BATCH24: a open without level support and ask for a batch oplock\n");
3543 ZERO_STRUCT(break_info
);
3545 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3546 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3547 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3548 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3549 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3550 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3551 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3552 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3553 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3555 ZERO_STRUCT(break_info
);
3557 torture_comment(tctx
, "a 2nd open with level2 oplock support should generate a break to none\n");
3558 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3559 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3560 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3561 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3563 torture_wait_for_oplock_break(tctx
);
3564 CHECK_VAL(break_info
.count
, 1);
3565 CHECK_VAL(break_info
.fnum
, fnum3
);
3566 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3567 CHECK_VAL(break_info
.failures
, 0);
3569 smbcli_close(cli3
->tree
, fnum3
);
3570 smbcli_close(cli2
->tree
, fnum2
);
3573 smb_raw_exit(cli1
->session
);
3574 smb_raw_exit(cli2
->session
);
3575 smb_raw_exit(cli3
->session
);
3576 smbcli_deltree(cli1
->tree
, BASEDIR
);
3580 static bool test_raw_oplock_batch25(struct torture_context
*tctx
,
3581 struct smbcli_state
*cli1
,
3582 struct smbcli_state
*cli2
)
3584 const char *fname
= BASEDIR
"\\test_batch25.dat";
3588 union smb_setfileinfo sfi
;
3591 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3596 smbcli_unlink(cli1
->tree
, fname
);
3598 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3601 base ntcreatex parms
3603 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3604 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3605 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3606 io
.ntcreatex
.in
.alloc_size
= 0;
3607 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3608 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3609 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3610 io
.ntcreatex
.in
.create_options
= 0;
3611 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3612 io
.ntcreatex
.in
.security_flags
= 0;
3613 io
.ntcreatex
.in
.fname
= fname
;
3615 torture_comment(tctx
, "BATCH25: open a file with an batch oplock "
3616 "(share mode: none)\n");
3618 ZERO_STRUCT(break_info
);
3619 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3620 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3621 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3622 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3623 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3624 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3625 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3627 torture_comment(tctx
, "setpathinfo attribute info should not trigger "
3628 "a break nor a violation\n");
3630 sfi
.generic
.level
= RAW_SFILEINFO_SETATTR
;
3631 sfi
.generic
.in
.file
.path
= fname
;
3632 sfi
.setattr
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
3633 sfi
.setattr
.in
.write_time
= 0;
3635 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
3636 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3638 torture_wait_for_oplock_break(tctx
);
3639 CHECK_VAL(break_info
.count
, 0);
3641 smbcli_close(cli1
->tree
, fnum
);
3644 smb_raw_exit(cli1
->session
);
3645 smb_raw_exit(cli2
->session
);
3646 smbcli_deltree(cli1
->tree
, BASEDIR
);
3651 * Similar to batch17/18, but test with open share mode rather than
3654 static bool test_raw_oplock_batch26(struct torture_context
*tctx
,
3655 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3657 const char *fname1
= BASEDIR
"\\test_batch26_1.dat";
3658 const char *fname2
= BASEDIR
"\\test_batch26_2.dat";
3662 union smb_rename rn
;
3665 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3670 smbcli_unlink(cli1
->tree
, fname1
);
3671 smbcli_unlink(cli1
->tree
, fname2
);
3673 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3677 base ntcreatex parms
3679 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3680 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3681 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3682 io
.ntcreatex
.in
.alloc_size
= 0;
3683 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3684 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3685 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
3686 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3687 io
.ntcreatex
.in
.create_options
= 0;
3688 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3689 io
.ntcreatex
.in
.security_flags
= 0;
3690 io
.ntcreatex
.in
.fname
= fname1
;
3692 torture_comment(tctx
,
3693 "BATCH26: open a file with an batch oplock "
3694 "(share mode: all)\n");
3696 ZERO_STRUCT(break_info
);
3697 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3698 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3699 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3702 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3703 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3704 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3705 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3707 torture_comment(tctx
, "rename should trigger a break\n");
3709 rn
.generic
.level
= RAW_RENAME_RENAME
;
3710 rn
.rename
.in
.pattern1
= fname1
;
3711 rn
.rename
.in
.pattern2
= fname2
;
3712 rn
.rename
.in
.attrib
= 0;
3714 torture_comment(tctx
, "trying rename while first file open\n");
3715 status
= smb_raw_rename(cli2
->tree
, &rn
);
3716 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3718 torture_wait_for_oplock_break(tctx
);
3719 CHECK_VAL(break_info
.count
, 1);
3720 CHECK_VAL(break_info
.failures
, 0);
3721 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3723 /* Close and reopen with batch again. */
3724 smbcli_close(cli1
->tree
, fnum
);
3725 ZERO_STRUCT(break_info
);
3727 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3728 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3729 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3730 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3732 /* Now try ntrename. */
3733 torture_comment(tctx
, "ntrename should trigger a break\n");
3735 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
3736 rn
.ntrename
.in
.attrib
= 0;
3737 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
3738 rn
.ntrename
.in
.old_name
= fname1
;
3739 rn
.ntrename
.in
.new_name
= fname2
;
3740 torture_comment(tctx
, "trying rename while first file open\n");
3741 status
= smb_raw_rename(cli2
->tree
, &rn
);
3742 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3744 torture_wait_for_oplock_break(tctx
);
3745 CHECK_VAL(break_info
.count
, 1);
3746 CHECK_VAL(break_info
.failures
, 0);
3747 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3749 smbcli_close(cli1
->tree
, fnum
);
3752 smb_raw_exit(cli1
->session
);
3753 smb_raw_exit(cli2
->session
);
3754 smbcli_deltree(cli1
->tree
, BASEDIR
);
3758 /* Test how oplocks work on streams. */
3759 static bool test_raw_oplock_stream1(struct torture_context
*tctx
,
3760 struct smbcli_state
*cli1
,
3761 struct smbcli_state
*cli2
)
3765 const char *fname_base
= BASEDIR
"\\test_stream1.txt";
3766 const char *stream
= "Stream One:$DATA";
3767 const char *fname_stream
, *fname_default_stream
;
3768 const char *default_stream
= "::$DATA";
3772 int stream_fnum
= -1;
3773 uint32_t batch_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3774 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
| NTCREATEX_FLAGS_EXTENDED
;
3775 uint32_t exclusive_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3776 NTCREATEX_FLAGS_EXTENDED
;
3778 #define NSTREAM_OPLOCK_RESULTS 8
3781 bool open_base_file
;
3782 uint32_t oplock_req
;
3783 uint32_t oplock_granted
;
3784 } stream_oplock_results
[NSTREAM_OPLOCK_RESULTS
] = {
3785 /* Request oplock on stream without the base file open. */
3786 {&fname_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3787 {&fname_default_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3788 {&fname_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3789 {&fname_default_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3791 /* Request oplock on stream with the base file open. */
3792 {&fname_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3793 {&fname_default_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3794 {&fname_stream
, true, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3795 {&fname_default_stream
, true, exclusive_req
, LEVEL_II_OPLOCK_RETURN
},
3800 /* Only passes against windows at the moment. */
3801 if (torture_setting_bool(tctx
, "samba3", false) ||
3802 torture_setting_bool(tctx
, "samba4", false)) {
3803 torture_skip(tctx
, "STREAM1 disabled against samba3+4\n");
3806 fname_stream
= talloc_asprintf(tctx
, "%s:%s", fname_base
, stream
);
3807 fname_default_stream
= talloc_asprintf(tctx
, "%s%s", fname_base
,
3810 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3813 smbcli_unlink(cli1
->tree
, fname_base
);
3815 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3816 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3818 /* Setup generic open parameters. */
3819 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3820 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3821 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
3822 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
3823 io
.ntcreatex
.in
.create_options
= 0;
3824 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3825 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3826 NTCREATEX_SHARE_ACCESS_WRITE
;
3827 io
.ntcreatex
.in
.alloc_size
= 0;
3828 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3829 io
.ntcreatex
.in
.security_flags
= 0;
3831 /* Create the file with a stream */
3832 io
.ntcreatex
.in
.fname
= fname_stream
;
3833 io
.ntcreatex
.in
.flags
= 0;
3834 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
3835 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3836 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3837 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3839 /* Change the disposition to open now that the file has been created. */
3840 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3842 /* Try some permutations of taking oplocks on streams. */
3843 for (i
= 0; i
< NSTREAM_OPLOCK_RESULTS
; i
++) {
3844 const char *fname
= *stream_oplock_results
[i
].fname
;
3845 bool open_base_file
= stream_oplock_results
[i
].open_base_file
;
3846 uint32_t oplock_req
= stream_oplock_results
[i
].oplock_req
;
3847 uint32_t oplock_granted
=
3848 stream_oplock_results
[i
].oplock_granted
;
3851 if (open_base_file
) {
3852 torture_comment(tctx
, "Opening base file: %s with "
3853 "%d\n", fname_base
, batch_req
);
3854 io
.ntcreatex
.in
.fname
= fname_base
;
3855 io
.ntcreatex
.in
.flags
= batch_req
;
3856 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3857 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3858 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3859 BATCH_OPLOCK_RETURN
);
3860 base_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3863 torture_comment(tctx
, "%d: Opening stream: %s with %d\n", i
,
3865 io
.ntcreatex
.in
.fname
= fname
;
3866 io
.ntcreatex
.in
.flags
= oplock_req
;
3868 /* Do the open with the desired oplock on the stream. */
3869 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3870 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3871 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, oplock_granted
);
3872 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3874 /* Cleanup the base file if it was opened. */
3875 if (base_fnum
!= -1) {
3876 smbcli_close(cli2
->tree
, base_fnum
);
3880 /* Open the stream with an exclusive oplock. */
3881 torture_comment(tctx
, "Opening stream: %s with %d\n",
3882 fname_stream
, exclusive_req
);
3883 io
.ntcreatex
.in
.fname
= fname_stream
;
3884 io
.ntcreatex
.in
.flags
= exclusive_req
;
3885 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3886 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3887 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3888 stream_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3890 /* Open the base file and see if it contends. */
3891 ZERO_STRUCT(break_info
);
3892 torture_comment(tctx
, "Opening base file: %s with "
3893 "%d\n", fname_base
, batch_req
);
3894 io
.ntcreatex
.in
.fname
= fname_base
;
3895 io
.ntcreatex
.in
.flags
= batch_req
;
3896 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3897 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3898 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3899 BATCH_OPLOCK_RETURN
);
3900 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3902 torture_wait_for_oplock_break(tctx
);
3903 CHECK_VAL(break_info
.count
, 0);
3904 CHECK_VAL(break_info
.failures
, 0);
3906 /* Open the stream again to see if it contends. */
3907 ZERO_STRUCT(break_info
);
3908 torture_comment(tctx
, "Opening stream again: %s with "
3909 "%d\n", fname_base
, batch_req
);
3910 io
.ntcreatex
.in
.fname
= fname_stream
;
3911 io
.ntcreatex
.in
.flags
= exclusive_req
;
3912 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3913 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3914 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3915 LEVEL_II_OPLOCK_RETURN
);
3916 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3918 torture_wait_for_oplock_break(tctx
);
3919 CHECK_VAL(break_info
.count
, 1);
3920 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3921 CHECK_VAL(break_info
.failures
, 0);
3923 /* Close the stream. */
3924 if (stream_fnum
!= -1) {
3925 smbcli_close(cli1
->tree
, stream_fnum
);
3929 smbcli_close(cli1
->tree
, fnum
);
3930 smb_raw_exit(cli1
->session
);
3931 smb_raw_exit(cli2
->session
);
3932 smbcli_deltree(cli1
->tree
, BASEDIR
);
3936 static bool test_raw_oplock_doc(struct torture_context
*tctx
,
3937 struct smbcli_state
*cli
,
3938 struct smbcli_state
*cli2
)
3940 const char *fname
= BASEDIR
"\\test_oplock_doc.dat";
3946 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
3949 smbcli_unlink(cli
->tree
, fname
);
3951 smbcli_oplock_handler(cli
->transport
, oplock_handler_ack_to_given
,
3955 base ntcreatex parms
3957 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3958 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3959 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3960 io
.ntcreatex
.in
.alloc_size
= 0;
3961 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3962 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3963 NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
;
3964 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3965 io
.ntcreatex
.in
.create_options
= 0;
3966 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3967 io
.ntcreatex
.in
.security_flags
= 0;
3968 io
.ntcreatex
.in
.fname
= fname
;
3970 torture_comment(tctx
, "open a file with a batch oplock\n");
3971 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3972 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3973 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3975 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
3976 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3977 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3978 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3980 torture_comment(tctx
, "Set delete-on-close\n");
3981 status
= smbcli_nt_delete_on_close(cli
->tree
, fnum
, true);
3982 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3984 torture_comment(tctx
, "2nd open should not break and get "
3985 "DELETE_PENDING\n");
3986 ZERO_STRUCT(break_info
);
3987 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3988 io
.ntcreatex
.in
.create_options
= 0;
3989 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
3990 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3991 CHECK_STATUS(tctx
, status
, NT_STATUS_DELETE_PENDING
);
3992 CHECK_VAL(break_info
.count
, 0);
3994 smbcli_close(cli
->tree
, fnum
);
3997 smb_raw_exit(cli
->session
);
3998 smbcli_deltree(cli
->tree
, BASEDIR
);
4002 /* Open a file with a batch oplock, then open it again from a second client
4003 * requesting no oplock. Having two open file handles should break our own
4004 * oplock during BRL acquisition.
4006 static bool test_raw_oplock_brl1(struct torture_context
*tctx
,
4007 struct smbcli_state
*cli1
,
4008 struct smbcli_state
*cli2
)
4010 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4019 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4024 smbcli_unlink(cli1
->tree
, fname
);
4026 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4030 base ntcreatex parms
4032 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4033 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4034 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4035 SEC_RIGHTS_FILE_WRITE
;
4036 io
.ntcreatex
.in
.alloc_size
= 0;
4037 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4038 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4039 NTCREATEX_SHARE_ACCESS_WRITE
;
4040 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4041 io
.ntcreatex
.in
.create_options
= 0;
4042 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4043 io
.ntcreatex
.in
.security_flags
= 0;
4044 io
.ntcreatex
.in
.fname
= fname
;
4047 with a batch oplock we get a break
4049 torture_comment(tctx
, "open with batch oplock\n");
4050 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4051 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4052 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4054 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4055 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4056 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4057 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
4058 /* create a file with bogus data */
4059 memset(buf
, 0, sizeof(buf
));
4061 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4064 torture_comment(tctx
, "Failed to create file\n");
4068 torture_comment(tctx
, "a 2nd open should give a break\n");
4069 ZERO_STRUCT(break_info
);
4071 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
4072 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
4073 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
4074 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4075 CHECK_VAL(break_info
.count
, 1);
4076 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
4077 CHECK_VAL(break_info
.failures
, 0);
4078 CHECK_VAL(break_info
.fnum
, fnum
);
4080 ZERO_STRUCT(break_info
);
4082 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
4084 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
4085 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4087 torture_wait_for_oplock_break(tctx
);
4088 CHECK_VAL(break_info
.count
, 1);
4089 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
4090 CHECK_VAL(break_info
.fnum
, fnum
);
4091 CHECK_VAL(break_info
.failures
, 0);
4093 /* expect no oplock break */
4094 ZERO_STRUCT(break_info
);
4095 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
4096 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
4098 torture_wait_for_oplock_break(tctx
);
4099 CHECK_VAL(break_info
.count
, 0);
4100 CHECK_VAL(break_info
.level
, 0);
4101 CHECK_VAL(break_info
.fnum
, 0);
4102 CHECK_VAL(break_info
.failures
, 0);
4104 smbcli_close(cli1
->tree
, fnum
);
4105 smbcli_close(cli2
->tree
, fnum2
);
4108 smb_raw_exit(cli1
->session
);
4109 smb_raw_exit(cli2
->session
);
4110 smbcli_deltree(cli1
->tree
, BASEDIR
);
4115 /* Open a file with a batch oplock on one client and then acquire a brl.
4116 * We should not contend our own oplock.
4118 static bool test_raw_oplock_brl2(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
4120 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4128 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4133 smbcli_unlink(cli1
->tree
, fname
);
4135 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4139 base ntcreatex parms
4141 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4142 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4143 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4144 SEC_RIGHTS_FILE_WRITE
;
4145 io
.ntcreatex
.in
.alloc_size
= 0;
4146 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4147 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4148 NTCREATEX_SHARE_ACCESS_WRITE
;
4149 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4150 io
.ntcreatex
.in
.create_options
= 0;
4151 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4152 io
.ntcreatex
.in
.security_flags
= 0;
4153 io
.ntcreatex
.in
.fname
= fname
;
4156 with a batch oplock we get a break
4158 torture_comment(tctx
, "open with batch oplock\n");
4159 ZERO_STRUCT(break_info
);
4160 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4161 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4162 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4164 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4165 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4166 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4167 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
4169 /* create a file with bogus data */
4170 memset(buf
, 0, sizeof(buf
));
4172 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4175 torture_comment(tctx
, "Failed to create file\n");
4179 torture_comment(tctx
, "a self BRL acquisition should not break to "
4182 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
4183 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4185 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
4186 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
4188 /* With one file handle open a BRL should not contend our oplock.
4189 * Thus, no oplock break will be received and the entire break_info
4190 * struct will be 0 */
4191 torture_wait_for_oplock_break(tctx
);
4192 CHECK_VAL(break_info
.fnum
, 0);
4193 CHECK_VAL(break_info
.count
, 0);
4194 CHECK_VAL(break_info
.level
, 0);
4195 CHECK_VAL(break_info
.failures
, 0);
4197 smbcli_close(cli1
->tree
, fnum
);
4200 smb_raw_exit(cli1
->session
);
4201 smbcli_deltree(cli1
->tree
, BASEDIR
);
4205 /* Open a file with a batch oplock twice from one client and then acquire a
4206 * brl. BRL acquisition should break our own oplock.
4208 static bool test_raw_oplock_brl3(struct torture_context
*tctx
,
4209 struct smbcli_state
*cli1
)
4211 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4219 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4224 smbcli_unlink(cli1
->tree
, fname
);
4226 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4230 base ntcreatex parms
4232 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4233 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4234 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4235 SEC_RIGHTS_FILE_WRITE
;
4236 io
.ntcreatex
.in
.alloc_size
= 0;
4237 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4238 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4239 NTCREATEX_SHARE_ACCESS_WRITE
;
4240 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4241 io
.ntcreatex
.in
.create_options
= 0;
4242 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4243 io
.ntcreatex
.in
.security_flags
= 0;
4244 io
.ntcreatex
.in
.fname
= fname
;
4247 with a batch oplock we get a break
4249 torture_comment(tctx
, "open with batch oplock\n");
4250 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4251 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4252 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4254 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4255 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4256 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4257 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
4259 /* create a file with bogus data */
4260 memset(buf
, 0, sizeof(buf
));
4262 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4265 torture_comment(tctx
, "Failed to create file\n");
4270 torture_comment(tctx
, "a 2nd open should give a break\n");
4271 ZERO_STRUCT(break_info
);
4273 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
4274 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4275 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
4276 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4277 CHECK_VAL(break_info
.count
, 1);
4278 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
4279 CHECK_VAL(break_info
.failures
, 0);
4280 CHECK_VAL(break_info
.fnum
, fnum
);
4282 ZERO_STRUCT(break_info
);
4284 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
4286 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
4287 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4289 torture_wait_for_oplock_break(tctx
);
4290 CHECK_VAL(break_info
.count
, 1);
4291 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
4292 CHECK_VAL(break_info
.fnum
, fnum
);
4293 CHECK_VAL(break_info
.failures
, 0);
4295 /* expect no oplock break */
4296 ZERO_STRUCT(break_info
);
4297 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
4298 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
4300 torture_wait_for_oplock_break(tctx
);
4301 CHECK_VAL(break_info
.count
, 0);
4302 CHECK_VAL(break_info
.level
, 0);
4303 CHECK_VAL(break_info
.fnum
, 0);
4304 CHECK_VAL(break_info
.failures
, 0);
4306 smbcli_close(cli1
->tree
, fnum
);
4307 smbcli_close(cli1
->tree
, fnum2
);
4310 smb_raw_exit(cli1
->session
);
4311 smbcli_deltree(cli1
->tree
, BASEDIR
);
4316 * Open a file with an exclusive oplock from the 1st client and acquire a
4317 * brl. Then open the same file from the 2nd client that should give oplock
4318 * break with level2 to the 1st and return no oplock to the 2nd.
4320 static bool test_raw_oplock_brl4(struct torture_context
*tctx
,
4321 struct smbcli_state
*cli1
,
4322 struct smbcli_state
*cli2
)
4324 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
4332 if (!torture_setup_dir(cli1
, BASEDIR
)) {
4337 smbcli_unlink(cli1
->tree
, fname
);
4339 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
4343 base ntcreatex parms
4345 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4346 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4347 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
4348 SEC_RIGHTS_FILE_WRITE
;
4349 io
.ntcreatex
.in
.alloc_size
= 0;
4350 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4351 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
4352 NTCREATEX_SHARE_ACCESS_WRITE
;
4353 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4354 io
.ntcreatex
.in
.create_options
= 0;
4355 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4356 io
.ntcreatex
.in
.security_flags
= 0;
4357 io
.ntcreatex
.in
.fname
= fname
;
4359 torture_comment(tctx
, "open with exclusive oplock\n");
4360 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4361 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
4363 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
4365 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4366 fnum
= io
.ntcreatex
.out
.file
.fnum
;
4367 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
4369 /* create a file with bogus data */
4370 memset(buf
, 0, sizeof(buf
));
4372 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
4375 torture_comment(tctx
, "Failed to create file\n");
4379 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 1, 0, WRITE_LOCK
);
4380 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4382 torture_comment(tctx
, "a 2nd open should give a break to the 1st\n");
4383 ZERO_STRUCT(break_info
);
4385 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
4387 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
4388 CHECK_VAL(break_info
.count
, 1);
4389 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
4390 CHECK_VAL(break_info
.failures
, 0);
4391 CHECK_VAL(break_info
.fnum
, fnum
);
4393 torture_comment(tctx
, "and return no oplock to the 2nd\n");
4394 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
4395 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
4397 smbcli_close(cli1
->tree
, fnum
);
4398 smbcli_close(cli2
->tree
, fnum2
);
4401 smb_raw_exit(cli1
->session
);
4402 smb_raw_exit(cli2
->session
);
4403 smbcli_deltree(cli1
->tree
, BASEDIR
);
4408 basic testing of oplocks
4410 struct torture_suite
*torture_raw_oplock(TALLOC_CTX
*mem_ctx
)
4412 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "oplock");
4414 torture_suite_add_2smb_test(suite
, "exclusive1", test_raw_oplock_exclusive1
);
4415 torture_suite_add_2smb_test(suite
, "exclusive2", test_raw_oplock_exclusive2
);
4416 torture_suite_add_2smb_test(suite
, "exclusive3", test_raw_oplock_exclusive3
);
4417 torture_suite_add_2smb_test(suite
, "exclusive4", test_raw_oplock_exclusive4
);
4418 torture_suite_add_2smb_test(suite
, "exclusive5", test_raw_oplock_exclusive5
);
4419 torture_suite_add_2smb_test(suite
, "exclusive6", test_raw_oplock_exclusive6
);
4420 torture_suite_add_2smb_test(suite
, "exclusive7", test_raw_oplock_exclusive7
);
4421 torture_suite_add_2smb_test(suite
, "exclusive8",
4422 test_raw_oplock_exclusive8
);
4423 torture_suite_add_2smb_test(suite
, "exclusive9",
4424 test_raw_oplock_exclusive9
);
4425 torture_suite_add_2smb_test(suite
, "level_ii_1",
4426 test_raw_oplock_level_ii_1
);
4427 torture_suite_add_2smb_test(suite
, "batch1", test_raw_oplock_batch1
);
4428 torture_suite_add_2smb_test(suite
, "batch2", test_raw_oplock_batch2
);
4429 torture_suite_add_2smb_test(suite
, "batch3", test_raw_oplock_batch3
);
4430 torture_suite_add_2smb_test(suite
, "batch4", test_raw_oplock_batch4
);
4431 torture_suite_add_2smb_test(suite
, "batch5", test_raw_oplock_batch5
);
4432 torture_suite_add_2smb_test(suite
, "batch6", test_raw_oplock_batch6
);
4433 torture_suite_add_2smb_test(suite
, "batch7", test_raw_oplock_batch7
);
4434 torture_suite_add_2smb_test(suite
, "batch8", test_raw_oplock_batch8
);
4435 torture_suite_add_2smb_test(suite
, "batch9", test_raw_oplock_batch9
);
4436 torture_suite_add_2smb_test(suite
, "batch9a", test_raw_oplock_batch9a
);
4437 torture_suite_add_2smb_test(suite
, "batch10", test_raw_oplock_batch10
);
4438 torture_suite_add_2smb_test(suite
, "batch11", test_raw_oplock_batch11
);
4439 torture_suite_add_2smb_test(suite
, "batch12", test_raw_oplock_batch12
);
4440 torture_suite_add_2smb_test(suite
, "batch13", test_raw_oplock_batch13
);
4441 torture_suite_add_2smb_test(suite
, "batch14", test_raw_oplock_batch14
);
4442 torture_suite_add_2smb_test(suite
, "batch15", test_raw_oplock_batch15
);
4443 torture_suite_add_2smb_test(suite
, "batch16", test_raw_oplock_batch16
);
4444 torture_suite_add_2smb_test(suite
, "batch17", test_raw_oplock_batch17
);
4445 torture_suite_add_2smb_test(suite
, "batch18", test_raw_oplock_batch18
);
4446 torture_suite_add_2smb_test(suite
, "batch19", test_raw_oplock_batch19
);
4447 torture_suite_add_2smb_test(suite
, "batch20", test_raw_oplock_batch20
);
4448 torture_suite_add_2smb_test(suite
, "batch21", test_raw_oplock_batch21
);
4449 torture_suite_add_2smb_test(suite
, "batch22", test_raw_oplock_batch22
);
4450 torture_suite_add_2smb_test(suite
, "batch23", test_raw_oplock_batch23
);
4451 torture_suite_add_2smb_test(suite
, "batch24", test_raw_oplock_batch24
);
4452 torture_suite_add_2smb_test(suite
, "batch25", test_raw_oplock_batch25
);
4453 torture_suite_add_2smb_test(suite
, "batch26", test_raw_oplock_batch26
);
4454 torture_suite_add_2smb_test(suite
, "stream1", test_raw_oplock_stream1
);
4455 torture_suite_add_2smb_test(suite
, "doc1", test_raw_oplock_doc
);
4456 torture_suite_add_2smb_test(suite
, "brl1", test_raw_oplock_brl1
);
4457 torture_suite_add_1smb_test(suite
, "brl2", test_raw_oplock_brl2
);
4458 torture_suite_add_1smb_test(suite
, "brl3", test_raw_oplock_brl3
);
4459 torture_suite_add_2smb_test(suite
, "brl4", test_raw_oplock_brl4
);
4465 stress testing of oplocks
4467 bool torture_bench_oplock(struct torture_context
*torture
)
4469 struct smbcli_state
**cli
;
4471 TALLOC_CTX
*mem_ctx
= talloc_new(torture
);
4472 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
4474 int timelimit
= torture_setting_int(torture
, "timelimit", 10);
4478 cli
= talloc_array(mem_ctx
, struct smbcli_state
*, torture_nprocs
);
4480 torture_comment(torture
, "Opening %d connections\n", torture_nprocs
);
4481 for (i
=0;i
<torture_nprocs
;i
++) {
4482 if (!torture_open_connection_ev(&cli
[i
], i
, torture
, torture
->ev
)) {
4485 talloc_steal(mem_ctx
, cli
[i
]);
4486 smbcli_oplock_handler(cli
[i
]->transport
, oplock_handler_close
,
4490 if (!torture_setup_dir(cli
[0], BASEDIR
)) {
4495 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
4496 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4497 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4498 io
.ntcreatex
.in
.alloc_size
= 0;
4499 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4500 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
4501 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4502 io
.ntcreatex
.in
.create_options
= 0;
4503 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4504 io
.ntcreatex
.in
.security_flags
= 0;
4505 io
.ntcreatex
.in
.fname
= BASEDIR
"\\test.dat";
4506 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4507 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4508 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4510 tv
= timeval_current();
4513 we open the same file with SHARE_ACCESS_NONE from all the
4514 connections in a round robin fashion. Each open causes an
4515 oplock break on the previous connection, which is answered
4516 by the oplock_handler_close() to close the file.
4518 This measures how fast we can pass on oplocks, and stresses
4519 the oplock handling code
4521 torture_comment(torture
, "Running for %d seconds\n", timelimit
);
4522 while (timeval_elapsed(&tv
) < timelimit
) {
4523 for (i
=0;i
<torture_nprocs
;i
++) {
4526 status
= smb_raw_open(cli
[i
]->tree
, mem_ctx
, &io
);
4527 CHECK_STATUS(torture
, status
, NT_STATUS_OK
);
4531 if (torture_setting_bool(torture
, "progress", true)) {
4532 torture_comment(torture
, "%.2f ops/second\r", count
/timeval_elapsed(&tv
));
4536 torture_comment(torture
, "%.2f ops/second\n", count
/timeval_elapsed(&tv
));
4538 smb_raw_exit(cli
[torture_nprocs
-1]->session
);
4541 smb_raw_exit(cli
[0]->session
);
4542 smbcli_deltree(cli
[0]->tree
, BASEDIR
);
4543 talloc_free(mem_ctx
);
4548 static struct hold_oplock_info
{
4550 bool close_on_break
;
4551 uint32_t share_access
;
4555 .fname
= BASEDIR
"\\notshared_close",
4556 .close_on_break
= true,
4557 .share_access
= NTCREATEX_SHARE_ACCESS_NONE
,
4560 .fname
= BASEDIR
"\\notshared_noclose",
4561 .close_on_break
= false,
4562 .share_access
= NTCREATEX_SHARE_ACCESS_NONE
,
4565 .fname
= BASEDIR
"\\shared_close",
4566 .close_on_break
= true,
4567 .share_access
= NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
4570 .fname
= BASEDIR
"\\shared_noclose",
4571 .close_on_break
= false,
4572 .share_access
= NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
4576 static bool oplock_handler_hold(struct smbcli_transport
*transport
,
4577 uint16_t tid
, uint16_t fnum
, uint8_t level
,
4580 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
4581 struct hold_oplock_info
*info
;
4584 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4585 if (hold_info
[i
].fnum
== fnum
) break;
4588 if (i
== ARRAY_SIZE(hold_info
)) {
4589 printf("oplock break for unknown fnum %u\n", fnum
);
4593 info
= &hold_info
[i
];
4595 if (info
->close_on_break
) {
4596 printf("oplock break on %s - closing\n",
4598 oplock_handler_close(transport
, tid
, fnum
, level
, private_data
);
4602 printf("oplock break on %s - acking break\n", info
->fname
);
4604 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
4609 used for manual testing of oplocks - especially interaction with
4610 other filesystems (such as NFS and local access)
4612 bool torture_hold_oplock(struct torture_context
*torture
,
4613 struct smbcli_state
*cli
)
4615 struct tevent_context
*ev
= torture
->ev
;
4618 printf("Setting up open files with oplocks in %s\n", BASEDIR
);
4620 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
4622 smbcli_oplock_handler(cli
->transport
, oplock_handler_hold
, cli
->tree
);
4624 /* setup the files */
4625 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4630 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4631 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4632 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4633 io
.ntcreatex
.in
.alloc_size
= 0;
4634 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4635 io
.ntcreatex
.in
.share_access
= hold_info
[i
].share_access
;
4636 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4637 io
.ntcreatex
.in
.create_options
= 0;
4638 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4639 io
.ntcreatex
.in
.security_flags
= 0;
4640 io
.ntcreatex
.in
.fname
= hold_info
[i
].fname
;
4641 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4642 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4643 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4644 printf("opening %s\n", hold_info
[i
].fname
);
4646 status
= smb_raw_open(cli
->tree
, cli
, &io
);
4647 if (!NT_STATUS_IS_OK(status
)) {
4648 printf("Failed to open %s - %s\n",
4649 hold_info
[i
].fname
, nt_errstr(status
));
4653 if (io
.ntcreatex
.out
.oplock_level
!= BATCH_OPLOCK_RETURN
) {
4654 printf("Oplock not granted for %s - expected %d but got %d\n",
4655 hold_info
[i
].fname
, BATCH_OPLOCK_RETURN
,
4656 io
.ntcreatex
.out
.oplock_level
);
4659 hold_info
[i
].fnum
= io
.ntcreatex
.out
.file
.fnum
;
4661 /* make the file non-zero size */
4662 if (smbcli_write(cli
->tree
, hold_info
[i
].fnum
, 0, &c
, 0, 1) != 1) {
4663 printf("Failed to write to file\n");
4668 printf("Waiting for oplock events\n");
4669 tevent_loop_wait(ev
);